• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vortex-data / vortex / 16938362485

13 Aug 2025 01:15PM UTC coverage: 87.665% (-0.02%) from 87.684%
16938362485

push

github

web-flow
fix: Correctly convert arrow temporal arrays with timezone (#4227)

Signed-off-by: Robert Kruszewski <github@robertk.io>

27 of 28 new or added lines in 1 file covered. (96.43%)

28 existing lines in 1 file now uncovered.

56487 of 64435 relevant lines covered (87.67%)

627480.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.56
/vortex-array/src/arrow/convert.rs
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3

4
use std::sync::Arc;
5

6
use arrow_array::cast::{AsArray, as_null_array};
7
use arrow_array::types::{
8
    ByteArrayType, ByteViewType, Date32Type, Date64Type, Decimal128Type, Decimal256Type,
9
    Float16Type, Float32Type, Float64Type, Int8Type, Int16Type, Int32Type, Int64Type,
10
    Time32MillisecondType, Time32SecondType, Time64MicrosecondType, Time64NanosecondType,
11
    TimestampMicrosecondType, TimestampMillisecondType, TimestampNanosecondType,
12
    TimestampSecondType, UInt8Type, UInt16Type, UInt32Type, UInt64Type,
13
};
14
use arrow_array::{
15
    Array as ArrowArray, ArrowPrimitiveType, BooleanArray as ArrowBooleanArray, GenericByteArray,
16
    GenericByteViewArray, GenericListArray, NullArray as ArrowNullArray, OffsetSizeTrait,
17
    PrimitiveArray as ArrowPrimitiveArray, RecordBatch, StructArray as ArrowStructArray,
18
    make_array,
19
};
20
use arrow_buffer::buffer::{NullBuffer, OffsetBuffer};
21
use arrow_buffer::{ArrowNativeType, BooleanBuffer, Buffer as ArrowBuffer, ScalarBuffer};
22
use arrow_schema::{DataType, TimeUnit as ArrowTimeUnit};
23
use itertools::Itertools;
24
use vortex_buffer::{Alignment, Buffer, ByteBuffer};
25
use vortex_dtype::datetime::TimeUnit;
26
use vortex_dtype::{DType, DecimalDType, NativePType, PType};
27
use vortex_error::{VortexExpect as _, vortex_panic};
28
use vortex_scalar::i256;
29

30
use crate::arrays::{
31
    BoolArray, DecimalArray, ListArray, NullArray, PrimitiveArray, StructArray, TemporalArray,
32
    VarBinArray, VarBinViewArray,
33
};
34
use crate::arrow::FromArrowArray;
35
use crate::validity::Validity;
36
use crate::{ArrayRef, IntoArray};
37

38
impl IntoArray for ArrowBuffer {
39
    fn into_array(self) -> ArrayRef {
1✔
40
        PrimitiveArray::from_byte_buffer(
1✔
41
            ByteBuffer::from_arrow_buffer(self, Alignment::of::<u8>()),
1✔
42
            PType::U8,
1✔
43
            Validity::NonNullable,
1✔
44
        )
1✔
45
        .into_array()
1✔
46
    }
1✔
47
}
48

49
impl IntoArray for BooleanBuffer {
50
    fn into_array(self) -> ArrayRef {
1✔
51
        BoolArray::new(self, Validity::NonNullable).into_array()
1✔
52
    }
1✔
53
}
54

55
impl<T> IntoArray for ScalarBuffer<T>
56
where
57
    T: ArrowNativeType + NativePType,
58
{
59
    fn into_array(self) -> ArrayRef {
1✔
60
        PrimitiveArray::new(
1✔
61
            Buffer::<T>::from_arrow_scalar_buffer(self),
1✔
62
            Validity::NonNullable,
1✔
63
        )
1✔
64
        .into_array()
1✔
65
    }
1✔
66
}
67

68
impl<O> IntoArray for OffsetBuffer<O>
69
where
70
    O: NativePType + OffsetSizeTrait,
71
{
72
    fn into_array(self) -> ArrayRef {
106✔
73
        let primitive = PrimitiveArray::new(
106✔
74
            Buffer::from_arrow_scalar_buffer(self.into_inner()),
106✔
75
            Validity::NonNullable,
106✔
76
        );
77

78
        primitive.into_array()
106✔
79
    }
106✔
80
}
81

82
macro_rules! impl_from_arrow_primitive {
83
    ($ty:path) => {
84
        impl FromArrowArray<&ArrowPrimitiveArray<$ty>> for ArrayRef {
85
            fn from_arrow(value: &ArrowPrimitiveArray<$ty>, nullable: bool) -> Self {
88,699✔
86
                let buffer = Buffer::from_arrow_scalar_buffer(value.values().clone());
88,699✔
87
                let validity = nulls(value.nulls(), nullable);
88,699✔
88
                PrimitiveArray::new(buffer, validity).into_array()
88,699✔
89
            }
88,699✔
90
        }
91
    };
92
}
93

94
impl_from_arrow_primitive!(Int8Type);
95
impl_from_arrow_primitive!(Int16Type);
96
impl_from_arrow_primitive!(Int32Type);
97
impl_from_arrow_primitive!(Int64Type);
98
impl_from_arrow_primitive!(UInt8Type);
99
impl_from_arrow_primitive!(UInt16Type);
100
impl_from_arrow_primitive!(UInt32Type);
101
impl_from_arrow_primitive!(UInt64Type);
102
impl_from_arrow_primitive!(Float16Type);
103
impl_from_arrow_primitive!(Float32Type);
104
impl_from_arrow_primitive!(Float64Type);
105

106
impl FromArrowArray<&ArrowPrimitiveArray<Decimal128Type>> for ArrayRef {
107
    fn from_arrow(array: &ArrowPrimitiveArray<Decimal128Type>, nullable: bool) -> Self {
60✔
108
        let decimal_type = DecimalDType::new(array.precision(), array.scale());
60✔
109
        let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
60✔
110
        let validity = nulls(array.nulls(), nullable);
60✔
111
        DecimalArray::new(buffer, decimal_type, validity).into_array()
60✔
112
    }
60✔
113
}
114

115
impl FromArrowArray<&ArrowPrimitiveArray<Decimal256Type>> for ArrayRef {
116
    fn from_arrow(array: &ArrowPrimitiveArray<Decimal256Type>, nullable: bool) -> Self {
2✔
117
        let decimal_type = DecimalDType::new(array.precision(), array.scale());
2✔
118
        let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
2✔
119
        // SAFETY: Our i256 implementation has the same bit-pattern representation of the
120
        //  arrow_buffer::i256 type. It is safe to treat values held inside the buffer as values
121
        //  of either type.
122
        let buffer =
2✔
123
            unsafe { std::mem::transmute::<Buffer<arrow_buffer::i256>, Buffer<i256>>(buffer) };
2✔
124
        let validity = nulls(array.nulls(), nullable);
2✔
125
        DecimalArray::new(buffer, decimal_type, validity).into_array()
2✔
126
    }
2✔
127
}
128

129
macro_rules! impl_from_arrow_temporal {
130
    ($ty:path) => {
131
        impl FromArrowArray<&ArrowPrimitiveArray<$ty>> for ArrayRef {
132
            fn from_arrow(value: &ArrowPrimitiveArray<$ty>, nullable: bool) -> Self {
121✔
133
                temporal_array(value, nullable)
121✔
134
            }
121✔
135
        }
136
    };
137
}
138

139
// timestamp
140
impl_from_arrow_temporal!(TimestampSecondType);
141
impl_from_arrow_temporal!(TimestampMillisecondType);
142
impl_from_arrow_temporal!(TimestampMicrosecondType);
143
impl_from_arrow_temporal!(TimestampNanosecondType);
144

145
// time
146
impl_from_arrow_temporal!(Time32SecondType);
147
impl_from_arrow_temporal!(Time32MillisecondType);
148
impl_from_arrow_temporal!(Time64MicrosecondType);
149
impl_from_arrow_temporal!(Time64NanosecondType);
150

151
// date
152
impl_from_arrow_temporal!(Date32Type);
153
impl_from_arrow_temporal!(Date64Type);
154

155
fn temporal_array<T: ArrowPrimitiveType>(value: &ArrowPrimitiveArray<T>, nullable: bool) -> ArrayRef
121✔
156
where
121✔
157
    T::Native: NativePType,
121✔
158
{
159
    let arr = PrimitiveArray::new(
121✔
160
        Buffer::from_arrow_scalar_buffer(value.values().clone()),
121✔
161
        nulls(value.nulls(), nullable),
121✔
162
    )
163
    .into_array();
121✔
164

165
    match value.data_type() {
121✔
166
        DataType::Timestamp(time_unit, tz) => {
88✔
167
            let tz = tz.as_ref().map(|s| s.to_string());
88✔
168
            TemporalArray::new_timestamp(arr, time_unit.into(), tz).into()
88✔
169
        }
170
        DataType::Time32(time_unit) => TemporalArray::new_time(arr, time_unit.into()).into(),
4✔
171
        DataType::Time64(time_unit) => TemporalArray::new_time(arr, time_unit.into()).into(),
4✔
172
        DataType::Date32 => TemporalArray::new_date(arr, TimeUnit::D).into(),
23✔
173
        DataType::Date64 => TemporalArray::new_date(arr, TimeUnit::Ms).into(),
2✔
174
        DataType::Duration(_) => unimplemented!(),
×
175
        DataType::Interval(_) => unimplemented!(),
×
NEW
176
        _ => vortex_panic!("Invalid temporal type: {}", value.data_type()),
×
177
    }
178
}
121✔
179

180
impl<T: ByteArrayType> FromArrowArray<&GenericByteArray<T>> for ArrayRef
181
where
182
    <T as ByteArrayType>::Offset: NativePType,
183
{
184
    fn from_arrow(value: &GenericByteArray<T>, nullable: bool) -> Self {
92✔
185
        let dtype = match T::DATA_TYPE {
92✔
186
            DataType::Binary | DataType::LargeBinary => DType::Binary(nullable.into()),
4✔
187
            DataType::Utf8 | DataType::LargeUtf8 => DType::Utf8(nullable.into()),
88✔
188
            _ => vortex_panic!("Invalid data type for ByteArray: {}", T::DATA_TYPE),
×
189
        };
190
        VarBinArray::try_new(
92✔
191
            value.offsets().clone().into_array(),
92✔
192
            ByteBuffer::from_arrow_buffer(value.values().clone(), Alignment::of::<u8>()),
92✔
193
            dtype,
92✔
194
            nulls(value.nulls(), nullable),
92✔
195
        )
92✔
196
        .vortex_expect("Failed to convert Arrow GenericByteArray to Vortex VarBinArray")
92✔
197
        .into_array()
92✔
198
    }
92✔
199
}
200

201
impl<T: ByteViewType> FromArrowArray<&GenericByteViewArray<T>> for ArrayRef {
202
    fn from_arrow(value: &GenericByteViewArray<T>, nullable: bool) -> Self {
3,537✔
203
        let dtype = match T::DATA_TYPE {
3,537✔
204
            DataType::BinaryView => DType::Binary(nullable.into()),
61✔
205
            DataType::Utf8View => DType::Utf8(nullable.into()),
3,476✔
206
            _ => vortex_panic!("Invalid data type for ByteViewArray: {}", T::DATA_TYPE),
×
207
        };
208

209
        let views_buffer = Buffer::from_byte_buffer(
3,537✔
210
            Buffer::from_arrow_scalar_buffer(value.views().clone()).into_byte_buffer(),
3,537✔
211
        );
212

213
        VarBinViewArray::try_new(
3,537✔
214
            views_buffer,
3,537✔
215
            Arc::from(
3,537✔
216
                value
3,537✔
217
                    .data_buffers()
3,537✔
218
                    .iter()
3,537✔
219
                    .map(|b| ByteBuffer::from_arrow_buffer(b.clone(), Alignment::of::<u8>()))
3,798✔
220
                    .collect::<Vec<_>>(),
3,537✔
221
            ),
222
            dtype,
3,537✔
223
            nulls(value.nulls(), nullable),
3,537✔
224
        )
225
        .vortex_expect("Failed to convert Arrow GenericByteViewArray to Vortex VarBinViewArray")
3,537✔
226
        .into_array()
3,537✔
227
    }
3,537✔
228
}
229

230
impl FromArrowArray<&ArrowBooleanArray> for ArrayRef {
231
    fn from_arrow(value: &ArrowBooleanArray, nullable: bool) -> Self {
52,204✔
232
        BoolArray::new(value.values().clone(), nulls(value.nulls(), nullable)).into_array()
52,204✔
233
    }
52,204✔
234
}
235

236
/// Strip out the nulls from this array and return a new array without nulls.
237
fn remove_nulls(data: arrow_data::ArrayData) -> arrow_data::ArrayData {
4✔
238
    if data.null_count() == 0 {
4✔
239
        // No nulls to remove, return the array as is
240
        return data;
×
241
    }
4✔
242

243
    let children = match data.data_type() {
4✔
244
        DataType::Struct(fields) => Some(
1✔
245
            fields
1✔
246
                .iter()
1✔
247
                .zip(data.child_data().iter())
1✔
248
                .map(|(field, child_data)| {
1✔
249
                    if field.is_nullable() {
1✔
250
                        child_data.clone()
×
251
                    } else {
252
                        remove_nulls(child_data.clone())
1✔
253
                    }
254
                })
1✔
255
                .collect_vec(),
1✔
256
        ),
257
        DataType::List(f)
×
258
        | DataType::LargeList(f)
×
259
        | DataType::ListView(f)
×
260
        | DataType::LargeListView(f)
×
261
        | DataType::FixedSizeList(f, _)
×
262
            if !f.is_nullable() =>
×
263
        {
264
            // All list types only have one child
265
            assert_eq!(
×
266
                data.child_data().len(),
×
267
                1,
268
                "List types should have one child"
×
269
            );
270
            Some(vec![remove_nulls(data.child_data()[0].clone())])
×
271
        }
272
        _ => None,
3✔
273
    };
274

275
    let mut builder = data.into_builder().nulls(None);
4✔
276
    if let Some(children) = children {
4✔
277
        builder = builder.child_data(children);
1✔
278
    }
3✔
279
    builder
4✔
280
        .build()
4✔
281
        .vortex_expect("reconstructing array without nulls")
4✔
282
}
4✔
283

284
impl FromArrowArray<&ArrowStructArray> for ArrayRef {
285
    fn from_arrow(value: &ArrowStructArray, nullable: bool) -> Self {
192✔
286
        StructArray::try_new(
192✔
287
            value.column_names().iter().copied().collect(),
192✔
288
            value
192✔
289
                .columns()
192✔
290
                .iter()
192✔
291
                .zip(value.fields())
192✔
292
                .map(|(c, field)| {
1,220✔
293
                    // Arrow pushes down nulls, even into non-nullable fields. So we strip them
294
                    // out here because Vortex is a little more strict.
295
                    if c.null_count() > 0 && !field.is_nullable() {
1,220✔
296
                        let stripped = make_array(remove_nulls(c.into_data()));
3✔
297
                        Self::from_arrow(stripped.as_ref(), false)
3✔
298
                    } else {
299
                        Self::from_arrow(c.as_ref(), field.is_nullable())
1,217✔
300
                    }
301
                })
1,220✔
302
                .collect(),
192✔
303
            value.len(),
192✔
304
            nulls(value.nulls(), nullable),
192✔
305
        )
306
        .vortex_expect("Failed to convert Arrow StructArray to Vortex StructArray")
192✔
307
        .into_array()
192✔
308
    }
192✔
309
}
310

311
impl<O: OffsetSizeTrait + NativePType> FromArrowArray<&GenericListArray<O>> for ArrayRef {
312
    fn from_arrow(value: &GenericListArray<O>, nullable: bool) -> Self {
13✔
313
        // Extract the validity of the underlying element array
314
        let elem_nullable = match value.data_type() {
13✔
315
            DataType::List(field) => field.is_nullable(),
11✔
316
            DataType::LargeList(field) => field.is_nullable(),
2✔
317
            dt => vortex_panic!("Invalid data type for ListArray: {dt}"),
×
318
        };
319
        ListArray::try_new(
13✔
320
            Self::from_arrow(value.values().as_ref(), elem_nullable),
13✔
321
            // offsets are always non-nullable
13✔
322
            value.offsets().clone().into_array(),
13✔
323
            nulls(value.nulls(), nullable),
13✔
324
        )
13✔
325
        .vortex_expect("Failed to convert Arrow StructArray to Vortex StructArray")
13✔
326
        .into_array()
13✔
327
    }
13✔
328
}
329

330
impl FromArrowArray<&ArrowNullArray> for ArrayRef {
331
    fn from_arrow(value: &ArrowNullArray, nullable: bool) -> Self {
1✔
332
        assert!(nullable);
1✔
333
        NullArray::new(value.len()).into_array()
1✔
334
    }
1✔
335
}
336

337
fn nulls(nulls: Option<&NullBuffer>, nullable: bool) -> Validity {
144,919✔
338
    if nullable {
144,919✔
339
        nulls
38,326✔
340
            .map(|nulls| {
38,326✔
341
                if nulls.null_count() == nulls.len() {
20,404✔
342
                    Validity::AllInvalid
719✔
343
                } else {
344
                    Validity::from(nulls.inner().clone())
19,685✔
345
                }
346
            })
20,404✔
347
            .unwrap_or_else(|| Validity::AllValid)
38,326✔
348
    } else {
349
        assert!(nulls.map(|x| x.null_count() == 0).unwrap_or(true));
106,593✔
350
        Validity::NonNullable
106,593✔
351
    }
352
}
144,919✔
353

354
impl FromArrowArray<&dyn ArrowArray> for ArrayRef {
355
    fn from_arrow(array: &dyn ArrowArray, nullable: bool) -> Self {
90,400✔
356
        match array.data_type() {
90,400✔
357
            DataType::Boolean => Self::from_arrow(array.as_boolean(), nullable),
4✔
358
            DataType::UInt8 => Self::from_arrow(array.as_primitive::<UInt8Type>(), nullable),
1,995✔
359
            DataType::UInt16 => Self::from_arrow(array.as_primitive::<UInt16Type>(), nullable),
3,640✔
360
            DataType::UInt32 => Self::from_arrow(array.as_primitive::<UInt32Type>(), nullable),
6,046✔
361
            DataType::UInt64 => Self::from_arrow(array.as_primitive::<UInt64Type>(), nullable),
10,695✔
362
            DataType::Int8 => Self::from_arrow(array.as_primitive::<Int8Type>(), nullable),
786✔
363
            DataType::Int16 => Self::from_arrow(array.as_primitive::<Int16Type>(), nullable),
1,137✔
364
            DataType::Int32 => Self::from_arrow(array.as_primitive::<Int32Type>(), nullable),
19,673✔
365
            DataType::Int64 => Self::from_arrow(array.as_primitive::<Int64Type>(), nullable),
6,397✔
366
            DataType::Float16 => Self::from_arrow(array.as_primitive::<Float16Type>(), nullable),
5✔
367
            DataType::Float32 => Self::from_arrow(array.as_primitive::<Float32Type>(), nullable),
17,905✔
368
            DataType::Float64 => Self::from_arrow(array.as_primitive::<Float64Type>(), nullable),
18,331✔
369
            DataType::Utf8 => Self::from_arrow(array.as_string::<i32>(), nullable),
45✔
370
            DataType::LargeUtf8 => Self::from_arrow(array.as_string::<i64>(), nullable),
39✔
371
            DataType::Binary => Self::from_arrow(array.as_binary::<i32>(), nullable),
×
372
            DataType::LargeBinary => Self::from_arrow(array.as_binary::<i64>(), nullable),
×
373
            DataType::BinaryView => Self::from_arrow(array.as_binary_view(), nullable),
59✔
374
            DataType::Utf8View => Self::from_arrow(array.as_string_view(), nullable),
3,474✔
375
            DataType::Struct(_) => Self::from_arrow(array.as_struct(), nullable),
4✔
376
            DataType::List(_) => Self::from_arrow(array.as_list::<i32>(), nullable),
8✔
377
            DataType::LargeList(_) => Self::from_arrow(array.as_list::<i64>(), nullable),
×
378
            DataType::Null => Self::from_arrow(as_null_array(array), nullable),
×
379
            DataType::Timestamp(u, _) => match u {
78✔
380
                ArrowTimeUnit::Second => {
381
                    Self::from_arrow(array.as_primitive::<TimestampSecondType>(), nullable)
×
382
                }
383
                ArrowTimeUnit::Millisecond => {
384
                    Self::from_arrow(array.as_primitive::<TimestampMillisecondType>(), nullable)
×
385
                }
386
                ArrowTimeUnit::Microsecond => {
387
                    Self::from_arrow(array.as_primitive::<TimestampMicrosecondType>(), nullable)
78✔
388
                }
389
                ArrowTimeUnit::Nanosecond => {
390
                    Self::from_arrow(array.as_primitive::<TimestampNanosecondType>(), nullable)
×
391
                }
392
            },
393
            DataType::Date32 => Self::from_arrow(array.as_primitive::<Date32Type>(), nullable),
21✔
394
            DataType::Date64 => Self::from_arrow(array.as_primitive::<Date64Type>(), nullable),
×
395
            DataType::Time32(u) => match u {
×
396
                ArrowTimeUnit::Second => {
397
                    Self::from_arrow(array.as_primitive::<Time32SecondType>(), nullable)
×
398
                }
399
                ArrowTimeUnit::Millisecond => {
400
                    Self::from_arrow(array.as_primitive::<Time32MillisecondType>(), nullable)
×
401
                }
402
                _ => unreachable!(),
×
403
            },
404
            DataType::Time64(u) => match u {
×
405
                ArrowTimeUnit::Microsecond => {
406
                    Self::from_arrow(array.as_primitive::<Time64MicrosecondType>(), nullable)
×
407
                }
408
                ArrowTimeUnit::Nanosecond => {
409
                    Self::from_arrow(array.as_primitive::<Time64NanosecondType>(), nullable)
×
410
                }
411
                _ => unreachable!(),
×
412
            },
413
            DataType::Decimal128(..) => {
414
                Self::from_arrow(array.as_primitive::<Decimal128Type>(), nullable)
58✔
415
            }
416
            DataType::Decimal256(..) => {
417
                Self::from_arrow(array.as_primitive::<Decimal256Type>(), nullable)
×
418
            }
419
            _ => vortex_panic!(
×
420
                "Array encoding not implemented for Arrow data type {}",
×
421
                array.data_type().clone()
×
422
            ),
423
        }
424
    }
90,400✔
425
}
426

427
impl FromArrowArray<RecordBatch> for ArrayRef {
428
    fn from_arrow(array: RecordBatch, nullable: bool) -> Self {
146✔
429
        ArrayRef::from_arrow(&arrow_array::StructArray::from(array), nullable)
146✔
430
    }
146✔
431
}
432

433
impl FromArrowArray<&RecordBatch> for ArrayRef {
434
    fn from_arrow(array: &RecordBatch, nullable: bool) -> Self {
28✔
435
        Self::from_arrow(array.clone(), nullable)
28✔
436
    }
28✔
437
}
438

439
#[cfg(test)]
440
mod tests {
441
    use std::sync::Arc;
442

443
    use arrow_array::builder::{
444
        BinaryViewBuilder, Decimal128Builder, Decimal256Builder, Int32Builder, LargeListBuilder,
445
        ListBuilder, StringViewBuilder,
446
    };
447
    use arrow_array::types::{ArrowPrimitiveType, Float16Type};
448
    use arrow_array::{
449
        Array as ArrowArray, BinaryArray, BooleanArray, Date32Array, Date64Array, Float32Array,
450
        Float64Array, Int8Array, Int16Array, Int32Array, Int64Array, LargeBinaryArray,
451
        LargeStringArray, NullArray, RecordBatch, StringArray, StructArray, Time32MillisecondArray,
452
        Time32SecondArray, Time64MicrosecondArray, Time64NanosecondArray,
453
        TimestampMicrosecondArray, TimestampMillisecondArray, TimestampNanosecondArray,
454
        TimestampSecondArray, UInt8Array, UInt16Array, UInt32Array, UInt64Array, new_null_array,
455
    };
456
    use arrow_buffer::{BooleanBuffer, Buffer as ArrowBuffer, OffsetBuffer, ScalarBuffer};
457
    use arrow_schema::{DataType, Field, Fields, Schema};
458
    use vortex_dtype::datetime::{TIMESTAMP_ID, TemporalMetadata, TimeUnit};
459
    use vortex_dtype::{DType, ExtDType, Nullability, PType};
460

461
    use crate::arrays::{
462
        DecimalVTable, ListVTable, PrimitiveVTable, StructVTable, TemporalArray, VarBinVTable,
463
        VarBinViewVTable,
464
    };
465
    use crate::arrow::FromArrowArray as _;
466
    use crate::{ArrayRef, IntoArray};
467

468
    // Test primitive array conversions
469
    #[test]
470
    fn test_int8_array_conversion() {
1✔
471
        let arrow_array = Int8Array::from(vec![Some(1), None, Some(3), Some(4)]);
1✔
472
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
473

474
        let arrow_array_non_null = Int8Array::from(vec![1, 2, 3, 4]);
1✔
475
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
476

477
        assert_eq!(vortex_array.len(), 4);
1✔
478
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
479

480
        // Verify metadata - should be PrimitiveArray with I8 ptype
481
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
482
        assert_eq!(primitive_array.ptype(), PType::I8);
1✔
483

484
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
485
        assert_eq!(primitive_array_non_null.ptype(), PType::I8);
1✔
486
    }
1✔
487

488
    #[test]
489
    fn test_int16_array_conversion() {
1✔
490
        let arrow_array = Int16Array::from(vec![Some(100), None, Some(300), Some(400)]);
1✔
491
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
492

493
        let arrow_array_non_null = Int16Array::from(vec![100, 200, 300, 400]);
1✔
494
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
495

496
        assert_eq!(vortex_array.len(), 4);
1✔
497
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
498

499
        // Verify metadata - should be PrimitiveArray with I16 ptype
500
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
501
        assert_eq!(primitive_array.ptype(), PType::I16);
1✔
502

503
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
504
        assert_eq!(primitive_array_non_null.ptype(), PType::I16);
1✔
505
    }
1✔
506

507
    #[test]
508
    fn test_int32_array_conversion() {
1✔
509
        let arrow_array = Int32Array::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
510
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
511

512
        let arrow_array_non_null = Int32Array::from(vec![1000, 2000, 3000, 4000]);
1✔
513
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
514

515
        assert_eq!(vortex_array.len(), 4);
1✔
516
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
517

518
        // Verify metadata - should be PrimitiveArray with I32 ptype
519
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
520
        assert_eq!(primitive_array.ptype(), PType::I32);
1✔
521

522
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
523
        assert_eq!(primitive_array_non_null.ptype(), PType::I32);
1✔
524
    }
1✔
525

526
    #[test]
527
    fn test_int64_array_conversion() {
1✔
528
        let arrow_array = Int64Array::from(vec![Some(10000), None, Some(30000), Some(40000)]);
1✔
529
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
530

531
        let arrow_array_non_null = Int64Array::from(vec![10000_i64, 20000, 30000, 40000]);
1✔
532
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
533

534
        assert_eq!(vortex_array.len(), 4);
1✔
535
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
536

537
        // Verify metadata - should be PrimitiveArray with I64 ptype
538
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
539
        assert_eq!(primitive_array.ptype(), PType::I64);
1✔
540

541
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
542
        assert_eq!(primitive_array_non_null.ptype(), PType::I64);
1✔
543
    }
1✔
544

545
    #[test]
546
    fn test_uint8_array_conversion() {
1✔
547
        let arrow_array = UInt8Array::from(vec![Some(1), None, Some(3), Some(4)]);
1✔
548
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
549

550
        let arrow_array_non_null = UInt8Array::from(vec![1_u8, 2, 3, 4]);
1✔
551
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
552

553
        assert_eq!(vortex_array.len(), 4);
1✔
554
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
555

556
        // Verify metadata - should be PrimitiveArray with U8 ptype
557
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
558
        assert_eq!(primitive_array.ptype(), PType::U8);
1✔
559

560
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
561
        assert_eq!(primitive_array_non_null.ptype(), PType::U8);
1✔
562
    }
1✔
563

564
    #[test]
565
    fn test_uint16_array_conversion() {
1✔
566
        let arrow_array = UInt16Array::from(vec![Some(100), None, Some(300), Some(400)]);
1✔
567
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
568

569
        let arrow_array_non_null = UInt16Array::from(vec![100_u16, 200, 300, 400]);
1✔
570
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
571

572
        assert_eq!(vortex_array.len(), 4);
1✔
573
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
574

575
        // Verify metadata - should be PrimitiveArray with U16 ptype
576
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
577
        assert_eq!(primitive_array.ptype(), PType::U16);
1✔
578

579
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
580
        assert_eq!(primitive_array_non_null.ptype(), PType::U16);
1✔
581
    }
1✔
582

583
    #[test]
584
    fn test_uint32_array_conversion() {
1✔
585
        let arrow_array = UInt32Array::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
586
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
587

588
        let arrow_array_non_null = UInt32Array::from(vec![1000_u32, 2000, 3000, 4000]);
1✔
589
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
590

591
        assert_eq!(vortex_array.len(), 4);
1✔
592
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
593

594
        // Verify metadata - should be PrimitiveArray with U32 ptype
595
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
596
        assert_eq!(primitive_array.ptype(), PType::U32);
1✔
597

598
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
599
        assert_eq!(primitive_array_non_null.ptype(), PType::U32);
1✔
600
    }
1✔
601

602
    #[test]
603
    fn test_uint64_array_conversion() {
1✔
604
        let arrow_array = UInt64Array::from(vec![Some(10000), None, Some(30000), Some(40000)]);
1✔
605
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
606

607
        let arrow_array_non_null = UInt64Array::from(vec![10000_u64, 20000, 30000, 40000]);
1✔
608
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
609

610
        assert_eq!(vortex_array.len(), 4);
1✔
611
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
612

613
        // Verify metadata - should be PrimitiveArray with U64 ptype
614
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
615
        assert_eq!(primitive_array.ptype(), PType::U64);
1✔
616

617
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
618
        assert_eq!(primitive_array_non_null.ptype(), PType::U64);
1✔
619
    }
1✔
620

621
    #[test]
622
    fn test_float16_array_conversion() {
1✔
623
        let values = vec![
1✔
624
            Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5)),
1✔
625
            None,
1✔
626
            Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(3.5)),
1✔
627
        ];
