viirya commented on code in PR #11165:
URL: https://github.com/apache/arrow-rs/pull/11165#discussion_r4068973102


##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -605,6 +619,36 @@ impl ParquetPushDecoder {
         self.state.peek_next_row_group()
     }
 
+    /// Preview at most two filter-free row groups using the demand range 
planner.
+    ///
+    /// Returns `None` outside a row-group boundary or when row predicates are
+    /// present; returns an empty vector when there is no selected work. This
+    /// never advances the decoder, evaluates predicates, reads data, or 
creates
+    /// batch readers. Ranges fully covered by an input buffer are excluded;

Review Comment:
   Could we make explicit that all preview entries use the same current buffer 
state, without simulating buffer consumption by earlier entries? For example, 
with a plan of `[B, B]` and B already buffered, both entries can have empty 
ranges even though the first read may consume those buffers and the second read 
subsequently requests B again. The duplicate-group test covers this, but the 
distinction would also be useful in the public API docs.
   
   Relatedly, did you consider returning all required ranges independently of 
buffer coverage? The current behavior matches `NeedsData`, which is useful, but 
I would like to understand why it is the preferred contract for a caller 
managing its own read-ahead cache.



##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -605,6 +619,36 @@ impl ParquetPushDecoder {
         self.state.peek_next_row_group()
     }
 
+    /// Preview at most two filter-free row groups using the demand range 
planner.
+    ///
+    /// Returns `None` outside a row-group boundary or when row predicates are
+    /// present; returns an empty vector when there is no selected work. This
+    /// never advances the decoder, evaluates predicates, reads data, or 
creates
+    /// batch readers. Ranges fully covered by an input buffer are excluded;
+    /// partially covered ranges are returned unchanged, matching `NeedsData`.
+    ///
+    /// `max_row_groups` must be 1 or 2. Errors leave the decoder unchanged;
+    /// speculative callers should defer them to normal ordered demand. The
+    /// snapshot is only advisory: see [`RowGroupRangePreview`]. Cost includes
+    /// cloning the remaining row-group plan and selections.
+    pub fn preview_row_group_ranges(
+        &self,
+        max_row_groups: usize,
+    ) -> Result<Option<Vec<RowGroupRangePreview>>, ParquetError> {
+        if !(1..=2).contains(&max_row_groups) {

Review Comment:
   What motivates restricting `max_row_groups` to exactly 1 or 2? The 
implementation appears capable of walking more groups, and a scheduler reading 
from high-latency storage may want a deeper window. Bounding each call makes 
sense, but could the caller choose that bound through this parameter? If the 
cap is intentional for the initial API, could we document the use case or 
tradeoff behind it?



##########
parquet/src/arrow/async_reader/mod.rs:
##########
@@ -580,6 +580,15 @@ impl<T: AsyncFileReader + Send + 'static> 
ParquetRecordBatchStreamBuilder<T> {
         Self::new_builder(AsyncReader(input), metadata)
     }
 
+    /// Consume this builder and return its underlying async reader.

Review Comment:
   This ownership handoff looks useful and straightforward. One clarification 
for the motivating workflow: metadata-only preparation can already use 
`AsyncFileReader::get_metadata()` or `ArrowReaderMetadata::load_async(&mut 
reader, ...)` without transferring ownership to a stream builder. The builder’s 
Bloom-filter helper seems to be the stronger motivation here. As a possible 
follow-up, would it make sense to expose that helper independently of the 
builder as well? That need not block adding `into_inner()`.



##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -605,6 +619,36 @@ impl ParquetPushDecoder {
         self.state.peek_next_row_group()
     }
 
+    /// Preview at most two filter-free row groups using the demand range 
planner.
+    ///
+    /// Returns `None` outside a row-group boundary or when row predicates are
+    /// present; returns an empty vector when there is no selected work. This
+    /// never advances the decoder, evaluates predicates, reads data, or 
creates
+    /// batch readers. Ranges fully covered by an input buffer are excluded;
+    /// partially covered ranges are returned unchanged, matching `NeedsData`.
+    ///
+    /// `max_row_groups` must be 1 or 2. Errors leave the decoder unchanged;
+    /// speculative callers should defer them to normal ordered demand. The
+    /// snapshot is only advisory: see [`RowGroupRangePreview`]. Cost includes

Review Comment:
   Thanks for documenting the cloning cost. Since this API is intended for 
read-ahead, callers may invoke it at every row-group boundary. Cloning the 
entire remaining queue on each call gives quadratic cumulative queue-copying 
work across a scan, even with a preview depth of one or two. Have you evaluated 
this for files with many row groups or large selections? A focused measurement 
would help establish whether this is an acceptable initial tradeoff.



##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -605,6 +619,36 @@ impl ParquetPushDecoder {
         self.state.peek_next_row_group()
     }
 
+    /// Preview at most two filter-free row groups using the demand range 
planner.
+    ///
+    /// Returns `None` outside a row-group boundary or when row predicates are

Review Comment:
   Could we link to `is_at_row_group_boundary()` and add a short usage example 
with `try_next_reader()`? A loop using only `try_decode()` does not expose an 
intermediate previewable boundary: returned batches leave the decoder in 
`DecodingRowGroup`, and subsequent calls advance internally into the next 
group. An example showing when to preview, start speculative I/O, and reconcile 
it with ordered demand would make the intended usage much clearer.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to