1#![allow(deprecated)]
12
13use std::sync::Arc;
14
15use arrow_array::AnyDictionaryArray;
16use arrow_array::Array as ArrowArray;
17use arrow_array::ArrowPrimitiveType;
18use arrow_array::BooleanArray as ArrowBooleanArray;
19use arrow_array::DictionaryArray;
20use arrow_array::FixedSizeListArray as ArrowFixedSizeListArray;
21use arrow_array::GenericByteArray;
22use arrow_array::GenericByteViewArray;
23use arrow_array::GenericListArray;
24use arrow_array::GenericListViewArray;
25use arrow_array::MapArray as ArrowMapArray;
26use arrow_array::NullArray as ArrowNullArray;
27use arrow_array::OffsetSizeTrait;
28use arrow_array::PrimitiveArray as ArrowPrimitiveArray;
29use arrow_array::RecordBatch;
30use arrow_array::StructArray as ArrowStructArray;
31use arrow_array::cast::AsArray;
32use arrow_array::cast::as_null_array;
33use arrow_array::make_array;
34use arrow_array::types::ArrowDictionaryKeyType;
35use arrow_array::types::ByteArrayType;
36use arrow_array::types::ByteViewType;
37use arrow_array::types::Date32Type;
38use arrow_array::types::Date64Type;
39use arrow_array::types::Decimal32Type;
40use arrow_array::types::Decimal64Type;
41use arrow_array::types::Decimal128Type;
42use arrow_array::types::Decimal256Type;
43use arrow_array::types::Float16Type;
44use arrow_array::types::Float32Type;
45use arrow_array::types::Float64Type;
46use arrow_array::types::Int8Type;
47use arrow_array::types::Int16Type;
48use arrow_array::types::Int32Type;
49use arrow_array::types::Int64Type;
50use arrow_array::types::Time32MillisecondType;
51use arrow_array::types::Time32SecondType;
52use arrow_array::types::Time64MicrosecondType;
53use arrow_array::types::Time64NanosecondType;
54use arrow_array::types::TimestampMicrosecondType;
55use arrow_array::types::TimestampMillisecondType;
56use arrow_array::types::TimestampNanosecondType;
57use arrow_array::types::TimestampSecondType;
58use arrow_array::types::UInt8Type;
59use arrow_array::types::UInt16Type;
60use arrow_array::types::UInt32Type;
61use arrow_array::types::UInt64Type;
62use arrow_buffer::ArrowNativeType;
63use arrow_buffer::BooleanBuffer;
64use arrow_buffer::Buffer as ArrowBuffer;
65use arrow_buffer::ScalarBuffer;
66use arrow_buffer::buffer::NullBuffer;
67use arrow_buffer::buffer::OffsetBuffer;
68use arrow_schema::DataType;
69use arrow_schema::TimeUnit as ArrowTimeUnit;
70use vortex_array::ArrayRef;
71use vortex_array::IntoArray;
72use vortex_array::arrays::BoolArray;
73use vortex_array::arrays::DecimalArray;
74use vortex_array::arrays::DictArray;
75use vortex_array::arrays::FixedSizeListArray;
76use vortex_array::arrays::ListArray;
77use vortex_array::arrays::ListViewArray;
78use vortex_array::arrays::MapArray;
79use vortex_array::arrays::NullArray;
80use vortex_array::arrays::PrimitiveArray;
81use vortex_array::arrays::Struct;
82use vortex_array::arrays::StructArray;
83use vortex_array::arrays::TemporalArray;
84use vortex_array::arrays::VarBinArray;
85use vortex_array::arrays::VarBinViewArray;
86use vortex_array::arrays::struct_::StructArrayExt;
87use vortex_array::dtype::DType;
88use vortex_array::dtype::DecimalDType;
89use vortex_array::dtype::FieldNames;
90use vortex_array::dtype::IntegerPType;
91use vortex_array::dtype::MapDType;
92use vortex_array::dtype::NativePType;
93use vortex_array::dtype::Nullability;
94use vortex_array::dtype::PType;
95use vortex_array::dtype::i256;
96use vortex_array::extension::datetime::TimeUnit;
97use vortex_array::validity::Validity;
98use vortex_buffer::Alignment;
99use vortex_buffer::BitBuffer;
100use vortex_buffer::Buffer;
101use vortex_buffer::ByteBuffer;
102use vortex_error::VortexResult;
103use vortex_error::vortex_bail;
104use vortex_error::vortex_ensure;
105use vortex_error::vortex_ensure_eq;
106use vortex_error::vortex_err;
107use vortex_error::vortex_panic;
108
109use crate::FromArrowArray;
110use crate::dtype::from_arrow_time_unit;
111
112pub trait IntoVortexArray {
117 fn into_array(self) -> ArrayRef;
119}
120
121impl IntoVortexArray for ArrowBuffer {
122 fn into_array(self) -> ArrayRef {
123 PrimitiveArray::from_byte_buffer(
124 ByteBuffer::from_arrow_buffer(self, Alignment::of::<u8>()),
125 PType::U8,
126 Validity::NonNullable,
127 )
128 .into_array()
129 }
130}
131
132impl IntoVortexArray for BooleanBuffer {
133 fn into_array(self) -> ArrayRef {
134 BoolArray::new(self.into(), Validity::NonNullable).into_array()
135 }
136}
137
138impl<T> IntoVortexArray for ScalarBuffer<T>
139where
140 T: ArrowNativeType + NativePType,
141{
142 fn into_array(self) -> ArrayRef {
143 PrimitiveArray::new(
144 Buffer::<T>::from_arrow_scalar_buffer(self),
145 Validity::NonNullable,
146 )
147 .into_array()
148 }
149}
150
151impl<O> IntoVortexArray for OffsetBuffer<O>
152where
153 O: IntegerPType + OffsetSizeTrait,
154{
155 fn into_array(self) -> ArrayRef {
156 let primitive = PrimitiveArray::new(
157 Buffer::from_arrow_scalar_buffer(self.into_inner()),
158 Validity::NonNullable,
159 );
160
161 primitive.into_array()
162 }
163}
164
165pub fn from_arrow_primitive<T: ArrowPrimitiveType>(
170 value: &ArrowPrimitiveArray<T>,
171 nullable: bool,
172) -> VortexResult<ArrayRef>
173where
174 T::Native: NativePType,
175{
176 let buffer = Buffer::from_arrow_scalar_buffer(value.values().clone());
177 let validity = nulls(value.nulls(), nullable)?;
178 Ok(PrimitiveArray::new(buffer, validity).into_array())
179}
180
181macro_rules! impl_from_arrow_primitive {
182 ($T:path) => {
183 impl FromArrowArray<&ArrowPrimitiveArray<$T>> for ArrayRef {
184 fn from_arrow(value: &ArrowPrimitiveArray<$T>, nullable: bool) -> VortexResult<Self> {
185 from_arrow_primitive(value, nullable)
186 }
187 }
188 };
189}
190
191impl_from_arrow_primitive!(Int8Type);
192impl_from_arrow_primitive!(Int16Type);
193impl_from_arrow_primitive!(Int32Type);
194impl_from_arrow_primitive!(Int64Type);
195impl_from_arrow_primitive!(UInt8Type);
196impl_from_arrow_primitive!(UInt16Type);
197impl_from_arrow_primitive!(UInt32Type);
198impl_from_arrow_primitive!(UInt64Type);
199impl_from_arrow_primitive!(Float16Type);
200impl_from_arrow_primitive!(Float32Type);
201impl_from_arrow_primitive!(Float64Type);
202
203pub fn from_arrow_decimal32(
205 array: &ArrowPrimitiveArray<Decimal32Type>,
206 nullable: bool,
207) -> VortexResult<ArrayRef> {
208 let decimal_type = DecimalDType::new(array.precision(), array.scale());
209 let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
210 let validity = nulls(array.nulls(), nullable)?;
211 Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
212}
213
214impl FromArrowArray<&ArrowPrimitiveArray<Decimal32Type>> for ArrayRef {
215 fn from_arrow(
216 array: &ArrowPrimitiveArray<Decimal32Type>,
217 nullable: bool,
218 ) -> VortexResult<Self> {
219 from_arrow_decimal32(array, nullable)
220 }
221}
222
223pub fn from_arrow_decimal64(
225 array: &ArrowPrimitiveArray<Decimal64Type>,
226 nullable: bool,
227) -> VortexResult<ArrayRef> {
228 let decimal_type = DecimalDType::new(array.precision(), array.scale());
229 let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
230 let validity = nulls(array.nulls(), nullable)?;
231 Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
232}
233
234impl FromArrowArray<&ArrowPrimitiveArray<Decimal64Type>> for ArrayRef {
235 fn from_arrow(
236 array: &ArrowPrimitiveArray<Decimal64Type>,
237 nullable: bool,
238 ) -> VortexResult<Self> {
239 from_arrow_decimal64(array, nullable)
240 }
241}
242
243pub fn from_arrow_decimal128(
245 array: &ArrowPrimitiveArray<Decimal128Type>,
246 nullable: bool,
247) -> VortexResult<ArrayRef> {
248 let decimal_type = DecimalDType::new(array.precision(), array.scale());
249 let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
250 let validity = nulls(array.nulls(), nullable)?;
251 Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
252}
253
254impl FromArrowArray<&ArrowPrimitiveArray<Decimal128Type>> for ArrayRef {
255 fn from_arrow(
256 array: &ArrowPrimitiveArray<Decimal128Type>,
257 nullable: bool,
258 ) -> VortexResult<Self> {
259 from_arrow_decimal128(array, nullable)
260 }
261}
262
263pub fn from_arrow_decimal256(
265 array: &ArrowPrimitiveArray<Decimal256Type>,
266 nullable: bool,
267) -> VortexResult<ArrayRef> {
268 let decimal_type = DecimalDType::new(array.precision(), array.scale());
269 let buffer = Buffer::from_arrow_scalar_buffer(array.values().clone());
270 let buffer = unsafe { std::mem::transmute::<Buffer<arrow_buffer::i256>, Buffer<i256>>(buffer) };
274 let validity = nulls(array.nulls(), nullable)?;
275 Ok(DecimalArray::new(buffer, decimal_type, validity).into_array())
276}
277
278impl FromArrowArray<&ArrowPrimitiveArray<Decimal256Type>> for ArrayRef {
279 fn from_arrow(
280 array: &ArrowPrimitiveArray<Decimal256Type>,
281 nullable: bool,
282 ) -> VortexResult<Self> {
283 from_arrow_decimal256(array, nullable)
284 }
285}
286
287macro_rules! impl_from_arrow_temporal {
288 ($T:path) => {
289 impl FromArrowArray<&ArrowPrimitiveArray<$T>> for ArrayRef {
290 fn from_arrow(
291 value: &ArrowPrimitiveArray<$T>,
292 nullable: bool,
293 ) -> vortex_error::VortexResult<Self> {
294 from_arrow_temporal(value, nullable)
295 }
296 }
297 };
298}
299
300impl_from_arrow_temporal!(TimestampSecondType);
302impl_from_arrow_temporal!(TimestampMillisecondType);
303impl_from_arrow_temporal!(TimestampMicrosecondType);
304impl_from_arrow_temporal!(TimestampNanosecondType);
305
306impl_from_arrow_temporal!(Time32SecondType);
308impl_from_arrow_temporal!(Time32MillisecondType);
309impl_from_arrow_temporal!(Time64MicrosecondType);
310impl_from_arrow_temporal!(Time64NanosecondType);
311
312impl_from_arrow_temporal!(Date32Type);
314impl_from_arrow_temporal!(Date64Type);
315
316pub fn from_arrow_temporal<T: ArrowPrimitiveType>(
319 value: &ArrowPrimitiveArray<T>,
320 nullable: bool,
321) -> VortexResult<ArrayRef>
322where
323 T::Native: NativePType,
324{
325 let arr = PrimitiveArray::new(
326 Buffer::from_arrow_scalar_buffer(value.values().clone()),
327 nulls(value.nulls(), nullable)?,
328 )
329 .into_array();
330
331 Ok(match value.data_type() {
332 DataType::Timestamp(time_unit, tz) => {
333 TemporalArray::new_timestamp(arr, from_arrow_time_unit(*time_unit), tz.clone()).into()
334 }
335 DataType::Time32(time_unit) => {
336 TemporalArray::new_time(arr, from_arrow_time_unit(*time_unit)).into()
337 }
338 DataType::Time64(time_unit) => {
339 TemporalArray::new_time(arr, from_arrow_time_unit(*time_unit)).into()
340 }
341 DataType::Date32 => TemporalArray::new_date(arr, TimeUnit::Days).into(),
342 DataType::Date64 => TemporalArray::new_date(arr, TimeUnit::Milliseconds).into(),
343 DataType::Duration(_) | DataType::Interval(_) => {
344 vortex_bail!("Arrow {} arrays are not supported", value.data_type())
345 }
346 _ => vortex_panic!("Invalid temporal type: {}", value.data_type()),
347 })
348}
349
350pub fn from_arrow_bytes<T: ByteArrayType>(
352 value: &GenericByteArray<T>,
353 nullable: bool,
354) -> VortexResult<ArrayRef>
355where
356 <T as ByteArrayType>::Offset: IntegerPType,
357{
358 let dtype = match T::DATA_TYPE {
359 DataType::Binary | DataType::LargeBinary => DType::Binary(nullable.into()),
360 DataType::Utf8 | DataType::LargeUtf8 => DType::Utf8(nullable.into()),
361 dt => vortex_panic!("Invalid data type for ByteArray: {dt}"),
362 };
363 Ok(unsafe {
365 VarBinArray::new_unchecked(
366 value.offsets().clone().into_array(),
367 ByteBuffer::from_arrow_buffer(value.values().clone(), Alignment::of::<u8>()),
368 dtype,
369 nulls(value.nulls(), nullable)?,
370 )
371 }
372 .into_array())
373}
374
375impl<T: ByteArrayType> FromArrowArray<&GenericByteArray<T>> for ArrayRef
376where
377 <T as ByteArrayType>::Offset: IntegerPType,
378{
379 fn from_arrow(value: &GenericByteArray<T>, nullable: bool) -> VortexResult<Self> {
380 from_arrow_bytes(value, nullable)
381 }
382}
383
384pub fn from_arrow_byte_view<T: ByteViewType>(
386 value: &GenericByteViewArray<T>,
387 nullable: bool,
388) -> VortexResult<ArrayRef> {
389 let dtype = match T::DATA_TYPE {
390 DataType::BinaryView => DType::Binary(nullable.into()),
391 DataType::Utf8View => DType::Utf8(nullable.into()),
392 dt => vortex_panic!("Invalid data type for ByteViewArray: {dt}"),
393 };
394
395 let views_buffer = Buffer::from_byte_buffer(
396 Buffer::from_arrow_scalar_buffer(value.views().clone()).into_byte_buffer(),
397 );
398
399 Ok(unsafe {
402 VarBinViewArray::new_unchecked(
403 views_buffer,
404 Arc::from(
405 value
406 .data_buffers()
407 .iter()
408 .map(|b| ByteBuffer::from_arrow_buffer(b.clone(), Alignment::of::<u8>()))
409 .collect::<Vec<_>>(),
410 ),
411 dtype,
412 nulls(value.nulls(), nullable)?,
413 )
414 .into_array()
415 })
416}
417
418impl<T: ByteViewType> FromArrowArray<&GenericByteViewArray<T>> for ArrayRef {
419 fn from_arrow(value: &GenericByteViewArray<T>, nullable: bool) -> VortexResult<Self> {
420 from_arrow_byte_view(value, nullable)
421 }
422}
423
424pub fn from_arrow_boolean(value: &ArrowBooleanArray, nullable: bool) -> VortexResult<ArrayRef> {
426 Ok(BoolArray::new(
427 value.values().clone().into(),
428 nulls(value.nulls(), nullable)?,
429 )
430 .into_array())
431}
432
433impl FromArrowArray<&ArrowBooleanArray> for ArrayRef {
434 fn from_arrow(value: &ArrowBooleanArray, nullable: bool) -> VortexResult<Self> {
435 from_arrow_boolean(value, nullable)
436 }
437}
438
439pub(crate) fn remove_nulls(data: arrow_data::ArrayData) -> VortexResult<arrow_data::ArrayData> {
441 if data.null_count() == 0 {
442 return Ok(data);
444 }
445
446 let children = match data.data_type() {
447 DataType::Struct(fields) => Some(
448 fields
449 .iter()
450 .zip(data.child_data().iter())
451 .map(|(field, child_data)| {
452 if field.is_nullable() {
453 Ok(child_data.clone())
454 } else {
455 remove_nulls(child_data.clone())
456 }
457 })
458 .collect::<VortexResult<Vec<_>>>()?,
459 ),
460 DataType::List(f)
461 | DataType::LargeList(f)
462 | DataType::ListView(f)
463 | DataType::LargeListView(f)
464 | DataType::FixedSizeList(f, _)
465 if !f.is_nullable() =>
466 {
467 vortex_ensure_eq!(
469 data.child_data().len(),
470 1,
471 "List types should have one child"
472 );
473 Some(vec![remove_nulls(data.child_data()[0].clone())?])
474 }
475 _ => None,
476 };
477
478 let mut builder = data.into_builder().nulls(None);
479 if let Some(children) = children {
480 builder = builder.child_data(children);
481 }
482 builder
483 .build()
484 .map_err(|e| vortex_err!("Failed to reconstruct Arrow array without nulls: {e}"))
485}
486
487pub fn from_arrow_struct(value: &ArrowStructArray, nullable: bool) -> VortexResult<ArrayRef> {
489 Ok(StructArray::try_new(
490 value.column_names().iter().copied().collect(),
491 value
492 .columns()
493 .iter()
494 .zip(value.fields())
495 .map(|(c, field)| {
496 if c.null_count() > 0 && !field.is_nullable() {
499 let stripped = make_array(remove_nulls(c.into_data())?);
500 from_arrow_dyn(stripped.as_ref(), false)
501 } else {
502 from_arrow_dyn(c.as_ref(), field.is_nullable())
503 }
504 })
505 .collect::<VortexResult<Vec<_>>>()?,
506 value.len(),
507 nulls(value.nulls(), nullable)?,
508 )?
509 .into_array())
510}
511
512impl FromArrowArray<&ArrowStructArray> for ArrayRef {
513 fn from_arrow(value: &ArrowStructArray, nullable: bool) -> VortexResult<Self> {
514 from_arrow_struct(value, nullable)
515 }
516}
517
518pub fn from_arrow_list<O: IntegerPType + OffsetSizeTrait>(
520 value: &GenericListArray<O>,
521 nullable: bool,
522) -> VortexResult<ArrayRef> {
523 let elements_are_nullable = match value.data_type() {
525 DataType::List(field) => field.is_nullable(),
526 DataType::LargeList(field) => field.is_nullable(),
527 dt => vortex_panic!("Invalid data type for ListArray: {dt}"),
528 };
529
530 let elements = from_arrow_dyn(value.values().as_ref(), elements_are_nullable)?;
531
532 let offsets = value.offsets().clone().into_array();
534 let nulls = nulls(value.nulls(), nullable)?;
535
536 Ok(ListArray::try_new(elements, offsets, nulls)?.into_array())
537}
538
539impl<O: IntegerPType + OffsetSizeTrait> FromArrowArray<&GenericListArray<O>> for ArrayRef {
540 fn from_arrow(value: &GenericListArray<O>, nullable: bool) -> VortexResult<Self> {
541 from_arrow_list(value, nullable)
542 }
543}
544
545pub fn from_arrow_list_view<O: OffsetSizeTrait + NativePType>(
547 array: &GenericListViewArray<O>,
548 nullable: bool,
549) -> VortexResult<ArrayRef> {
550 let elements_are_nullable = match array.data_type() {
552 DataType::ListView(field) => field.is_nullable(),
553 DataType::LargeListView(field) => field.is_nullable(),
554 dt => vortex_panic!("Invalid data type for ListViewArray: {dt}"),
555 };
556
557 let elements = from_arrow_dyn(array.values().as_ref(), elements_are_nullable)?;
558
559 let offsets = array.offsets().clone().into_array();
561 let sizes = array.sizes().clone().into_array();
562 let nulls = nulls(array.nulls(), nullable)?;
563
564 Ok(ListViewArray::try_new(elements, offsets, sizes, nulls)?.into_array())
565}
566
567impl<O: OffsetSizeTrait + NativePType> FromArrowArray<&GenericListViewArray<O>> for ArrayRef {
568 fn from_arrow(array: &GenericListViewArray<O>, nullable: bool) -> VortexResult<Self> {
569 from_arrow_list_view(array, nullable)
570 }
571}
572
573pub fn from_arrow_fixed_size_list(
575 array: &ArrowFixedSizeListArray,
576 nullable: bool,
577) -> VortexResult<ArrayRef> {
578 let DataType::FixedSizeList(field, list_size) = array.data_type() else {
579 vortex_panic!("Invalid data type for ListArray: {}", array.data_type());
580 };
581
582 Ok(FixedSizeListArray::try_new(
583 from_arrow_dyn(array.values().as_ref(), field.is_nullable())?,
584 *list_size as u32,
585 nulls(array.nulls(), nullable)?,
586 array.len(),
587 )?
588 .into_array())
589}
590
591impl FromArrowArray<&ArrowFixedSizeListArray> for ArrayRef {
592 fn from_arrow(array: &ArrowFixedSizeListArray, nullable: bool) -> VortexResult<Self> {
593 from_arrow_fixed_size_list(array, nullable)
594 }
595}
596
597pub(crate) fn map_from_arrow_parts(
598 entries: ArrayRef,
599 offsets: &OffsetBuffer<i32>,
600 arrow_nulls: Option<&NullBuffer>,
601 keys_sorted: bool,
602 nullable: bool,
603) -> VortexResult<ArrayRef> {
604 let DType::Struct(struct_dtype, Nullability::NonNullable) = entries.dtype() else {
605 vortex_bail!(
606 "Arrow map entries must import as non-nullable struct, got {}",
607 entries.dtype()
608 );
609 };
610 vortex_ensure!(
611 struct_dtype.nfields() == 2,
612 "Arrow map entries struct must contain exactly two fields"
613 );
614
615 let key_dtype = struct_dtype
616 .field_by_index(0)
617 .ok_or_else(|| vortex_err!("Arrow map entries struct missing key field"))?;
618 vortex_ensure!(
619 !key_dtype.is_nullable(),
620 "Arrow map key field must be non-nullable"
621 );
622 let value_dtype = struct_dtype
623 .field_by_index(1)
624 .ok_or_else(|| vortex_err!("Arrow map entries struct missing value field"))?;
625 let map_dtype = MapDType::try_new(key_dtype, value_dtype, keys_sorted)?;
626 let entries_struct = entries.as_::<Struct>();
627 let entries = StructArray::try_new(
628 FieldNames::from(["key", "value"]),
629 vec![
630 entries_struct.unmasked_field(0).clone(),
631 entries_struct.unmasked_field(1).clone(),
632 ],
633 entries.len(),
634 Validity::NonNullable,
635 )?
636 .into_array();
637
638 let len = offsets.len() - 1;
639 let sizes = Buffer::<i32>::from_iter(offsets.windows(2).map(|window| window[1] - window[0]))
640 .into_array();
641 let offsets = offsets.inner().slice(0, len).into_array();
642 let validity = nulls(arrow_nulls, nullable)?;
643 let entries = ListViewArray::try_new(entries, offsets, sizes, validity)?;
644 let entries = unsafe { entries.with_zero_copy_to_list(true) };
648
649 Ok(MapArray::try_new(map_dtype, entries)?.into_array())
650}
651
652pub fn from_arrow_map(array: &ArrowMapArray, nullable: bool) -> VortexResult<ArrayRef> {
654 let DataType::Map(_, keys_sorted) = array.data_type() else {
655 vortex_panic!("Invalid data type for MapArray: {}", array.data_type());
656 };
657 let entries = from_arrow_struct(array.entries(), false)?;
658 map_from_arrow_parts(
659 entries,
660 array.offsets(),
661 array.nulls(),
662 *keys_sorted,
663 nullable,
664 )
665}
666
667impl FromArrowArray<&ArrowMapArray> for ArrayRef {
668 fn from_arrow(array: &ArrowMapArray, nullable: bool) -> VortexResult<Self> {
669 from_arrow_map(array, nullable)
670 }
671}
672
673pub fn from_arrow_null(value: &ArrowNullArray, nullable: bool) -> VortexResult<ArrayRef> {
675 vortex_ensure!(
676 nullable,
677 "Cannot convert an Arrow NullArray into a non-nullable Vortex array"
678 );
679 Ok(NullArray::new(value.len()).into_array())
680}
681
682impl FromArrowArray<&ArrowNullArray> for ArrayRef {
683 fn from_arrow(value: &ArrowNullArray, nullable: bool) -> VortexResult<Self> {
684 from_arrow_null(value, nullable)
685 }
686}
687
688pub fn from_arrow_dictionary<K: ArrowDictionaryKeyType>(
690 array: &DictionaryArray<K>,
691 nullable: bool,
692) -> VortexResult<DictArray> {
693 let keys = AnyDictionaryArray::keys(array);
694 let keys = from_arrow_dyn(keys, keys.is_nullable())?;
695 let values = from_arrow_dyn(array.values().as_ref(), nullable)?;
696 Ok(unsafe { DictArray::new_unchecked(keys, values) })
698}
699
700impl<K: ArrowDictionaryKeyType> FromArrowArray<&DictionaryArray<K>> for DictArray {
701 fn from_arrow(array: &DictionaryArray<K>, nullable: bool) -> VortexResult<Self> {
702 from_arrow_dictionary(array, nullable)
703 }
704}
705
706pub fn nulls(nulls: Option<&NullBuffer>, nullable: bool) -> VortexResult<Validity> {
713 if nullable {
714 Ok(nulls
715 .map(|nulls| {
716 if nulls.null_count() == nulls.len() {
717 Validity::AllInvalid
718 } else {
719 Validity::from(BitBuffer::from(nulls.inner().clone()))
720 }
721 })
722 .unwrap_or(Validity::AllValid))
723 } else {
724 let null_count = nulls.map(NullBuffer::null_count).unwrap_or(0);
725 vortex_ensure_eq!(
726 null_count,
727 0,
728 "Cannot convert an Arrow array containing {null_count} nulls into a non-nullable Vortex array"
729 );
730 Ok(Validity::NonNullable)
731 }
732}
733
734pub fn from_arrow_dyn(array: &dyn ArrowArray, nullable: bool) -> VortexResult<ArrayRef> {
737 match array.data_type() {
738 DataType::Boolean => from_arrow_boolean(array.as_boolean(), nullable),
739 DataType::UInt8 => from_arrow_primitive(array.as_primitive::<UInt8Type>(), nullable),
740 DataType::UInt16 => from_arrow_primitive(array.as_primitive::<UInt16Type>(), nullable),
741 DataType::UInt32 => from_arrow_primitive(array.as_primitive::<UInt32Type>(), nullable),
742 DataType::UInt64 => from_arrow_primitive(array.as_primitive::<UInt64Type>(), nullable),
743 DataType::Int8 => from_arrow_primitive(array.as_primitive::<Int8Type>(), nullable),
744 DataType::Int16 => from_arrow_primitive(array.as_primitive::<Int16Type>(), nullable),
745 DataType::Int32 => from_arrow_primitive(array.as_primitive::<Int32Type>(), nullable),
746 DataType::Int64 => from_arrow_primitive(array.as_primitive::<Int64Type>(), nullable),
747 DataType::Float16 => from_arrow_primitive(array.as_primitive::<Float16Type>(), nullable),
748 DataType::Float32 => from_arrow_primitive(array.as_primitive::<Float32Type>(), nullable),
749 DataType::Float64 => from_arrow_primitive(array.as_primitive::<Float64Type>(), nullable),
750 DataType::Utf8 => from_arrow_bytes(array.as_string::<i32>(), nullable),
751 DataType::LargeUtf8 => from_arrow_bytes(array.as_string::<i64>(), nullable),
752 DataType::Binary => from_arrow_bytes(array.as_binary::<i32>(), nullable),
753 DataType::LargeBinary => from_arrow_bytes(array.as_binary::<i64>(), nullable),
754 DataType::BinaryView => from_arrow_byte_view(array.as_binary_view(), nullable),
755 DataType::Utf8View => from_arrow_byte_view(array.as_string_view(), nullable),
756 DataType::Struct(_) => from_arrow_struct(array.as_struct(), nullable),
757 DataType::List(_) => from_arrow_list(array.as_list::<i32>(), nullable),
758 DataType::LargeList(_) => from_arrow_list(array.as_list::<i64>(), nullable),
759 DataType::ListView(_) => from_arrow_list_view(array.as_list_view::<i32>(), nullable),
760 DataType::LargeListView(_) => from_arrow_list_view(array.as_list_view::<i64>(), nullable),
761 DataType::FixedSizeList(..) => {
762 from_arrow_fixed_size_list(array.as_fixed_size_list(), nullable)
763 }
764 DataType::Map(..) => from_arrow_map(array.as_map(), nullable),
765 DataType::Null => from_arrow_null(as_null_array(array), nullable),
766 DataType::Timestamp(u, _) => match u {
767 ArrowTimeUnit::Second => {
768 from_arrow_temporal(array.as_primitive::<TimestampSecondType>(), nullable)
769 }
770 ArrowTimeUnit::Millisecond => {
771 from_arrow_temporal(array.as_primitive::<TimestampMillisecondType>(), nullable)
772 }
773 ArrowTimeUnit::Microsecond => {
774 from_arrow_temporal(array.as_primitive::<TimestampMicrosecondType>(), nullable)
775 }
776 ArrowTimeUnit::Nanosecond => {
777 from_arrow_temporal(array.as_primitive::<TimestampNanosecondType>(), nullable)
778 }
779 },
780 DataType::Date32 => from_arrow_temporal(array.as_primitive::<Date32Type>(), nullable),
781 DataType::Date64 => from_arrow_temporal(array.as_primitive::<Date64Type>(), nullable),
782 DataType::Time32(u) => match u {
783 ArrowTimeUnit::Second => {
784 from_arrow_temporal(array.as_primitive::<Time32SecondType>(), nullable)
785 }
786 ArrowTimeUnit::Millisecond => {
787 from_arrow_temporal(array.as_primitive::<Time32MillisecondType>(), nullable)
788 }
789 ArrowTimeUnit::Microsecond | ArrowTimeUnit::Nanosecond => unreachable!(),
790 },
791 DataType::Time64(u) => match u {
792 ArrowTimeUnit::Microsecond => {
793 from_arrow_temporal(array.as_primitive::<Time64MicrosecondType>(), nullable)
794 }
795 ArrowTimeUnit::Nanosecond => {
796 from_arrow_temporal(array.as_primitive::<Time64NanosecondType>(), nullable)
797 }
798 ArrowTimeUnit::Second | ArrowTimeUnit::Millisecond => unreachable!(),
799 },
800 DataType::Decimal32(..) => {
801 from_arrow_decimal32(array.as_primitive::<Decimal32Type>(), nullable)
802 }
803 DataType::Decimal64(..) => {
804 from_arrow_decimal64(array.as_primitive::<Decimal64Type>(), nullable)
805 }
806 DataType::Decimal128(..) => {
807 from_arrow_decimal128(array.as_primitive::<Decimal128Type>(), nullable)
808 }
809 DataType::Decimal256(..) => {
810 from_arrow_decimal256(array.as_primitive::<Decimal256Type>(), nullable)
811 }
812 DataType::Dictionary(key_type, _) => match key_type.as_ref() {
813 DataType::Int8 => Ok(from_arrow_dictionary(
814 array.as_dictionary::<Int8Type>(),
815 nullable,
816 )?
817 .into_array()),
818 DataType::Int16 => Ok(from_arrow_dictionary(
819 array.as_dictionary::<Int16Type>(),
820 nullable,
821 )?
822 .into_array()),
823 DataType::Int32 => Ok(from_arrow_dictionary(
824 array.as_dictionary::<Int32Type>(),
825 nullable,
826 )?
827 .into_array()),
828 DataType::Int64 => Ok(from_arrow_dictionary(
829 array.as_dictionary::<Int64Type>(),
830 nullable,
831 )?
832 .into_array()),
833 DataType::UInt8 => Ok(from_arrow_dictionary(
834 array.as_dictionary::<UInt8Type>(),
835 nullable,
836 )?
837 .into_array()),
838 DataType::UInt16 => Ok(from_arrow_dictionary(
839 array.as_dictionary::<UInt16Type>(),
840 nullable,
841 )?
842 .into_array()),
843 DataType::UInt32 => Ok(from_arrow_dictionary(
844 array.as_dictionary::<UInt32Type>(),
845 nullable,
846 )?
847 .into_array()),
848 DataType::UInt64 => Ok(from_arrow_dictionary(
849 array.as_dictionary::<UInt64Type>(),
850 nullable,
851 )?
852 .into_array()),
853 key_dt => vortex_bail!("Unsupported dictionary key type: {key_dt}"),
854 },
855 dt => vortex_bail!("Array encoding not implemented for Arrow data type {dt}"),
856 }
857}
858
859impl FromArrowArray<&dyn ArrowArray> for ArrayRef {
860 fn from_arrow(array: &dyn ArrowArray, nullable: bool) -> VortexResult<Self> {
861 from_arrow_dyn(array, nullable)
862 }
863}
864
865pub fn from_arrow_batch(batch: &RecordBatch, nullable: bool) -> VortexResult<ArrayRef> {
867 from_arrow_struct(&arrow_array::StructArray::from(batch.clone()), nullable)
868}
869
870impl FromArrowArray<RecordBatch> for ArrayRef {
871 fn from_arrow(array: RecordBatch, nullable: bool) -> VortexResult<Self> {
872 from_arrow_batch(&array, nullable)
873 }
874}
875
876impl FromArrowArray<&RecordBatch> for ArrayRef {
877 fn from_arrow(array: &RecordBatch, nullable: bool) -> VortexResult<Self> {
878 from_arrow_batch(array, nullable)
879 }
880}
881
882#[cfg(test)]
883mod tests {
884 use std::sync::Arc;
885
886 use arrow_array::Array as ArrowArray;
887 use arrow_array::BinaryArray;
888 use arrow_array::BooleanArray;
889 use arrow_array::Date32Array;
890 use arrow_array::Date64Array;
891 use arrow_array::FixedSizeListArray as ArrowFixedSizeListArray;
892 use arrow_array::Float32Array;
893 use arrow_array::Float64Array;
894 use arrow_array::GenericListViewArray;
895 use arrow_array::Int8Array;
896 use arrow_array::Int16Array;
897 use arrow_array::Int32Array;
898 use arrow_array::Int64Array;
899 use arrow_array::LargeBinaryArray;
900 use arrow_array::LargeStringArray;
901 use arrow_array::NullArray;
902 use arrow_array::RecordBatch;
903 use arrow_array::StringArray;
904 use arrow_array::StructArray;
905 use arrow_array::Time32MillisecondArray;
906 use arrow_array::Time32SecondArray;
907 use arrow_array::Time64MicrosecondArray;
908 use arrow_array::Time64NanosecondArray;
909 use arrow_array::TimestampMicrosecondArray;
910 use arrow_array::TimestampMillisecondArray;
911 use arrow_array::TimestampNanosecondArray;
912 use arrow_array::TimestampSecondArray;
913 use arrow_array::UInt8Array;
914 use arrow_array::UInt16Array;
915 use arrow_array::UInt32Array;
916 use arrow_array::UInt64Array;
917 use arrow_array::builder::BinaryViewBuilder;
918 use arrow_array::builder::Decimal128Builder;
919 use arrow_array::builder::Decimal256Builder;
920 use arrow_array::builder::Int32Builder;
921 use arrow_array::builder::LargeListBuilder;
922 use arrow_array::builder::ListBuilder;
923 use arrow_array::builder::MapBuilder as ArrowMapBuilder;
924 use arrow_array::builder::StringBuilder;
925 use arrow_array::builder::StringViewBuilder;
926 use arrow_array::new_null_array;
927 use arrow_array::types::ArrowPrimitiveType;
928 use arrow_array::types::Float16Type;
929 use arrow_buffer::BooleanBuffer;
930 use arrow_buffer::Buffer as ArrowBuffer;
931 use arrow_buffer::OffsetBuffer;
932 use arrow_buffer::ScalarBuffer;
933 use arrow_schema::DataType;
934 use arrow_schema::Field;
935 use arrow_schema::Fields;
936 use arrow_schema::Schema;
937 use rstest::rstest;
938 use vortex_array::ArrayRef;
939 use vortex_array::arrays::Decimal;
940 use vortex_array::arrays::FixedSizeList;
941 use vortex_array::arrays::List;
942 use vortex_array::arrays::ListView;
943 use vortex_array::arrays::Primitive;
944 use vortex_array::arrays::Struct;
945 use vortex_array::arrays::VarBinView;
946 use vortex_array::arrays::fixed_size_list::FixedSizeListArrayExt;
947 use vortex_array::arrays::fixed_size_list::FixedSizeListArraySlotsExt;
948 use vortex_array::arrays::list::ListArraySlotsExt;
949 use vortex_array::arrays::listview::ListViewArraySlotsExt;
950 use vortex_array::arrays::struct_::StructArrayExt;
951 use vortex_array::dtype::DType;
952 use vortex_array::dtype::Nullability;
953 use vortex_array::dtype::PType;
954 use vortex_array::extension::datetime::TimeUnit;
955 use vortex_array::extension::datetime::Timestamp;
956 use vortex_error::VortexResult;
957
958 use crate::FromArrowArray as _;
959 use crate::IntoVortexArray as _;
960 use crate::convert::from_arrow_batch;
961 use crate::convert::from_arrow_dyn;
962
963 #[rstest]
964 #[case::i8(
965 Arc::new(Int8Array::from(vec![Some(1), None, Some(3), Some(4)])),
966 Arc::new(Int8Array::from(vec![1, 2, 3, 4])),
967 PType::I8,
968 )]
969 #[case::i16(
970 Arc::new(Int16Array::from(vec![Some(100), None, Some(300), Some(400)])),
971 Arc::new(Int16Array::from(vec![100, 200, 300, 400])),
972 PType::I16,
973 )]
974 #[case::i32(
975 Arc::new(Int32Array::from(vec![Some(1000), None, Some(3000), Some(4000)])),
976 Arc::new(Int32Array::from(vec![1000, 2000, 3000, 4000])),
977 PType::I32,
978 )]
979 #[case::i64(
980 Arc::new(Int64Array::from(vec![Some(10000), None, Some(30000), Some(40000)])),
981 Arc::new(Int64Array::from(vec![10000_i64, 20000, 30000, 40000])),
982 PType::I64,
983 )]
984 #[case::u8(
985 Arc::new(UInt8Array::from(vec![Some(1), None, Some(3), Some(4)])),
986 Arc::new(UInt8Array::from(vec![1_u8, 2, 3, 4])),
987 PType::U8,
988 )]
989 #[case::u16(
990 Arc::new(UInt16Array::from(vec![Some(100), None, Some(300), Some(400)])),
991 Arc::new(UInt16Array::from(vec![100_u16, 200, 300, 400])),
992 PType::U16,
993 )]
994 #[case::u32(
995 Arc::new(UInt32Array::from(vec![Some(1000), None, Some(3000), Some(4000)])),
996 Arc::new(UInt32Array::from(vec![1000_u32, 2000, 3000, 4000])),
997 PType::U32,
998 )]
999 #[case::u64(
1000 Arc::new(UInt64Array::from(vec![Some(10000), None, Some(30000), Some(40000)])),
1001 Arc::new(UInt64Array::from(vec![10000_u64, 20000, 30000, 40000])),
1002 PType::U64,
1003 )]
1004 #[case::f32(
1005 Arc::new(Float32Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)])),
1006 Arc::new(Float32Array::from(vec![1.5_f32, 2.5, 3.5, 4.5])),
1007 PType::F32,
1008 )]
1009 #[case::f64(
1010 Arc::new(Float64Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)])),
1011 Arc::new(Float64Array::from(vec![1.5_f64, 2.5, 3.5, 4.5])),
1012 PType::F64,
1013 )]
1014 fn test_primitive_array_conversion(
1015 #[case] nullable: Arc<dyn ArrowArray>,
1016 #[case] non_nullable: Arc<dyn ArrowArray>,
1017 #[case] expected_ptype: PType,
1018 ) {
1019 let v_null = ArrayRef::from_arrow(nullable.as_ref(), true).unwrap();
1020 let v_non_null = ArrayRef::from_arrow(non_nullable.as_ref(), false).unwrap();
1021 assert_eq!(v_null.len(), 4);
1022 assert_eq!(v_non_null.len(), 4);
1023 assert_eq!(v_null.as_::<Primitive>().ptype(), expected_ptype);
1024 assert_eq!(v_non_null.as_::<Primitive>().ptype(), expected_ptype);
1025 }
1026
1027 #[test]
1028 fn test_float16_array_conversion() {
1029 let values = vec![
1030 Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5)),
1031 None,
1032 Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(3.5)),
1033 ];
1034 let arrow_array = arrow_array::PrimitiveArray::<Float16Type>::from(values);
1035 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1036
1037 let non_null_values = vec![
1038 <Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5),
1039 <Float16Type as ArrowPrimitiveType>::Native::from_f32(2.5),
1040 ];
1041 let arrow_array_non_null =
1042 arrow_array::PrimitiveArray::<Float16Type>::from(non_null_values);
1043 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1044
1045 assert_eq!(vortex_array.len(), 3);
1046 assert_eq!(vortex_array_non_null.len(), 2);
1047
1048 let primitive_array = vortex_array.as_::<Primitive>();
1050 assert_eq!(primitive_array.ptype(), PType::F16);
1051
1052 let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
1053 assert_eq!(primitive_array_non_null.ptype(), PType::F16);
1054 }
1055
1056 #[test]
1058 fn test_decimal128_array_conversion() {
1059 let mut builder = Decimal128Builder::with_capacity(4);
1060 builder.append_value(12345);
1061 builder.append_null();
1062 builder.append_value(67890);
1063 builder.append_value(11111);
1064 let decimal_array = builder.finish().with_precision_and_scale(10, 2).unwrap();
1065
1066 let vortex_array = ArrayRef::from_arrow(&decimal_array, true).unwrap();
1067 assert_eq!(vortex_array.len(), 4);
1068
1069 let mut builder_non_null = Decimal128Builder::with_capacity(3);
1070 builder_non_null.append_value(12345);
1071 builder_non_null.append_value(67890);
1072 builder_non_null.append_value(11111);
1073 let decimal_array_non_null = builder_non_null
1074 .finish()
1075 .with_precision_and_scale(10, 2)
1076 .unwrap();
1077
1078 let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false).unwrap();
1079 assert_eq!(vortex_array_non_null.len(), 3);
1080
1081 let decimal_vortex_array = vortex_array.as_::<Decimal>();
1083 assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 10);
1084 assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 2);
1085
1086 let decimal_vortex_array_non_null = vortex_array_non_null.as_::<Decimal>();
1087 assert_eq!(
1088 decimal_vortex_array_non_null.decimal_dtype().precision(),
1089 10
1090 );
1091 assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 2);
1092 }
1093
1094 #[test]
1095 fn test_decimal256_array_conversion() {
1096 let mut builder = Decimal256Builder::with_capacity(4);
1097 builder.append_value(arrow_buffer::i256::from_i128(12345));
1098 builder.append_null();
1099 builder.append_value(arrow_buffer::i256::from_i128(67890));
1100 builder.append_value(arrow_buffer::i256::from_i128(11111));
1101 let decimal_array = builder.finish().with_precision_and_scale(38, 10).unwrap();
1102
1103 let vortex_array = ArrayRef::from_arrow(&decimal_array, true).unwrap();
1104 assert_eq!(vortex_array.len(), 4);
1105
1106 let mut builder_non_null = Decimal256Builder::with_capacity(3);
1107 builder_non_null.append_value(arrow_buffer::i256::from_i128(12345));
1108 builder_non_null.append_value(arrow_buffer::i256::from_i128(67890));
1109 builder_non_null.append_value(arrow_buffer::i256::from_i128(11111));
1110 let decimal_array_non_null = builder_non_null
1111 .finish()
1112 .with_precision_and_scale(38, 10)
1113 .unwrap();
1114
1115 let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false).unwrap();
1116 assert_eq!(vortex_array_non_null.len(), 3);
1117
1118 let decimal_vortex_array = vortex_array.as_::<Decimal>();
1120 assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 38);
1121 assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 10);
1122
1123 let decimal_vortex_array_non_null = vortex_array_non_null.as_::<Decimal>();
1124 assert_eq!(
1125 decimal_vortex_array_non_null.decimal_dtype().precision(),
1126 38
1127 );
1128 assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 10);
1129 }
1130
1131 #[rstest]
1133 #[case::timestamp_second(
1134 Arc::new(TimestampSecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1135 Arc::new(TimestampSecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1136 )]
1137 #[case::timestamp_millisecond(
1138 Arc::new(TimestampMillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1139 Arc::new(TimestampMillisecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1140 )]
1141 #[case::timestamp_microsecond(
1142 Arc::new(TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1143 Arc::new(TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1144 )]
1145 #[case::timestamp_nanosecond(
1146 Arc::new(TimestampNanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1147 Arc::new(TimestampNanosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1148 )]
1149 #[case::time32_second(
1150 Arc::new(Time32SecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1151 Arc::new(Time32SecondArray::from(vec![1000_i32, 2000, 3000, 4000])),
1152 )]
1153 #[case::time32_millisecond(
1154 Arc::new(Time32MillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1155 Arc::new(Time32MillisecondArray::from(vec![1000_i32, 2000, 3000, 4000])),
1156 )]
1157 #[case::time64_microsecond(
1158 Arc::new(Time64MicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1159 Arc::new(Time64MicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1160 )]
1161 #[case::time64_nanosecond(
1162 Arc::new(Time64NanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1163 Arc::new(Time64NanosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1164 )]
1165 #[case::date32(
1166 Arc::new(Date32Array::from(vec![Some(18000), None, Some(18002), Some(18003)])),
1167 Arc::new(Date32Array::from(vec![18000_i32, 18001, 18002, 18003])),
1168 )]
1169 #[case::date64(
1170 Arc::new(Date64Array::from(vec![Some(1555200000000), None, Some(1555286400000), Some(1555372800000)]
1171 )),
1172 Arc::new(Date64Array::from(vec![1555200000000_i64, 1555213600000, 1555286400000, 1555372800000]
1173 )),
1174 )]
1175 fn test_temporal_array_conversion(
1176 #[case] nullable: Arc<dyn ArrowArray>,
1177 #[case] non_nullable: Arc<dyn ArrowArray>,
1178 ) {
1179 let v_null = ArrayRef::from_arrow(nullable.as_ref(), true).unwrap();
1180 let v_non_null = ArrayRef::from_arrow(non_nullable.as_ref(), false).unwrap();
1181 assert_eq!(v_null.len(), 4);
1182 assert_eq!(v_non_null.len(), 4);
1183 }
1184
1185 #[test]
1186 fn test_timestamp_timezone_microsecond_array_conversion() {
1187 let arrow_array =
1188 TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])
1189 .with_timezone("UTC");
1190 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1191
1192 let arrow_array_non_null =
1193 TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]).with_timezone("UTC");
1194 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1195
1196 assert_eq!(vortex_array.len(), 4);
1197 assert_eq!(
1198 vortex_array.dtype(),
1199 &DType::Extension(
1200 Timestamp::new_with_tz(
1201 TimeUnit::Microseconds,
1202 Some("UTC".into()),
1203 Nullability::Nullable
1204 )
1205 .erased()
1206 ),
1207 );
1208 assert_eq!(vortex_array_non_null.len(), 4);
1209 assert_eq!(
1210 vortex_array_non_null.dtype(),
1211 &DType::Extension(
1212 Timestamp::new_with_tz(
1213 TimeUnit::Microseconds,
1214 Some("UTC".into()),
1215 Nullability::NonNullable
1216 )
1217 .erased()
1218 )
1219 );
1220 }
1221
1222 #[rstest]
1224 #[case::utf8(
1225 Arc::new(StringArray::from(vec![Some("hello"), None, Some("world"), Some("test")])),
1226 Arc::new(StringArray::from(vec!["hello", "world", "test", "vortex"])),
1227 DType::Utf8(Nullability::NonNullable),
1228 )]
1229 #[case::large_utf8(
1230 Arc::new(LargeStringArray::from(vec![Some("hello"), None, Some("world"), Some("test")])),
1231 Arc::new(LargeStringArray::from(vec!["hello", "world", "test", "vortex"])),
1232 DType::Utf8(Nullability::NonNullable),
1233 )]
1234 #[case::binary(
1235 Arc::new(BinaryArray::from(vec![
1236 Some("hello".as_bytes()), None, Some("world".as_bytes()), Some("test".as_bytes()),
1237 ])),
1238 Arc::new(BinaryArray::from(vec![
1239 "hello".as_bytes(), "world".as_bytes(), "test".as_bytes(), "vortex".as_bytes(),
1240 ])),
1241 DType::Binary(Nullability::NonNullable),
1242 )]
1243 #[case::large_binary(
1244 Arc::new(LargeBinaryArray::from(vec![
1245 Some("hello".as_bytes()), None, Some("world".as_bytes()), Some("test".as_bytes()),
1246 ])),
1247 Arc::new(LargeBinaryArray::from(vec![
1248 "hello".as_bytes(), "world".as_bytes(), "test".as_bytes(), "vortex".as_bytes(),
1249 ])),
1250 DType::Binary(Nullability::NonNullable),
1251 )]
1252 fn test_string_binary_array_conversion(
1253 #[case] nullable: Arc<dyn ArrowArray>,
1254 #[case] non_nullable: Arc<dyn ArrowArray>,
1255 #[case] expected_non_nullable_dtype: DType,
1256 ) {
1257 let v_null = ArrayRef::from_arrow(nullable.as_ref(), true).unwrap();
1258 let v_non_null = ArrayRef::from_arrow(non_nullable.as_ref(), false).unwrap();
1259 assert_eq!(v_null.len(), 4);
1260 assert_eq!(v_non_null.len(), 4);
1261 assert_eq!(v_null.dtype(), &expected_non_nullable_dtype.as_nullable());
1262 assert_eq!(v_non_null.dtype(), &expected_non_nullable_dtype);
1263 }
1264
1265 #[test]
1266 fn test_utf8_view_array_conversion() {
1267 let mut builder = StringViewBuilder::new();
1268 builder.append_value("hello");
1269 builder.append_null();
1270 builder.append_value("world");
1271 builder.append_value("test");
1272 let arrow_array = builder.finish();
1273 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1274
1275 let mut builder_non_null = StringViewBuilder::new();
1276 builder_non_null.append_value("hello");
1277 builder_non_null.append_value("world");
1278 builder_non_null.append_value("test");
1279 builder_non_null.append_value("vortex");
1280 let arrow_array_non_null = builder_non_null.finish();
1281 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1282
1283 assert_eq!(vortex_array.len(), 4);
1284 assert_eq!(vortex_array_non_null.len(), 4);
1285
1286 let varbin_view_array = vortex_array.as_::<VarBinView>();
1288 assert_eq!(
1289 varbin_view_array.data_buffers().len(),
1290 arrow_array.data_buffers().len()
1291 );
1292 assert_eq!(varbin_view_array.dtype(), &DType::Utf8(true.into()));
1293
1294 let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinView>();
1295 assert_eq!(
1296 varbin_view_array_non_null.data_buffers().len(),
1297 arrow_array_non_null.data_buffers().len()
1298 );
1299 assert_eq!(
1300 varbin_view_array_non_null.dtype(),
1301 &DType::Utf8(false.into())
1302 );
1303 }
1304
1305 #[test]
1306 fn test_binary_view_array_conversion() {
1307 let mut builder = BinaryViewBuilder::new();
1308 builder.append_value(b"hello");
1309 builder.append_null();
1310 builder.append_value(b"world");
1311 builder.append_value(b"test");
1312 let arrow_array = builder.finish();
1313 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1314
1315 let mut builder_non_null = BinaryViewBuilder::new();
1316 builder_non_null.append_value(b"hello");
1317 builder_non_null.append_value(b"world");
1318 builder_non_null.append_value(b"test");
1319 builder_non_null.append_value(b"vortex");
1320 let arrow_array_non_null = builder_non_null.finish();
1321 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1322
1323 assert_eq!(vortex_array.len(), 4);
1324 assert_eq!(vortex_array_non_null.len(), 4);
1325
1326 let varbin_view_array = vortex_array.as_::<VarBinView>();
1328 assert_eq!(
1329 varbin_view_array.data_buffers().len(),
1330 arrow_array.data_buffers().len()
1331 );
1332 assert_eq!(varbin_view_array.dtype(), &DType::Binary(true.into()));
1333
1334 let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinView>();
1335 assert_eq!(
1336 varbin_view_array_non_null.data_buffers().len(),
1337 arrow_array_non_null.data_buffers().len()
1338 );
1339 assert_eq!(
1340 varbin_view_array_non_null.dtype(),
1341 &DType::Binary(false.into())
1342 );
1343 }
1344
1345 #[test]
1347 fn test_boolean_array_conversion() {
1348 let arrow_array = BooleanArray::from(vec![Some(true), None, Some(false), Some(true)]);
1349 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1350
1351 let arrow_array_non_null = BooleanArray::from(vec![true, false, true, false]);
1352 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1353
1354 assert_eq!(vortex_array.len(), 4);
1355 assert_eq!(vortex_array_non_null.len(), 4);
1356 }
1357
1358 #[test]
1360 fn test_struct_array_conversion() {
1361 let fields = vec![
1362 Field::new("field1", DataType::Int32, true),
1363 Field::new("field2", DataType::Utf8, false),
1364 ];
1365 let schema = Fields::from(fields);
1366
1367 let field1_data = Int32Array::from(vec![Some(1), None, Some(3)]);
1368 let field2_data = StringArray::from(vec!["a", "b", "c"]);
1369
1370 let arrow_array = StructArray::new(
1371 schema.clone(),
1372 vec![Arc::new(field1_data), Arc::new(field2_data)],
1373 None,
1374 );
1375
1376 let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1377 assert_eq!(vortex_array.len(), 3);
1378
1379 let struct_vortex_array = vortex_array.as_::<Struct>();
1381 assert_eq!(struct_vortex_array.names().len(), 2);
1382 assert_eq!(struct_vortex_array.names()[0], "field1");
1383 assert_eq!(struct_vortex_array.names()[1], "field2");
1384
1385 let nullable_array = StructArray::new(
1387 schema,
1388 vec![
1389 Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])),
1390 Arc::new(StringArray::from(vec!["a", "b", "c"])),
1391 ],
1392 Some(arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![
1393 true, false, true,
1394 ]))),
1395 );
1396
1397 let vortex_nullable_array = ArrayRef::from_arrow(&nullable_array, true).unwrap();
1398 assert_eq!(vortex_nullable_array.len(), 3);
1399
1400 let struct_vortex_nullable_array = vortex_nullable_array.as_::<Struct>();
1402 assert_eq!(struct_vortex_nullable_array.names().len(), 2);
1403 assert_eq!(struct_vortex_nullable_array.names()[0], "field1");
1404 assert_eq!(struct_vortex_nullable_array.names()[1], "field2");
1405 }
1406
1407 #[test]
1409 fn test_list_array_conversion() {
1410 let mut builder = ListBuilder::new(Int32Builder::new());
1411 builder.append_value([Some(1), None, Some(3)]);
1412 builder.append_null();
1413 builder.append_value([Some(4), Some(5)]);
1414 let arrow_array = builder.finish();
1415
1416 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1417 assert_eq!(vortex_array.len(), 3);
1418
1419 let list_vortex_array = vortex_array.as_::<List>();
1421 let offsets_array = list_vortex_array.offsets().as_::<Primitive>();
1422 assert_eq!(offsets_array.len(), 4); assert_eq!(offsets_array.ptype(), PType::I32);
1424
1425 let mut builder_non_null = ListBuilder::new(Int32Builder::new());
1427 builder_non_null.append_value([Some(1), None, Some(3)]);
1428 builder_non_null.append_value([Some(4), Some(5)]);
1429 let arrow_array_non_null = builder_non_null.finish();
1430
1431 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1432 assert_eq!(vortex_array_non_null.len(), 2);
1433
1434 let list_vortex_array_non_null = vortex_array_non_null.as_::<List>();
1436 let offsets_array_non_null = list_vortex_array_non_null.offsets().as_::<Primitive>();
1437 assert_eq!(offsets_array_non_null.len(), 3); assert_eq!(offsets_array_non_null.ptype(), PType::I32);
1439 }
1440
1441 #[test]
1442 fn test_large_list_array_conversion() {
1443 let mut builder = LargeListBuilder::new(Int32Builder::new());
1444 builder.append_value([Some(1), None, Some(3)]);
1445 builder.append_null();
1446 builder.append_value([Some(4), Some(5)]);
1447 let arrow_array = builder.finish();
1448
1449 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1450 assert_eq!(vortex_array.len(), 3);
1451
1452 let list_vortex_array = vortex_array.as_::<List>();
1454 let offsets_array = list_vortex_array.offsets().as_::<Primitive>();
1455 assert_eq!(offsets_array.len(), 4); assert_eq!(offsets_array.ptype(), PType::I64); let mut builder_non_null = LargeListBuilder::new(Int32Builder::new());
1460 builder_non_null.append_value([Some(1), None, Some(3)]);
1461 builder_non_null.append_value([Some(4), Some(5)]);
1462 let arrow_array_non_null = builder_non_null.finish();
1463
1464 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1465 assert_eq!(vortex_array_non_null.len(), 2);
1466
1467 let list_vortex_array_non_null = vortex_array_non_null.as_::<List>();
1469 let offsets_array_non_null = list_vortex_array_non_null.offsets().as_::<Primitive>();
1470 assert_eq!(offsets_array_non_null.len(), 3); assert_eq!(offsets_array_non_null.ptype(), PType::I64); }
1473
1474 #[test]
1475 fn test_fixed_size_list_array_conversion() {
1476 let values = Int32Array::from(vec![
1478 Some(1),
1479 Some(2),
1480 Some(3), Some(4),
1482 None,
1483 Some(6), Some(7),
1485 Some(8),
1486 Some(9), Some(10),
1488 Some(11),
1489 Some(12), ]);
1491
1492 let field = Arc::new(Field::new("item", DataType::Int32, true));
1494 let arrow_array =
1495 ArrowFixedSizeListArray::try_new(Arc::clone(&field), 3, Arc::new(values), None)
1496 .unwrap();
1497 let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1498
1499 assert_eq!(vortex_array.len(), 4);
1500
1501 let fsl_vortex_array = vortex_array.as_::<FixedSizeList>();
1503 assert_eq!(fsl_vortex_array.list_size(), 3);
1504 assert_eq!(fsl_vortex_array.elements().len(), 12); let values_nullable = Int32Array::from(vec![
1508 Some(1),
1509 Some(2),
1510 Some(3), Some(4),
1512 None,
1513 Some(6), Some(7),
1515 Some(8),
1516 Some(9), ]);
1518
1519 let null_buffer =
1521 arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![true, false, true]));
1522
1523 let arrow_array_nullable = ArrowFixedSizeListArray::try_new(
1524 field,
1525 3,
1526 Arc::new(values_nullable),
1527 Some(null_buffer),
1528 )
1529 .unwrap();
1530 let vortex_array_nullable = ArrayRef::from_arrow(&arrow_array_nullable, true).unwrap();
1531
1532 assert_eq!(vortex_array_nullable.len(), 3);
1533
1534 let fsl_vortex_array_nullable = vortex_array_nullable.as_::<FixedSizeList>();
1536 assert_eq!(fsl_vortex_array_nullable.list_size(), 3);
1537 assert_eq!(fsl_vortex_array_nullable.elements().len(), 9); }
1539
1540 #[test]
1541 fn test_list_view_array_conversion() {
1542 let values = Int32Array::from(vec![
1544 Some(1),
1545 Some(2),
1546 Some(3), Some(4),
1548 Some(5), Some(6), Some(7),
1551 Some(8),
1552 Some(9),
1553 Some(10), ]);
1555
1556 let offsets = ScalarBuffer::from(vec![0i32, 3, 5, 6]);
1558 let sizes = ScalarBuffer::from(vec![3i32, 2, 1, 4]);
1559
1560 let field = Arc::new(Field::new("item", DataType::Int32, true));
1561 let arrow_array = GenericListViewArray::try_new(
1562 Arc::clone(&field),
1563 offsets.clone(),
1564 sizes.clone(),
1565 Arc::new(values.clone()),
1566 None,
1567 )
1568 .unwrap();
1569
1570 let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1571 assert_eq!(vortex_array.len(), 4);
1572
1573 let list_view_vortex_array = vortex_array.as_::<ListView>();
1575 let offsets_array = list_view_vortex_array.offsets().as_::<Primitive>();
1576 let sizes_array = list_view_vortex_array.sizes().as_::<Primitive>();
1577
1578 assert_eq!(offsets_array.len(), 4);
1579 assert_eq!(offsets_array.ptype(), PType::I32);
1580 assert_eq!(sizes_array.len(), 4);
1581 assert_eq!(sizes_array.ptype(), PType::I32);
1582
1583 let null_buffer =
1585 arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![true, false, true, true]));
1586
1587 let arrow_array_nullable = GenericListViewArray::try_new(
1588 Arc::clone(&field),
1589 offsets,
1590 sizes,
1591 Arc::new(values.clone()),
1592 Some(null_buffer),
1593 )
1594 .unwrap();
1595
1596 let vortex_array_nullable = ArrayRef::from_arrow(&arrow_array_nullable, true).unwrap();
1597 assert_eq!(vortex_array_nullable.len(), 4);
1598
1599 let large_offsets = ScalarBuffer::from(vec![0i64, 3, 5, 6]);
1601 let large_sizes = ScalarBuffer::from(vec![3i64, 2, 1, 4]);
1602
1603 let large_arrow_array = GenericListViewArray::try_new(
1604 field,
1605 large_offsets,
1606 large_sizes,
1607 Arc::new(values),
1608 None,
1609 )
1610 .unwrap();
1611
1612 let large_vortex_array = ArrayRef::from_arrow(&large_arrow_array, false).unwrap();
1613 assert_eq!(large_vortex_array.len(), 4);
1614
1615 let large_list_view_vortex_array = large_vortex_array.as_::<ListView>();
1617 let large_offsets_array = large_list_view_vortex_array.offsets().as_::<Primitive>();
1618 let large_sizes_array = large_list_view_vortex_array.sizes().as_::<Primitive>();
1619
1620 assert_eq!(large_offsets_array.len(), 4);
1621 assert_eq!(large_offsets_array.ptype(), PType::I64); assert_eq!(large_sizes_array.len(), 4);
1623 assert_eq!(large_sizes_array.ptype(), PType::I64); }
1625
1626 #[test]
1628 fn test_null_array_conversion() {
1629 let arrow_array = NullArray::new(5);
1630 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1631 assert_eq!(vortex_array.len(), 5);
1632 }
1633
1634 #[test]
1636 fn test_arrow_buffer_conversion() {
1637 let data = vec![1u8, 2, 3, 4, 5];
1638 let arrow_buffer = ArrowBuffer::from_vec(data);
1639 let vortex_array = arrow_buffer.into_array();
1640 assert_eq!(vortex_array.len(), 5);
1641 }
1642
1643 #[test]
1644 fn test_boolean_buffer_conversion() {
1645 let data = vec![true, false, true, false, true];
1646 let boolean_buffer = BooleanBuffer::from(data);
1647 let vortex_array = boolean_buffer.into_array();
1648 assert_eq!(vortex_array.len(), 5);
1649 }
1650
1651 #[test]
1652 fn test_scalar_buffer_conversion() {
1653 let data = vec![1i32, 2, 3, 4, 5];
1654 let scalar_buffer = ScalarBuffer::from(data);
1655 let vortex_array = scalar_buffer.into_array();
1656 assert_eq!(vortex_array.len(), 5);
1657 }
1658
1659 #[test]
1660 fn test_offset_buffer_conversion() {
1661 let data = vec![0i32, 2, 5, 8, 10];
1662 let offset_buffer = OffsetBuffer::new(ScalarBuffer::from(data));
1663 let vortex_array = offset_buffer.into_array();
1664 assert_eq!(vortex_array.len(), 5);
1665 }
1666
1667 #[test]
1669 fn test_record_batch_conversion() {
1670 let schema = Arc::new(Schema::new(vec![
1671 Field::new("field1", DataType::Int32, false),
1672 Field::new("field2", DataType::Utf8, false),
1673 ]));
1674
1675 let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1676 let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1677
1678 let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1679
1680 let vortex_array = ArrayRef::from_arrow(record_batch, false).unwrap();
1681 assert_eq!(vortex_array.len(), 4);
1682
1683 let schema = Arc::new(Schema::new(vec![
1685 Field::new("field1", DataType::Int32, false),
1686 Field::new("field2", DataType::Utf8, false),
1687 ]));
1688
1689 let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1690 let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1691
1692 let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1693
1694 let vortex_array = ArrayRef::from_arrow(&record_batch, false).unwrap();
1695 assert_eq!(vortex_array.len(), 4);
1696 }
1697
1698 #[test]
1700 fn test_dyn_array_conversion() {
1701 let int_array = Int32Array::from(vec![1, 2, 3, 4]);
1702 let dyn_array: &dyn ArrowArray = &int_array;
1703 let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1704 assert_eq!(vortex_array.len(), 4);
1705
1706 let string_array = StringArray::from(vec!["a", "b", "c"]);
1707 let dyn_array: &dyn ArrowArray = &string_array;
1708 let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1709 assert_eq!(vortex_array.len(), 3);
1710
1711 let bool_array = BooleanArray::from(vec![true, false, true]);
1712 let dyn_array: &dyn ArrowArray = &bool_array;
1713 let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1714 assert_eq!(vortex_array.len(), 3);
1715 }
1716
1717 #[test]
1719 pub fn nullable_may_contain_non_nullable() {
1720 let null_struct_array_with_non_nullable_field = new_null_array(
1721 &DataType::Struct(Fields::from(vec![Field::new(
1722 "non_nullable_inner",
1723 DataType::Int32,
1724 false,
1725 )])),
1726 1,
1727 );
1728 ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).unwrap();
1729 }
1730
1731 #[test]
1732 pub fn nullable_may_contain_deeply_nested_non_nullable() {
1733 let null_struct_array_with_non_nullable_field = new_null_array(
1734 &DataType::Struct(Fields::from(vec![Field::new(
1735 "non_nullable_inner",
1736 DataType::Struct(Fields::from(vec![Field::new(
1737 "non_nullable_deeper_inner",
1738 DataType::Int32,
1739 false,
1740 )])),
1741 false,
1742 )])),
1743 1,
1744 );
1745 ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).unwrap();
1746 }
1747
1748 #[test]
1749 fn dyn_dispatch_imports_map() -> VortexResult<()> {
1750 let mut builder = ArrowMapBuilder::new(None, StringBuilder::new(), Int32Builder::new());
1751 builder.keys().append_value("joe");
1752 builder.values().append_value(1);
1753 builder.append(true)?;
1754 builder.append(false)?;
1755 let arrow = builder.finish();
1756
1757 let expected = DType::map(
1758 DType::Utf8(Nullability::NonNullable),
1759 DType::Primitive(PType::I32, Nullability::Nullable),
1760 false,
1761 Nullability::Nullable,
1762 )?;
1763
1764 assert_eq!(from_arrow_dyn(&arrow, true)?.dtype(), &expected);
1766
1767 let batch = RecordBatch::try_from_iter_with_nullable([(
1769 "maps",
1770 Arc::new(arrow) as Arc<dyn ArrowArray>,
1771 true,
1772 )])?;
1773 let imported = from_arrow_batch(&batch, false)?;
1774 assert_eq!(
1775 imported.as_::<Struct>().unmasked_field(0).dtype(),
1776 &expected
1777 );
1778
1779 Ok(())
1780 }
1781
1782 #[test]
1783 fn non_nullable_request_rejects_nulls() {
1784 let arrow_array = Int32Array::from(vec![Some(1), None, Some(3)]);
1787 assert!(ArrayRef::from_arrow(&arrow_array, false).is_err());
1788 }
1789
1790 #[test]
1791 fn non_nullable_request_rejects_null_array() {
1792 let arrow_array = NullArray::new(5);
1795 assert!(ArrayRef::from_arrow(&arrow_array, false).is_err());
1796 }
1797
1798 #[test]
1799 fn non_nullable_struct_with_nulls_errors() {
1800 let struct_array = new_null_array(
1803 &DataType::Struct(Fields::from(vec![Field::new("a", DataType::Int32, true)])),
1804 3,
1805 );
1806 assert!(ArrayRef::from_arrow(struct_array.as_ref(), false).is_err());
1807 }
1808
1809 #[test]
1810 fn non_nullable_list_with_nulls_errors() {
1811 let mut builder = ListBuilder::new(Int32Builder::new());
1814 builder.append_value([Some(1), Some(2)]);
1815 builder.append_null();
1816 let list = builder.finish();
1817 assert!(ArrayRef::from_arrow(&list, false).is_err());
1818 }
1819
1820 #[test]
1821 pub fn nullable_struct_containing_non_nullable_dictionary_with_nulls_errors() {
1822 let null_struct_array_with_non_nullable_field = new_null_array(
1826 &DataType::Struct(Fields::from(vec![Field::new(
1827 "non_nullable_deeper_inner",
1828 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1829 false,
1830 )])),
1831 1,
1832 );
1833
1834 assert!(
1835 ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).is_err()
1836 );
1837 }
1838}