628
        let arrow_array = arrow_array::PrimitiveArray::<Float16Type>::from(values);
1✔
629
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
630

631
        let non_null_values = vec![
1✔
632
            <Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5),
1✔
633
            <Float16Type as ArrowPrimitiveType>::Native::from_f32(2.5),
1✔
634
        ];
635
        let arrow_array_non_null =
1✔
636
            arrow_array::PrimitiveArray::<Float16Type>::from(non_null_values);
1✔
637
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
638

639
        assert_eq!(vortex_array.len(), 3);
1✔
640
        assert_eq!(vortex_array_non_null.len(), 2);
1✔
641

642
        // Verify metadata - should be PrimitiveArray with F16 ptype
643
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
644
        assert_eq!(primitive_array.ptype(), PType::F16);
1✔
645

646
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
647
        assert_eq!(primitive_array_non_null.ptype(), PType::F16);
1✔
648
    }
1✔
649

650
    #[test]
651
    fn test_float32_array_conversion() {
1✔
652
        let arrow_array = Float32Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)]);
1✔
653
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
654

655
        let arrow_array_non_null = Float32Array::from(vec![1.5_f32, 2.5, 3.5, 4.5]);
1✔
656
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
657

658
        assert_eq!(vortex_array.len(), 4);
1✔
659
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
660

