Skip to main content

parquet_variant_compute/
arrow_to_variant.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: See the NOTICE file distributed with this work for additional information regarding copyright ownership
3// SPDX-FileContributor: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements
4
5use arrow::array::{
6    Array, AsArray, FixedSizeListArray, GenericBinaryArray, GenericListArray, GenericListViewArray,
7    GenericStringArray, ListLikeArray, OffsetSizeTrait, PrimitiveArray,
8};
9use arrow::compute::{CastOptions, kernels::cast};
10use arrow::datatypes::{
11    self as datatypes, ArrowNativeType, ArrowPrimitiveType, ArrowTemporalType, ArrowTimestampType,
12    DecimalType, RunEndIndexType,
13};
14use arrow::temporal_conversions::{as_date, as_datetime, as_time};
15use arrow_schema::{ArrowError, DataType, TimeUnit};
16use chrono::{DateTime, TimeZone, Utc};
17use parquet_variant::{
18    ObjectFieldBuilder, Variant, VariantBuilderExt, VariantDecimal4, VariantDecimal8,
19    VariantDecimal16, VariantDecimalType,
20};
21use std::collections::HashMap;
22
23// ============================================================================
24// Row-oriented builders for efficient Arrow-to-Variant conversion
25// ============================================================================
26
27/// Row builder for converting Arrow arrays to VariantArray row by row
28pub(crate) enum ArrowToVariantRowBuilder<'a> {
29    Null(NullArrowToVariantBuilder),
30    Boolean(BooleanArrowToVariantBuilder<'a>),
31    PrimitiveInt8(PrimitiveArrowToVariantBuilder<'a, datatypes::Int8Type>),
32    PrimitiveInt16(PrimitiveArrowToVariantBuilder<'a, datatypes::Int16Type>),
33    PrimitiveInt32(PrimitiveArrowToVariantBuilder<'a, datatypes::Int32Type>),
34    PrimitiveInt64(PrimitiveArrowToVariantBuilder<'a, datatypes::Int64Type>),
35    PrimitiveUInt8(PrimitiveArrowToVariantBuilder<'a, datatypes::UInt8Type>),
36    PrimitiveUInt16(PrimitiveArrowToVariantBuilder<'a, datatypes::UInt16Type>),
37    PrimitiveUInt32(PrimitiveArrowToVariantBuilder<'a, datatypes::UInt32Type>),
38    PrimitiveUInt64(PrimitiveArrowToVariantBuilder<'a, datatypes::UInt64Type>),
39    PrimitiveFloat16(PrimitiveArrowToVariantBuilder<'a, datatypes::Float16Type>),
40    PrimitiveFloat32(PrimitiveArrowToVariantBuilder<'a, datatypes::Float32Type>),
41    PrimitiveFloat64(PrimitiveArrowToVariantBuilder<'a, datatypes::Float64Type>),
42    Decimal32(DecimalArrowToVariantBuilder<'a, datatypes::Decimal32Type, VariantDecimal4>),
43    Decimal64(DecimalArrowToVariantBuilder<'a, datatypes::Decimal64Type, VariantDecimal8>),
44    Decimal128(DecimalArrowToVariantBuilder<'a, datatypes::Decimal128Type, VariantDecimal16>),
45    Decimal256(Decimal256ArrowToVariantBuilder<'a>),
46    TimestampSecond(TimestampArrowToVariantBuilder<'a, datatypes::TimestampSecondType>),
47    TimestampMillisecond(TimestampArrowToVariantBuilder<'a, datatypes::TimestampMillisecondType>),
48    TimestampMicrosecond(TimestampArrowToVariantBuilder<'a, datatypes::TimestampMicrosecondType>),
49    TimestampNanosecond(TimestampArrowToVariantBuilder<'a, datatypes::TimestampNanosecondType>),
50    Date32(DateArrowToVariantBuilder<'a, datatypes::Date32Type>),
51    Date64(DateArrowToVariantBuilder<'a, datatypes::Date64Type>),
52    Time32Second(TimeArrowToVariantBuilder<'a, datatypes::Time32SecondType>),
53    Time32Millisecond(TimeArrowToVariantBuilder<'a, datatypes::Time32MillisecondType>),
54    Time64Microsecond(TimeArrowToVariantBuilder<'a, datatypes::Time64MicrosecondType>),
55    Time64Nanosecond(TimeArrowToVariantBuilder<'a, datatypes::Time64NanosecondType>),
56    Binary(BinaryArrowToVariantBuilder<'a, i32>),
57    LargeBinary(BinaryArrowToVariantBuilder<'a, i64>),
58    BinaryView(BinaryViewArrowToVariantBuilder<'a>),
59    FixedSizeBinary(FixedSizeBinaryArrowToVariantBuilder<'a>),
60    Utf8(StringArrowToVariantBuilder<'a, i32>),
61    LargeUtf8(StringArrowToVariantBuilder<'a, i64>),
62    Utf8View(StringViewArrowToVariantBuilder<'a>),
63    List(ListArrowToVariantBuilder<'a, GenericListArray<i32>>),
64    LargeList(ListArrowToVariantBuilder<'a, GenericListArray<i64>>),
65    ListView(ListArrowToVariantBuilder<'a, GenericListViewArray<i32>>),
66    LargeListView(ListArrowToVariantBuilder<'a, GenericListViewArray<i64>>),
67    FixedSizeList(ListArrowToVariantBuilder<'a, FixedSizeListArray>),
68    Struct(StructArrowToVariantBuilder<'a>),
69    Map(MapArrowToVariantBuilder<'a>),
70    Union(UnionArrowToVariantBuilder<'a>),
71    Dictionary(DictionaryArrowToVariantBuilder<'a>),
72    RunEndEncodedInt16(RunEndEncodedArrowToVariantBuilder<'a, datatypes::Int16Type>),
73    RunEndEncodedInt32(RunEndEncodedArrowToVariantBuilder<'a, datatypes::Int32Type>),
74    RunEndEncodedInt64(RunEndEncodedArrowToVariantBuilder<'a, datatypes::Int64Type>),
75}
76
77impl ArrowToVariantRowBuilder<'_> {
78    /// Appends a single row at the given index to the supplied builder.
79    pub fn append_row(
80        &mut self,
81        builder: &mut impl VariantBuilderExt,
82        index: usize,
83    ) -> Result<(), ArrowError> {
84        use ArrowToVariantRowBuilder::*;
85        match self {
86            Null(b) => b.append_row(builder, index),
87            Boolean(b) => b.append_row(builder, index),
88            PrimitiveInt8(b) => b.append_row(builder, index),
89            PrimitiveInt16(b) => b.append_row(builder, index),
90            PrimitiveInt32(b) => b.append_row(builder, index),
91            PrimitiveInt64(b) => b.append_row(builder, index),
92            PrimitiveUInt8(b) => b.append_row(builder, index),
93            PrimitiveUInt16(b) => b.append_row(builder, index),
94            PrimitiveUInt32(b) => b.append_row(builder, index),
95            PrimitiveUInt64(b) => b.append_row(builder, index),
96            PrimitiveFloat16(b) => b.append_row(builder, index),
97            PrimitiveFloat32(b) => b.append_row(builder, index),
98            PrimitiveFloat64(b) => b.append_row(builder, index),
99            Decimal32(b) => b.append_row(builder, index),
100            Decimal64(b) => b.append_row(builder, index),
101            Decimal128(b) => b.append_row(builder, index),
102            Decimal256(b) => b.append_row(builder, index),
103            TimestampSecond(b) => b.append_row(builder, index),
104            TimestampMillisecond(b) => b.append_row(builder, index),
105            TimestampMicrosecond(b) => b.append_row(builder, index),
106            TimestampNanosecond(b) => b.append_row(builder, index),
107            Date32(b) => b.append_row(builder, index),
108            Date64(b) => b.append_row(builder, index),
109            Time32Second(b) => b.append_row(builder, index),
110            Time32Millisecond(b) => b.append_row(builder, index),
111            Time64Microsecond(b) => b.append_row(builder, index),
112            Time64Nanosecond(b) => b.append_row(builder, index),
113            Binary(b) => b.append_row(builder, index),
114            LargeBinary(b) => b.append_row(builder, index),
115            BinaryView(b) => b.append_row(builder, index),
116            FixedSizeBinary(b) => b.append_row(builder, index),
117            Utf8(b) => b.append_row(builder, index),
118            LargeUtf8(b) => b.append_row(builder, index),
119            Utf8View(b) => b.append_row(builder, index),
120            List(b) => b.append_row(builder, index),
121            LargeList(b) => b.append_row(builder, index),
122            ListView(b) => b.append_row(builder, index),
123            LargeListView(b) => b.append_row(builder, index),
124            FixedSizeList(b) => b.append_row(builder, index),
125            Struct(b) => b.append_row(builder, index),
126            Map(b) => b.append_row(builder, index),
127            Union(b) => b.append_row(builder, index),
128            Dictionary(b) => b.append_row(builder, index),
129            RunEndEncodedInt16(b) => b.append_row(builder, index),
130            RunEndEncodedInt32(b) => b.append_row(builder, index),
131            RunEndEncodedInt64(b) => b.append_row(builder, index),
132        }
133    }
134}
135
136/// Factory function to create the appropriate row builder for a given DataType
137pub(crate) fn make_arrow_to_variant_row_builder<'a>(
138    data_type: &'a DataType,
139    array: &'a dyn Array,
140    options: &'a CastOptions,
141) -> Result<ArrowToVariantRowBuilder<'a>, ArrowError> {
142    use ArrowToVariantRowBuilder::*;
143    let builder =
144        match data_type {
145            DataType::Null => Null(NullArrowToVariantBuilder),
146            DataType::Boolean => Boolean(BooleanArrowToVariantBuilder::new(array)),
147            DataType::Int8 => PrimitiveInt8(PrimitiveArrowToVariantBuilder::new(array)),
148            DataType::Int16 => PrimitiveInt16(PrimitiveArrowToVariantBuilder::new(array)),
149            DataType::Int32 => PrimitiveInt32(PrimitiveArrowToVariantBuilder::new(array)),
150            DataType::Int64 => PrimitiveInt64(PrimitiveArrowToVariantBuilder::new(array)),
151            DataType::UInt8 => PrimitiveUInt8(PrimitiveArrowToVariantBuilder::new(array)),
152            DataType::UInt16 => PrimitiveUInt16(PrimitiveArrowToVariantBuilder::new(array)),
153            DataType::UInt32 => PrimitiveUInt32(PrimitiveArrowToVariantBuilder::new(array)),
154            DataType::UInt64 => PrimitiveUInt64(PrimitiveArrowToVariantBuilder::new(array)),
155            DataType::Float16 => PrimitiveFloat16(PrimitiveArrowToVariantBuilder::new(array)),
156            DataType::Float32 => PrimitiveFloat32(PrimitiveArrowToVariantBuilder::new(array)),
157            DataType::Float64 => PrimitiveFloat64(PrimitiveArrowToVariantBuilder::new(array)),
158            DataType::Decimal32(_, scale) => {
159                Decimal32(DecimalArrowToVariantBuilder::new(array, options, *scale))
160            }
161            DataType::Decimal64(_, scale) => {
162                Decimal64(DecimalArrowToVariantBuilder::new(array, options, *scale))
163            }
164            DataType::Decimal128(_, scale) => {
165                Decimal128(DecimalArrowToVariantBuilder::new(array, options, *scale))
166            }
167            DataType::Decimal256(_, scale) => {
168                Decimal256(Decimal256ArrowToVariantBuilder::new(array, options, *scale))
169            }
170            DataType::Timestamp(time_unit, time_zone) => {
171                match time_unit {
172                    TimeUnit::Second => TimestampSecond(TimestampArrowToVariantBuilder::new(
173                        array,
174                        options,
175                        time_zone.is_some(),
176                    )),
177                    TimeUnit::Millisecond => TimestampMillisecond(
178                        TimestampArrowToVariantBuilder::new(array, options, time_zone.is_some()),
179                    ),
180                    TimeUnit::Microsecond => TimestampMicrosecond(
181                        TimestampArrowToVariantBuilder::new(array, options, time_zone.is_some()),
182                    ),
183                    TimeUnit::Nanosecond => TimestampNanosecond(
184                        TimestampArrowToVariantBuilder::new(array, options, time_zone.is_some()),
185                    ),
186                }
187            }
188            DataType::Date32 => Date32(DateArrowToVariantBuilder::new(array, options)),
189            DataType::Date64 => Date64(DateArrowToVariantBuilder::new(array, options)),
190            DataType::Time32(time_unit) => match time_unit {
191                TimeUnit::Second => Time32Second(TimeArrowToVariantBuilder::new(array, options)),
192                TimeUnit::Millisecond => {
193                    Time32Millisecond(TimeArrowToVariantBuilder::new(array, options))
194                }
195                _ => {
196                    return Err(ArrowError::CastError(format!(
197                        "Unsupported Time32 unit: {time_unit:?}"
198                    )));
199                }
200            },
201            DataType::Time64(time_unit) => match time_unit {
202                TimeUnit::Microsecond => {
203                    Time64Microsecond(TimeArrowToVariantBuilder::new(array, options))
204                }
205                TimeUnit::Nanosecond => {
206                    Time64Nanosecond(TimeArrowToVariantBuilder::new(array, options))
207                }
208                _ => {
209                    return Err(ArrowError::CastError(format!(
210                        "Unsupported Time64 unit: {time_unit:?}"
211                    )));
212                }
213            },
214            DataType::Duration(_) | DataType::Interval(_) => {
215                return Err(ArrowError::InvalidArgumentError(
216                    "Casting duration/interval types to Variant is not supported. \
217                    The Variant format does not define duration/interval types."
218                        .to_string(),
219                ));
220            }
221            DataType::Binary => Binary(BinaryArrowToVariantBuilder::new(array)),
222            DataType::LargeBinary => LargeBinary(BinaryArrowToVariantBuilder::new(array)),
223            DataType::BinaryView => BinaryView(BinaryViewArrowToVariantBuilder::new(array)),
224            DataType::FixedSizeBinary(_) => {
225                FixedSizeBinary(FixedSizeBinaryArrowToVariantBuilder::new(array))
226            }
227            DataType::Utf8 => Utf8(StringArrowToVariantBuilder::new(array)),
228            DataType::LargeUtf8 => LargeUtf8(StringArrowToVariantBuilder::new(array)),
229            DataType::Utf8View => Utf8View(StringViewArrowToVariantBuilder::new(array)),
230            DataType::List(_) => List(ListArrowToVariantBuilder::new(array.as_list(), options)?),
231            DataType::LargeList(_) => {
232                LargeList(ListArrowToVariantBuilder::new(array.as_list(), options)?)
233            }
234            DataType::ListView(_) => ListView(ListArrowToVariantBuilder::new(
235                array.as_list_view(),
236                options,
237            )?),
238            DataType::LargeListView(_) => LargeListView(ListArrowToVariantBuilder::new(
239                array.as_list_view(),
240                options,
241            )?),
242            DataType::FixedSizeList(_, _) => FixedSizeList(ListArrowToVariantBuilder::new(
243                array.as_fixed_size_list(),
244                options,
245            )?),
246            DataType::Struct(_) => Struct(StructArrowToVariantBuilder::new(
247                array.as_struct(),
248                options,
249            )?),
250            DataType::Map(_, _) => Map(MapArrowToVariantBuilder::new(array, options)?),
251            DataType::Union(_, _) => Union(UnionArrowToVariantBuilder::new(array, options)?),
252            DataType::Dictionary(_, _) => {
253                Dictionary(DictionaryArrowToVariantBuilder::new(array, options)?)
254            }
255            DataType::RunEndEncoded(run_ends, _) => match run_ends.data_type() {
256                DataType::Int16 => {
257                    RunEndEncodedInt16(RunEndEncodedArrowToVariantBuilder::new(array, options)?)
258                }
259                DataType::Int32 => {
260                    RunEndEncodedInt32(RunEndEncodedArrowToVariantBuilder::new(array, options)?)
261                }
262                DataType::Int64 => {
263                    RunEndEncodedInt64(RunEndEncodedArrowToVariantBuilder::new(array, options)?)
264                }
265                _ => {
266                    return Err(ArrowError::CastError(format!(
267                        "Unsupported run ends type: {}",
268                        run_ends.data_type()
269                    )));
270                }
271            },
272        };
273    Ok(builder)
274}
275
276/// Macro to define (possibly generic) row builders with consistent structure and behavior.
277///
278/// The macro optionally allows to define a transform for values read from the underlying
279/// array. Transforms of the form `|value| { ... }` are infallible (and should produce something
280/// that implements `Into<Variant>`), while transforms of the form `|value| -> Option<_> { ... }`
281/// are fallible (and should produce `Option<impl Into<Variant>>`); a failed tarnsform will either
282/// append null to the builder or return an error, depending on cast options.
283///
284/// Also supports optional extra fields that are passed to the constructor and which are available
285/// by reference in the value transform. Providing a fallible value transform requires also
286/// providing the extra field `options: &'a CastOptions`.
287// TODO: If/when the macro_metavar_expr feature stabilizes, the `ignore` meta-function would allow
288// us to "use" captured tokens without emitting them:
289//
290// ```
291// $(
292//     ${ignore($value)}
293//     $(
294//         ${ignore($option_ty)}
295//         options: &$lifetime CastOptions,
296//     )?
297// )?
298// ```
299//
300// That, in turn, would allow us to inject the `options` field whenever the user specifies a
301// fallible value transform, instead of requiring them to manually define it. This might not be
302// worth the trouble, tho, because it makes for some pretty bulky and unwieldy macro expansions.
303macro_rules! define_row_builder {
304    (
305        struct $name:ident<$lifetime:lifetime $(, $generic:ident $( : $bound:path )? )*>
306        $( where $where_path:path: $where_bound:path $(,)? )?
307        $({ $( $field:ident: $field_type:ty ),+ $(,)? })?,
308        |$array_param:ident| -> $array_type:ty { $init_expr:expr }
309        $(, |$value:ident| $(-> Option<$option_ty:ty>)? $value_transform:expr )?
310    ) => {
311        pub(crate) struct $name<$lifetime $(, $generic: $( $bound )? )*>
312        $( where $where_path: $where_bound )?
313        {
314            array: &$lifetime $array_type,
315            $( $( $field: $field_type, )+ )?
316            _phantom: std::marker::PhantomData<($( $generic, )*)>, // capture all type params
317        }
318
319        impl<$lifetime $(, $generic: $( $bound )? )*> $name<$lifetime $(, $generic)*>
320        $( where $where_path: $where_bound )?
321        {
322            pub(crate) fn new($array_param: &$lifetime dyn Array $( $(, $field: $field_type )+ )?) -> Self {
323                Self {
324                    array: $init_expr,
325                    $( $( $field, )+ )?
326                    _phantom: std::marker::PhantomData,
327                }
328            }
329
330            fn append_row(&self, builder: &mut impl VariantBuilderExt, index: usize) -> Result<(), ArrowError> {
331                if self.array.is_null(index) {
332                    builder.append_null();
333                } else {
334                    // Macro hygiene: Give any extra fields names the value transform can access.
335                    //
336                    // The value transform doesn't normally reference cast options, but the macro's
337                    // caller still has to declare the field because stable rust has no way to "use"
338                    // a captured token without emitting it. So, silence unused variable warnings,
339                    // assuming that's the `options` field. Unfortunately, that also silences
340                    // legitimate compiler warnings if an infallible value transform fails to use
341                    // its first extra field.
342                    $(
343                        #[expect(unused)]
344                        $( let $field = &self.$field; )+
345                    )?
346
347                    // Apply the value transform, if any (with name swapping for hygiene)
348                    let value = self.array.value(index);
349                    $(
350                        let $value = value;
351                        let value = $value_transform;
352                        $(
353                            // NOTE: The `?` macro expansion fails without the type annotation.
354                            let Some(value): Option<$option_ty> = value else {
355                                return if self.options.safe {
356                                    // Overflow is encoded as Variant::Null,
357                                    // distinct from None indicating a missing value
358                                    builder.append_value(Variant::Null);
359                                    Ok(())
360                                } else {
361                                    Err(ArrowError::ComputeError(format!(
362                                        "Failed to convert value at index {index}: conversion failed",
363                                    )))
364                                };
365                            };
366                        )?
367                    )?
368                    builder.append_value(value);
369                }
370                Ok(())
371            }
372        }
373    };
374}
375
376define_row_builder!(
377    struct BooleanArrowToVariantBuilder<'a>,
378    |array| -> arrow::array::BooleanArray { array.as_boolean() }
379);
380
381define_row_builder!(
382    struct PrimitiveArrowToVariantBuilder<'a, T: ArrowPrimitiveType>
383    where T::Native: Into<Variant<'a, 'a>>,
384    |array| -> PrimitiveArray<T> { array.as_primitive() }
385);
386
387define_row_builder!(
388    struct DecimalArrowToVariantBuilder<'a, A: DecimalType, V>
389    where
390        V: VariantDecimalType<Native = A::Native>,
391    {
392        options: &'a CastOptions<'a>,
393        scale: i8,
394    },
395    |array| -> PrimitiveArray<A> { array.as_primitive() },
396    |value| -> Option<_> { V::try_new_with_signed_scale(value, *scale).ok() }
397);
398
399// Decimal256 needs a two-stage conversion via i128
400define_row_builder!(
401    struct Decimal256ArrowToVariantBuilder<'a> {
402        options: &'a CastOptions<'a>,
403        scale: i8,
404    },
405    |array| -> arrow::array::Decimal256Array { array.as_primitive() },
406    |value| -> Option<_> {
407        let value = value.to_i128();
408        value.and_then(|v| VariantDecimal16::try_new_with_signed_scale(v, *scale).ok())
409    }
410);
411
412define_row_builder!(
413    struct TimestampArrowToVariantBuilder<'a, T: ArrowTimestampType> {
414        options: &'a CastOptions<'a>,
415        has_time_zone: bool,
416    },
417    |array| -> PrimitiveArray<T> { array.as_primitive() },
418    |value| -> Option<_> {
419        // Convert using Arrow's temporal conversion functions
420        as_datetime::<T>(value).map(|naive_datetime| {
421            if *has_time_zone {
422                // Has timezone -> DateTime<Utc> -> TimestampMicros/TimestampNanos
423                let utc_dt: DateTime<Utc> = Utc.from_utc_datetime(&naive_datetime);
424                Variant::from(utc_dt) // Uses From<DateTime<Utc>> for Variant
425            } else {
426                // No timezone -> NaiveDateTime -> TimestampNtzMicros/TimestampNtzNanos
427                Variant::from(naive_datetime) // Uses From<NaiveDateTime> for Variant
428            }
429        })
430    }
431);
432
433define_row_builder!(
434    struct DateArrowToVariantBuilder<'a, T: ArrowTemporalType>
435    where
436        i64: From<T::Native>,
437    {
438        options: &'a CastOptions<'a>,
439    },
440    |array| -> PrimitiveArray<T> { array.as_primitive() },
441    |value| -> Option<_> {
442        let date_value = i64::from(value);
443        as_date::<T>(date_value)
444    }
445);
446
447define_row_builder!(
448    struct TimeArrowToVariantBuilder<'a, T: ArrowTemporalType>
449    where
450        i64: From<T::Native>,
451    {
452        options: &'a CastOptions<'a>,
453    },
454    |array| -> PrimitiveArray<T> { array.as_primitive() },
455    |value| -> Option<_> {
456        let time_value = i64::from(value);
457        as_time::<T>(time_value)
458    }
459);
460
461define_row_builder!(
462    struct BinaryArrowToVariantBuilder<'a, O: OffsetSizeTrait>,
463    |array| -> GenericBinaryArray<O> { array.as_binary() }
464);
465
466define_row_builder!(
467    struct BinaryViewArrowToVariantBuilder<'a>,
468    |array| -> arrow::array::BinaryViewArray { array.as_byte_view() }
469);
470
471define_row_builder!(
472    struct FixedSizeBinaryArrowToVariantBuilder<'a>,
473    |array| -> arrow::array::FixedSizeBinaryArray { array.as_fixed_size_binary() }
474);
475
476define_row_builder!(
477    struct StringArrowToVariantBuilder<'a, O: OffsetSizeTrait>,
478    |array| -> GenericStringArray<O> { array.as_string() }
479);
480
481define_row_builder!(
482    struct StringViewArrowToVariantBuilder<'a>,
483    |array| -> arrow::array::StringViewArray { array.as_string_view() }
484);
485
486/// Null builder that always appends null
487pub(crate) struct NullArrowToVariantBuilder;
488
489impl NullArrowToVariantBuilder {
490    fn append_row(
491        &self,
492        builder: &mut impl VariantBuilderExt,
493        _index: usize,
494    ) -> Result<(), ArrowError> {
495        builder.append_null();
496        Ok(())
497    }
498}
499
500/// Generic list builder for ListLikeArray types including List, LargeList, ListView, LargeListView,
501/// and FixedSizeList
502pub(crate) struct ListArrowToVariantBuilder<'a, L: ListLikeArray> {
503    list_array: &'a L,
504    values_builder: Box<ArrowToVariantRowBuilder<'a>>,
505}
506
507impl<'a, L: ListLikeArray> ListArrowToVariantBuilder<'a, L> {
508    pub(crate) fn new(array: &'a L, options: &'a CastOptions) -> Result<Self, ArrowError> {
509        let values = array.values();
510        let values_builder =
511            make_arrow_to_variant_row_builder(values.data_type(), values, options)?;
512
513        Ok(Self {
514            list_array: array,
515            values_builder: Box::new(values_builder),
516        })
517    }
518
519    fn append_row(
520        &mut self,
521        builder: &mut impl VariantBuilderExt,
522        index: usize,
523    ) -> Result<(), ArrowError> {
524        if self.list_array.is_null(index) {
525            builder.append_null();
526            return Ok(());
527        }
528
529        let range = self.list_array.element_range(index);
530
531        let mut list_builder = builder.try_new_list()?;
532        for value_index in range {
533            self.values_builder
534                .append_row(&mut list_builder, value_index)?;
535        }
536        list_builder.finish();
537        Ok(())
538    }
539}
540
541/// Struct builder for StructArray
542pub(crate) struct StructArrowToVariantBuilder<'a> {
543    struct_array: &'a arrow::array::StructArray,
544    field_builders: Vec<(&'a str, ArrowToVariantRowBuilder<'a>)>,
545}
546
547impl<'a> StructArrowToVariantBuilder<'a> {
548    pub(crate) fn new(
549        struct_array: &'a arrow::array::StructArray,
550        options: &'a CastOptions,
551    ) -> Result<Self, ArrowError> {
552        let mut field_builders = Vec::new();
553
554        // Create a row builder for each field
555        for (field_name, field_array) in struct_array
556            .column_names()
557            .iter()
558            .zip(struct_array.columns().iter())
559        {
560            let field_builder = make_arrow_to_variant_row_builder(
561                field_array.data_type(),
562                field_array.as_ref(),
563                options,
564            )?;
565            field_builders.push((*field_name, field_builder));
566        }
567
568        Ok(Self {
569            struct_array,
570            field_builders,
571        })
572    }
573
574    fn append_row(
575        &mut self,
576        builder: &mut impl VariantBuilderExt,
577        index: usize,
578    ) -> Result<(), ArrowError> {
579        if self.struct_array.is_null(index) {
580            builder.append_null();
581        } else {
582            // Create object builder for this struct row
583            let mut obj_builder = builder.try_new_object()?;
584
585            // Process each field
586            for (field_name, row_builder) in &mut self.field_builders {
587                let mut field_builder = ObjectFieldBuilder::new(field_name, &mut obj_builder);
588                row_builder.append_row(&mut field_builder, index)?;
589            }
590
591            obj_builder.finish();
592        }
593        Ok(())
594    }
595}
596
597/// Map builder for MapArray types
598pub(crate) struct MapArrowToVariantBuilder<'a> {
599    map_array: &'a arrow::array::MapArray,
600    key_strings: arrow::array::StringArray,
601    values_builder: Box<ArrowToVariantRowBuilder<'a>>,
602}
603
604impl<'a> MapArrowToVariantBuilder<'a> {
605    pub(crate) fn new(array: &'a dyn Array, options: &'a CastOptions) -> Result<Self, ArrowError> {
606        let map_array = array.as_map();
607
608        // Pre-cast keys to strings once
609        let keys = cast(map_array.keys(), &DataType::Utf8)?;
610        let key_strings = keys.as_string::<i32>().clone();
611
612        // Create recursive builder for values
613        let values = map_array.values();
614        let values_builder =
615            make_arrow_to_variant_row_builder(values.data_type(), values.as_ref(), options)?;
616
617        Ok(Self {
618            map_array,
619            key_strings,
620            values_builder: Box::new(values_builder),
621        })
622    }
623
624    fn append_row(
625        &mut self,
626        builder: &mut impl VariantBuilderExt,
627        index: usize,
628    ) -> Result<(), ArrowError> {
629        // Check for NULL map first (via null bitmap)
630        if self.map_array.is_null(index) {
631            builder.append_null();
632            return Ok(());
633        }
634
635        let offsets = self.map_array.offsets();
636        let start = offsets[index].as_usize();
637        let end = offsets[index + 1].as_usize();
638
639        // Create object builder for this map
640        let mut object_builder = builder.try_new_object()?;
641
642        // Add each key-value pair (loop does nothing for empty maps - correct!)
643        for kv_index in start..end {
644            let key = self.key_strings.value(kv_index);
645            let mut field_builder = ObjectFieldBuilder::new(key, &mut object_builder);
646            self.values_builder
647                .append_row(&mut field_builder, kv_index)?;
648        }
649
650        object_builder.finish();
651        Ok(())
652    }
653}
654
655/// Union builder for both sparse and dense union arrays
656///
657/// NOTE: Union type ids are _not_ required to be dense, hence the hash map for child builders.
658pub(crate) struct UnionArrowToVariantBuilder<'a> {
659    union_array: &'a arrow::array::UnionArray,
660    child_builders: HashMap<i8, Box<ArrowToVariantRowBuilder<'a>>>,
661}
662
663impl<'a> UnionArrowToVariantBuilder<'a> {
664    pub(crate) fn new(array: &'a dyn Array, options: &'a CastOptions) -> Result<Self, ArrowError> {
665        let union_array = array.as_union();
666        let type_ids = union_array.type_ids();
667
668        // Create child builders for each union field
669        let mut child_builders = HashMap::new();
670        for &type_id in type_ids {
671            let child_array = union_array.child(type_id);
672            let child_builder = make_arrow_to_variant_row_builder(
673                child_array.data_type(),
674                child_array.as_ref(),
675                options,
676            )?;
677            child_builders.insert(type_id, Box::new(child_builder));
678        }
679
680        Ok(Self {
681            union_array,
682            child_builders,
683        })
684    }
685
686    fn append_row(
687        &mut self,
688        builder: &mut impl VariantBuilderExt,
689        index: usize,
690    ) -> Result<(), ArrowError> {
691        let type_id = self.union_array.type_id(index);
692        let value_offset = self.union_array.value_offset(index);
693
694        // Delegate to the appropriate child builder, or append null to handle an invalid type_id
695        match self.child_builders.get_mut(&type_id) {
696            Some(child_builder) => child_builder.append_row(builder, value_offset)?,
697            None => builder.append_null(),
698        }
699
700        Ok(())
701    }
702}
703
704/// Dictionary array builder with simple O(1) indexing
705pub(crate) struct DictionaryArrowToVariantBuilder<'a> {
706    keys: &'a dyn Array, // only needed for null checks
707    normalized_keys: Vec<usize>,
708    values_builder: Box<ArrowToVariantRowBuilder<'a>>,
709}
710
711impl<'a> DictionaryArrowToVariantBuilder<'a> {
712    pub(crate) fn new(array: &'a dyn Array, options: &'a CastOptions) -> Result<Self, ArrowError> {
713        let dict_array = array.as_any_dictionary();
714        let values = dict_array.values();
715        let values_builder =
716            make_arrow_to_variant_row_builder(values.data_type(), values.as_ref(), options)?;
717
718        // WARNING: normalized_keys panics if values is empty
719        let normalized_keys = match values.len() {
720            0 => Vec::new(),
721            _ => dict_array.normalized_keys(),
722        };
723
724        Ok(Self {
725            keys: dict_array.keys(),
726            normalized_keys,
727            values_builder: Box::new(values_builder),
728        })
729    }
730
731    fn append_row(
732        &mut self,
733        builder: &mut impl VariantBuilderExt,
734        index: usize,
735    ) -> Result<(), ArrowError> {
736        if self.keys.is_null(index) {
737            builder.append_null();
738        } else {
739            let normalized_key = self.normalized_keys[index];
740            self.values_builder.append_row(builder, normalized_key)?;
741        }
742        Ok(())
743    }
744}
745
746/// Run-end encoded array builder with efficient sequential access
747pub(crate) struct RunEndEncodedArrowToVariantBuilder<'a, R: RunEndIndexType> {
748    run_array: &'a arrow::array::RunArray<R>,
749    values_builder: Box<ArrowToVariantRowBuilder<'a>>,
750
751    run_ends: &'a [R::Native],
752    run_number: usize, // Physical index into run_ends and values
753    run_start: usize,  // Logical start index of current run
754}
755
756impl<'a, R: RunEndIndexType> RunEndEncodedArrowToVariantBuilder<'a, R> {
757    pub(crate) fn new(array: &'a dyn Array, options: &'a CastOptions) -> Result<Self, ArrowError> {
758        let Some(run_array) = array.as_run_opt() else {
759            return Err(ArrowError::CastError("Expected RunArray".to_string()));
760        };
761
762        let values = run_array.values();
763        let values_builder =
764            make_arrow_to_variant_row_builder(values.data_type(), values.as_ref(), options)?;
765
766        Ok(Self {
767            run_array,
768            values_builder: Box::new(values_builder),
769            run_ends: run_array.run_ends().values(),
770            run_number: 0,
771            run_start: 0,
772        })
773    }
774
775    fn set_run_for_index(&mut self, index: usize) -> Result<(), ArrowError> {
776        if index >= self.run_start {
777            let Some(run_end) = self.run_ends.get(self.run_number) else {
778                return Err(ArrowError::CastError(format!(
779                    "Index {index} beyond run array"
780                )));
781            };
782            if index < run_end.as_usize() {
783                return Ok(());
784            }
785            if index == run_end.as_usize() {
786                self.run_number += 1;
787                self.run_start = run_end.as_usize();
788                return Ok(());
789            }
790        }
791
792        // Use partition_point for all non-sequential cases
793        let run_number = self
794            .run_ends
795            .partition_point(|&run_end| run_end.as_usize() <= index);
796        if run_number >= self.run_ends.len() {
797            return Err(ArrowError::CastError(format!(
798                "Index {index} beyond run array"
799            )));
800        }
801        self.run_number = run_number;
802        self.run_start = match run_number {
803            0 => 0,
804            _ => self.run_ends[run_number - 1].as_usize(),
805        };
806        Ok(())
807    }
808
809    fn append_row(
810        &mut self,
811        builder: &mut impl VariantBuilderExt,
812        index: usize,
813    ) -> Result<(), ArrowError> {
814        self.set_run_for_index(index)?;
815
816        // Handle null values
817        if self.run_array.values().is_null(self.run_number) {
818            builder.append_null();
819            return Ok(());
820        }
821
822        // Re-encode the value
823        self.values_builder.append_row(builder, self.run_number)?;
824
825        Ok(())
826    }
827}
828
829#[cfg(test)]
830mod tests {
831    use super::*;
832    use crate::{VariantArray, VariantArrayBuilder};
833    use arrow::array::{ArrayRef, BooleanArray, Int32Array, StringArray};
834    use arrow::datatypes::Int32Type;
835    use std::sync::Arc;
836
837    /// Builds a VariantArray from an Arrow array using the row builder.
838    fn execute_row_builder_test(array: &dyn Array) -> VariantArray {
839        execute_row_builder_test_with_options(
840            array,
841            CastOptions {
842                safe: false,
843                ..Default::default()
844            },
845        )
846    }
847
848    /// Variant of `execute_row_builder_test` that allows specifying options
849    fn execute_row_builder_test_with_options(
850        array: &dyn Array,
851        options: CastOptions,
852    ) -> VariantArray {
853        let mut row_builder =
854            make_arrow_to_variant_row_builder(array.data_type(), array, &options).unwrap();
855
856        let mut array_builder = VariantArrayBuilder::new(array.len());
857
858        // The repetitive loop that appears in every test
859        for i in 0..array.len() {
860            row_builder.append_row(&mut array_builder, i).unwrap();
861        }
862
863        let variant_array = array_builder.build();
864        assert_eq!(variant_array.len(), array.len());
865        variant_array
866    }
867
868    /// Generic helper function to test row builders with basic assertion patterns.
869    /// Uses execute_row_builder_test and adds simple value comparison assertions.
870    fn test_row_builder_basic(array: &dyn Array, expected_values: Vec<Option<Variant>>) {
871        test_row_builder_basic_with_options(
872            array,
873            expected_values,
874            CastOptions {
875                safe: false,
876                ..Default::default()
877            },
878        );
879    }
880
881    /// Variant of `test_row_builder_basic` that allows specifying options
882    fn test_row_builder_basic_with_options(
883        array: &dyn Array,
884        expected_values: Vec<Option<Variant>>,
885        options: CastOptions,
886    ) {
887        let variant_array = execute_row_builder_test_with_options(array, options);
888
889        // The repetitive assertion pattern
890        for (i, expected) in expected_values.iter().enumerate() {
891            match expected {
892                Some(variant) => {
893                    assert_eq!(variant_array.value(i), *variant, "Mismatch at index {i}")
894                }
895                None => assert!(variant_array.is_null(i), "Expected null at index {i}"),
896            }
897        }
898    }
899
900    #[test]
901    fn test_primitive_row_builder() {
902        let int_array = Int32Array::from(vec![Some(42), None, Some(100)]);
903        test_row_builder_basic(
904            &int_array,
905            vec![Some(Variant::Int32(42)), None, Some(Variant::Int32(100))],
906        );
907    }
908
909    #[test]
910    fn test_string_row_builder() {
911        let string_array = StringArray::from(vec![Some("hello"), None, Some("world")]);
912        test_row_builder_basic(
913            &string_array,
914            vec![
915                Some(Variant::from("hello")),
916                None,
917                Some(Variant::from("world")),
918            ],
919        );
920    }
921
922    #[test]
923    fn test_boolean_row_builder() {
924        let bool_array = BooleanArray::from(vec![Some(true), None, Some(false)]);
925        test_row_builder_basic(
926            &bool_array,
927            vec![Some(Variant::from(true)), None, Some(Variant::from(false))],
928        );
929    }
930
931    #[test]
932    fn test_struct_row_builder() {
933        use arrow::array::{ArrayRef, Int32Array, StringArray, StructArray};
934        use arrow_schema::{DataType, Field};
935        use std::sync::Arc;
936
937        // Create a struct array with int and string fields
938        let int_field = Field::new("id", DataType::Int32, true);
939        let string_field = Field::new("name", DataType::Utf8, true);
940
941        let int_array = Int32Array::from(vec![Some(1), None, Some(3)]);
942        let string_array = StringArray::from(vec![Some("Alice"), Some("Bob"), None]);
943
944        let struct_array = StructArray::try_new(
945            vec![int_field, string_field].into(),
946            vec![
947                Arc::new(int_array) as ArrayRef,
948                Arc::new(string_array) as ArrayRef,
949            ],
950            None,
951        )
952        .unwrap();
953
954        let variant_array = execute_row_builder_test(&struct_array);
955
956        // Check first row - should have both fields
957        let first_variant = variant_array.value(0);
958        assert_eq!(first_variant.get_object_field("id"), Some(Variant::from(1)));
959        assert_eq!(
960            first_variant.get_object_field("name"),
961            Some(Variant::from("Alice"))
962        );
963
964        // Check second row - should have name field but not id (null field omitted)
965        let second_variant = variant_array.value(1);
966        assert_eq!(second_variant.get_object_field("id"), None); // null field omitted
967        assert_eq!(
968            second_variant.get_object_field("name"),
969            Some(Variant::from("Bob"))
970        );
971
972        // Check third row - should have id field but not name (null field omitted)
973        let third_variant = variant_array.value(2);
974        assert_eq!(third_variant.get_object_field("id"), Some(Variant::from(3)));
975        assert_eq!(third_variant.get_object_field("name"), None); // null field omitted
976    }
977
978    #[test]
979    fn test_run_end_encoded_row_builder() {
980        use arrow::array::{Int32Array, RunArray};
981        use arrow::datatypes::Int32Type;
982
983        // Create a run-end encoded array: [A, A, B, B, B, C]
984        // run_ends: [2, 5, 6]
985        // values: ["A", "B", "C"]
986        let values = StringArray::from(vec!["A", "B", "C"]);
987        let run_ends = Int32Array::from(vec![2, 5, 6]);
988        let run_array = RunArray::<Int32Type>::try_new(&run_ends, &values).unwrap();
989
990        let variant_array = execute_row_builder_test(&run_array);
991
992        // Verify the values
993        assert_eq!(variant_array.value(0), Variant::from("A")); // Run 0
994        assert_eq!(variant_array.value(1), Variant::from("A")); // Run 0
995        assert_eq!(variant_array.value(2), Variant::from("B")); // Run 1
996        assert_eq!(variant_array.value(3), Variant::from("B")); // Run 1
997        assert_eq!(variant_array.value(4), Variant::from("B")); // Run 1
998        assert_eq!(variant_array.value(5), Variant::from("C")); // Run 2
999    }
1000
1001    #[test]
1002    fn test_run_end_encoded_random_access() {
1003        use arrow::array::{Int32Array, RunArray};
1004        use arrow::datatypes::Int32Type;
1005
1006        // Create a run-end encoded array: [A, A, B, B, B, C]
1007        let values = StringArray::from(vec!["A", "B", "C"]);
1008        let run_ends = Int32Array::from(vec![2, 5, 6]);
1009        let run_array = RunArray::<Int32Type>::try_new(&run_ends, &values).unwrap();
1010
1011        let options = CastOptions {
1012            safe: false,
1013            ..Default::default()
1014        };
1015        let mut row_builder =
1016            make_arrow_to_variant_row_builder(run_array.data_type(), &run_array, &options).unwrap();
1017
1018        // Test random access pattern (backward jumps, forward jumps)
1019        let access_pattern = [0, 5, 2, 4, 1, 3]; // Mix of all cases
1020        let expected_values = ["A", "C", "B", "B", "A", "B"];
1021
1022        for (i, &index) in access_pattern.iter().enumerate() {
1023            let mut array_builder = VariantArrayBuilder::new(1);
1024            row_builder.append_row(&mut array_builder, index).unwrap();
1025            let variant_array = array_builder.build();
1026            assert_eq!(variant_array.value(0), Variant::from(expected_values[i]));
1027        }
1028    }
1029
1030    #[test]
1031    fn test_run_end_encoded_with_nulls() {
1032        use arrow::array::{Int32Array, RunArray};
1033        use arrow::datatypes::Int32Type;
1034
1035        // Create a run-end encoded array with null values: [A, A, null, null, B]
1036        let values = StringArray::from(vec![Some("A"), None, Some("B")]);
1037        let run_ends = Int32Array::from(vec![2, 4, 5]);
1038        let run_array = RunArray::<Int32Type>::try_new(&run_ends, &values).unwrap();
1039
1040        let options = CastOptions {
1041            safe: false,
1042            ..Default::default()
1043        };
1044        let mut row_builder =
1045            make_arrow_to_variant_row_builder(run_array.data_type(), &run_array, &options).unwrap();
1046        let mut array_builder = VariantArrayBuilder::new(5);
1047
1048        // Test sequential access
1049        for i in 0..5 {
1050            row_builder.append_row(&mut array_builder, i).unwrap();
1051        }
1052
1053        let variant_array = array_builder.build();
1054        assert_eq!(variant_array.len(), 5);
1055
1056        // Verify the values
1057        assert_eq!(variant_array.value(0), Variant::from("A")); // Run 0
1058        assert_eq!(variant_array.value(1), Variant::from("A")); // Run 0
1059        assert!(variant_array.is_null(2)); // Run 1 (null)
1060        assert!(variant_array.is_null(3)); // Run 1 (null)
1061        assert_eq!(variant_array.value(4), Variant::from("B")); // Run 2
1062    }
1063
1064    #[test]
1065    fn test_dictionary_row_builder() {
1066        use arrow::array::{DictionaryArray, Int32Array};
1067        use arrow::datatypes::Int32Type;
1068
1069        // Create a dictionary array: keys=[0, 1, 0, 2, 1], values=["apple", "banana", "cherry"]
1070        let values = StringArray::from(vec!["apple", "banana", "cherry"]);
1071        let keys = Int32Array::from(vec![0, 1, 0, 2, 1]);
1072        let dict_array = DictionaryArray::<Int32Type>::try_new(keys, Arc::new(values)).unwrap();
1073
1074        let variant_array = execute_row_builder_test(&dict_array);
1075
1076        // Verify the values match the dictionary lookup
1077        assert_eq!(variant_array.value(0), Variant::from("apple")); // keys[0] = 0 -> values[0] = "apple"
1078        assert_eq!(variant_array.value(1), Variant::from("banana")); // keys[1] = 1 -> values[1] = "banana"
1079        assert_eq!(variant_array.value(2), Variant::from("apple")); // keys[2] = 0 -> values[0] = "apple"
1080        assert_eq!(variant_array.value(3), Variant::from("cherry")); // keys[3] = 2 -> values[2] = "cherry"
1081        assert_eq!(variant_array.value(4), Variant::from("banana")); // keys[4] = 1 -> values[1] = "banana"
1082    }
1083
1084    #[test]
1085    fn test_dictionary_with_nulls() {
1086        use arrow::array::{DictionaryArray, Int32Array};
1087        use arrow::datatypes::Int32Type;
1088
1089        // Create a dictionary array with null keys: keys=[0, null, 1, null, 2], values=["x", "y", "z"]
1090        let values = StringArray::from(vec!["x", "y", "z"]);
1091        let keys = Int32Array::from(vec![Some(0), None, Some(1), None, Some(2)]);
1092        let dict_array = DictionaryArray::<Int32Type>::try_new(keys, Arc::new(values)).unwrap();
1093
1094        let options = CastOptions {
1095            safe: false,
1096            ..Default::default()
1097        };
1098        let mut row_builder =
1099            make_arrow_to_variant_row_builder(dict_array.data_type(), &dict_array, &options)
1100                .unwrap();
1101        let mut array_builder = VariantArrayBuilder::new(5);
1102
1103        // Test sequential access
1104        for i in 0..5 {
1105            row_builder.append_row(&mut array_builder, i).unwrap();
1106        }
1107
1108        let variant_array = array_builder.build();
1109        assert_eq!(variant_array.len(), 5);
1110
1111        // Verify the values and nulls
1112        assert_eq!(variant_array.value(0), Variant::from("x")); // keys[0] = 0 -> values[0] = "x"
1113        assert!(variant_array.is_null(1)); // keys[1] = null
1114        assert_eq!(variant_array.value(2), Variant::from("y")); // keys[2] = 1 -> values[1] = "y"
1115        assert!(variant_array.is_null(3)); // keys[3] = null
1116        assert_eq!(variant_array.value(4), Variant::from("z")); // keys[4] = 2 -> values[2] = "z"
1117    }
1118
1119    #[test]
1120    fn test_dictionary_random_access() {
1121        use arrow::array::{DictionaryArray, Int32Array};
1122        use arrow::datatypes::Int32Type;
1123
1124        // Create a dictionary array: keys=[0, 1, 2, 0, 1, 2], values=["red", "green", "blue"]
1125        let values = StringArray::from(vec!["red", "green", "blue"]);
1126        let keys = Int32Array::from(vec![0, 1, 2, 0, 1, 2]);
1127        let dict_array = DictionaryArray::<Int32Type>::try_new(keys, Arc::new(values)).unwrap();
1128
1129        let options = CastOptions {
1130            safe: false,
1131            ..Default::default()
1132        };
1133        let mut row_builder =
1134            make_arrow_to_variant_row_builder(dict_array.data_type(), &dict_array, &options)
1135                .unwrap();
1136
1137        // Test random access pattern
1138        let access_pattern = [5, 0, 3, 1, 4, 2]; // Random order
1139        let expected_values = ["blue", "red", "red", "green", "green", "blue"];
1140
1141        for (i, &index) in access_pattern.iter().enumerate() {
1142            let mut array_builder = VariantArrayBuilder::new(1);
1143            row_builder.append_row(&mut array_builder, index).unwrap();
1144            let variant_array = array_builder.build();
1145            assert_eq!(variant_array.value(0), Variant::from(expected_values[i]));
1146        }
1147    }
1148
1149    #[test]
1150    fn test_nested_dictionary() {
1151        use arrow::array::{DictionaryArray, Int32Array, StructArray};
1152        use arrow::datatypes::{Field, Int32Type};
1153
1154        // Create a dictionary with struct values
1155        let id_array = Int32Array::from(vec![1, 2, 3]);
1156        let name_array = StringArray::from(vec!["Alice", "Bob", "Charlie"]);
1157        let struct_array = StructArray::from(vec![
1158            (
1159                Arc::new(Field::new("id", DataType::Int32, false)),
1160                Arc::new(id_array) as ArrayRef,
1161            ),
1162            (
1163                Arc::new(Field::new("name", DataType::Utf8, false)),
1164                Arc::new(name_array) as ArrayRef,
1165            ),
1166        ]);
1167
1168        let keys = Int32Array::from(vec![0, 1, 0, 2, 1]);
1169        let dict_array =
1170            DictionaryArray::<Int32Type>::try_new(keys, Arc::new(struct_array)).unwrap();
1171
1172        let options = CastOptions {
1173            safe: false,
1174            ..Default::default()
1175        };
1176        let mut row_builder =
1177            make_arrow_to_variant_row_builder(dict_array.data_type(), &dict_array, &options)
1178                .unwrap();
1179        let mut array_builder = VariantArrayBuilder::new(5);
1180
1181        // Test sequential access
1182        for i in 0..5 {
1183            row_builder.append_row(&mut array_builder, i).unwrap();
1184        }
1185
1186        let variant_array = array_builder.build();
1187        assert_eq!(variant_array.len(), 5);
1188
1189        // Verify the nested struct values
1190        let first_variant = variant_array.value(0);
1191        assert_eq!(first_variant.get_object_field("id"), Some(Variant::from(1)));
1192        assert_eq!(
1193            first_variant.get_object_field("name"),
1194            Some(Variant::from("Alice"))
1195        );
1196
1197        let second_variant = variant_array.value(1);
1198        assert_eq!(
1199            second_variant.get_object_field("id"),
1200            Some(Variant::from(2))
1201        );
1202        assert_eq!(
1203            second_variant.get_object_field("name"),
1204            Some(Variant::from("Bob"))
1205        );
1206
1207        // Test that repeated keys give same values
1208        let third_variant = variant_array.value(2);
1209        assert_eq!(third_variant.get_object_field("id"), Some(Variant::from(1)));
1210        assert_eq!(
1211            third_variant.get_object_field("name"),
1212            Some(Variant::from("Alice"))
1213        );
1214    }
1215
1216    #[test]
1217    fn test_list_row_builder() {
1218        use arrow::array::ListArray;
1219
1220        // Create a list array: [[1, 2], [3, 4, 5], null, []]
1221        let data = vec![
1222            Some(vec![Some(1), Some(2)]),
1223            Some(vec![Some(3), Some(4), Some(5)]),
1224            None,
1225            Some(vec![]),
1226        ];
1227        let list_array = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1228
1229        let variant_array = execute_row_builder_test(&list_array);
1230
1231        // Row 0: [1, 2]
1232        let row0 = variant_array.value(0);
1233        let list0 = row0.as_list().unwrap();
1234        assert_eq!(list0.len(), 2);
1235        assert_eq!(list0.get(0), Some(Variant::from(1)));
1236        assert_eq!(list0.get(1), Some(Variant::from(2)));
1237
1238        // Row 1: [3, 4, 5]
1239        let row1 = variant_array.value(1);
1240        let list1 = row1.as_list().unwrap();
1241        assert_eq!(list1.len(), 3);
1242        assert_eq!(list1.get(0), Some(Variant::from(3)));
1243        assert_eq!(list1.get(1), Some(Variant::from(4)));
1244        assert_eq!(list1.get(2), Some(Variant::from(5)));
1245
1246        // Row 2: null
1247        assert!(variant_array.is_null(2));
1248
1249        // Row 3: []
1250        let row3 = variant_array.value(3);
1251        let list3 = row3.as_list().unwrap();
1252        assert_eq!(list3.len(), 0);
1253    }
1254
1255    #[test]
1256    fn test_sliced_list_row_builder() {
1257        use arrow::array::ListArray;
1258
1259        // Create a list array: [[1, 2], [3, 4, 5], [6]]
1260        let data = vec![
1261            Some(vec![Some(1), Some(2)]),
1262            Some(vec![Some(3), Some(4), Some(5)]),
1263            Some(vec![Some(6)]),
1264        ];
1265        let list_array = ListArray::from_iter_primitive::<Int32Type, _, _>(data);
1266
1267        // Slice to get just the middle element: [[3, 4, 5]]
1268        let sliced_array = list_array.slice(1, 1);
1269
1270        let options = CastOptions {
1271            safe: false,
1272            ..Default::default()
1273        };
1274        let mut row_builder =
1275            make_arrow_to_variant_row_builder(sliced_array.data_type(), &sliced_array, &options)
1276                .unwrap();
1277        let mut variant_array_builder = VariantArrayBuilder::new(sliced_array.len());
1278
1279        // Test the single row
1280        row_builder
1281            .append_row(&mut variant_array_builder, 0)
1282            .unwrap();
1283        let variant_array = variant_array_builder.build();
1284
1285        // Verify result
1286        assert_eq!(variant_array.len(), 1);
1287
1288        // Row 0: [3, 4, 5]
1289        let row0 = variant_array.value(0);
1290        let list0 = row0.as_list().unwrap();
1291        assert_eq!(list0.len(), 3);
1292        assert_eq!(list0.get(0), Some(Variant::from(3)));
1293        assert_eq!(list0.get(1), Some(Variant::from(4)));
1294        assert_eq!(list0.get(2), Some(Variant::from(5)));
1295    }
1296
1297    #[test]
1298    fn test_nested_list_row_builder() {
1299        use arrow::array::ListArray;
1300        use arrow::datatypes::Field;
1301
1302        // Build the nested structure manually
1303        let inner_field = Arc::new(Field::new("item", DataType::Int32, true));
1304        let inner_list_field = Arc::new(Field::new("item", DataType::List(inner_field), true));
1305
1306        let values_data = vec![Some(vec![Some(1), Some(2)]), Some(vec![Some(3)])];
1307        let values_list = ListArray::from_iter_primitive::<Int32Type, _, _>(values_data);
1308
1309        let outer_offsets = arrow::buffer::OffsetBuffer::new(vec![0i32, 2, 2].into());
1310        let outer_list = ListArray::new(
1311            inner_list_field,
1312            outer_offsets,
1313            Arc::new(values_list),
1314            Some(arrow::buffer::NullBuffer::from(vec![true, false])),
1315        );
1316
1317        let options = CastOptions {
1318            safe: false,
1319            ..Default::default()
1320        };
1321        let mut row_builder =
1322            make_arrow_to_variant_row_builder(outer_list.data_type(), &outer_list, &options)
1323                .unwrap();
1324        let mut variant_array_builder = VariantArrayBuilder::new(outer_list.len());
1325
1326        for i in 0..outer_list.len() {
1327            row_builder
1328                .append_row(&mut variant_array_builder, i)
1329                .unwrap();
1330        }
1331
1332        let variant_array = variant_array_builder.build();
1333
1334        // Verify results
1335        assert_eq!(variant_array.len(), 2);
1336
1337        // Row 0: [[1, 2], [3]]
1338        let row0 = variant_array.value(0);
1339        let outer_list0 = row0.as_list().unwrap();
1340        assert_eq!(outer_list0.len(), 2);
1341
1342        let inner_list0_0 = outer_list0.get(0).unwrap();
1343        let inner_list0_0 = inner_list0_0.as_list().unwrap();
1344        assert_eq!(inner_list0_0.len(), 2);
1345        assert_eq!(inner_list0_0.get(0), Some(Variant::from(1)));
1346        assert_eq!(inner_list0_0.get(1), Some(Variant::from(2)));
1347
1348        let inner_list0_1 = outer_list0.get(1).unwrap();
1349        let inner_list0_1 = inner_list0_1.as_list().unwrap();
1350        assert_eq!(inner_list0_1.len(), 1);
1351        assert_eq!(inner_list0_1.get(0), Some(Variant::from(3)));
1352
1353        // Row 1: null
1354        assert!(variant_array.is_null(1));
1355    }
1356
1357    #[test]
1358    fn test_map_row_builder() {
1359        use arrow::array::{Int32Array, MapArray, StringArray, StructArray};
1360        use arrow::buffer::{NullBuffer, OffsetBuffer};
1361        use arrow::datatypes::{DataType, Field, Fields};
1362        use std::sync::Arc;
1363
1364        // Create the entries struct array (key-value pairs)
1365        let keys = StringArray::from(vec!["key1", "key2", "key3"]);
1366        let values = Int32Array::from(vec![1, 2, 3]);
1367        let entries_fields = Fields::from(vec![
1368            Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, DataType::Utf8, false),
1369            Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Int32, true),
1370        ]);
1371        let entries = StructArray::new(
1372            entries_fields.clone(),
1373            vec![Arc::new(keys), Arc::new(values)],
1374            None, // No nulls in the entries themselves
1375        );
1376
1377        // Create offsets for 4 maps: [0..1], [1..1], [1..1], [1..3]
1378        // Map 0: {"key1": 1}    (1 entry)
1379        // Map 1: {}             (0 entries - empty)
1380        // Map 2: null           (0 entries but NULL via null buffer)
1381        // Map 3: {"key2": 2, "key3": 3}  (2 entries)
1382        let offsets = OffsetBuffer::new(vec![0, 1, 1, 1, 3].into());
1383
1384        // Create null buffer - map at index 2 is NULL
1385        let null_buffer = Some(NullBuffer::from(vec![true, true, false, true]));
1386
1387        // Create the map field
1388        let map_field = Arc::new(Field::new(
1389            Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
1390            DataType::Struct(entries_fields),
1391            false, // Keys are non-nullable
1392        ));
1393
1394        // Create MapArray using try_new
1395        let map_array = MapArray::try_new(
1396            map_field,
1397            offsets,
1398            entries,
1399            null_buffer,
1400            false, // not ordered
1401        )
1402        .unwrap();
1403
1404        let variant_array = execute_row_builder_test(&map_array);
1405
1406        // Map 0: {"key1": 1}
1407        let map0 = variant_array.value(0);
1408        let obj0 = map0.as_object().unwrap();
1409        assert_eq!(obj0.len(), 1);
1410        assert_eq!(obj0.get("key1"), Some(Variant::from(1)));
1411
1412        // Map 1: {} (empty object, not null)
1413        let map1 = variant_array.value(1);
1414        let obj1 = map1.as_object().unwrap();
1415        assert_eq!(obj1.len(), 0); // Empty object
1416
1417        // Map 2: null (actual NULL)
1418        assert!(variant_array.is_null(2));
1419
1420        // Map 3: {"key2": 2, "key3": 3}
1421        let map3 = variant_array.value(3);
1422        let obj3 = map3.as_object().unwrap();
1423        assert_eq!(obj3.len(), 2);
1424        assert_eq!(obj3.get("key2"), Some(Variant::from(2)));
1425        assert_eq!(obj3.get("key3"), Some(Variant::from(3)));
1426    }
1427
1428    #[test]
1429    fn test_union_sparse_row_builder() {
1430        use arrow::array::{Float64Array, Int32Array, StringArray, UnionArray};
1431        use arrow::buffer::ScalarBuffer;
1432        use arrow::datatypes::{DataType, Field, UnionFields};
1433        use std::sync::Arc;
1434
1435        // Create a sparse union array with mixed types (int, float, string)
1436        let int_array = Int32Array::from(vec![Some(1), None, None, None, Some(34), None]);
1437        let float_array = Float64Array::from(vec![None, Some(3.2), None, Some(32.5), None, None]);
1438        let string_array = StringArray::from(vec![None, None, Some("hello"), None, None, None]);
1439        let type_ids = [0, 1, 2, 1, 0, 0].into_iter().collect::<ScalarBuffer<i8>>();
1440
1441        let union_fields = UnionFields::from_fields(vec![
1442            Field::new("int_field", DataType::Int32, false),
1443            Field::new("float_field", DataType::Float64, false),
1444            Field::new("string_field", DataType::Utf8, false),
1445        ]);
1446
1447        let children: Vec<Arc<dyn Array>> = vec![
1448            Arc::new(int_array),
1449            Arc::new(float_array),
1450            Arc::new(string_array),
1451        ];
1452
1453        let union_array = UnionArray::try_new(
1454            union_fields,
1455            type_ids,
1456            None, // Sparse union
1457            children,
1458        )
1459        .unwrap();
1460
1461        let variant_array = execute_row_builder_test(&union_array);
1462        assert_eq!(variant_array.value(0), Variant::Int32(1));
1463        assert_eq!(variant_array.value(1), Variant::Double(3.2));
1464        assert_eq!(variant_array.value(2), Variant::from("hello"));
1465        assert_eq!(variant_array.value(3), Variant::Double(32.5));
1466        assert_eq!(variant_array.value(4), Variant::Int32(34));
1467        assert!(variant_array.is_null(5));
1468    }
1469
1470    #[test]
1471    fn test_union_dense_row_builder() {
1472        use arrow::array::{Float64Array, Int32Array, StringArray, UnionArray};
1473        use arrow::buffer::ScalarBuffer;
1474        use arrow::datatypes::{DataType, Field, UnionFields};
1475        use std::sync::Arc;
1476
1477        // Create a dense union array with mixed types (int, float, string)
1478        let int_array = Int32Array::from(vec![Some(1), Some(34), None]);
1479        let float_array = Float64Array::from(vec![3.2, 32.5]);
1480        let string_array = StringArray::from(vec!["hello"]);
1481        let type_ids = [0, 1, 2, 1, 0, 0].into_iter().collect::<ScalarBuffer<i8>>();
1482        let offsets = [0, 0, 0, 1, 1, 2]
1483            .into_iter()
1484            .collect::<ScalarBuffer<i32>>();
1485
1486        let union_fields = UnionFields::from_fields(vec![
1487            Field::new("int_field", DataType::Int32, false),
1488            Field::new("float_field", DataType::Float64, false),
1489            Field::new("string_field", DataType::Utf8, false),
1490        ]);
1491
1492        let children: Vec<Arc<dyn Array>> = vec![
1493            Arc::new(int_array),
1494            Arc::new(float_array),
1495            Arc::new(string_array),
1496        ];
1497
1498        let union_array = UnionArray::try_new(
1499            union_fields,
1500            type_ids,
1501            Some(offsets), // Dense union
1502            children,
1503        )
1504        .unwrap();
1505
1506        // Test the row builder
1507        let options = CastOptions {
1508            safe: false,
1509            ..Default::default()
1510        };
1511        let mut row_builder =
1512            make_arrow_to_variant_row_builder(union_array.data_type(), &union_array, &options)
1513                .unwrap();
1514
1515        let mut variant_builder = VariantArrayBuilder::new(union_array.len());
1516        for i in 0..union_array.len() {
1517            row_builder.append_row(&mut variant_builder, i).unwrap();
1518        }
1519        let variant_array = variant_builder.build();
1520
1521        assert_eq!(variant_array.len(), 6);
1522        assert_eq!(variant_array.value(0), Variant::Int32(1));
1523        assert_eq!(variant_array.value(1), Variant::Double(3.2));
1524        assert_eq!(variant_array.value(2), Variant::from("hello"));
1525        assert_eq!(variant_array.value(3), Variant::Double(32.5));
1526        assert_eq!(variant_array.value(4), Variant::Int32(34));
1527        assert!(variant_array.is_null(5));
1528    }
1529
1530    #[test]
1531    fn test_union_sparse_type_ids_row_builder() {
1532        use arrow::array::{Int32Array, StringArray, UnionArray};
1533        use arrow::buffer::ScalarBuffer;
1534        use arrow::datatypes::{DataType, Field, UnionFields};
1535        use std::sync::Arc;
1536
1537        // Create a sparse union with non-contiguous type IDs (1, 3)
1538        let int_array = Int32Array::from(vec![Some(42), None]);
1539        let string_array = StringArray::from(vec![None, Some("test")]);
1540        let type_ids = [1, 3].into_iter().collect::<ScalarBuffer<i8>>();
1541
1542        let union_fields = UnionFields::try_new(
1543            vec![1, 3], // Non-contiguous type IDs
1544            vec![
1545                Field::new("int_field", DataType::Int32, false),
1546                Field::new("string_field", DataType::Utf8, false),
1547            ],
1548        )
1549        .unwrap();
1550
1551        let children: Vec<Arc<dyn Array>> = vec![Arc::new(int_array), Arc::new(string_array)];
1552
1553        let union_array = UnionArray::try_new(
1554            union_fields,
1555            type_ids,
1556            None, // Sparse union
1557            children,
1558        )
1559        .unwrap();
1560
1561        // Test the row builder
1562        let options = CastOptions {
1563            safe: false,
1564            ..Default::default()
1565        };
1566        let mut row_builder =
1567            make_arrow_to_variant_row_builder(union_array.data_type(), &union_array, &options)
1568                .unwrap();
1569
1570        let mut variant_builder = VariantArrayBuilder::new(union_array.len());
1571        for i in 0..union_array.len() {
1572            row_builder.append_row(&mut variant_builder, i).unwrap();
1573        }
1574        let variant_array = variant_builder.build();
1575
1576        // Verify results
1577        assert_eq!(variant_array.len(), 2);
1578
1579        // Row 0: int 42 (type_id = 1)
1580        assert_eq!(variant_array.value(0), Variant::Int32(42));
1581
1582        // Row 1: string "test" (type_id = 3)
1583        assert_eq!(variant_array.value(1), Variant::from("test"));
1584    }
1585
1586    #[test]
1587    fn test_decimal32_row_builder() {
1588        use arrow::array::Decimal32Array;
1589        use parquet_variant::VariantDecimal4;
1590
1591        // Test Decimal32Array with scale 2 (e.g., for currency: 12.34)
1592        let decimal_array = Decimal32Array::from(vec![Some(1234), None, Some(-5678)])
1593            .with_precision_and_scale(9, 2)
1594            .unwrap();
1595
1596        test_row_builder_basic(
1597            &decimal_array,
1598            vec![
1599                Some(Variant::from(VariantDecimal4::try_new(1234, 2).unwrap())),
1600                None,
1601                Some(Variant::from(VariantDecimal4::try_new(-5678, 2).unwrap())),
1602            ],
1603        );
1604    }
1605
1606    #[test]
1607    fn test_decimal128_row_builder() {
1608        use arrow::array::Decimal128Array;
1609        use parquet_variant::VariantDecimal16;
1610
1611        // Test Decimal128Array with negative scale (multiply by 10^|scale|)
1612        let decimal_array = Decimal128Array::from(vec![Some(123), None, Some(456)])
1613            .with_precision_and_scale(10, -2)
1614            .unwrap();
1615
1616        test_row_builder_basic(
1617            &decimal_array,
1618            vec![
1619                Some(Variant::from(VariantDecimal16::try_new(12300, 0).unwrap())),
1620                None,
1621                Some(Variant::from(VariantDecimal16::try_new(45600, 0).unwrap())),
1622            ],
1623        );
1624    }
1625
1626    #[test]
1627    fn test_decimal256_overflow_row_builder() {
1628        use arrow::array::Decimal256Array;
1629        use arrow::datatypes::i256;
1630
1631        // Test Decimal256Array with a value that overflows i128
1632        let large_value = i256::from_i128(i128::MAX) + i256::from(1); // Overflows i128
1633        let decimal_array = Decimal256Array::from(vec![Some(large_value), Some(i256::from(123))])
1634            .with_precision_and_scale(76, 3)
1635            .unwrap();
1636
1637        test_row_builder_basic_with_options(
1638            &decimal_array,
1639            vec![
1640                Some(Variant::Null), // Overflow value becomes Variant::Null
1641                Some(Variant::from(VariantDecimal16::try_new(123, 3).unwrap())),
1642            ],
1643            CastOptions::default(),
1644        );
1645    }
1646
1647    #[test]
1648    fn test_binary_row_builder() {
1649        use arrow::array::BinaryArray;
1650
1651        let binary_data = vec![
1652            Some(b"hello".as_slice()),
1653            None,
1654            Some(b"\x00\x01\x02\xFF".as_slice()),
1655            Some(b"".as_slice()), // Empty binary
1656        ];
1657        let binary_array = BinaryArray::from(binary_data);
1658
1659        test_row_builder_basic(
1660            &binary_array,
1661            vec![
1662                Some(Variant::from(b"hello".as_slice())),
1663                None,
1664                Some(Variant::from([0x00, 0x01, 0x02, 0xFF].as_slice())),
1665                Some(Variant::from([].as_slice())),
1666            ],
1667        );
1668    }
1669
1670    #[test]
1671    fn test_binary_view_row_builder() {
1672        use arrow::array::BinaryViewArray;
1673
1674        let binary_data = vec![
1675            Some(b"short".as_slice()),
1676            None,
1677            Some(b"this is a longer binary view that exceeds inline storage".as_slice()),
1678        ];
1679        let binary_view_array = BinaryViewArray::from(binary_data);
1680
1681        test_row_builder_basic(
1682            &binary_view_array,
1683            vec![
1684                Some(Variant::from(b"short".as_slice())),
1685                None,
1686                Some(Variant::from(
1687                    b"this is a longer binary view that exceeds inline storage".as_slice(),
1688                )),
1689            ],
1690        );
1691    }
1692
1693    #[test]
1694    fn test_fixed_size_binary_row_builder() {
1695        use arrow::array::FixedSizeBinaryArray;
1696
1697        let binary_data = vec![
1698            Some([0x01, 0x02, 0x03, 0x04]),
1699            None,
1700            Some([0xFF, 0xFE, 0xFD, 0xFC]),
1701        ];
1702        let fixed_binary_array =
1703            FixedSizeBinaryArray::try_from_sparse_iter_with_size(binary_data.into_iter(), 4)
1704                .unwrap();
1705
1706        test_row_builder_basic(
1707            &fixed_binary_array,
1708            vec![
1709                Some(Variant::from([0x01, 0x02, 0x03, 0x04].as_slice())),
1710                None,
1711                Some(Variant::from([0xFF, 0xFE, 0xFD, 0xFC].as_slice())),
1712            ],
1713        );
1714    }
1715
1716    #[test]
1717    fn test_utf8_view_row_builder() {
1718        use arrow::array::StringViewArray;
1719
1720        let string_data = vec![
1721            Some("short"),
1722            None,
1723            Some("this is a much longer string that will be stored out-of-line in the buffer"),
1724        ];
1725        let string_view_array = StringViewArray::from(string_data);
1726
1727        test_row_builder_basic(
1728            &string_view_array,
1729            vec![
1730                Some(Variant::from("short")),
1731                None,
1732                Some(Variant::from(
1733                    "this is a much longer string that will be stored out-of-line in the buffer",
1734                )),
1735            ],
1736        );
1737    }
1738
1739    #[test]
1740    fn test_timestamp_second_row_builder() {
1741        use arrow::array::TimestampSecondArray;
1742
1743        let timestamp_data = vec![
1744            Some(1609459200), // 2021-01-01 00:00:00 UTC
1745            None,
1746            Some(1640995200), // 2022-01-01 00:00:00 UTC
1747        ];
1748        let timestamp_array = TimestampSecondArray::from(timestamp_data);
1749
1750        let expected_naive1 = DateTime::from_timestamp(1609459200, 0).unwrap().naive_utc();
1751        let expected_naive2 = DateTime::from_timestamp(1640995200, 0).unwrap().naive_utc();
1752
1753        test_row_builder_basic(
1754            &timestamp_array,
1755            vec![
1756                Some(Variant::from(expected_naive1)),
1757                None,
1758                Some(Variant::from(expected_naive2)),
1759            ],
1760        );
1761    }
1762
1763    #[test]
1764    fn test_timestamp_with_timezone_row_builder() {
1765        use arrow::array::TimestampMicrosecondArray;
1766        use chrono::DateTime;
1767
1768        let timestamp_data = vec![
1769            Some(1609459200000000), // 2021-01-01 00:00:00 UTC (in microseconds)
1770            None,
1771            Some(1640995200000000), // 2022-01-01 00:00:00 UTC (in microseconds)
1772        ];
1773        let timezone = "UTC".to_string();
1774        let timestamp_array =
1775            TimestampMicrosecondArray::from(timestamp_data).with_timezone(timezone);
1776
1777        let expected_utc1 = DateTime::from_timestamp(1609459200, 0).unwrap();
1778        let expected_utc2 = DateTime::from_timestamp(1640995200, 0).unwrap();
1779
1780        test_row_builder_basic(
1781            &timestamp_array,
1782            vec![
1783                Some(Variant::from(expected_utc1)),
1784                None,
1785                Some(Variant::from(expected_utc2)),
1786            ],
1787        );
1788    }
1789
1790    #[test]
1791    fn test_timestamp_nanosecond_precision_row_builder() {
1792        use arrow::array::TimestampNanosecondArray;
1793
1794        let timestamp_data = vec![
1795            Some(1609459200123456789), // 2021-01-01 00:00:00.123456789 UTC
1796            None,
1797            Some(1609459200000000000), // 2021-01-01 00:00:00.000000000 UTC (no fractional seconds)
1798        ];
1799        let timestamp_array = TimestampNanosecondArray::from(timestamp_data);
1800
1801        let expected_with_nanos = DateTime::from_timestamp(1609459200, 123456789)
1802            .unwrap()
1803            .naive_utc();
1804        let expected_no_nanos = DateTime::from_timestamp(1609459200, 0).unwrap().naive_utc();
1805
1806        test_row_builder_basic(
1807            &timestamp_array,
1808            vec![
1809                Some(Variant::from(expected_with_nanos)),
1810                None,
1811                Some(Variant::from(expected_no_nanos)),
1812            ],
1813        );
1814    }
1815
1816    #[test]
1817    fn test_timestamp_millisecond_row_builder() {
1818        use arrow::array::TimestampMillisecondArray;
1819
1820        let timestamp_data = vec![
1821            Some(1609459200123), // 2021-01-01 00:00:00.123 UTC
1822            None,
1823            Some(1609459200000), // 2021-01-01 00:00:00.000 UTC
1824        ];
1825        let timestamp_array = TimestampMillisecondArray::from(timestamp_data);
1826
1827        let expected_with_millis = DateTime::from_timestamp(1609459200, 123000000)
1828            .unwrap()
1829            .naive_utc();
1830        let expected_no_millis = DateTime::from_timestamp(1609459200, 0).unwrap().naive_utc();
1831
1832        test_row_builder_basic(
1833            &timestamp_array,
1834            vec![
1835                Some(Variant::from(expected_with_millis)),
1836                None,
1837                Some(Variant::from(expected_no_millis)),
1838            ],
1839        );
1840    }
1841
1842    #[test]
1843    fn test_date32_row_builder() {
1844        use arrow::array::Date32Array;
1845        use chrono::NaiveDate;
1846
1847        let date_data = vec![
1848            Some(0), // 1970-01-01
1849            None,
1850            Some(19723),   // 2024-01-01 (days since epoch)
1851            Some(-719162), // 0001-01-01 (near minimum)
1852        ];
1853        let date_array = Date32Array::from(date_data);
1854
1855        let expected_epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1856        let expected_2024 = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
1857        let expected_min = NaiveDate::from_ymd_opt(1, 1, 1).unwrap();
1858
1859        test_row_builder_basic(
1860            &date_array,
1861            vec![
1862                Some(Variant::from(expected_epoch)),
1863                None,
1864                Some(Variant::from(expected_2024)),
1865                Some(Variant::from(expected_min)),
1866            ],
1867        );
1868    }
1869
1870    #[test]
1871    fn test_date64_row_builder() {
1872        use arrow::array::Date64Array;
1873        use chrono::NaiveDate;
1874
1875        // Test Date64Array with various dates (milliseconds since epoch)
1876        let date_data = vec![
1877            Some(0), // 1970-01-01
1878            None,
1879            Some(1704067200000), // 2024-01-01 (milliseconds since epoch)
1880            Some(86400000),      // 1970-01-02
1881        ];
1882        let date_array = Date64Array::from(date_data);
1883
1884        let expected_epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
1885        let expected_2024 = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
1886        let expected_next_day = NaiveDate::from_ymd_opt(1970, 1, 2).unwrap();
1887
1888        test_row_builder_basic(
1889            &date_array,
1890            vec![
1891                Some(Variant::from(expected_epoch)),
1892                None,
1893                Some(Variant::from(expected_2024)),
1894                Some(Variant::from(expected_next_day)),
1895            ],
1896        );
1897    }
1898
1899    #[test]
1900    fn test_time32_second_row_builder() {
1901        use arrow::array::Time32SecondArray;
1902        use chrono::NaiveTime;
1903
1904        // Test Time32SecondArray with various times (seconds since midnight)
1905        let time_data = vec![
1906            Some(0), // 00:00:00
1907            None,
1908            Some(3661),  // 01:01:01
1909            Some(86399), // 23:59:59
1910        ];
1911        let time_array = Time32SecondArray::from(time_data);
1912
1913        let expected_midnight = NaiveTime::from_hms_opt(0, 0, 0).unwrap();
1914        let expected_time = NaiveTime::from_hms_opt(1, 1, 1).unwrap();
1915        let expected_last = NaiveTime::from_hms_opt(23, 59, 59).unwrap();
1916
1917        test_row_builder_basic(
1918            &time_array,
1919            vec![
1920                Some(Variant::from(expected_midnight)),
1921                None,
1922                Some(Variant::from(expected_time)),
1923                Some(Variant::from(expected_last)),
1924            ],
1925        );
1926    }
1927
1928    #[test]
1929    fn test_time32_millisecond_row_builder() {
1930        use arrow::array::Time32MillisecondArray;
1931        use chrono::NaiveTime;
1932
1933        // Test Time32MillisecondArray with various times (milliseconds since midnight)
1934        let time_data = vec![
1935            Some(0), // 00:00:00.000
1936            None,
1937            Some(3661123),  // 01:01:01.123
1938            Some(86399999), // 23:59:59.999
1939        ];
1940        let time_array = Time32MillisecondArray::from(time_data);
1941
1942        let expected_midnight = NaiveTime::from_hms_milli_opt(0, 0, 0, 0).unwrap();
1943        let expected_time = NaiveTime::from_hms_milli_opt(1, 1, 1, 123).unwrap();
1944        let expected_last = NaiveTime::from_hms_milli_opt(23, 59, 59, 999).unwrap();
1945
1946        test_row_builder_basic(
1947            &time_array,
1948            vec![
1949                Some(Variant::from(expected_midnight)),
1950                None,
1951                Some(Variant::from(expected_time)),
1952                Some(Variant::from(expected_last)),
1953            ],
1954        );
1955    }
1956
1957    #[test]
1958    fn test_time64_microsecond_row_builder() {
1959        use arrow::array::Time64MicrosecondArray;
1960        use chrono::NaiveTime;
1961
1962        // Test Time64MicrosecondArray with various times (microseconds since midnight)
1963        let time_data = vec![
1964            Some(0), // 00:00:00.000000
1965            None,
1966            Some(3661123456),  // 01:01:01.123456
1967            Some(86399999999), // 23:59:59.999999
1968        ];
1969        let time_array = Time64MicrosecondArray::from(time_data);
1970
1971        let expected_midnight = NaiveTime::from_hms_micro_opt(0, 0, 0, 0).unwrap();
1972        let expected_time = NaiveTime::from_hms_micro_opt(1, 1, 1, 123456).unwrap();
1973        let expected_last = NaiveTime::from_hms_micro_opt(23, 59, 59, 999999).unwrap();
1974
1975        test_row_builder_basic(
1976            &time_array,
1977            vec![
1978                Some(Variant::from(expected_midnight)),
1979                None,
1980                Some(Variant::from(expected_time)),
1981                Some(Variant::from(expected_last)),
1982            ],
1983        );
1984    }
1985
1986    #[test]
1987    fn test_time64_nanosecond_row_builder() {
1988        use arrow::array::Time64NanosecondArray;
1989        use chrono::NaiveTime;
1990
1991        // Test Time64NanosecondArray with various times (nanoseconds since midnight)
1992        let time_data = vec![
1993            Some(0), // 00:00:00.000000000
1994            None,
1995            Some(3661123456789),  // 01:01:01.123456789
1996            Some(86399999999999), // 23:59:59.999999999
1997        ];
1998        let time_array = Time64NanosecondArray::from(time_data);
1999
2000        let expected_midnight = NaiveTime::from_hms_nano_opt(0, 0, 0, 0).unwrap();
2001        // Nanoseconds are truncated to microsecond precision in Variant
2002        let expected_time = NaiveTime::from_hms_micro_opt(1, 1, 1, 123456).unwrap();
2003        let expected_last = NaiveTime::from_hms_micro_opt(23, 59, 59, 999999).unwrap();
2004
2005        test_row_builder_basic(
2006            &time_array,
2007            vec![
2008                Some(Variant::from(expected_midnight)),
2009                None,
2010                Some(Variant::from(expected_time)),
2011                Some(Variant::from(expected_last)),
2012            ],
2013        );
2014    }
2015}