Skip to main content

parquet/arrow/array_reader/
primitive_array.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 crate::arrow::array_reader::{ArrayReader, read_records, skip_records};
19use crate::arrow::record_reader::RecordReader;
20use crate::arrow::schema::parquet_to_arrow_field;
21use crate::basic::Type as PhysicalType;
22use crate::column::page::PageIterator;
23use crate::data_type::{DataType, Int96};
24use crate::errors::Result;
25use crate::schema::types::ColumnDescPtr;
26use arrow_array::{
27    Array, ArrayRef, BooleanArray, Date64Array, Decimal64Array, Decimal128Array, Decimal256Array,
28    Float32Array, Float64Array, Int8Array, Int16Array, Int32Array, Int64Array, PrimitiveArray,
29    UInt8Array, UInt16Array, builder::PrimitiveDictionaryBuilder, cast::AsArray, downcast_integer,
30    types::*,
31};
32use arrow_array::{
33    TimestampMicrosecondArray, TimestampMillisecondArray, TimestampNanosecondArray,
34    TimestampSecondArray, UInt32Array, UInt64Array,
35};
36use arrow_buffer::{BooleanBuffer, Buffer, NullBuffer, ScalarBuffer, i256};
37use arrow_schema::{DataType as ArrowType, TimeUnit};
38use std::any::Any;
39use std::sync::Arc;
40
41/// Provides conversion from `Vec<T>` to `Buffer`
42pub trait IntoBuffer {
43    fn into_buffer(self, target_type: &ArrowType) -> Buffer;
44}
45
46macro_rules! native_buffer {
47    ($($t:ty),*) => {
48        $(impl IntoBuffer for Vec<$t> {
49            fn into_buffer(self, _target_type: &ArrowType) -> Buffer {
50                Buffer::from_vec(self)
51            }
52        })*
53    };
54}
55native_buffer!(i8, i16, i32, i64, u8, u16, u32, u64, f32, f64);
56
57impl IntoBuffer for Vec<bool> {
58    fn into_buffer(self, _target_type: &ArrowType) -> Buffer {
59        BooleanBuffer::from(self.as_slice()).into_inner()
60    }
61}
62
63impl IntoBuffer for Vec<Int96> {
64    fn into_buffer(self, target_type: &ArrowType) -> Buffer {
65        let mut builder = Vec::with_capacity(self.len());
66        match target_type {
67            ArrowType::Timestamp(TimeUnit::Second, _) => {
68                builder.extend(self.iter().map(|x| x.to_seconds()));
69            }
70            ArrowType::Timestamp(TimeUnit::Millisecond, _) => {
71                builder.extend(self.iter().map(|x| x.to_millis()));
72            }
73            ArrowType::Timestamp(TimeUnit::Microsecond, _) => {
74                builder.extend(self.iter().map(|x| x.to_micros()));
75            }
76            ArrowType::Timestamp(TimeUnit::Nanosecond, _) => {
77                builder.extend(self.iter().map(|x| x.to_nanos()));
78            }
79            _ => unreachable!("Invalid target_type for Int96."),
80        }
81        Buffer::from_vec(builder)
82    }
83}
84
85/// Primitive array readers are leaves of array reader tree. They accept page iterator
86/// and read them into primitive arrays.
87pub struct PrimitiveArrayReader<T>
88where
89    T: DataType,
90    T::T: Copy + Default,
91    Vec<T::T>: IntoBuffer,
92{
93    data_type: ArrowType,
94    pages: Box<dyn PageIterator>,
95    def_levels_buffer: Option<Vec<i16>>,
96    rep_levels_buffer: Option<Vec<i16>>,
97    record_reader: RecordReader<T>,
98}
99
100impl<T> PrimitiveArrayReader<T>
101where
102    T: DataType,
103    T::T: Copy + Default,
104    Vec<T::T>: IntoBuffer,
105{
106    /// Construct primitive array reader.
107    ///
108    /// `padding_threshold` controls how null padding is applied. When
109    /// `None`, the reader pads all null positions (full padding). When
110    /// `Some(threshold)`, entries with `def < threshold` are excluded
111    /// from the value buffer (selective padding for list children).
112    pub fn new(
113        pages: Box<dyn PageIterator>,
114        column_desc: ColumnDescPtr,
115        arrow_type: Option<ArrowType>,
116        batch_size: usize,
117        padding_threshold: Option<i16>,
118    ) -> Result<Self> {
119        // Check if Arrow type is specified, else create it from Parquet type
120        let data_type = match arrow_type {
121            Some(t) => t,
122            None => parquet_to_arrow_field(column_desc.as_ref())?
123                .data_type()
124                .clone(),
125        };
126
127        let mut record_reader = RecordReader::<T>::new(column_desc, batch_size);
128        if let Some(threshold) = padding_threshold {
129            record_reader.set_padding_threshold(threshold);
130        }
131
132        Ok(Self {
133            data_type,
134            pages,
135            def_levels_buffer: None,
136            rep_levels_buffer: None,
137            record_reader,
138        })
139    }
140}
141
142/// Implementation of primitive array reader.
143impl<T> ArrayReader for PrimitiveArrayReader<T>
144where
145    T: DataType,
146    T::T: Copy + Default,
147    Vec<T::T>: IntoBuffer,
148{
149    fn as_any(&self) -> &dyn Any {
150        self
151    }
152
153    /// Returns data type of primitive array.
154    fn get_data_type(&self) -> &ArrowType {
155        &self.data_type
156    }
157
158    fn read_records(&mut self, batch_size: usize) -> Result<usize> {
159        read_records(&mut self.record_reader, self.pages.as_mut(), batch_size)
160    }
161
162    fn consume_batch(&mut self) -> Result<ArrayRef> {
163        let target_type = &self.data_type;
164
165        // Convert physical data to equivalent arrow type, and then perform
166        // coercion as needed
167        let len = self.record_reader.values_written();
168
169        let record_data = self
170            .record_reader
171            .consume_record_data()
172            .into_buffer(target_type);
173
174        let nulls = self
175            .record_reader
176            .consume_compact_bitmap()
177            .and_then(|b| NullBuffer::from_unsliced_buffer(b, len));
178
179        let array: ArrayRef = match T::get_physical_type() {
180            PhysicalType::BOOLEAN => Arc::new(BooleanArray::new(
181                BooleanBuffer::new(record_data, 0, len),
182                nulls,
183            )),
184            PhysicalType::INT32 => Arc::new(Int32Array::new(
185                ScalarBuffer::new(record_data, 0, len),
186                nulls,
187            )),
188            PhysicalType::INT64 => Arc::new(Int64Array::new(
189                ScalarBuffer::new(record_data, 0, len),
190                nulls,
191            )),
192            PhysicalType::FLOAT => Arc::new(Float32Array::new(
193                ScalarBuffer::new(record_data, 0, len),
194                nulls,
195            )),
196            PhysicalType::DOUBLE => Arc::new(Float64Array::new(
197                ScalarBuffer::new(record_data, 0, len),
198                nulls,
199            )),
200            PhysicalType::INT96 => Arc::new(Int64Array::new(
201                ScalarBuffer::new(record_data, 0, len),
202                nulls,
203            )),
204            PhysicalType::BYTE_ARRAY | PhysicalType::FIXED_LEN_BYTE_ARRAY => {
205                unreachable!("PrimitiveArrayReaders don't support complex physical types");
206            }
207        };
208
209        // Coerce the arrow type to the desired array type
210        let array = coerce_array(array, target_type)?;
211
212        // save definition and repetition buffers
213        self.def_levels_buffer = self.record_reader.consume_def_levels();
214        self.rep_levels_buffer = self.record_reader.consume_rep_levels();
215        self.record_reader.reset();
216        Ok(array)
217    }
218
219    fn skip_records(&mut self, num_records: usize) -> Result<usize> {
220        skip_records(&mut self.record_reader, self.pages.as_mut(), num_records)
221    }
222
223    fn get_def_levels(&self) -> Option<&[i16]> {
224        self.def_levels_buffer.as_deref()
225    }
226
227    fn get_rep_levels(&self) -> Option<&[i16]> {
228        self.rep_levels_buffer.as_deref()
229    }
230
231    fn max_def_level(&self) -> i16 {
232        self.record_reader.max_def_level()
233    }
234}
235
236/// Coerce the parquet physical type array to the target type
237///
238/// This should match the logic in schema::primitive::apply_hint
239fn coerce_array(array: ArrayRef, target_type: &ArrowType) -> Result<ArrayRef> {
240    if let ArrowType::Dictionary(key_type, value_type) = target_type {
241        let dictionary = pack_dictionary(key_type, array.as_ref())?;
242        let any_dictionary = dictionary.as_any_dictionary();
243
244        let coerced_values =
245            coerce_array(Arc::clone(any_dictionary.values()), value_type.as_ref())?;
246
247        return Ok(any_dictionary.with_values(coerced_values));
248    }
249
250    match array.data_type() {
251        ArrowType::Int32 => coerce_i32(array.as_primitive(), target_type),
252        ArrowType::Int64 => coerce_i64(array.as_primitive(), target_type),
253        ArrowType::Boolean | ArrowType::Float32 | ArrowType::Float64 => Ok(array),
254        _ => unreachable!("Cannot coerce array of type {}", array.data_type()),
255    }
256}
257
258fn coerce_i32(array: &Int32Array, target_type: &ArrowType) -> Result<ArrayRef> {
259    Ok(match target_type {
260        ArrowType::UInt8 => {
261            let array = array.unary(|i| i as u8) as UInt8Array;
262            Arc::new(array) as ArrayRef
263        }
264        ArrowType::Int8 => {
265            let array = array.unary(|i| i as i8) as Int8Array;
266            Arc::new(array) as ArrayRef
267        }
268        ArrowType::UInt16 => {
269            let array = array.unary(|i| i as u16) as UInt16Array;
270            Arc::new(array) as ArrayRef
271        }
272        ArrowType::Int16 => {
273            let array = array.unary(|i| i as i16) as Int16Array;
274            Arc::new(array) as ArrayRef
275        }
276        ArrowType::Int32 => Arc::new(array.clone()),
277        // follow C++ implementation and use overflow/reinterpret cast from  i32 to u32 which will map
278        // `i32::MIN..0` to `(i32::MAX as u32)..u32::MAX`
279        ArrowType::UInt32 => Arc::new(UInt32Array::new(
280            array.values().inner().clone().into(),
281            array.nulls().cloned(),
282        )) as ArrayRef,
283        ArrowType::Date32 => Arc::new(array.reinterpret_cast::<Date32Type>()) as _,
284        ArrowType::Date64 => {
285            let array: Date64Array = array.unary(|x| x as i64 * 86_400_000);
286            Arc::new(array) as ArrayRef
287        }
288        ArrowType::Time32(TimeUnit::Second) => {
289            Arc::new(array.reinterpret_cast::<Time32SecondType>()) as ArrayRef
290        }
291        ArrowType::Time32(TimeUnit::Millisecond) => {
292            Arc::new(array.reinterpret_cast::<Time32MillisecondType>()) as ArrayRef
293        }
294        ArrowType::Timestamp(time_unit, timezone) => match time_unit {
295            TimeUnit::Second => {
296                let array: TimestampSecondArray = array
297                    .unary(|x| x as i64)
298                    .with_timezone_opt(timezone.clone());
299                Arc::new(array) as _
300            }
301            TimeUnit::Millisecond => {
302                let array: TimestampMillisecondArray = array
303                    .unary(|x| x as i64)
304                    .with_timezone_opt(timezone.clone());
305                Arc::new(array) as _
306            }
307            TimeUnit::Microsecond => {
308                let array: TimestampMicrosecondArray = array
309                    .unary(|x| x as i64)
310                    .with_timezone_opt(timezone.clone());
311                Arc::new(array) as _
312            }
313            TimeUnit::Nanosecond => {
314                let array: TimestampNanosecondArray = array
315                    .unary(|x| x as i64)
316                    .with_timezone_opt(timezone.clone());
317                Arc::new(array) as _
318            }
319        },
320        ArrowType::Decimal32(p, s) => {
321            let array = array
322                .reinterpret_cast::<Decimal32Type>()
323                .with_precision_and_scale(*p, *s)?;
324            Arc::new(array) as ArrayRef
325        }
326        ArrowType::Decimal64(p, s) => {
327            let array: Decimal64Array =
328                array.unary(|i| i as i64).with_precision_and_scale(*p, *s)?;
329            Arc::new(array) as ArrayRef
330        }
331        ArrowType::Decimal128(p, s) => {
332            let array: Decimal128Array = array
333                .unary(|i| i as i128)
334                .with_precision_and_scale(*p, *s)?;
335            Arc::new(array) as ArrayRef
336        }
337        ArrowType::Decimal256(p, s) => {
338            let array: Decimal256Array = array
339                .unary(|i| i256::from_i128(i as i128))
340                .with_precision_and_scale(*p, *s)?;
341            Arc::new(array) as ArrayRef
342        }
343        _ => unreachable!("Cannot coerce i32 to {target_type}"),
344    })
345}
346
347fn coerce_i64(array: &Int64Array, target_type: &ArrowType) -> Result<ArrayRef> {
348    Ok(match target_type {
349        ArrowType::Int64 => Arc::new(array.clone()) as _,
350        // follow C++ implementation and use overflow/reinterpret cast from i64 to u64 which will map
351        // `i64::MIN..0` to `(i64::MAX as u64)..u64::MAX`
352        ArrowType::UInt64 => Arc::new(UInt64Array::new(
353            array.values().inner().clone().into(),
354            array.nulls().cloned(),
355        )) as ArrayRef,
356        ArrowType::Date64 => Arc::new(array.reinterpret_cast::<Date64Type>()) as _,
357        ArrowType::Time64(TimeUnit::Microsecond) => {
358            Arc::new(array.reinterpret_cast::<Time64MicrosecondType>()) as _
359        }
360        ArrowType::Time64(TimeUnit::Nanosecond) => {
361            Arc::new(array.reinterpret_cast::<Time64NanosecondType>()) as _
362        }
363        ArrowType::Duration(unit) => match unit {
364            TimeUnit::Second => Arc::new(array.reinterpret_cast::<DurationSecondType>()) as _,
365            TimeUnit::Millisecond => {
366                Arc::new(array.reinterpret_cast::<DurationMillisecondType>()) as _
367            }
368            TimeUnit::Microsecond => {
369                Arc::new(array.reinterpret_cast::<DurationMicrosecondType>()) as _
370            }
371            TimeUnit::Nanosecond => {
372                Arc::new(array.reinterpret_cast::<DurationNanosecondType>()) as _
373            }
374        },
375        ArrowType::Timestamp(time_unit, timezone) => match time_unit {
376            TimeUnit::Second => {
377                let array = array
378                    .reinterpret_cast::<TimestampSecondType>()
379                    .with_timezone_opt(timezone.clone());
380                Arc::new(array) as _
381            }
382            TimeUnit::Millisecond => {
383                let array = array
384                    .reinterpret_cast::<TimestampMillisecondType>()
385                    .with_timezone_opt(timezone.clone());
386                Arc::new(array) as _
387            }
388            TimeUnit::Microsecond => {
389                let array = array
390                    .reinterpret_cast::<TimestampMicrosecondType>()
391                    .with_timezone_opt(timezone.clone());
392                Arc::new(array) as _
393            }
394            TimeUnit::Nanosecond => {
395                let array = array
396                    .reinterpret_cast::<TimestampNanosecondType>()
397                    .with_timezone_opt(timezone.clone());
398                Arc::new(array) as _
399            }
400        },
401        ArrowType::Decimal64(p, s) => {
402            let array = array
403                .reinterpret_cast::<Decimal64Type>()
404                .with_precision_and_scale(*p, *s)?;
405            Arc::new(array) as _
406        }
407        ArrowType::Decimal128(p, s) => {
408            let array: Decimal128Array = array
409                .unary(|i| i as i128)
410                .with_precision_and_scale(*p, *s)?;
411            Arc::new(array) as _
412        }
413        ArrowType::Decimal256(p, s) => {
414            let array: Decimal256Array = array
415                .unary(|i| i256::from_i128(i as i128))
416                .with_precision_and_scale(*p, *s)?;
417            Arc::new(array) as _
418        }
419        _ => unreachable!("Cannot coerce i64 to {target_type}"),
420    })
421}
422
423macro_rules! pack_dictionary_helper {
424    ($t:ty, $values:ident) => {
425        match $values.data_type() {
426            ArrowType::Int32 => pack_dictionary_impl::<$t, Int32Type>($values.as_primitive()),
427            ArrowType::Int64 => pack_dictionary_impl::<$t, Int64Type>($values.as_primitive()),
428            ArrowType::Float32 => pack_dictionary_impl::<$t, Float32Type>($values.as_primitive()),
429            ArrowType::Float64 => pack_dictionary_impl::<$t, Float64Type>($values.as_primitive()),
430            _ => unreachable!("Invalid physical type"),
431        }
432    };
433}
434
435fn pack_dictionary(key: &ArrowType, values: &dyn Array) -> Result<ArrayRef> {
436    downcast_integer! {
437        key => (pack_dictionary_helper, values),
438        _ => unreachable!("Invalid key type"),
439    }
440}
441
442fn pack_dictionary_impl<K: ArrowDictionaryKeyType, V: ArrowPrimitiveType>(
443    values: &PrimitiveArray<V>,
444) -> Result<ArrayRef> {
445    let mut builder = PrimitiveDictionaryBuilder::<K, V>::with_capacity(1024, values.len());
446    builder.extend(values);
447    Ok(Arc::new(builder.finish()))
448}
449
450#[cfg(test)]
451mod tests {
452    use super::*;
453    use crate::arrow::array_reader::test_util::EmptyPageIterator;
454    use crate::arrow::arrow_reader::DEFAULT_BATCH_SIZE;
455    use crate::basic::Encoding;
456    use crate::column::page::Page;
457    use crate::data_type::{Int32Type, Int64Type};
458    use crate::schema::parser::parse_message_type;
459    use crate::schema::types::SchemaDescriptor;
460    use crate::util::InMemoryPageIterator;
461    use crate::util::test_common::rand_gen::make_pages;
462    use arrow::datatypes::ArrowPrimitiveType;
463    use arrow_array::{Array, Date32Array, PrimitiveArray};
464
465    use arrow::datatypes::DataType::{Date32, Decimal128};
466    use rand::distr::uniform::SampleUniform;
467    use std::collections::VecDeque;
468
469    #[allow(clippy::too_many_arguments)]
470    fn make_column_chunks<T: DataType>(
471        column_desc: ColumnDescPtr,
472        encoding: Encoding,
473        num_levels: usize,
474        min_value: T::T,
475        max_value: T::T,
476        def_levels: &mut Vec<i16>,
477        rep_levels: &mut Vec<i16>,
478        values: &mut Vec<T::T>,
479        page_lists: &mut Vec<Vec<Page>>,
480        use_v2: bool,
481        num_chunks: usize,
482    ) where
483        T::T: PartialOrd + SampleUniform + Copy,
484    {
485        for _i in 0..num_chunks {
486            let mut pages = VecDeque::new();
487            let mut data = Vec::new();
488            let mut page_def_levels = Vec::new();
489            let mut page_rep_levels = Vec::new();
490
491            make_pages::<T>(
492                column_desc.clone(),
493                encoding,
494                1,
495                num_levels,
496                min_value,
497                max_value,
498                &mut page_def_levels,
499                &mut page_rep_levels,
500                &mut data,
501                &mut pages,
502                use_v2,
503            );
504
505            def_levels.append(&mut page_def_levels);
506            rep_levels.append(&mut page_rep_levels);
507            values.append(&mut data);
508            page_lists.push(Vec::from(pages));
509        }
510    }
511
512    #[test]
513    fn test_primitive_array_reader_empty_pages() {
514        // Construct column schema
515        let message_type = "
516        message test_schema {
517          REQUIRED INT32 leaf;
518        }
519        ";
520
521        let schema = parse_message_type(message_type)
522            .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t))))
523            .unwrap();
524
525        let mut array_reader = PrimitiveArrayReader::<Int32Type>::new(
526            Box::<EmptyPageIterator>::default(),
527            schema.column(0),
528            None,
529            DEFAULT_BATCH_SIZE,
530            None,
531        )
532        .unwrap();
533
534        // expect no values to be read
535        let array = array_reader.next_batch(50).unwrap();
536        assert!(array.is_empty());
537    }
538
539    #[test]
540    fn test_primitive_array_reader_data() {
541        // Construct column schema
542        let message_type = "
543        message test_schema {
544          REQUIRED INT32 leaf;
545        }
546        ";
547
548        let schema = parse_message_type(message_type)
549            .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t))))
550            .unwrap();
551
552        let column_desc = schema.column(0);
553
554        // Construct page iterator
555        {
556            let mut data = Vec::new();
557            let mut page_lists = Vec::new();
558            make_column_chunks::<Int32Type>(
559                column_desc.clone(),
560                Encoding::PLAIN,
561                100,
562                1,
563                200,
564                &mut Vec::new(),
565                &mut Vec::new(),
566                &mut data,
567                &mut page_lists,
568                true,
569                2,
570            );
571            let page_iterator = InMemoryPageIterator::new(page_lists);
572
573            let mut array_reader = PrimitiveArrayReader::<Int32Type>::new(
574                Box::new(page_iterator),
575                column_desc,
576                None,
577                DEFAULT_BATCH_SIZE,
578                None,
579            )
580            .unwrap();
581
582            // Read first 50 values, which are all from the first column chunk
583            let array = array_reader.next_batch(50).unwrap();
584            let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
585
586            assert_eq!(&Int32Array::from(data[0..50].to_vec()), array);
587
588            // Read next 100 values, the first 50 ones are from the first column chunk,
589            // and the last 50 ones are from the second column chunk
590            let array = array_reader.next_batch(100).unwrap();
591            let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
592
593            assert_eq!(&Int32Array::from(data[50..150].to_vec()), array);
594
595            // Try to read 100 values, however there are only 50 values
596            let array = array_reader.next_batch(100).unwrap();
597            let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
598
599            assert_eq!(&Int32Array::from(data[150..200].to_vec()), array);
600        }
601    }
602
603    macro_rules! test_primitive_array_reader_one_type {
604        (
605            $arrow_parquet_type:ty,
606            $physical_type:expr,
607            $converted_type_str:expr,
608            $result_arrow_type:ty,
609            $result_arrow_cast_type:ty,
610            $result_primitive_type:ty
611            $(, $timezone:expr)?
612        ) => {{
613            let message_type = format!(
614                "
615            message test_schema {{
616              REQUIRED {:?} leaf ({});
617          }}
618            ",
619                $physical_type, $converted_type_str
620            );
621            let schema = parse_message_type(&message_type)
622                .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t))))
623                .unwrap();
624
625            let column_desc = schema.column(0);
626
627            // Construct page iterator
628            {
629                let mut data = Vec::new();
630                let mut page_lists = Vec::new();
631                make_column_chunks::<$arrow_parquet_type>(
632                    column_desc.clone(),
633                    Encoding::PLAIN,
634                    100,
635                    1,
636                    200,
637                    &mut Vec::new(),
638                    &mut Vec::new(),
639                    &mut data,
640                    &mut page_lists,
641                    true,
642                    2,
643                );
644                let page_iterator = InMemoryPageIterator::new(page_lists);
645                let mut array_reader = PrimitiveArrayReader::<$arrow_parquet_type>::new(
646                    Box::new(page_iterator),
647                    column_desc.clone(),
648                    None,
649                    DEFAULT_BATCH_SIZE,
650                    None,
651                )
652                .expect("Unable to get array reader");
653
654                let array = array_reader
655                    .next_batch(50)
656                    .expect("Unable to get batch from reader");
657
658                let result_data_type = <$result_arrow_type>::DATA_TYPE;
659                let array = array
660                    .as_any()
661                    .downcast_ref::<PrimitiveArray<$result_arrow_type>>()
662                    .expect(
663                        format!(
664                            "Unable to downcast {:?} to {:?}",
665                            array.data_type(),
666                            result_data_type
667                        )
668                        .as_str(),
669                    )
670                    $(.clone().with_timezone($timezone))?
671                    ;
672
673                // create expected array as primitive, and cast to result type
674                let expected = PrimitiveArray::<$result_arrow_cast_type>::from(
675                    data[0..50]
676                        .iter()
677                        .map(|x| *x as $result_primitive_type)
678                        .collect::<Vec<$result_primitive_type>>(),
679                );
680                let expected = Arc::new(expected) as ArrayRef;
681                let expected = arrow::compute::cast(&expected, &result_data_type)
682                    .expect("Unable to cast expected array");
683                assert_eq!(expected.data_type(), &result_data_type);
684                let expected = expected
685                    .as_any()
686                    .downcast_ref::<PrimitiveArray<$result_arrow_type>>()
687                    .expect(
688                        format!(
689                            "Unable to downcast expected {:?} to {:?}",
690                            expected.data_type(),
691                            result_data_type
692                        )
693                        .as_str(),
694                    )
695                    $(.clone().with_timezone($timezone))?
696                    ;
697                assert_eq!(expected, array);
698            }
699        }};
700    }
701
702    #[test]
703    fn test_primitive_array_reader_temporal_types() {
704        test_primitive_array_reader_one_type!(
705            crate::data_type::Int32Type,
706            PhysicalType::INT32,
707            "DATE",
708            arrow::datatypes::Date32Type,
709            arrow::datatypes::Int32Type,
710            i32
711        );
712        test_primitive_array_reader_one_type!(
713            crate::data_type::Int32Type,
714            PhysicalType::INT32,
715            "TIME_MILLIS",
716            arrow::datatypes::Time32MillisecondType,
717            arrow::datatypes::Int32Type,
718            i32
719        );
720        test_primitive_array_reader_one_type!(
721            crate::data_type::Int64Type,
722            PhysicalType::INT64,
723            "TIME_MICROS",
724            arrow::datatypes::Time64MicrosecondType,
725            arrow::datatypes::Int64Type,
726            i64
727        );
728        test_primitive_array_reader_one_type!(
729            crate::data_type::Int64Type,
730            PhysicalType::INT64,
731            "TIMESTAMP_MILLIS",
732            arrow::datatypes::TimestampMillisecondType,
733            arrow::datatypes::Int64Type,
734            i64,
735            "UTC"
736        );
737        test_primitive_array_reader_one_type!(
738            crate::data_type::Int64Type,
739            PhysicalType::INT64,
740            "TIMESTAMP_MICROS",
741            arrow::datatypes::TimestampMicrosecondType,
742            arrow::datatypes::Int64Type,
743            i64,
744            "UTC"
745        );
746    }
747
748    #[test]
749    fn test_primitive_array_reader_def_and_rep_levels() {
750        // Construct column schema
751        let message_type = "
752        message test_schema {
753            REPEATED Group test_mid {
754                OPTIONAL INT32 leaf;
755            }
756        }
757        ";
758
759        let schema = parse_message_type(message_type)
760            .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t))))
761            .unwrap();
762
763        let column_desc = schema.column(0);
764
765        // Construct page iterator
766        {
767            let mut def_levels = Vec::new();
768            let mut rep_levels = Vec::new();
769            let mut page_lists = Vec::new();
770            make_column_chunks::<Int32Type>(
771                column_desc.clone(),
772                Encoding::PLAIN,
773                100,
774                1,
775                200,
776                &mut def_levels,
777                &mut rep_levels,
778                &mut Vec::new(),
779                &mut page_lists,
780                true,
781                2,
782            );
783
784            let page_iterator = InMemoryPageIterator::new(page_lists);
785
786            let mut array_reader = PrimitiveArrayReader::<Int32Type>::new(
787                Box::new(page_iterator),
788                column_desc,
789                None,
790                DEFAULT_BATCH_SIZE,
791                None,
792            )
793            .unwrap();
794
795            let mut accu_len: usize = 0;
796
797            // Read first 50 values, which are all from the first column chunk
798            let array = array_reader.next_batch(50).unwrap();
799            assert_eq!(
800                Some(&def_levels[accu_len..(accu_len + array.len())]),
801                array_reader.get_def_levels()
802            );
803            assert_eq!(
804                Some(&rep_levels[accu_len..(accu_len + array.len())]),
805                array_reader.get_rep_levels()
806            );
807            accu_len += array.len();
808
809            // Read next 100 values, the first 50 ones are from the first column chunk,
810            // and the last 50 ones are from the second column chunk
811            let array = array_reader.next_batch(100).unwrap();
812            assert_eq!(
813                Some(&def_levels[accu_len..(accu_len + array.len())]),
814                array_reader.get_def_levels()
815            );
816            assert_eq!(
817                Some(&rep_levels[accu_len..(accu_len + array.len())]),
818                array_reader.get_rep_levels()
819            );
820            accu_len += array.len();
821
822            // Try to read 100 values, however there are only 50 values
823            let array = array_reader.next_batch(100).unwrap();
824            assert_eq!(
825                Some(&def_levels[accu_len..(accu_len + array.len())]),
826                array_reader.get_def_levels()
827            );
828            assert_eq!(
829                Some(&rep_levels[accu_len..(accu_len + array.len())]),
830                array_reader.get_rep_levels()
831            );
832        }
833    }
834
835    #[test]
836    fn test_primitive_array_reader_decimal_types() {
837        // parquet `INT32` to decimal
838        let message_type = "
839            message test_schema {
840                REQUIRED INT32 decimal1 (DECIMAL(8,2));
841        }
842        ";
843        let schema = parse_message_type(message_type)
844            .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t))))
845            .unwrap();
846        let column_desc = schema.column(0);
847
848        // create the array reader
849        {
850            let mut data = Vec::new();
851            let mut page_lists = Vec::new();
852            make_column_chunks::<Int32Type>(
853                column_desc.clone(),
854                Encoding::PLAIN,
855                100,
856                -99999999,
857                99999999,
858                &mut Vec::new(),
859                &mut Vec::new(),
860                &mut data,
861                &mut page_lists,
862                true,
863                2,
864            );
865            let page_iterator = InMemoryPageIterator::new(page_lists);
866
867            let mut array_reader = PrimitiveArrayReader::<Int32Type>::new(
868                Box::new(page_iterator),
869                column_desc,
870                None,
871                DEFAULT_BATCH_SIZE,
872                None,
873            )
874            .unwrap();
875
876            // read data from the reader
877            // the data type is decimal(8,2)
878            let array = array_reader.next_batch(50).unwrap();
879            assert_eq!(array.data_type(), &Decimal128(8, 2));
880            let array = array.as_any().downcast_ref::<Decimal128Array>().unwrap();
881            let data_decimal_array = data[0..50]
882                .iter()
883                .copied()
884                .map(|v| Some(v as i128))
885                .collect::<Decimal128Array>()
886                .with_precision_and_scale(8, 2)
887                .unwrap();
888            assert_eq!(array, &data_decimal_array);
889
890            // not equal with different data type(precision and scale)
891            let data_decimal_array = data[0..50]
892                .iter()
893                .copied()
894                .map(|v| Some(v as i128))
895                .collect::<Decimal128Array>()
896                .with_precision_and_scale(9, 0)
897                .unwrap();
898            assert_ne!(array, &data_decimal_array)
899        }
900
901        // parquet `INT64` to decimal
902        let message_type = "
903            message test_schema {
904                REQUIRED INT64 decimal1 (DECIMAL(18,4));
905        }
906        ";
907        let schema = parse_message_type(message_type)
908            .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t))))
909            .unwrap();
910        let column_desc = schema.column(0);
911
912        // create the array reader
913        {
914            let mut data = Vec::new();
915            let mut page_lists = Vec::new();
916            make_column_chunks::<Int64Type>(
917                column_desc.clone(),
918                Encoding::PLAIN,
919                100,
920                -999999999999999999,
921                999999999999999999,
922                &mut Vec::new(),
923                &mut Vec::new(),
924                &mut data,
925                &mut page_lists,
926                true,
927                2,
928            );
929            let page_iterator = InMemoryPageIterator::new(page_lists);
930
931            let mut array_reader = PrimitiveArrayReader::<Int64Type>::new(
932                Box::new(page_iterator),
933                column_desc,
934                None,
935                DEFAULT_BATCH_SIZE,
936                None,
937            )
938            .unwrap();
939
940            // read data from the reader
941            // the data type is decimal(18,4)
942            let array = array_reader.next_batch(50).unwrap();
943            assert_eq!(array.data_type(), &Decimal128(18, 4));
944            let array = array.as_any().downcast_ref::<Decimal128Array>().unwrap();
945            let data_decimal_array = data[0..50]
946                .iter()
947                .copied()
948                .map(|v| Some(v as i128))
949                .collect::<Decimal128Array>()
950                .with_precision_and_scale(18, 4)
951                .unwrap();
952            assert_eq!(array, &data_decimal_array);
953
954            // not equal with different data type(precision and scale)
955            let data_decimal_array = data[0..50]
956                .iter()
957                .copied()
958                .map(|v| Some(v as i128))
959                .collect::<Decimal128Array>()
960                .with_precision_and_scale(34, 0)
961                .unwrap();
962            assert_ne!(array, &data_decimal_array)
963        }
964    }
965
966    #[test]
967    fn test_primitive_array_reader_date32_type() {
968        // parquet `INT32` to date
969        let message_type = "
970            message test_schema {
971                REQUIRED INT32 date1 (DATE);
972        }
973        ";
974        let schema = parse_message_type(message_type)
975            .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t))))
976            .unwrap();
977        let column_desc = schema.column(0);
978
979        // create the array reader
980        {
981            let mut data = Vec::new();
982            let mut page_lists = Vec::new();
983            make_column_chunks::<Int32Type>(
984                column_desc.clone(),
985                Encoding::PLAIN,
986                100,
987                -99999999,
988                99999999,
989                &mut Vec::new(),
990                &mut Vec::new(),
991                &mut data,
992                &mut page_lists,
993                true,
994                2,
995            );
996            let page_iterator = InMemoryPageIterator::new(page_lists);
997
998            let mut array_reader = PrimitiveArrayReader::<Int32Type>::new(
999                Box::new(page_iterator),
1000                column_desc,
1001                None,
1002                DEFAULT_BATCH_SIZE,
1003                None,
1004            )
1005            .unwrap();
1006
1007            // read data from the reader
1008            // the data type is date
1009            let array = array_reader.next_batch(50).unwrap();
1010            assert_eq!(array.data_type(), &Date32);
1011            let array = array.as_any().downcast_ref::<Date32Array>().unwrap();
1012            let data_date_array = data[0..50]
1013                .iter()
1014                .copied()
1015                .map(Some)
1016                .collect::<Date32Array>();
1017            assert_eq!(array, &data_date_array);
1018        }
1019    }
1020}