661
        // Verify metadata - should be PrimitiveArray with F32 ptype
662
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
663
        assert_eq!(primitive_array.ptype(), PType::F32);
1✔
664

665
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
666
        assert_eq!(primitive_array_non_null.ptype(), PType::F32);
1✔
667
    }
1✔
668

669
    #[test]
670
    fn test_float64_array_conversion() {
1✔
671
        let arrow_array = Float64Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)]);
1✔
672
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
673

674
        let arrow_array_non_null = Float64Array::from(vec![1.5_f64, 2.5, 3.5, 4.5]);
1✔
675
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
676

677
        assert_eq!(vortex_array.len(), 4);
1✔
678
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
679

680
        // Verify metadata - should be PrimitiveArray with F64 ptype
681
        let primitive_array = vortex_array.as_::<PrimitiveVTable>();
1✔
682
        assert_eq!(primitive_array.ptype(), PType::F64);
1✔
683

684
        let primitive_array_non_null = vortex_array_non_null.as_::<PrimitiveVTable>();
1✔
685
        assert_eq!(primitive_array_non_null.ptype(), PType::F64);
1✔
686
    }
1✔
687

688
    // Test decimal array conversions
689
    #[test]
690
    fn test_decimal128_array_conversion() {
1✔
691
        let mut builder = Decimal128Builder::with_capacity(4);
1✔
692
        builder.append_value(12345);
1✔
693
        builder.append_null();
1✔
694
        builder.append_value(67890);
1✔
695
        builder.append_value(11111);
1✔
696
        let decimal_array = builder.finish().with_precision_and_scale(10, 2).unwrap();
1✔
697

698
        let vortex_array = ArrayRef::from_arrow(&decimal_array, true);
1✔
699
        assert_eq!(vortex_array.len(), 4);
1✔
700

701
        let mut builder_non_null = Decimal128Builder::with_capacity(3);
1✔
702
        builder_non_null.append_value(12345);
1✔
703
        builder_non_null.append_value(67890);
1✔
704
        builder_non_null.append_value(11111);
1✔
705
        let decimal_array_non_null = builder_non_null
1✔
706
            .finish()
1✔
707
            .with_precision_and_scale(10, 2)
1✔
708
            .unwrap();
1✔
709

710
        let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false);
