Copilot commented on code in PR #11168:
URL: https://github.com/apache/arrow-rs/pull/11168#discussion_r4078642576


##########
parquet/src/column/page.rs:
##########
@@ -404,6 +404,22 @@ pub trait PageReader: Iterator<Item = Result<Page>> + Send 
{
     /// column index information
     fn skip_next_page(&mut self) -> Result<()>;
 
+    /// Decodes and returns a dictionary page this reader has previously
+    /// skipped past, if any.
+    ///
+    /// [`Self::skip_next_page`] may skip a dictionary page without decoding
+    /// it, since skipping rows never needs dictionary contents. If decoding
+    /// later reaches a dictionary-encoded data page, the reader is asked for
+    /// the dictionary through this method, which pays the deferred
+    /// decompression exactly once. A chunk skipped end to end never pays it.
+    ///
+    /// The default implementation returns `Ok(None)`, meaning the reader
+    /// never defers: every dictionary page it consumes is returned through
+    /// [`Self::get_next_page`] as before.
+    fn take_deferred_dictionary(&mut self) -> Result<Option<Page>> {
+        Ok(None)

Review Comment:
   This default is not behaviorally compatible with existing `PageReader` 
implementations. `skip_records` now consumes a dictionary via `skip_next_page`, 
but readers such as `InMemoryPageReader` only advance past it and this method 
returns `None`; the following dictionary-encoded data page then reaches 
`set_data` without `set_dict` and panics at `Decoder for dict should have been 
set`. Please either preserve/restore the skipped dictionary for non-deferred 
readers or provide an eager compatibility path; a no-op default cannot make 
existing custom implementations correct.



##########
parquet/src/column/reader.rs:
##########
@@ -317,9 +317,15 @@ where
                     return Ok(num_records - remaining_records);
                 };
 
-                // If dictionary, we must read it
+                // If dictionary, skip it without decoding: skipping rows
+                // never needs dictionary contents (value skips only advance
+                // the index cursor, whole-page skips touch nothing). The page
+                // reader keeps the page's location, so a later data page that
+                // does need the dictionary still gets it, paying the deferred
+                // decompression exactly once. A chunk skipped end to end
+                // never pays it. See `PageReader::take_deferred_dictionary`.
                 if metadata.is_dict {
-                    self.read_dictionary_page()?;
+                    self.page_reader.skip_next_page()?;

Review Comment:
   This now consumes a dictionary page for every `PageReader`, but the new 
`take_deferred_dictionary` default returns `None`. For example, 
`InMemoryPageReader::skip_next_page` drops the `Page::DictionaryPage`; a 
subsequent dictionary-encoded data page then reaches 
`ColumnValueDecoderImpl::set_data` without an installed decoder and panics at 
`decoder.rs:210-213`. Either make every `PageReader` retain skipped 
dictionaries (including existing/custom implementations) or gate this path on 
readers that support deferral.



##########
parquet/src/file/serialized_reader.rs:
##########
@@ -1151,18 +1207,55 @@ impl<R: ChunkReader> PageReader for 
SerializedPageReader<R> {
                 ..
             } => {
                 if dictionary_page.is_some() {
-                    // If a dictionary page exists, consume it by taking it 
(sets to None)
-                    dictionary_page.take();
+                    // Consume the dictionary page, keeping its location.
+                    
dictionary_page.take().map(DeferredDictionaryPage::Location)

Review Comment:
   The offset-index state still has no way to represent an offset-less 
dictionary page. `dictionary_page` is only synthesized when the first 
`PageLocation` differs from `ColumnChunkMetaData::byte_range().0`; when 
`dictionary_page_offset` is absent, `byte_range()` starts at 
`data_page_offset`, which is the first data-page location, so this branch 
skips/reads data pages without ever retaining the leading dictionary. Such a 
file will fail once a dictionary-encoded data page is decoded, despite the 
stated support for dictionaries whose metadata offset is missing. The 
page-index path needs an actual leading-header check (or must fall back to the 
values state) before applying this deferral.



-- 
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