Skip to main content

parquet/arrow/record_reader/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use arrow_buffer::{BooleanBufferBuilder, Buffer};
19
20use crate::arrow::record_reader::{
21    buffer::ValuesBuffer,
22    definition_levels::{DefinitionLevelBuffer, DefinitionLevelBufferDecoder},
23};
24use crate::column::reader::decoder::RepetitionLevelDecoderImpl;
25use crate::column::{
26    page::PageReader,
27    reader::{
28        GenericColumnReader,
29        decoder::{ColumnValueDecoder, ColumnValueDecoderImpl},
30    },
31};
32use crate::data_type::DataType;
33use crate::errors::{ParquetError, Result};
34use crate::schema::types::ColumnDescPtr;
35
36pub(crate) mod buffer;
37pub(crate) mod definition_levels;
38
39/// A `RecordReader` is a stateful column reader that delimits semantic records.
40pub type RecordReader<T> = GenericRecordReader<Vec<<T as DataType>::T>, ColumnValueDecoderImpl<T>>;
41
42pub(crate) type ColumnReader<CV> =
43    GenericColumnReader<RepetitionLevelDecoderImpl, DefinitionLevelBufferDecoder, CV>;
44
45/// A generic stateful column reader that delimits semantic records
46///
47/// This type is hidden from the docs, and relies on private traits with no
48/// public implementations. As such this type signature may be changed without
49/// breaking downstream users as it can only be constructed through type aliases
50pub struct GenericRecordReader<V, CV> {
51    column_desc: ColumnDescPtr,
52
53    /// Values buffer, lazily initialized on first read to avoid
54    /// allocating a buffer that may never be used (e.g., after the last batch)
55    values: Option<V>,
56    def_levels: Option<DefinitionLevelBuffer>,
57    rep_levels: Option<Vec<i16>>,
58    column_reader: Option<ColumnReader<CV>>,
59    /// Number of buffered levels / null-padded values
60    num_values: usize,
61    /// Number of buffered records
62    num_records: usize,
63    /// Capacity hint for pre-allocating buffers based on batch size
64    capacity_hint: usize,
65    /// Number of values in the values buffer (may differ from num_values when
66    /// padding_threshold is set, since parent-level padding is excluded).
67    values_written: usize,
68    /// Definition-level threshold used for selective null padding.
69    ///
70    /// With full padding (`None`), the leaf values buffer has one slot for each
71    /// decoded definition level. This includes placeholders for null or empty
72    /// parent lists, which parent `ListArrayReader`s later have to filter out
73    /// before computing offsets.
74    ///
75    /// With selective padding (`Some(threshold)`), the threshold is the nearest
76    /// enclosing list/map definition level. Entries with `def < threshold`
77    /// describe a null/empty parent and are skipped entirely. Entries with
78    /// `def >= threshold` belong to an actual child item slot: real values are
79    /// copied, and item-level nulls are padded. The companion `compact_bitmap`
80    /// has the same compact length and becomes the leaf null bitmap.
81    padding_threshold: Option<i16>,
82    /// Compact bitmap accumulated during selective padding. Each bit
83    /// corresponds to an item-level entry (def >= threshold): set when the
84    /// value is real (def >= max_def), unset for item-level nulls. Used both
85    /// as the valid_mask for `pad_nulls` (via `as_slice()`) and as the null
86    /// bitmap consumed by the leaf reader (via `consume_compact_bitmap`).
87    compact_bitmap: Option<BooleanBufferBuilder>,
88}
89
90impl<V, CV> GenericRecordReader<V, CV>
91where
92    V: ValuesBuffer,
93    CV: ColumnValueDecoder<Buffer = V>,
94{
95    /// Create a new [`GenericRecordReader`]
96    ///
97    /// The capacity is used to pre-allocate internal buffers for full-padding
98    /// reads, avoiding reallocations when reading fragmented row selections.
99    pub fn new(desc: ColumnDescPtr, capacity: usize) -> Self {
100        let def_levels = (desc.max_def_level() > 0)
101            .then(|| DefinitionLevelBuffer::new(&desc, packed_null_mask(&desc)));
102
103        let rep_levels = (desc.max_rep_level() > 0).then(Vec::new);
104
105        Self {
106            values: None, // Lazily initialized on first read
107            def_levels,
108            rep_levels,
109            column_reader: None,
110            column_desc: desc,
111            num_values: 0,
112            num_records: 0,
113            capacity_hint: capacity,
114            values_written: 0,
115            padding_threshold: None,
116            compact_bitmap: None,
117        }
118    }
119
120    /// Set the current page reader.
121    pub fn set_page_reader(&mut self, page_reader: Box<dyn PageReader>) -> Result<()> {
122        let descr = &self.column_desc;
123        let values_decoder = CV::new(descr);
124
125        let def_level_decoder = (descr.max_def_level() != 0).then(|| {
126            DefinitionLevelBufferDecoder::new(descr.max_def_level(), packed_null_mask(descr))
127        });
128
129        let rep_level_decoder = (descr.max_rep_level() != 0)
130            .then(|| RepetitionLevelDecoderImpl::new(descr.max_rep_level()));
131
132        self.column_reader = Some(GenericColumnReader::new_with_decoders(
133            self.column_desc.clone(),
134            page_reader,
135            values_decoder,
136            def_level_decoder,
137            rep_level_decoder,
138        ));
139        Ok(())
140    }
141
142    /// Try to read `num_records` of column data into internal buffer.
143    ///
144    /// # Returns
145    ///
146    /// Number of actual records read.
147    pub fn read_records(&mut self, num_records: usize) -> Result<usize> {
148        if self.column_reader.is_none() {
149            return Ok(0);
150        }
151
152        let mut records_read = 0;
153
154        loop {
155            let records_to_read = num_records - records_read;
156            records_read += self.read_one_batch(records_to_read)?;
157            if records_read == num_records || !self.column_reader.as_mut().unwrap().has_next()? {
158                break;
159            }
160        }
161        Ok(records_read)
162    }
163
164    /// Try to skip the next `num_records` rows
165    ///
166    /// # Returns
167    ///
168    /// Number of records skipped
169    pub fn skip_records(&mut self, num_records: usize) -> Result<usize> {
170        match self.column_reader.as_mut() {
171            Some(reader) => reader.skip_records(num_records),
172            None => Ok(0),
173        }
174    }
175
176    /// Returns number of records stored in buffer.
177    #[cfg_attr(not(test), expect(unused))]
178    pub fn num_records(&self) -> usize {
179        self.num_records
180    }
181
182    /// Return number of values stored in buffer.
183    /// If the parquet column is not repeated, it should be equals to `num_records`,
184    /// otherwise it should be larger than or equal to `num_records`.
185    pub fn num_values(&self) -> usize {
186        self.num_values
187    }
188
189    /// Returns definition level data.
190    /// The implementation has side effects. It will create a new buffer to hold those
191    /// definition level values that have already been read into memory but not counted
192    /// as record values, e.g. those from `self.num_values` to `self.values_written`.
193    pub fn consume_def_levels(&mut self) -> Option<Vec<i16>> {
194        self.def_levels.as_mut()?.consume_levels()
195    }
196
197    /// Return repetition level data.
198    /// The side effect is similar to `consume_def_levels`.
199    pub fn consume_rep_levels(&mut self) -> Option<Vec<i16>> {
200        self.rep_levels.as_mut().map(std::mem::take)
201    }
202
203    /// Returns currently stored buffer data.
204    /// The side effect is similar to `consume_def_levels`.
205    pub fn consume_record_data(&mut self) -> V {
206        // Take the buffer, leaving None. The next read will lazily allocate a new buffer.
207        // This avoids allocating a buffer that may never be used (e.g., after the last batch).
208        self.values.take().unwrap_or_else(|| V::with_capacity(0))
209    }
210
211    /// Reset state of record reader.
212    /// Should be called after consuming data, e.g. `consume_rep_levels`,
213    /// `consume_rep_levels`, `consume_record_data` and `consume_compact_bitmap`.
214    pub fn reset(&mut self) {
215        self.num_values = 0;
216        self.num_records = 0;
217        self.values_written = 0;
218        self.compact_bitmap = None;
219    }
220
221    /// Returns the maximum definition level for the column being read.
222    pub fn max_def_level(&self) -> i16 {
223        self.column_desc.max_def_level()
224    }
225
226    /// Set the padding threshold. When set, `pad_nulls` only pads entries
227    /// where `def >= threshold` (item-level nulls within non-null lists),
228    /// skipping list-level padding entries (def < threshold).
229    pub fn set_padding_threshold(&mut self, threshold: i16) {
230        self.padding_threshold = Some(threshold);
231    }
232
233    /// Returns the number of values in the values buffer.
234    /// When padding_threshold is None, this equals `num_values` (full padding).
235    /// When padding_threshold is set, this is the item_count (selective padding).
236    pub fn values_written(&self) -> usize {
237        if self.padding_threshold.is_some() {
238            self.values_written
239        } else {
240            self.num_values
241        }
242    }
243
244    /// Consume the compact null bitmap built during selective padding.
245    /// Returns the full bitmap when not using selective padding.
246    pub fn consume_compact_bitmap(&mut self) -> Option<Buffer> {
247        if self.padding_threshold.is_some() {
248            if let Some(levels) = self.def_levels.as_mut() {
249                levels.consume_bitmask();
250            }
251            self.compact_bitmap
252                .as_mut()
253                .map(|b| b.finish().into_inner())
254        } else {
255            self.consume_bitmap()
256        }
257    }
258
259    /// Returns bitmap data for nullable columns.
260    /// For non-nullable columns, the bitmap is discarded.
261    pub fn consume_bitmap(&mut self) -> Option<Buffer> {
262        let mask = self
263            .def_levels
264            .as_mut()
265            .and_then(|levels| levels.consume_bitmask());
266
267        // While we always consume the bitmask here, we only want to return
268        // the bitmask for nullable arrays. (Marking nulls on a non-nullable
269        // array may fail validations, even if those nulls are masked off at
270        // a higher level.)
271        if self.column_desc.self_type().is_optional() {
272            mask
273        } else {
274            None
275        }
276    }
277
278    /// Try to read one batch of data returning the number of records read
279    fn read_one_batch(&mut self, batch_size: usize) -> Result<usize> {
280        if batch_size == 0 {
281            return Ok(0);
282        }
283        // Update capacity hint to the largest batch size seen.
284        if batch_size > self.capacity_hint {
285            self.capacity_hint = batch_size;
286        }
287
288        let padding_threshold = self.padding_threshold;
289        let max_def = self.column_desc.max_def_level();
290        let mut physical_values_to_read = 0usize;
291        let mut output_slots_to_read = 0usize;
292
293        let values = self.values.get_or_insert_with(|| V::with_capacity(0));
294        let compact_bitmap = &mut self.compact_bitmap;
295
296        if padding_threshold.is_none() {
297            values.reserve_exact(self.capacity_hint.saturating_sub(self.num_values));
298        }
299
300        let (records_read, values_read, levels_read) = self
301            .column_reader
302            .as_mut()
303            .unwrap()
304            .read_records_with_reservation(
305                batch_size,
306                self.def_levels.as_mut(),
307                self.rep_levels.as_mut(),
308                values,
309                |values, values_to_read, levels_to_read, def_levels| {
310                    let output_slots = if let Some(threshold) = padding_threshold {
311                        let bitmap =
312                            compact_bitmap.get_or_insert_with(|| BooleanBufferBuilder::new(0));
313                        if values_to_read == levels_to_read {
314                            // Every level is at `max_def`, so each one is a non-null
315                            // child value and no level needs to be filtered out
316                            bitmap.append_n(levels_to_read, true);
317                            levels_to_read
318                        } else {
319                            let def_levels = def_levels.ok_or_else(|| {
320                                general_err!(
321                                    "Definition levels should exist when data is less than levels!"
322                                )
323                            })?;
324                            let all_levels = def_levels.levels().ok_or_else(|| {
325                                general_err!(
326                                    "Raw definition levels must be available for selective padding"
327                                )
328                            })?;
329                            let batch_levels = &all_levels[all_levels.len() - levels_to_read..];
330
331                            definition_levels::build_filtered_validity_bitmap(
332                                batch_levels,
333                                None,
334                                Some(threshold),
335                                max_def,
336                                bitmap,
337                            )
338                        }
339                    } else {
340                        levels_to_read
341                    };
342
343                    let additional = output_slots_to_read
344                        .saturating_add(output_slots)
345                        .saturating_sub(physical_values_to_read);
346                    values.reserve_exact(additional);
347
348                    output_slots_to_read += output_slots;
349                    physical_values_to_read += values_to_read;
350                    Ok(())
351                },
352            )?;
353
354        if self.padding_threshold.is_some() {
355            debug_assert_eq!(
356                physical_values_to_read, values_read,
357                "reservation accounting must match decoded values"
358            );
359            let item_count = output_slots_to_read;
360            let bitmap = compact_bitmap.get_or_insert_with(|| BooleanBufferBuilder::new(0));
361
362            // Pad values to item_count positions (only if there are gaps).
363            if values_read < item_count {
364                values.reserve_exact(item_count - values_read);
365                values.pad_nulls(
366                    self.values_written,
367                    values_read,
368                    item_count,
369                    bitmap.as_slice(),
370                )?;
371            }
372
373            debug_assert_eq!(
374                bitmap.len(),
375                self.values_written + item_count,
376                "compact bitmap length must equal total items written"
377            );
378            self.values_written += item_count;
379        } else if values_read < levels_read {
380            debug_assert_eq!(
381                output_slots_to_read, levels_read,
382                "reservation accounting must match decoded levels"
383            );
384            // Full padding: pad all null positions.
385            let def_levels = self.def_levels.as_ref().ok_or_else(|| {
386                general_err!("Definition levels should exist when data is less than levels!")
387            })?;
388
389            values.reserve_exact(levels_read - values_read);
390            values.pad_nulls(
391                self.num_values,
392                values_read,
393                levels_read,
394                def_levels.nulls().as_slice(),
395            )?;
396        }
397
398        self.num_records += records_read;
399        self.num_values += levels_read;
400        Ok(records_read)
401    }
402}
403
404/// Returns true if we do not need to unpack the nullability for this column, this is
405/// only possible if the max definition level is 1, and corresponds to nulls at the
406/// leaf level, as opposed to a nullable parent nested type
407fn packed_null_mask(descr: &ColumnDescPtr) -> bool {
408    descr.max_def_level() == 1 && descr.max_rep_level() == 0 && descr.self_type().is_optional()
409}
410
411#[cfg(test)]
412mod tests {
413    use std::sync::Arc;
414
415    use arrow::buffer::Buffer;
416
417    use crate::arrow::arrow_reader::DEFAULT_BATCH_SIZE;
418    use crate::basic::Encoding;
419    use crate::data_type::Int32Type;
420    use crate::schema::parser::parse_message_type;
421    use crate::schema::types::SchemaDescriptor;
422    use crate::util::test_common::page_util::{
423        DataPageBuilder, DataPageBuilderImpl, InMemoryPageReader,
424    };
425
426    use super::RecordReader;
427
428    #[test]
429    fn test_read_required_records() {
430        // Construct column schema
431        let message_type = "
432        message test_schema {
433          REQUIRED INT32 leaf;
434        }
435        ";
436        let desc = parse_message_type(message_type)
437            .map(|t| SchemaDescriptor::new(Arc::new(t)))
438            .map(|s| s.column(0))
439            .unwrap();
440
441        // Construct record reader
442        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
443
444        // First page
445
446        // Records data:
447        // test_schema
448        //   leaf: 4
449        // test_schema
450        //   leaf: 7
451        // test_schema
452        //   leaf: 6
453        // test_schema
454        //   left: 3
455        // test_schema
456        //   left: 2
457        {
458            let values = [4, 7, 6, 3, 2];
459            let mut pb = DataPageBuilderImpl::new(desc.clone(), 5, true);
460            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
461            let page = pb.consume();
462
463            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
464            record_reader.set_page_reader(page_reader).unwrap();
465            assert_eq!(2, record_reader.read_records(2).unwrap());
466            assert_eq!(2, record_reader.num_records());
467            assert_eq!(2, record_reader.num_values());
468            assert_eq!(3, record_reader.read_records(3).unwrap());
469            assert_eq!(5, record_reader.num_records());
470            assert_eq!(5, record_reader.num_values());
471        }
472
473        // Second page
474
475        // Records data:
476        // test_schema
477        //   leaf: 8
478        // test_schema
479        //   leaf: 9
480        {
481            let values = [8, 9];
482            let mut pb = DataPageBuilderImpl::new(desc, 2, true);
483            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
484            let page = pb.consume();
485
486            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
487            record_reader.set_page_reader(page_reader).unwrap();
488            assert_eq!(2, record_reader.read_records(10).unwrap());
489            assert_eq!(7, record_reader.num_records());
490            assert_eq!(7, record_reader.num_values());
491        }
492
493        assert_eq!(record_reader.consume_record_data(), &[4, 7, 6, 3, 2, 8, 9]);
494        assert_eq!(None, record_reader.consume_def_levels());
495        assert_eq!(None, record_reader.consume_bitmap());
496    }
497
498    #[test]
499    fn test_capacity_hint_preserved_across_fragmented_reads() {
500        let message_type = "
501        message test_schema {
502          REQUIRED INT32 leaf;
503        }
504        ";
505        let desc = parse_message_type(message_type)
506            .map(|t| SchemaDescriptor::new(Arc::new(t)))
507            .map(|s| s.column(0))
508            .unwrap();
509
510        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), 8);
511        let values = [1, 2, 3, 4];
512        let mut pb = DataPageBuilderImpl::new(desc, 4, true);
513        pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
514        let page = pb.consume();
515
516        let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
517        record_reader.set_page_reader(page_reader).unwrap();
518
519        assert_eq!(1, record_reader.read_records(1).unwrap());
520        assert_eq!(1, record_reader.read_records(1).unwrap());
521
522        let record_data = record_reader.consume_record_data();
523        assert_eq!(record_data, &[1, 2]);
524        assert!(
525            record_data.capacity() >= 8,
526            "capacity hint should survive fragmented reads, got {}",
527            record_data.capacity()
528        );
529    }
530
531    #[test]
532    fn test_read_optional_records() {
533        // Construct column schema
534        let message_type = "
535        message test_schema {
536          OPTIONAL Group test_struct {
537            OPTIONAL INT32 leaf;
538          }
539        }
540        ";
541
542        let desc = parse_message_type(message_type)
543            .map(|t| SchemaDescriptor::new(Arc::new(t)))
544            .map(|s| s.column(0))
545            .unwrap();
546
547        // Construct record reader
548        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
549
550        // First page
551
552        // Records data:
553        // test_schema
554        //   test_struct
555        // test_schema
556        //   test_struct
557        //     left: 7
558        // test_schema
559        // test_schema
560        //   test_struct
561        //     leaf: 6
562        // test_schema
563        //   test_struct
564        //     leaf: 6
565        {
566            let values = [7, 6, 3];
567            //empty, non-empty, empty, non-empty, non-empty
568            let def_levels = [1i16, 2i16, 0i16, 2i16, 2i16];
569            let mut pb = DataPageBuilderImpl::new(desc.clone(), 5, true);
570            pb.add_def_levels(2, &def_levels);
571            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
572            let page = pb.consume();
573
574            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
575            record_reader.set_page_reader(page_reader).unwrap();
576            assert_eq!(2, record_reader.read_records(2).unwrap());
577            assert_eq!(2, record_reader.num_records());
578            assert_eq!(2, record_reader.num_values());
579            assert_eq!(3, record_reader.read_records(3).unwrap());
580            assert_eq!(5, record_reader.num_records());
581            assert_eq!(5, record_reader.num_values());
582        }
583
584        // Second page
585
586        // Records data:
587        // test_schema
588        // test_schema
589        //   test_struct
590        //     left: 8
591        {
592            let values = [8];
593            //empty, non-empty
594            let def_levels = [0i16, 2i16];
595            let mut pb = DataPageBuilderImpl::new(desc, 2, true);
596            pb.add_def_levels(2, &def_levels);
597            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
598            let page = pb.consume();
599
600            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
601            record_reader.set_page_reader(page_reader).unwrap();
602            assert_eq!(2, record_reader.read_records(10).unwrap());
603            assert_eq!(7, record_reader.num_records());
604            assert_eq!(7, record_reader.num_values());
605        }
606
607        // Verify result def levels
608        assert_eq!(
609            Some(vec![1i16, 2i16, 0i16, 2i16, 2i16, 0i16, 2i16]),
610            record_reader.consume_def_levels()
611        );
612
613        // Verify bitmap
614        let expected_valid = &[false, true, false, true, true, false, true];
615        let expected_buffer = Buffer::from_iter(expected_valid.iter().copied());
616        assert_eq!(Some(expected_buffer), record_reader.consume_bitmap());
617
618        // Verify result record data
619        let actual = record_reader.consume_record_data();
620
621        let expected = &[0, 7, 0, 6, 3, 0, 8];
622        assert_eq!(actual.len(), expected.len());
623
624        // Only validate valid values are equal
625        let iter = expected_valid.iter().zip(&actual).zip(expected);
626        for ((valid, actual), expected) in iter {
627            if *valid {
628                assert_eq!(actual, expected)
629            }
630        }
631    }
632
633    #[test]
634    fn test_read_repeated_records() {
635        // Construct column schema
636        let message_type = "
637        message test_schema {
638          REPEATED Group test_struct {
639            REPEATED  INT32 leaf;
640          }
641        }
642        ";
643
644        let desc = parse_message_type(message_type)
645            .map(|t| SchemaDescriptor::new(Arc::new(t)))
646            .map(|s| s.column(0))
647            .unwrap();
648
649        // Construct record reader
650        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
651
652        // First page
653
654        // Records data:
655        // test_schema
656        //   test_struct
657        //     leaf: 4
658        // test_schema
659        // test_schema
660        //   test_struct
661        //   test_struct
662        //     leaf: 7
663        //     leaf: 6
664        //     leaf: 3
665        //   test_struct
666        //     leaf: 2
667        {
668            let values = [4, 7, 6, 3, 2];
669            let def_levels = [2i16, 0i16, 1i16, 2i16, 2i16, 2i16, 2i16];
670            let rep_levels = [0i16, 0i16, 0i16, 1i16, 2i16, 2i16, 1i16];
671            let mut pb = DataPageBuilderImpl::new(desc.clone(), 7, true);
672            pb.add_rep_levels(2, &rep_levels);
673            pb.add_def_levels(2, &def_levels);
674            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
675            let page = pb.consume();
676
677            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
678            record_reader.set_page_reader(page_reader).unwrap();
679
680            assert_eq!(1, record_reader.read_records(1).unwrap());
681            assert_eq!(1, record_reader.num_records());
682            assert_eq!(1, record_reader.num_values());
683            assert_eq!(2, record_reader.read_records(3).unwrap());
684            assert_eq!(3, record_reader.num_records());
685            assert_eq!(7, record_reader.num_values());
686        }
687
688        // Second page
689
690        // Records data:
691        // test_schema
692        //   test_struct
693        //     leaf: 8
694        //     leaf: 9
695        {
696            let values = [8, 9];
697            let def_levels = [2i16, 2i16];
698            let rep_levels = [0i16, 2i16];
699            let mut pb = DataPageBuilderImpl::new(desc, 2, true);
700            pb.add_rep_levels(2, &rep_levels);
701            pb.add_def_levels(2, &def_levels);
702            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
703            let page = pb.consume();
704
705            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
706            record_reader.set_page_reader(page_reader).unwrap();
707
708            assert_eq!(1, record_reader.read_records(10).unwrap());
709            assert_eq!(4, record_reader.num_records());
710            assert_eq!(9, record_reader.num_values());
711        }
712
713        // Verify result def levels
714        assert_eq!(
715            Some(vec![2i16, 0i16, 1i16, 2i16, 2i16, 2i16, 2i16, 2i16, 2i16]),
716            record_reader.consume_def_levels()
717        );
718
719        // Verify bitmap
720        let expected_valid = &[true, false, false, true, true, true, true, true, true];
721        let expected_buffer = Buffer::from_iter(expected_valid.iter().copied());
722        assert_eq!(Some(expected_buffer), record_reader.consume_bitmap());
723
724        // Verify result record data
725        let actual = record_reader.consume_record_data();
726        let expected = &[4, 0, 0, 7, 6, 3, 2, 8, 9];
727        assert_eq!(actual.len(), expected.len());
728
729        // Only validate valid values are equal
730        let iter = expected_valid.iter().zip(&actual).zip(expected);
731        for ((valid, actual), expected) in iter {
732            if *valid {
733                assert_eq!(actual, expected)
734            }
735        }
736    }
737
738    #[test]
739    fn test_selective_padding_consumes_full_bitmap() {
740        let message_type = "
741        message test_schema {
742          OPTIONAL GROUP my_list (LIST) {
743            REPEATED GROUP list {
744              OPTIONAL INT32 element;
745            }
746          }
747        }
748        ";
749
750        let desc = parse_message_type(message_type)
751            .map(|t| SchemaDescriptor::new(Arc::new(t)))
752            .map(|s| s.column(0))
753            .unwrap();
754
755        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
756        record_reader.set_padding_threshold(2);
757
758        let values = [10, 20];
759        let def_levels = [3i16, 2i16, 0i16, 2i16, 3i16];
760        let rep_levels = [0i16, 1i16, 0i16, 0i16, 1i16];
761        let mut pb = DataPageBuilderImpl::new(desc, 5, true);
762        pb.add_rep_levels(1, &rep_levels);
763        pb.add_def_levels(3, &def_levels);
764        pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
765
766        let page_reader = Box::new(InMemoryPageReader::new(vec![pb.consume()]));
767        record_reader.set_page_reader(page_reader).unwrap();
768        assert_eq!(3, record_reader.read_records(3).unwrap());
769
770        let expected_compact = Buffer::from_iter([true, false, false, true]);
771        assert_eq!(
772            Some(expected_compact),
773            record_reader.consume_compact_bitmap()
774        );
775        assert_eq!(None, record_reader.consume_bitmap());
776    }
777
778    #[test]
779    fn test_selective_padding_reserves_compact_capacity() {
780        let message_type = "
781        message test_schema {
782          OPTIONAL GROUP my_list (LIST) {
783            REPEATED GROUP list {
784              OPTIONAL INT32 element;
785            }
786          }
787        }
788        ";
789
790        let desc = parse_message_type(message_type)
791            .map(|t| SchemaDescriptor::new(Arc::new(t)))
792            .map(|s| s.column(0))
793            .unwrap();
794
795        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
796        record_reader.set_padding_threshold(2);
797
798        let values = [10];
799        let mut def_levels = vec![0i16; 30];
800        def_levels.extend([3i16, 2i16]);
801        let rep_levels = vec![0i16; def_levels.len()];
802
803        let mut pb = DataPageBuilderImpl::new(desc, def_levels.len() as u32, true);
804        pb.add_rep_levels(1, &rep_levels);
805        pb.add_def_levels(3, &def_levels);
806        pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
807
808        let page_reader = Box::new(InMemoryPageReader::new(vec![pb.consume()]));
809        record_reader.set_page_reader(page_reader).unwrap();
810        assert_eq!(def_levels.len(), record_reader.read_records(128).unwrap());
811
812        let expected_compact = Buffer::from_iter([true, false]);
813        assert_eq!(
814            Some(expected_compact),
815            record_reader.consume_compact_bitmap()
816        );
817
818        let actual = record_reader.consume_record_data();
819        assert_eq!(actual.len(), 2);
820        assert_eq!(actual[0], 10);
821        assert!(
822            actual.capacity() < def_levels.len(),
823            "selective padding should not reserve one child slot per list-level NULL"
824        );
825    }
826
827    #[test]
828    fn test_selective_padding_alternating_null_pages() {
829        let message_type = "
830        message test_schema {
831          OPTIONAL GROUP my_list (LIST) {
832            REPEATED GROUP list {
833              OPTIONAL INT32 element;
834            }
835          }
836        }
837        ";
838
839        let desc = parse_message_type(message_type)
840            .map(|t| SchemaDescriptor::new(Arc::new(t)))
841            .map(|s| s.column(0))
842            .unwrap();
843
844        // Pages with no nulls alternate with pages that have null lists, empty
845        // lists and null elements. Every page boundary falls in the middle of a
846        // byte of the child validity bitmap, and the last page crosses into its
847        // third byte.
848        let pages: &[(&[i16], &[i16], &[i32])] = &[
849            // [1, 2, 3], [4, 5]
850            (&[3, 3, 3, 3, 3], &[0, 1, 1, 0, 1], &[1, 2, 3, 4, 5]),
851            // null, [6, null], [], [null, 7, 8]
852            (&[0, 3, 2, 1, 2, 3, 3], &[0, 0, 1, 0, 0, 1, 1], &[6, 7, 8]),
853            // [9], [10, 11]
854            (&[3, 3, 3], &[0, 0, 1], &[9, 10, 11]),
855            // [12, null], null
856            (&[3, 2, 0], &[0, 1, 0], &[12]),
857            // [13, 14, 15, 16]
858            (&[3, 3, 3, 3], &[0, 1, 1, 1], &[13, 14, 15, 16]),
859        ];
860        let expected_valid = [
861            true, true, true, true, true, true, false, false, true, true, true, true, true, true,
862            false, true, true, true, true,
863        ];
864        let expected_values = [
865            1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12, 0, 13, 14, 15, 16,
866        ];
867        let num_records = 11;
868        let num_levels = 22;
869
870        let page_vec = pages
871            .iter()
872            .map(|(def_levels, rep_levels, values)| {
873                let mut pb = DataPageBuilderImpl::new(desc.clone(), def_levels.len() as u32, true);
874                pb.add_rep_levels(1, rep_levels);
875                pb.add_def_levels(3, def_levels);
876                pb.add_values::<Int32Type>(Encoding::PLAIN, values);
877                pb.consume()
878            })
879            .collect::<Vec<_>>();
880
881        // Read all records in one batch, then one record per batch
882        for batch_size in [num_records, 1] {
883            let mut record_reader =
884                RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
885            record_reader.set_padding_threshold(2);
886            record_reader
887                .set_page_reader(Box::new(InMemoryPageReader::new(page_vec.clone())))
888                .unwrap();
889
890            for _ in 0..num_records / batch_size {
891                assert_eq!(record_reader.read_records(batch_size).unwrap(), batch_size);
892            }
893            assert_eq!(record_reader.num_records(), num_records);
894            assert_eq!(record_reader.num_values(), num_levels);
895            assert_eq!(record_reader.values_written(), expected_values.len());
896
897            assert_eq!(
898                record_reader.consume_compact_bitmap(),
899                Some(Buffer::from_iter(expected_valid)),
900                "batch_size {batch_size}"
901            );
902
903            // Only compare the valid values
904            let actual = record_reader.consume_record_data();
905            assert_eq!(
906                actual.len(),
907                expected_values.len(),
908                "batch_size {batch_size}"
909            );
910            for (i, valid) in expected_valid.iter().enumerate() {
911                if *valid {
912                    assert_eq!(
913                        actual[i], expected_values[i],
914                        "batch_size {batch_size}, index {i}"
915                    );
916                }
917            }
918        }
919    }
920
921    #[test]
922    fn test_read_more_than_one_batch() {
923        // Construct column schema
924        let message_type = "
925        message test_schema {
926          REPEATED  INT32 leaf;
927        }
928        ";
929
930        let desc = parse_message_type(message_type)
931            .map(|t| SchemaDescriptor::new(Arc::new(t)))
932            .map(|s| s.column(0))
933            .unwrap();
934
935        // Construct record reader
936        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
937
938        {
939            let values = vec![100; 5000];
940            let def_levels = [1i16; 5000];
941            let mut rep_levels = [1i16; 5000];
942            for idx in 0..1000 {
943                rep_levels[idx * 5] = 0i16;
944            }
945
946            let mut pb = DataPageBuilderImpl::new(desc, 5000, true);
947            pb.add_rep_levels(1, &rep_levels);
948            pb.add_def_levels(1, &def_levels);
949            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
950            let page = pb.consume();
951
952            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
953            record_reader.set_page_reader(page_reader).unwrap();
954
955            assert_eq!(1000, record_reader.read_records(1000).unwrap());
956            assert_eq!(1000, record_reader.num_records());
957            assert_eq!(5000, record_reader.num_values());
958        }
959    }
960
961    #[test]
962    fn test_row_group_boundary() {
963        // Construct column schema
964        let message_type = "
965        message test_schema {
966          REPEATED Group test_struct {
967            REPEATED  INT32 leaf;
968          }
969        }
970        ";
971
972        let desc = parse_message_type(message_type)
973            .map(|t| SchemaDescriptor::new(Arc::new(t)))
974            .map(|s| s.column(0))
975            .unwrap();
976
977        let values = [1, 2, 3];
978        let def_levels = [1i16, 0i16, 1i16, 2i16, 2i16, 1i16, 2i16];
979        let rep_levels = [0i16, 0i16, 0i16, 1i16, 2i16, 0i16, 1i16];
980        let mut pb = DataPageBuilderImpl::new(desc.clone(), 7, true);
981        pb.add_rep_levels(2, &rep_levels);
982        pb.add_def_levels(2, &def_levels);
983        pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
984        let page = pb.consume();
985
986        let mut record_reader = RecordReader::<Int32Type>::new(desc, DEFAULT_BATCH_SIZE);
987        let page_reader = Box::new(InMemoryPageReader::new(vec![page.clone()]));
988        record_reader.set_page_reader(page_reader).unwrap();
989        assert_eq!(record_reader.read_records(4).unwrap(), 4);
990        assert_eq!(record_reader.num_records(), 4);
991        assert_eq!(record_reader.num_values(), 7);
992
993        assert_eq!(record_reader.read_records(4).unwrap(), 0);
994        assert_eq!(record_reader.num_records(), 4);
995        assert_eq!(record_reader.num_values(), 7);
996
997        record_reader.read_records(4).unwrap();
998
999        let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
1000        record_reader.set_page_reader(page_reader).unwrap();
1001
1002        assert_eq!(record_reader.read_records(4).unwrap(), 4);
1003        assert_eq!(record_reader.num_records(), 8);
1004        assert_eq!(record_reader.num_values(), 14);
1005
1006        assert_eq!(record_reader.read_records(4).unwrap(), 0);
1007        assert_eq!(record_reader.num_records(), 8);
1008        assert_eq!(record_reader.num_values(), 14);
1009    }
1010
1011    #[test]
1012    fn test_skip_required_records() {
1013        // Construct column schema
1014        let message_type = "
1015        message test_schema {
1016          REQUIRED INT32 leaf;
1017        }
1018        ";
1019        let desc = parse_message_type(message_type)
1020            .map(|t| SchemaDescriptor::new(Arc::new(t)))
1021            .map(|s| s.column(0))
1022            .unwrap();
1023
1024        // Construct record reader
1025        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
1026
1027        // First page
1028
1029        // Records data:
1030        // test_schema
1031        //   leaf: 4
1032        // test_schema
1033        //   leaf: 7
1034        // test_schema
1035        //   leaf: 6
1036        // test_schema
1037        //   left: 3
1038        // test_schema
1039        //   left: 2
1040        {
1041            let values = [4, 7, 6, 3, 2];
1042            let mut pb = DataPageBuilderImpl::new(desc.clone(), 5, true);
1043            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
1044            let page = pb.consume();
1045
1046            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
1047            record_reader.set_page_reader(page_reader).unwrap();
1048            assert_eq!(2, record_reader.skip_records(2).unwrap());
1049            assert_eq!(0, record_reader.num_records());
1050            assert_eq!(0, record_reader.num_values());
1051            assert_eq!(3, record_reader.read_records(3).unwrap());
1052            assert_eq!(3, record_reader.num_records());
1053            assert_eq!(3, record_reader.num_values());
1054        }
1055
1056        // Second page
1057
1058        // Records data:
1059        // test_schema
1060        //   leaf: 8
1061        // test_schema
1062        //   leaf: 9
1063        {
1064            let values = [8, 9];
1065            let mut pb = DataPageBuilderImpl::new(desc, 2, true);
1066            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
1067            let page = pb.consume();
1068
1069            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
1070            record_reader.set_page_reader(page_reader).unwrap();
1071            assert_eq!(2, record_reader.skip_records(10).unwrap());
1072            assert_eq!(3, record_reader.num_records());
1073            assert_eq!(3, record_reader.num_values());
1074            assert_eq!(0, record_reader.read_records(10).unwrap());
1075        }
1076
1077        assert_eq!(record_reader.consume_record_data(), &[6, 3, 2]);
1078        assert_eq!(None, record_reader.consume_def_levels());
1079        assert_eq!(None, record_reader.consume_bitmap());
1080    }
1081
1082    #[test]
1083    fn test_skip_optional_records() {
1084        // Construct column schema
1085        let message_type = "
1086        message test_schema {
1087          OPTIONAL Group test_struct {
1088            OPTIONAL INT32 leaf;
1089          }
1090        }
1091        ";
1092
1093        let desc = parse_message_type(message_type)
1094            .map(|t| SchemaDescriptor::new(Arc::new(t)))
1095            .map(|s| s.column(0))
1096            .unwrap();
1097
1098        // Construct record reader
1099        let mut record_reader = RecordReader::<Int32Type>::new(desc.clone(), DEFAULT_BATCH_SIZE);
1100
1101        // First page
1102
1103        // Records data:
1104        // test_schema
1105        //   test_struct
1106        // test_schema
1107        //   test_struct
1108        //     leaf: 7
1109        // test_schema
1110        // test_schema
1111        //   test_struct
1112        //     leaf: 6
1113        // test_schema
1114        //   test_struct
1115        //     leaf: 6
1116        {
1117            let values = [7, 6, 3];
1118            //empty, non-empty, empty, non-empty, non-empty
1119            let def_levels = [1i16, 2i16, 0i16, 2i16, 2i16];
1120            let mut pb = DataPageBuilderImpl::new(desc.clone(), 5, true);
1121            pb.add_def_levels(2, &def_levels);
1122            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
1123            let page = pb.consume();
1124
1125            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
1126            record_reader.set_page_reader(page_reader).unwrap();
1127            assert_eq!(2, record_reader.skip_records(2).unwrap());
1128            assert_eq!(0, record_reader.num_records());
1129            assert_eq!(0, record_reader.num_values());
1130            assert_eq!(3, record_reader.read_records(3).unwrap());
1131            assert_eq!(3, record_reader.num_records());
1132            assert_eq!(3, record_reader.num_values());
1133        }
1134
1135        // Second page
1136
1137        // Records data:
1138        // test_schema
1139        // test_schema
1140        //   test_struct
1141        //     left: 8
1142        {
1143            let values = [8];
1144            //empty, non-empty
1145            let def_levels = [0i16, 2i16];
1146            let mut pb = DataPageBuilderImpl::new(desc, 2, true);
1147            pb.add_def_levels(2, &def_levels);
1148            pb.add_values::<Int32Type>(Encoding::PLAIN, &values);
1149            let page = pb.consume();
1150
1151            let page_reader = Box::new(InMemoryPageReader::new(vec![page]));
1152            record_reader.set_page_reader(page_reader).unwrap();
1153            assert_eq!(2, record_reader.skip_records(10).unwrap());
1154            assert_eq!(3, record_reader.num_records());
1155            assert_eq!(3, record_reader.num_values());
1156            assert_eq!(0, record_reader.read_records(10).unwrap());
1157        }
1158
1159        // Verify result def levels
1160        assert_eq!(
1161            Some(vec![0i16, 2i16, 2i16]),
1162            record_reader.consume_def_levels()
1163        );
1164
1165        // Verify bitmap
1166        let expected_valid = &[false, true, true];
1167        let expected_buffer = Buffer::from_iter(expected_valid.iter().copied());
1168        assert_eq!(Some(expected_buffer), record_reader.consume_bitmap());
1169
1170        // Verify result record data
1171        let actual = record_reader.consume_record_data();
1172
1173        let expected = &[0, 6, 3];
1174        assert_eq!(actual.len(), expected.len());
1175
1176        // Only validate valid values are equal
1177        let iter = expected_valid.iter().zip(&actual).zip(expected);
1178        for ((valid, actual), expected) in iter {
1179            if *valid {
1180                assert_eq!(actual, expected)
1181            }
1182        }
1183    }
1184}