1✔
711
        assert_eq!(vortex_array_non_null.len(), 3);
1✔
712

713
        // Verify metadata - should be DecimalArray with correct precision and scale
714
        let decimal_vortex_array = vortex_array.as_::<DecimalVTable>();
1✔
715
        assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 10);
1✔
716
        assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 2);
1✔
717

718
        let decimal_vortex_array_non_null = vortex_array_non_null.as_::<DecimalVTable>();
1✔
719
        assert_eq!(
1✔
720
            decimal_vortex_array_non_null.decimal_dtype().precision(),
1✔
721
            10
722
        );
723
        assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 2);
1✔
724
    }
1✔
725

726
    #[test]
727
    fn test_decimal256_array_conversion() {
1✔
728
        let mut builder = Decimal256Builder::with_capacity(4);
1✔
729
        builder.append_value(arrow_buffer::i256::from_i128(12345));
1✔
730
        builder.append_null();
1✔
731
        builder.append_value(arrow_buffer::i256::from_i128(67890));
1✔
732
        builder.append_value(arrow_buffer::i256::from_i128(11111));
1✔
733
        let decimal_array = builder.finish().with_precision_and_scale(38, 10).unwrap();
1✔
734

735
        let vortex_array = ArrayRef::from_arrow(&decimal_array, true);
1✔
736
        assert_eq!(vortex_array.len(), 4);
1✔
737

738
        let mut builder_non_null = Decimal256Builder::with_capacity(3);
1✔
739
        builder_non_null.append_value(arrow_buffer::i256::from_i128(12345));
1✔
740
        builder_non_null.append_value(arrow_buffer::i256::from_i128(67890));
1✔
741
        builder_non_null.append_value(arrow_buffer::i256::from_i128(11111));
1✔
742
        let decimal_array_non_null = builder_non_null
1✔
743
            .finish()
1✔
744
            .with_precision_and_scale(38, 10)
1✔
745
            .unwrap();
1✔
746

747
        let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false);
