MCPcopy Create free account
hub / github.com/apache/datafusion / transition

Method transition

datafusion/datasource-parquet/src/push_decoder.rs:149–205  ·  view source on GitHub ↗

Advances the decoder state machine until the next [`RecordBatch`] is produced, the file is fully consumed, or an error occurs. On each iteration the decoder is polled via [`ParquetPushDecoder::try_decode`]: - [`NeedsData`](DecodeResult::NeedsData) – the requested byte ranges are fetched from the [`AsyncFileReader`] and fed back into the decoder. - [`Data`](DecodeResult::Data) – a decoded batch is

(mut self)

Source from the content-addressed store, hash-verified

147 /// miri where `&mut self` creates a single opaque borrow that conflicts
148 /// with `unfold`'s ownership across yield points.
149 async fn transition(mut self) -> Option<(Result<RecordBatch>, Self)> {
150 loop {
151 if self.remaining_limit == Some(0) {
152 return None;
153 }
154 match self.decoder.try_decode() {
155 Ok(DecodeResult::NeedsData(ranges)) => {
156 let data = self
157 .reader
158 .get_byte_ranges(ranges.clone())
159 .await
160 .map_err(DataFusionError::from);
161 match data {
162 Ok(data) => {
163 if let Err(e) = self.decoder.push_ranges(ranges, data) {
164 return Some((Err(DataFusionError::from(e)), self));
165 }
166 }
167 Err(e) => return Some((Err(e), self)),
168 }
169 }
170 Ok(DecodeResult::Data(batch)) => {
171 let batch = if let Some(remaining_limit) = self.remaining_limit {
172 if batch.num_rows() > remaining_limit {
173 self.remaining_limit = Some(0);
174 batch.slice(0, remaining_limit)
175 } else {
176 self.remaining_limit =
177 Some(remaining_limit - batch.num_rows());
178 batch
179 }
180 } else {
181 batch
182 };
183 let mut timer = self.baseline_metrics.elapsed_compute().timer();
184 self.copy_arrow_reader_metrics();
185 let result = self.project_batch(&batch);
186 timer.stop();
187 // Release the borrow on baseline_metrics before moving self
188 drop(timer);
189 return Some((result, self));
190 }
191 Ok(DecodeResult::Finished) => {
192 // If there are pending decoders (e.g. for consecutive runs
193 // with different filter configurations), switch to the next.
194 if let Some(next) = self.pending_decoders.pop_front() {
195 self.decoder = next;
196 continue;
197 }
198 return None;
199 }
200 Err(e) => {
201 return Some((Err(DataFusionError::from(e)), self));
202 }
203 }
204 }
205 }
206

Callers 1

into_streamMethod · 0.45

Calls 10

sliceMethod · 0.80
timerMethod · 0.80
pop_frontMethod · 0.80
try_decodeMethod · 0.45
get_byte_rangesMethod · 0.45
cloneMethod · 0.45
elapsed_computeMethod · 0.45
project_batchMethod · 0.45
stopMethod · 0.45

Tested by

no test coverage detected