1✔
748
        assert_eq!(vortex_array_non_null.len(), 3);
1✔
749

750
        // Verify metadata - should be DecimalArray with correct precision and scale
751
        let decimal_vortex_array = vortex_array.as_::<DecimalVTable>();
1✔
752
        assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 38);
1✔
753
        assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 10);
1✔
754

755
        let decimal_vortex_array_non_null = vortex_array_non_null.as_::<DecimalVTable>();
1✔
756
        assert_eq!(
1✔
757
            decimal_vortex_array_non_null.decimal_dtype().precision(),
1✔
758
            38
759
        );
760
        assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 10);
1✔
761
    }
1✔
762

763
    // Test temporal array conversions
764
    #[test]
765
    fn test_timestamp_second_array_conversion() {
1✔
766
        let arrow_array =
1✔
767
            TimestampSecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
768
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
769

770
        let arrow_array_non_null = TimestampSecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1✔
771
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
772

773
        assert_eq!(vortex_array.len(), 4);
1✔
774
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
775

776
        // Verify metadata - should be TemporalArray with Second time unit
777
        let temporal_array = TemporalArray::try_from(vortex_array.clone()).unwrap();
1✔
778
        assert_eq!(temporal_array.temporal_metadata().time_unit(), TimeUnit::S);
1✔
779

780
        let temporal_array_non_null =
1✔
781
            TemporalArray::try_from(vortex_array_non_null.clone()).unwrap();
1✔
782
        assert_eq!(
1✔
783
            temporal_array_non_null.temporal_metadata().time_unit(),
1✔
784
            TimeUnit::S
785
        );
786
    }
1✔
787

788
    #[test]
789
    fn test_timestamp_millisecond_array_conversion() {
1✔
790
        let arrow_array =
1✔
791
            TimestampMillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
792
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
793

794
        let arrow_array_non_null =
1✔
795
            TimestampMillisecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1✔
796
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
797

798
        assert_eq!(vortex_array.len(), 4);
1✔
799
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
800
    }
1✔
801

802
    #[test]
803
    fn test_timestamp_microsecond_array_conversion() {
1✔
804
        let arrow_array =
1✔
805
            TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
806
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
807

808
        let arrow_array_non_null =
1✔
809
            TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1✔
810
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
811

812
        assert_eq!(vortex_array.len(), 4);
1✔
813
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
814
    }
1✔
815

816
    #[test]
817
    fn test_timestamp_timezone_microsecond_array_conversion() {
1✔
818
        let arrow_array =
1✔
819
            TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])
1✔
820
                .with_timezone("UTC");
1✔
821
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
822

823
        let arrow_array_non_null =
1✔
824
            TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]).with_timezone("UTC");
1✔
825
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
826

827
        assert_eq!(vortex_array.len(), 4);
1✔
828
        assert_eq!(
1✔
829
            vortex_array.dtype(),
1✔
830
            &DType::Extension(Arc::new(ExtDType::new(
1✔
831
                TIMESTAMP_ID.clone(),
1✔
832
                Arc::new(DType::Primitive(PType::I64, Nullability::Nullable)),
1✔
833
                Some(TemporalMetadata::Timestamp(TimeUnit::Us, Some("UTC".to_string())).into())
1✔
834
            )))
1✔
835
        );
836
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
837
        assert_eq!(
1✔
838
            vortex_array_non_null.dtype(),
1✔
839
            &DType::Extension(Arc::new(ExtDType::new(
1✔
840
                TIMESTAMP_ID.clone(),
1✔
841
                Arc::new(DType::Primitive(PType::I64, Nullability::NonNullable)),
1✔
842
                Some(TemporalMetadata::Timestamp(TimeUnit::Us, Some("UTC".to_string())).into())
1✔
843
            )))
1✔
844
        );
845
    }
1✔
846

847
    #[test]
848
    fn test_timestamp_nanosecond_array_conversion() {
1✔
849
        let arrow_array =
1✔
850
            TimestampNanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
851
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
852

853
        let arrow_array_non_null = TimestampNanosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1✔
854
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
855

856
        assert_eq!(vortex_array.len(), 4);
1✔
857
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
858
    }
1✔
859

860
    #[test]
861
    fn test_time32_second_array_conversion() {
1✔
862
        let arrow_array = Time32SecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
863
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
864

865
        let arrow_array_non_null = Time32SecondArray::from(vec![1000_i32, 2000, 3000, 4000]);
1✔
866
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
867

868
        assert_eq!(vortex_array.len(), 4);
1✔
869
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
870

871
        // Verify metadata - should be TemporalArray with Second time unit
872
        let temporal_array = TemporalArray::try_from(vortex_array.clone()).unwrap();
1✔
873
        assert_eq!(temporal_array.temporal_metadata().time_unit(), TimeUnit::S);
1✔
874

875
        let temporal_array_non_null =
1✔
876
            TemporalArray::try_from(vortex_array_non_null.clone()).unwrap();
1✔
877
        assert_eq!(
1✔
878
            temporal_array_non_null.temporal_metadata().time_unit(),
1✔
879
            TimeUnit::S
880
        );
881
    }
1✔
882

883
    #[test]
884
    fn test_time32_millisecond_array_conversion() {
1✔
885
        let arrow_array =
1✔
886
            Time32MillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
887
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
888

889
        let arrow_array_non_null = Time32MillisecondArray::from(vec![1000_i32, 2000, 3000, 4000]);
1✔
890
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
891

892
        assert_eq!(vortex_array.len(), 4);
1✔
893
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
894
    }
1✔
895

896
    #[test]
897
    fn test_time64_microsecond_array_conversion() {
1✔
898
        let arrow_array =
1✔
899
            Time64MicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
900
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
901

902
        let arrow_array_non_null = Time64MicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1✔
903
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
904

905
        assert_eq!(vortex_array.len(), 4);
1✔
906
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
907
    }
1✔
908

909
    #[test]
910
    fn test_time64_nanosecond_array_conversion() {
1✔
911
        let arrow_array =
1✔
912
            Time64NanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)]);
1✔
913
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
914

915
        let arrow_array_non_null = Time64NanosecondArray::from(vec![1000_i64, 2000, 3000, 4000]);
1✔
916
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
917

918
        assert_eq!(vortex_array.len(), 4);
1✔
919
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
920
    }
1✔
921

922
    #[test]
923
    fn test_date32_array_conversion() {
1✔
924
        let arrow_array = Date32Array::from(vec![Some(18000), None, Some(18002), Some(18003)]);
1✔
925
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
926

927
        let arrow_array_non_null = Date32Array::from(vec![18000_i32, 18001, 18002, 18003]);
1✔
928
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
929

930
        assert_eq!(vortex_array.len(), 4);
1✔
931
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
932
    }
1✔
933

934
    #[test]
935
    fn test_date64_array_conversion() {
1✔
936
        let arrow_array = Date64Array::from(vec![
1✔
937
            Some(1555200000000),
1✔
938
            None,
1✔
939
            Some(1555286400000),
1✔
940
            Some(1555372800000),
1✔
941
        ]);
942
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
943

944
        let arrow_array_non_null = Date64Array::from(vec![
1✔
945
            1555200000000_i64,
946
            1555213600000,
947
            1555286400000,
948
            1555372800000,
949
        ]);
950
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
951

952
        assert_eq!(vortex_array.len(), 4);
1✔
953
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
954
    }
1✔
955

956
    // Test string/binary array conversions
957
    #[test]
958
    fn test_utf8_array_conversion() {
1✔
959
        let arrow_array = StringArray::from(vec![Some("hello"), None, Some("world"), Some("test")]);
1✔
960
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
961

962
        let arrow_array_non_null = StringArray::from(vec!["hello", "world", "test", "vortex"]);
1✔
963
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
964

965
        assert_eq!(vortex_array.len(), 4);
1✔
966
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
967

968
        // Verify metadata - should be VarBinArray with Utf8 dtype
969
        let varbin_array = vortex_array.as_::<VarBinVTable>();
1✔
970
        assert_eq!(varbin_array.dtype(), &DType::Utf8(true.into()));
1✔
971

972
        let varbin_array_non_null = vortex_array_non_null.as_::<VarBinVTable>();
1✔
973
        assert_eq!(varbin_array_non_null.dtype(), &DType::Utf8(false.into()));
1✔
974
    }
1✔
975

976
    #[test]
977
    fn test_large_utf8_array_conversion() {
1✔
978
        let arrow_array =
1✔
979
            LargeStringArray::from(vec![Some("hello"), None, Some("world"), Some("test")]);
1✔
980
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
981

982
        let arrow_array_non_null = LargeStringArray::from(vec!["hello", "world", "test", "vortex"]);
1✔
983
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
984

985
        assert_eq!(vortex_array.len(), 4);
1✔
986
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
987
    }
1✔
988

989
    #[test]
990
    fn test_binary_array_conversion() {
1✔
991
        let arrow_array = BinaryArray::from(vec![
1✔
992
            Some("hello".as_bytes()),
1✔
993
            None,
1✔
994
            Some("world".as_bytes()),
1✔
995
            Some("test".as_bytes()),
1✔
996
        ]);
997
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
998

999
        let arrow_array_non_null = BinaryArray::from(vec![
1✔
1000
            "hello".as_bytes(),
1✔
1001
            "world".as_bytes(),
1✔
1002
            "test".as_bytes(),
1✔
1003
            "vortex".as_bytes(),
1✔
1004
        ]);
1005
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
1006

1007
        assert_eq!(vortex_array.len(), 4);
1✔
1008
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
1009
    }
1✔
1010

1011
    #[test]
1012
    fn test_large_binary_array_conversion() {
1✔
1013
        let arrow_array = LargeBinaryArray::from(vec![
1✔
1014
            Some("hello".as_bytes()),
1✔
1015
            None,
1✔
1016
            Some("world".as_bytes()),
1✔
1017
            Some("test".as_bytes()),
1✔
1018
        ]);
1019
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
1020

1021
        let arrow_array_non_null = LargeBinaryArray::from(vec![
1✔
1022
            "hello".as_bytes(),
1✔
1023
            "world".as_bytes(),
1✔
1024
            "test".as_bytes(),
1✔
1025
            "vortex".as_bytes(),
1✔
1026
        ]);
1027
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
1028

1029
        assert_eq!(vortex_array.len(), 4);
1✔
1030
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
1031
    }
1✔
1032

1033
    #[test]
1034
    fn test_utf8_view_array_conversion() {
1✔
1035
        let mut builder = StringViewBuilder::new();
1✔
1036
        builder.append_value("hello");
1✔
1037
        builder.append_null();
1✔
1038
        builder.append_value("world");
1✔
1039
        builder.append_value("test");
1✔
1040
        let arrow_array = builder.finish();
1✔
1041
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
1042

1043
        let mut builder_non_null = StringViewBuilder::new();
1✔
1044
        builder_non_null.append_value("hello");
1✔
1045
        builder_non_null.append_value("world");
1✔
1046
        builder_non_null.append_value("test");
1✔
1047
        builder_non_null.append_value("vortex");
1✔
1048
        let arrow_array_non_null = builder_non_null.finish();
1✔
1049
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
1050

1051
        assert_eq!(vortex_array.len(), 4);
1✔
1052
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
1053

1054
        // Verify metadata - should be VarBinViewArray with correct buffer count and dtype
1055
        let varbin_view_array = vortex_array.as_::<VarBinViewVTable>();
1✔
1056
        assert_eq!(
1✔
1057
            varbin_view_array.buffers().len(),
1✔
1058
            arrow_array.data_buffers().len()
1✔
1059
        );
1060
        assert_eq!(varbin_view_array.dtype(), &DType::Utf8(true.into()));
1✔
1061

1062
        let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinViewVTable>();
1✔
1063
        assert_eq!(
1✔
1064
            varbin_view_array_non_null.buffers().len(),
1✔
1065
            arrow_array_non_null.data_buffers().len()
1✔
1066
        );
1067
        assert_eq!(
1✔
1068
            varbin_view_array_non_null.dtype(),
1✔
1069
            &DType::Utf8(false.into())
1✔
1070
        );
1071
    }
1✔
1072

1073
    #[test]
1074
    fn test_binary_view_array_conversion() {
1✔
1075
        let mut builder = BinaryViewBuilder::new();
1✔
1076
        builder.append_value(b"hello");
1✔
1077
        builder.append_null();
1✔
1078
        builder.append_value(b"world");
1✔
1079
        builder.append_value(b"test");
1✔
1080
        let arrow_array = builder.finish();
1✔
1081
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
1082

1083
        let mut builder_non_null = BinaryViewBuilder::new();
1✔
1084
        builder_non_null.append_value(b"hello");
1✔
1085
        builder_non_null.append_value(b"world");
1✔
1086
        builder_non_null.append_value(b"test");
1✔
1087
        builder_non_null.append_value(b"vortex");
1✔
1088
        let arrow_array_non_null = builder_non_null.finish();
1✔
1089
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
1090

1091
        assert_eq!(vortex_array.len(), 4);
1✔
1092
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
1093

1094
        // Verify metadata - should be VarBinViewArray with correct buffer count and dtype
1095
        let varbin_view_array = vortex_array.as_::<VarBinViewVTable>();
1✔
1096
        assert_eq!(
1✔
1097
            varbin_view_array.buffers().len(),
1✔
1098
            arrow_array.data_buffers().len()
1✔
1099
        );
1100
        assert_eq!(varbin_view_array.dtype(), &DType::Binary(true.into()));
1✔
1101

1102
        let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinViewVTable>();
1✔
1103
        assert_eq!(
1✔
1104
            varbin_view_array_non_null.buffers().len(),
1✔
1105
            arrow_array_non_null.data_buffers().len()
1✔
1106
        );
1107
        assert_eq!(
1✔
1108
            varbin_view_array_non_null.dtype(),
1✔
1109
            &DType::Binary(false.into())
1✔
1110
        );
1111
    }
1✔
1112

1113
    // Test boolean array conversions
1114
    #[test]
1115
    fn test_boolean_array_conversion() {
1✔
1116
        let arrow_array = BooleanArray::from(vec![Some(true), None, Some(false), Some(true)]);
1✔
1117
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
1118

1119
        let arrow_array_non_null = BooleanArray::from(vec![true, false, true, false]);
1✔
1120
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
1121

1122
        assert_eq!(vortex_array.len(), 4);
1✔
1123
        assert_eq!(vortex_array_non_null.len(), 4);
1✔
1124
    }
1✔
1125

1126
    // Test struct array conversions
1127
    #[test]
1128
    fn test_struct_array_conversion() {
1✔
1129
        let fields = vec![
1✔
1130
            Field::new("field1", DataType::Int32, true),
1✔
1131
            Field::new("field2", DataType::Utf8, false),
1✔
1132
        ];
1133
        let schema = Fields::from(fields);
1✔
1134

1135
        let field1_data = Int32Array::from(vec![Some(1), None, Some(3)]);
1✔
1136
        let field2_data = StringArray::from(vec!["a", "b", "c"]);
1✔
1137

1138
        let arrow_array = StructArray::new(
1✔
1139
            schema.clone(),
1✔
1140
            vec![Arc::new(field1_data), Arc::new(field2_data)],
1✔
1141
            None,
1✔
1142
        );
1143

1144
        let vortex_array = ArrayRef::from_arrow(&arrow_array, false);
1✔
1145
        assert_eq!(vortex_array.len(), 3);
1✔
1146

1147
        // Verify metadata - should be StructArray with correct field names
1148
        let struct_vortex_array = vortex_array.as_::<StructVTable>();
1✔
1149
        assert_eq!(struct_vortex_array.names().len(), 2);
1✔
1150
        assert_eq!(struct_vortex_array.names()[0], "field1".into());
1✔
1151
        assert_eq!(struct_vortex_array.names()[1], "field2".into());
1✔
1152

1153
        // Test nullable struct
1154
        let nullable_array = StructArray::new(
1✔
1155
            schema,
1✔
1156
            vec![
1✔
1157
                Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])),
1✔
1158
                Arc::new(StringArray::from(vec!["a", "b", "c"])),
1✔
1159
            ],
1160
            Some(arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![
1✔
1161
                true, false, true,
1✔
1162
            ]))),
1✔
1163
        );
1164

1165
        let vortex_nullable_array = ArrayRef::from_arrow(&nullable_array, true);
1✔
1166
        assert_eq!(vortex_nullable_array.len(), 3);
1✔
1167

1168
        // Verify metadata for nullable struct
1169
        let struct_vortex_nullable_array = vortex_nullable_array.as_::<StructVTable>();
1✔
1170
        assert_eq!(struct_vortex_nullable_array.names().len(), 2);
1✔
1171
        assert_eq!(struct_vortex_nullable_array.names()[0], "field1".into());
1✔
1172
        assert_eq!(struct_vortex_nullable_array.names()[1], "field2".into());
1✔
1173
    }
1✔
1174

1175
    // Test list array conversions
1176
    #[test]
1177
    fn test_list_array_conversion() {
1✔
1178
        let mut builder = ListBuilder::new(Int32Builder::new());
1✔
1179
        builder.append_value([Some(1), None, Some(3)]);
1✔
1180
        builder.append_null();
1✔
1181
        builder.append_value([Some(4), Some(5)]);
1✔
1182
        let arrow_array = builder.finish();
1✔
1183

1184
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
1185
        assert_eq!(vortex_array.len(), 3);
1✔
1186

1187
        // Verify metadata - should be ListArray with correct offsets
1188
        let list_vortex_array = vortex_array.as_::<ListVTable>();
1✔
1189
        let offsets_array = list_vortex_array.offsets().as_::<PrimitiveVTable>();
1✔
1190
        assert_eq!(offsets_array.len(), 4); // n+1 offsets for n lists
1✔
1191
        assert_eq!(offsets_array.ptype(), PType::I32);
1✔
1192

1193
        // Test non-nullable list
1194
        let mut builder_non_null = ListBuilder::new(Int32Builder::new());
1✔
1195
        builder_non_null.append_value([Some(1), None, Some(3)]);
1✔
1196
        builder_non_null.append_value([Some(4), Some(5)]);
1✔
1197
        let arrow_array_non_null = builder_non_null.finish();
1✔
1198

1199
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
1200
        assert_eq!(vortex_array_non_null.len(), 2);
1✔
1201

1202
        // Verify metadata for non-nullable list
1203
        let list_vortex_array_non_null = vortex_array_non_null.as_::<ListVTable>();
1✔
1204
        let offsets_array_non_null = list_vortex_array_non_null
1✔
1205
            .offsets()
1✔
1206
            .as_::<PrimitiveVTable>();
1✔
1207
        assert_eq!(offsets_array_non_null.len(), 3); // n+1 offsets for n lists
1✔
1208
        assert_eq!(offsets_array_non_null.ptype(), PType::I32);
1✔
1209
    }
1✔
1210

1211
    #[test]
1212
    fn test_large_list_array_conversion() {
1✔
1213
        let mut builder = LargeListBuilder::new(Int32Builder::new());
1✔
1214
        builder.append_value([Some(1), None, Some(3)]);
1✔
1215
        builder.append_null();
1✔
1216
        builder.append_value([Some(4), Some(5)]);
1✔
1217
        let arrow_array = builder.finish();
1✔
1218

1219
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
1220
        assert_eq!(vortex_array.len(), 3);
1✔
1221

1222
        // Verify metadata - should be ListArray with correct offsets (I64 for large lists)
1223
        let list_vortex_array = vortex_array.as_::<ListVTable>();
1✔
1224
        let offsets_array = list_vortex_array.offsets().as_::<PrimitiveVTable>();
1✔
1225
        assert_eq!(offsets_array.len(), 4); // n+1 offsets for n lists
1✔
1226
        assert_eq!(offsets_array.ptype(), PType::I64); // Large lists use I64 offsets
1✔
1227

1228
        // Test non-nullable large list
1229
        let mut builder_non_null = LargeListBuilder::new(Int32Builder::new());
1✔
1230
        builder_non_null.append_value([Some(1), None, Some(3)]);
1✔
1231
        builder_non_null.append_value([Some(4), Some(5)]);
1✔
1232
        let arrow_array_non_null = builder_non_null.finish();
1✔
1233

1234
        let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false);
1✔
1235
        assert_eq!(vortex_array_non_null.len(), 2);
1✔
1236

1237
        // Verify metadata for non-nullable large list
1238
        let list_vortex_array_non_null = vortex_array_non_null.as_::<ListVTable>();
1✔
1239
        let offsets_array_non_null = list_vortex_array_non_null
1✔
1240
            .offsets()
1✔
1241
            .as_::<PrimitiveVTable>();
1✔
1242
        assert_eq!(offsets_array_non_null.len(), 3); // n+1 offsets for n lists
1✔
1243
        assert_eq!(offsets_array_non_null.ptype(), PType::I64); // Large lists use I64 offsets
1✔
1244
    }
1✔
1245

1246
    // Test null array conversions
1247
    #[test]
1248
    fn test_null_array_conversion() {
1✔
1249
        let arrow_array = NullArray::new(5);
1✔
1250
        let vortex_array = ArrayRef::from_arrow(&arrow_array, true);
1✔
1251
        assert_eq!(vortex_array.len(), 5);
1✔
1252
    }
1✔
1253

1254
    // Test buffer conversions
1255
    #[test]
1256
    fn test_arrow_buffer_conversion() {
1✔
1257
        let data = vec![1u8, 2, 3, 4, 5];
1✔
1258
        let arrow_buffer = ArrowBuffer::from_vec(data);
1✔
1259
        let vortex_array = arrow_buffer.into_array();
1✔
1260
        assert_eq!(vortex_array.len(), 5);
1✔
1261
    }
1✔
1262

1263
    #[test]
1264
    fn test_boolean_buffer_conversion() {
1✔
1265
        let data = vec![true, false, true, false, true];
1✔
1266
        let boolean_buffer = BooleanBuffer::from(data);
1✔
1267
        let vortex_array = boolean_buffer.into_array();
1✔
1268
        assert_eq!(vortex_array.len(), 5);
1✔
1269
    }
1✔
1270

1271
    #[test]
1272
    fn test_scalar_buffer_conversion() {
1✔
1273
        let data = vec![1i32, 2, 3, 4, 5];
1✔
1274
        let scalar_buffer = ScalarBuffer::from(data);
1✔
1275
        let vortex_array = scalar_buffer.into_array();
1✔
1276
        assert_eq!(vortex_array.len(), 5);
1✔
1277
    }
1✔
1278

1279
    #[test]
1280
    fn test_offset_buffer_conversion() {
1✔
1281
        let data = vec![0i32, 2, 5, 8, 10];
1✔
1282
        let offset_buffer = OffsetBuffer::new(ScalarBuffer::from(data));
1✔
1283
        let vortex_array = offset_buffer.into_array();
1✔
1284
        assert_eq!(vortex_array.len(), 5);
1✔
1285
    }
1✔
1286

1287
    // Test RecordBatch conversions
1288
    #[test]
1289
    fn test_record_batch_conversion() {
1✔
1290
        let schema = Arc::new(Schema::new(vec![
1✔
1291
            Field::new("field1", DataType::Int32, false),
1✔
1292
            Field::new("field2", DataType::Utf8, false),
1✔
1293
        ]));
1294

1295
        let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1✔
1296
        let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1✔
1297

1298
        let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1✔
1299

1300
        let vortex_array = ArrayRef::from_arrow(record_batch, false);
1✔
1301
        assert_eq!(vortex_array.len(), 4);
1✔
1302

1303
        // Test with reference
1304
        let schema = Arc::new(Schema::new(vec![
1✔
1305
            Field::new("field1", DataType::Int32, false),
1✔
1306
            Field::new("field2", DataType::Utf8, false),
1✔
1307
        ]));
1308

1309
        let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1✔
1310
        let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1✔
1311

1312
        let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1✔
1313

1314
        let vortex_array = ArrayRef::from_arrow(&record_batch, false);
1✔
1315
        assert_eq!(vortex_array.len(), 4);
1✔
1316
    }
1✔
1317

1318
    // Test dynamic dispatch conversion
1319
    #[test]
1320
    fn test_dyn_array_conversion() {
1✔
1321
        let int_array = Int32Array::from(vec![1, 2, 3, 4]);
1✔
1322
        let dyn_array: &dyn ArrowArray = &int_array;
1✔
1323
        let vortex_array = ArrayRef::from_arrow(dyn_array, false);
1✔
1324
        assert_eq!(vortex_array.len(), 4);
1✔
1325

1326
        let string_array = StringArray::from(vec!["a", "b", "c"]);
1✔
1327
        let dyn_array: &dyn ArrowArray = &string_array;
1✔
1328
        let vortex_array = ArrayRef::from_arrow(dyn_array, false);
1✔
1329
        assert_eq!(vortex_array.len(), 3);
1✔
1330

1331
        let bool_array = BooleanArray::from(vec![true, false, true]);
1✔
1332
        let dyn_array: &dyn ArrowArray = &bool_array;
1✔
1333
        let vortex_array = ArrayRef::from_arrow(dyn_array, false);
1✔
1334
        assert_eq!(vortex_array.len(), 3);
1✔
1335
    }
1✔
1336

1337
    // Existing tests
1338
    #[test]
1339
    pub fn nullable_may_contain_non_nullable() {
1✔
1340
        let null_struct_array_with_non_nullable_field = new_null_array(
1✔
1341
            &DataType::Struct(Fields::from(vec![Field::new(
1✔
1342
                "non_nullable_inner",
1✔
1343
                DataType::Int32,
1✔
1344
                false,
1✔
1345
            )])),
1✔
1346
            1,
1347
        );
1348
        ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true);
1✔
1349
    }
1✔
1350

1351
    #[test]
1352
    pub fn nullable_may_contain_deeply_nested_non_nullable() {
1✔
1353
        let null_struct_array_with_non_nullable_field = new_null_array(
1✔
1354
            &DataType::Struct(Fields::from(vec![Field::new(
1✔
1355
                "non_nullable_inner",
1✔
1356
                DataType::Struct(Fields::from(vec![Field::new(
1✔
1357
                    "non_nullable_deeper_inner",
1✔
1358
                    DataType::Int32,
1✔
1359
                    false,
1✔
1360
                )])),
1✔
1361
                false,
1✔
1362
            )])),
1✔
1363
            1,
1364
        );
1365
        ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true);
1✔
1366
    }
1✔
1367

1368
    #[test]
1369
    #[should_panic]
1370
    pub fn cannot_handle_nullable_struct_containing_non_nullable_dictionary() {
1✔
1371
        let null_struct_array_with_non_nullable_field = new_null_array(
1✔
1372
            &DataType::Struct(Fields::from(vec![Field::new(
1✔
1373
                "non_nullable_deeper_inner",
1✔
1374
                DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1✔
1375
                false,
1✔
1376
            )])),
1✔
1377
            1,
1378
        );
1379

1380
        ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true);
1✔
1381
    }
1✔
1382
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc