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(_) => unimplemented!(),
344 DataType::Interval(_) => unimplemented!(),
345 _ => vortex_panic!("Invalid temporal type: {}", value.data_type()),
346 })
347}
348
349pub fn from_arrow_bytes<T: ByteArrayType>(
351 value: &GenericByteArray<T>,
352 nullable: bool,
353) -> VortexResult<ArrayRef>
354where
355 <T as ByteArrayType>::Offset: IntegerPType,
356{
357 let dtype = match T::DATA_TYPE {
358 DataType::Binary | DataType::LargeBinary => DType::Binary(nullable.into()),
359 DataType::Utf8 | DataType::LargeUtf8 => DType::Utf8(nullable.into()),
360 dt => vortex_panic!("Invalid data type for ByteArray: {dt}"),
361 };
362 Ok(unsafe {
364 VarBinArray::new_unchecked(
365 value.offsets().clone().into_array(),
366 ByteBuffer::from_arrow_buffer(value.values().clone(), Alignment::of::<u8>()),
367 dtype,
368 nulls(value.nulls(), nullable)?,
369 )
370 }
371 .into_array())
372}
373
374impl<T: ByteArrayType> FromArrowArray<&GenericByteArray<T>> for ArrayRef
375where
376 <T as ByteArrayType>::Offset: IntegerPType,
377{
378 fn from_arrow(value: &GenericByteArray<T>, nullable: bool) -> VortexResult<Self> {
379 from_arrow_bytes(value, nullable)
380 }
381}
382
383pub fn from_arrow_byte_view<T: ByteViewType>(
385 value: &GenericByteViewArray<T>,
386 nullable: bool,
387) -> VortexResult<ArrayRef> {
388 let dtype = match T::DATA_TYPE {
389 DataType::BinaryView => DType::Binary(nullable.into()),
390 DataType::Utf8View => DType::Utf8(nullable.into()),
391 dt => vortex_panic!("Invalid data type for ByteViewArray: {dt}"),
392 };
393
394 let views_buffer = Buffer::from_byte_buffer(
395 Buffer::from_arrow_scalar_buffer(value.views().clone()).into_byte_buffer(),
396 );
397
398 Ok(unsafe {
401 VarBinViewArray::new_unchecked(
402 views_buffer,
403 Arc::from(
404 value
405 .data_buffers()
406 .iter()
407 .map(|b| ByteBuffer::from_arrow_buffer(b.clone(), Alignment::of::<u8>()))
408 .collect::<Vec<_>>(),
409 ),
410 dtype,
411 nulls(value.nulls(), nullable)?,
412 )
413 .into_array()
414 })
415}
416
417impl<T: ByteViewType> FromArrowArray<&GenericByteViewArray<T>> for ArrayRef {
418 fn from_arrow(value: &GenericByteViewArray<T>, nullable: bool) -> VortexResult<Self> {
419 from_arrow_byte_view(value, nullable)
420 }
421}
422
423pub fn from_arrow_boolean(value: &ArrowBooleanArray, nullable: bool) -> VortexResult<ArrayRef> {
425 Ok(BoolArray::new(
426 value.values().clone().into(),
427 nulls(value.nulls(), nullable)?,
428 )
429 .into_array())
430}
431
432impl FromArrowArray<&ArrowBooleanArray> for ArrayRef {
433 fn from_arrow(value: &ArrowBooleanArray, nullable: bool) -> VortexResult<Self> {
434 from_arrow_boolean(value, nullable)
435 }
436}
437
438pub(crate) fn remove_nulls(data: arrow_data::ArrayData) -> VortexResult<arrow_data::ArrayData> {
440 if data.null_count() == 0 {
441 return Ok(data);
443 }
444
445 let children = match data.data_type() {
446 DataType::Struct(fields) => Some(
447 fields
448 .iter()
449 .zip(data.child_data().iter())
450 .map(|(field, child_data)| {
451 if field.is_nullable() {
452 Ok(child_data.clone())
453 } else {
454 remove_nulls(child_data.clone())
455 }
456 })
457 .collect::<VortexResult<Vec<_>>>()?,
458 ),
459 DataType::List(f)
460 | DataType::LargeList(f)
461 | DataType::ListView(f)
462 | DataType::LargeListView(f)
463 | DataType::FixedSizeList(f, _)
464 if !f.is_nullable() =>
465 {
466 vortex_ensure_eq!(
468 data.child_data().len(),
469 1,
470 "List types should have one child"
471 );
472 Some(vec![remove_nulls(data.child_data()[0].clone())?])
473 }
474 _ => None,
475 };
476
477 let mut builder = data.into_builder().nulls(None);
478 if let Some(children) = children {
479 builder = builder.child_data(children);
480 }
481 builder
482 .build()
483 .map_err(|e| vortex_err!("Failed to reconstruct Arrow array without nulls: {e}"))
484}
485
486pub fn from_arrow_struct(value: &ArrowStructArray, nullable: bool) -> VortexResult<ArrayRef> {
488 Ok(StructArray::try_new(
489 value.column_names().iter().copied().collect(),
490 value
491 .columns()
492 .iter()
493 .zip(value.fields())
494 .map(|(c, field)| {
495 if c.null_count() > 0 && !field.is_nullable() {
498 let stripped = make_array(remove_nulls(c.into_data())?);
499 from_arrow_dyn(stripped.as_ref(), false)
500 } else {
501 from_arrow_dyn(c.as_ref(), field.is_nullable())
502 }
503 })
504 .collect::<VortexResult<Vec<_>>>()?,
505 value.len(),
506 nulls(value.nulls(), nullable)?,
507 )?
508 .into_array())
509}
510
511impl FromArrowArray<&ArrowStructArray> for ArrayRef {
512 fn from_arrow(value: &ArrowStructArray, nullable: bool) -> VortexResult<Self> {
513 from_arrow_struct(value, nullable)
514 }
515}
516
517pub fn from_arrow_list<O: IntegerPType + OffsetSizeTrait>(
519 value: &GenericListArray<O>,
520 nullable: bool,
521) -> VortexResult<ArrayRef> {
522 let elements_are_nullable = match value.data_type() {
524 DataType::List(field) => field.is_nullable(),
525 DataType::LargeList(field) => field.is_nullable(),
526 dt => vortex_panic!("Invalid data type for ListArray: {dt}"),
527 };
528
529 let elements = from_arrow_dyn(value.values().as_ref(), elements_are_nullable)?;
530
531 let offsets = value.offsets().clone().into_array();
533 let nulls = nulls(value.nulls(), nullable)?;
534
535 Ok(ListArray::try_new(elements, offsets, nulls)?.into_array())
536}
537
538impl<O: IntegerPType + OffsetSizeTrait> FromArrowArray<&GenericListArray<O>> for ArrayRef {
539 fn from_arrow(value: &GenericListArray<O>, nullable: bool) -> VortexResult<Self> {
540 from_arrow_list(value, nullable)
541 }
542}
543
544pub fn from_arrow_list_view<O: OffsetSizeTrait + NativePType>(
546 array: &GenericListViewArray<O>,
547 nullable: bool,
548) -> VortexResult<ArrayRef> {
549 let elements_are_nullable = match array.data_type() {
551 DataType::ListView(field) => field.is_nullable(),
552 DataType::LargeListView(field) => field.is_nullable(),
553 dt => vortex_panic!("Invalid data type for ListViewArray: {dt}"),
554 };
555
556 let elements = from_arrow_dyn(array.values().as_ref(), elements_are_nullable)?;
557
558 let offsets = array.offsets().clone().into_array();
560 let sizes = array.sizes().clone().into_array();
561 let nulls = nulls(array.nulls(), nullable)?;
562
563 Ok(ListViewArray::try_new(elements, offsets, sizes, nulls)?.into_array())
564}
565
566impl<O: OffsetSizeTrait + NativePType> FromArrowArray<&GenericListViewArray<O>> for ArrayRef {
567 fn from_arrow(array: &GenericListViewArray<O>, nullable: bool) -> VortexResult<Self> {
568 from_arrow_list_view(array, nullable)
569 }
570}
571
572pub fn from_arrow_fixed_size_list(
574 array: &ArrowFixedSizeListArray,
575 nullable: bool,
576) -> VortexResult<ArrayRef> {
577 let DataType::FixedSizeList(field, list_size) = array.data_type() else {
578 vortex_panic!("Invalid data type for ListArray: {}", array.data_type());
579 };
580
581 Ok(FixedSizeListArray::try_new(
582 from_arrow_dyn(array.values().as_ref(), field.is_nullable())?,
583 *list_size as u32,
584 nulls(array.nulls(), nullable)?,
585 array.len(),
586 )?
587 .into_array())
588}
589
590impl FromArrowArray<&ArrowFixedSizeListArray> for ArrayRef {
591 fn from_arrow(array: &ArrowFixedSizeListArray, nullable: bool) -> VortexResult<Self> {
592 from_arrow_fixed_size_list(array, nullable)
593 }
594}
595
596pub(crate) fn map_from_arrow_parts(
597 entries: ArrayRef,
598 offsets: &OffsetBuffer<i32>,
599 arrow_nulls: Option<&NullBuffer>,
600 keys_sorted: bool,
601 nullable: bool,
602) -> VortexResult<ArrayRef> {
603 let DType::Struct(struct_dtype, Nullability::NonNullable) = entries.dtype() else {
604 vortex_bail!(
605 "Arrow map entries must import as non-nullable struct, got {}",
606 entries.dtype()
607 );
608 };
609 vortex_ensure!(
610 struct_dtype.nfields() == 2,
611 "Arrow map entries struct must contain exactly two fields"
612 );
613
614 let key_dtype = struct_dtype
615 .field_by_index(0)
616 .ok_or_else(|| vortex_err!("Arrow map entries struct missing key field"))?;
617 vortex_ensure!(
618 !key_dtype.is_nullable(),
619 "Arrow map key field must be non-nullable"
620 );
621 let value_dtype = struct_dtype
622 .field_by_index(1)
623 .ok_or_else(|| vortex_err!("Arrow map entries struct missing value field"))?;
624 let map_dtype = MapDType::try_new(key_dtype, value_dtype, keys_sorted)?;
625 let entries_struct = entries.as_::<Struct>();
626 let entries = StructArray::try_new(
627 FieldNames::from(["key", "value"]),
628 vec![
629 entries_struct.unmasked_field(0).clone(),
630 entries_struct.unmasked_field(1).clone(),
631 ],
632 entries.len(),
633 Validity::NonNullable,
634 )?
635 .into_array();
636
637 let len = offsets.len() - 1;
638 let sizes = Buffer::<i32>::from_iter(offsets.windows(2).map(|window| window[1] - window[0]))
639 .into_array();
640 let offsets = offsets.inner().slice(0, len).into_array();
641 let validity = nulls(arrow_nulls, nullable)?;
642 let entries = ListViewArray::try_new(entries, offsets, sizes, validity)?;
643 let entries = unsafe { entries.with_zero_copy_to_list(true) };
647
648 Ok(MapArray::try_new(map_dtype, entries)?.into_array())
649}
650
651pub fn from_arrow_map(array: &ArrowMapArray, nullable: bool) -> VortexResult<ArrayRef> {
653 let DataType::Map(_, keys_sorted) = array.data_type() else {
654 vortex_panic!("Invalid data type for MapArray: {}", array.data_type());
655 };
656 let entries = from_arrow_struct(array.entries(), false)?;
657 map_from_arrow_parts(
658 entries,
659 array.offsets(),
660 array.nulls(),
661 *keys_sorted,
662 nullable,
663 )
664}
665
666impl FromArrowArray<&ArrowMapArray> for ArrayRef {
667 fn from_arrow(array: &ArrowMapArray, nullable: bool) -> VortexResult<Self> {
668 from_arrow_map(array, nullable)
669 }
670}
671
672pub fn from_arrow_null(value: &ArrowNullArray, nullable: bool) -> VortexResult<ArrayRef> {
674 vortex_ensure!(
675 nullable,
676 "Cannot convert an Arrow NullArray into a non-nullable Vortex array"
677 );
678 Ok(NullArray::new(value.len()).into_array())
679}
680
681impl FromArrowArray<&ArrowNullArray> for ArrayRef {
682 fn from_arrow(value: &ArrowNullArray, nullable: bool) -> VortexResult<Self> {
683 from_arrow_null(value, nullable)
684 }
685}
686
687pub fn from_arrow_dictionary<K: ArrowDictionaryKeyType>(
689 array: &DictionaryArray<K>,
690 nullable: bool,
691) -> VortexResult<DictArray> {
692 let keys = AnyDictionaryArray::keys(array);
693 let keys = from_arrow_dyn(keys, keys.is_nullable())?;
694 let values = from_arrow_dyn(array.values().as_ref(), nullable)?;
695 Ok(unsafe { DictArray::new_unchecked(keys, values) })
697}
698
699impl<K: ArrowDictionaryKeyType> FromArrowArray<&DictionaryArray<K>> for DictArray {
700 fn from_arrow(array: &DictionaryArray<K>, nullable: bool) -> VortexResult<Self> {
701 from_arrow_dictionary(array, nullable)
702 }
703}
704
705pub(crate) fn nulls(nulls: Option<&NullBuffer>, nullable: bool) -> VortexResult<Validity> {
706 if nullable {
707 Ok(nulls
708 .map(|nulls| {
709 if nulls.null_count() == nulls.len() {
710 Validity::AllInvalid
711 } else {
712 Validity::from(BitBuffer::from(nulls.inner().clone()))
713 }
714 })
715 .unwrap_or(Validity::AllValid))
716 } else {
717 let null_count = nulls.map(NullBuffer::null_count).unwrap_or(0);
718 vortex_ensure_eq!(
719 null_count,
720 0,
721 "Cannot convert an Arrow array containing {null_count} nulls into a non-nullable Vortex array"
722 );
723 Ok(Validity::NonNullable)
724 }
725}
726
727pub fn from_arrow_dyn(array: &dyn ArrowArray, nullable: bool) -> VortexResult<ArrayRef> {
730 match array.data_type() {
731 DataType::Boolean => from_arrow_boolean(array.as_boolean(), nullable),
732 DataType::UInt8 => from_arrow_primitive(array.as_primitive::<UInt8Type>(), nullable),
733 DataType::UInt16 => from_arrow_primitive(array.as_primitive::<UInt16Type>(), nullable),
734 DataType::UInt32 => from_arrow_primitive(array.as_primitive::<UInt32Type>(), nullable),
735 DataType::UInt64 => from_arrow_primitive(array.as_primitive::<UInt64Type>(), nullable),
736 DataType::Int8 => from_arrow_primitive(array.as_primitive::<Int8Type>(), nullable),
737 DataType::Int16 => from_arrow_primitive(array.as_primitive::<Int16Type>(), nullable),
738 DataType::Int32 => from_arrow_primitive(array.as_primitive::<Int32Type>(), nullable),
739 DataType::Int64 => from_arrow_primitive(array.as_primitive::<Int64Type>(), nullable),
740 DataType::Float16 => from_arrow_primitive(array.as_primitive::<Float16Type>(), nullable),
741 DataType::Float32 => from_arrow_primitive(array.as_primitive::<Float32Type>(), nullable),
742 DataType::Float64 => from_arrow_primitive(array.as_primitive::<Float64Type>(), nullable),
743 DataType::Utf8 => from_arrow_bytes(array.as_string::<i32>(), nullable),
744 DataType::LargeUtf8 => from_arrow_bytes(array.as_string::<i64>(), nullable),
745 DataType::Binary => from_arrow_bytes(array.as_binary::<i32>(), nullable),
746 DataType::LargeBinary => from_arrow_bytes(array.as_binary::<i64>(), nullable),
747 DataType::BinaryView => from_arrow_byte_view(array.as_binary_view(), nullable),
748 DataType::Utf8View => from_arrow_byte_view(array.as_string_view(), nullable),
749 DataType::Struct(_) => from_arrow_struct(array.as_struct(), nullable),
750 DataType::List(_) => from_arrow_list(array.as_list::<i32>(), nullable),
751 DataType::LargeList(_) => from_arrow_list(array.as_list::<i64>(), nullable),
752 DataType::ListView(_) => from_arrow_list_view(array.as_list_view::<i32>(), nullable),
753 DataType::LargeListView(_) => from_arrow_list_view(array.as_list_view::<i64>(), nullable),
754 DataType::FixedSizeList(..) => {
755 from_arrow_fixed_size_list(array.as_fixed_size_list(), nullable)
756 }
757 DataType::Map(..) => from_arrow_map(array.as_map(), nullable),
758 DataType::Null => from_arrow_null(as_null_array(array), nullable),
759 DataType::Timestamp(u, _) => match u {
760 ArrowTimeUnit::Second => {
761 from_arrow_temporal(array.as_primitive::<TimestampSecondType>(), nullable)
762 }
763 ArrowTimeUnit::Millisecond => {
764 from_arrow_temporal(array.as_primitive::<TimestampMillisecondType>(), nullable)
765 }
766 ArrowTimeUnit::Microsecond => {
767 from_arrow_temporal(array.as_primitive::<TimestampMicrosecondType>(), nullable)
768 }
769 ArrowTimeUnit::Nanosecond => {
770 from_arrow_temporal(array.as_primitive::<TimestampNanosecondType>(), nullable)
771 }
772 },
773 DataType::Date32 => from_arrow_temporal(array.as_primitive::<Date32Type>(), nullable),
774 DataType::Date64 => from_arrow_temporal(array.as_primitive::<Date64Type>(), nullable),
775 DataType::Time32(u) => match u {
776 ArrowTimeUnit::Second => {
777 from_arrow_temporal(array.as_primitive::<Time32SecondType>(), nullable)
778 }
779 ArrowTimeUnit::Millisecond => {
780 from_arrow_temporal(array.as_primitive::<Time32MillisecondType>(), nullable)
781 }
782 ArrowTimeUnit::Microsecond | ArrowTimeUnit::Nanosecond => unreachable!(),
783 },
784 DataType::Time64(u) => match u {
785 ArrowTimeUnit::Microsecond => {
786 from_arrow_temporal(array.as_primitive::<Time64MicrosecondType>(), nullable)
787 }
788 ArrowTimeUnit::Nanosecond => {
789 from_arrow_temporal(array.as_primitive::<Time64NanosecondType>(), nullable)
790 }
791 ArrowTimeUnit::Second | ArrowTimeUnit::Millisecond => unreachable!(),
792 },
793 DataType::Decimal32(..) => {
794 from_arrow_decimal32(array.as_primitive::<Decimal32Type>(), nullable)
795 }
796 DataType::Decimal64(..) => {
797 from_arrow_decimal64(array.as_primitive::<Decimal64Type>(), nullable)
798 }
799 DataType::Decimal128(..) => {
800 from_arrow_decimal128(array.as_primitive::<Decimal128Type>(), nullable)
801 }
802 DataType::Decimal256(..) => {
803 from_arrow_decimal256(array.as_primitive::<Decimal256Type>(), nullable)
804 }
805 DataType::Dictionary(key_type, _) => match key_type.as_ref() {
806 DataType::Int8 => Ok(from_arrow_dictionary(
807 array.as_dictionary::<Int8Type>(),
808 nullable,
809 )?
810 .into_array()),
811 DataType::Int16 => Ok(from_arrow_dictionary(
812 array.as_dictionary::<Int16Type>(),
813 nullable,
814 )?
815 .into_array()),
816 DataType::Int32 => Ok(from_arrow_dictionary(
817 array.as_dictionary::<Int32Type>(),
818 nullable,
819 )?
820 .into_array()),
821 DataType::Int64 => Ok(from_arrow_dictionary(
822 array.as_dictionary::<Int64Type>(),
823 nullable,
824 )?
825 .into_array()),
826 DataType::UInt8 => Ok(from_arrow_dictionary(
827 array.as_dictionary::<UInt8Type>(),
828 nullable,
829 )?
830 .into_array()),
831 DataType::UInt16 => Ok(from_arrow_dictionary(
832 array.as_dictionary::<UInt16Type>(),
833 nullable,
834 )?
835 .into_array()),
836 DataType::UInt32 => Ok(from_arrow_dictionary(
837 array.as_dictionary::<UInt32Type>(),
838 nullable,
839 )?
840 .into_array()),
841 DataType::UInt64 => Ok(from_arrow_dictionary(
842 array.as_dictionary::<UInt64Type>(),
843 nullable,
844 )?
845 .into_array()),
846 key_dt => vortex_bail!("Unsupported dictionary key type: {key_dt}"),
847 },
848 dt => vortex_bail!("Array encoding not implemented for Arrow data type {dt}"),
849 }
850}
851
852impl FromArrowArray<&dyn ArrowArray> for ArrayRef {
853 fn from_arrow(array: &dyn ArrowArray, nullable: bool) -> VortexResult<Self> {
854 from_arrow_dyn(array, nullable)
855 }
856}
857
858pub fn from_arrow_batch(batch: &RecordBatch, nullable: bool) -> VortexResult<ArrayRef> {
860 from_arrow_struct(&arrow_array::StructArray::from(batch.clone()), nullable)
861}
862
863impl FromArrowArray<RecordBatch> for ArrayRef {
864 fn from_arrow(array: RecordBatch, nullable: bool) -> VortexResult<Self> {
865 from_arrow_batch(&array, nullable)
866 }
867}
868
869impl FromArrowArray<&RecordBatch> for ArrayRef {
870 fn from_arrow(array: &RecordBatch, nullable: bool) -> VortexResult<Self> {
871 from_arrow_batch(array, nullable)
872 }
873}
874
875#[cfg(test)]
876mod tests {
877 use std::sync::Arc;
878
879 use arrow_array::Array as ArrowArray;
880 use arrow_array::BinaryArray;
881 use arrow_array::BooleanArray;
882 use arrow_array::Date32Array;
883 use arrow_array::Date64Array;
884 use arrow_array::FixedSizeListArray as ArrowFixedSizeListArray;
885 use arrow_array::Float32Array;
886 use arrow_array::Float64Array;
887 use arrow_array::GenericListViewArray;
888 use arrow_array::Int8Array;
889 use arrow_array::Int16Array;
890 use arrow_array::Int32Array;
891 use arrow_array::Int64Array;
892 use arrow_array::LargeBinaryArray;
893 use arrow_array::LargeStringArray;
894 use arrow_array::NullArray;
895 use arrow_array::RecordBatch;
896 use arrow_array::StringArray;
897 use arrow_array::StructArray;
898 use arrow_array::Time32MillisecondArray;
899 use arrow_array::Time32SecondArray;
900 use arrow_array::Time64MicrosecondArray;
901 use arrow_array::Time64NanosecondArray;
902 use arrow_array::TimestampMicrosecondArray;
903 use arrow_array::TimestampMillisecondArray;
904 use arrow_array::TimestampNanosecondArray;
905 use arrow_array::TimestampSecondArray;
906 use arrow_array::UInt8Array;
907 use arrow_array::UInt16Array;
908 use arrow_array::UInt32Array;
909 use arrow_array::UInt64Array;
910 use arrow_array::builder::BinaryViewBuilder;
911 use arrow_array::builder::Decimal128Builder;
912 use arrow_array::builder::Decimal256Builder;
913 use arrow_array::builder::Int32Builder;
914 use arrow_array::builder::LargeListBuilder;
915 use arrow_array::builder::ListBuilder;
916 use arrow_array::builder::MapBuilder as ArrowMapBuilder;
917 use arrow_array::builder::StringBuilder;
918 use arrow_array::builder::StringViewBuilder;
919 use arrow_array::new_null_array;
920 use arrow_array::types::ArrowPrimitiveType;
921 use arrow_array::types::Float16Type;
922 use arrow_buffer::BooleanBuffer;
923 use arrow_buffer::Buffer as ArrowBuffer;
924 use arrow_buffer::OffsetBuffer;
925 use arrow_buffer::ScalarBuffer;
926 use arrow_schema::DataType;
927 use arrow_schema::Field;
928 use arrow_schema::Fields;
929 use arrow_schema::Schema;
930 use rstest::rstest;
931 use vortex_array::ArrayRef;
932 use vortex_array::arrays::Decimal;
933 use vortex_array::arrays::FixedSizeList;
934 use vortex_array::arrays::List;
935 use vortex_array::arrays::ListView;
936 use vortex_array::arrays::Primitive;
937 use vortex_array::arrays::Struct;
938 use vortex_array::arrays::VarBinView;
939 use vortex_array::arrays::fixed_size_list::FixedSizeListArrayExt;
940 use vortex_array::arrays::fixed_size_list::FixedSizeListArraySlotsExt;
941 use vortex_array::arrays::list::ListArraySlotsExt;
942 use vortex_array::arrays::listview::ListViewArraySlotsExt;
943 use vortex_array::arrays::struct_::StructArrayExt;
944 use vortex_array::dtype::DType;
945 use vortex_array::dtype::Nullability;
946 use vortex_array::dtype::PType;
947 use vortex_array::extension::datetime::TimeUnit;
948 use vortex_array::extension::datetime::Timestamp;
949 use vortex_error::VortexResult;
950
951 use crate::FromArrowArray as _;
952 use crate::IntoVortexArray as _;
953 use crate::convert::from_arrow_batch;
954 use crate::convert::from_arrow_dyn;
955
956 #[rstest]
957 #[case::i8(
958 Arc::new(Int8Array::from(vec![Some(1), None, Some(3), Some(4)])),
959 Arc::new(Int8Array::from(vec![1, 2, 3, 4])),
960 PType::I8,
961 )]
962 #[case::i16(
963 Arc::new(Int16Array::from(vec![Some(100), None, Some(300), Some(400)])),
964 Arc::new(Int16Array::from(vec![100, 200, 300, 400])),
965 PType::I16,
966 )]
967 #[case::i32(
968 Arc::new(Int32Array::from(vec![Some(1000), None, Some(3000), Some(4000)])),
969 Arc::new(Int32Array::from(vec![1000, 2000, 3000, 4000])),
970 PType::I32,
971 )]
972 #[case::i64(
973 Arc::new(Int64Array::from(vec![Some(10000), None, Some(30000), Some(40000)])),
974 Arc::new(Int64Array::from(vec![10000_i64, 20000, 30000, 40000])),
975 PType::I64,
976 )]
977 #[case::u8(
978 Arc::new(UInt8Array::from(vec![Some(1), None, Some(3), Some(4)])),
979 Arc::new(UInt8Array::from(vec![1_u8, 2, 3, 4])),
980 PType::U8,
981 )]
982 #[case::u16(
983 Arc::new(UInt16Array::from(vec![Some(100), None, Some(300), Some(400)])),
984 Arc::new(UInt16Array::from(vec![100_u16, 200, 300, 400])),
985 PType::U16,
986 )]
987 #[case::u32(
988 Arc::new(UInt32Array::from(vec![Some(1000), None, Some(3000), Some(4000)])),
989 Arc::new(UInt32Array::from(vec![1000_u32, 2000, 3000, 4000])),
990 PType::U32,
991 )]
992 #[case::u64(
993 Arc::new(UInt64Array::from(vec![Some(10000), None, Some(30000), Some(40000)])),
994 Arc::new(UInt64Array::from(vec![10000_u64, 20000, 30000, 40000])),
995 PType::U64,
996 )]
997 #[case::f32(
998 Arc::new(Float32Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)])),
999 Arc::new(Float32Array::from(vec![1.5_f32, 2.5, 3.5, 4.5])),
1000 PType::F32,
1001 )]
1002 #[case::f64(
1003 Arc::new(Float64Array::from(vec![Some(1.5), None, Some(3.5), Some(4.5)])),
1004 Arc::new(Float64Array::from(vec![1.5_f64, 2.5, 3.5, 4.5])),
1005 PType::F64,
1006 )]
1007 fn test_primitive_array_conversion(
1008 #[case] nullable: Arc<dyn ArrowArray>,
1009 #[case] non_nullable: Arc<dyn ArrowArray>,
1010 #[case] expected_ptype: PType,
1011 ) {
1012 let v_null = ArrayRef::from_arrow(nullable.as_ref(), true).unwrap();
1013 let v_non_null = ArrayRef::from_arrow(non_nullable.as_ref(), false).unwrap();
1014 assert_eq!(v_null.len(), 4);
1015 assert_eq!(v_non_null.len(), 4);
1016 assert_eq!(v_null.as_::<Primitive>().ptype(), expected_ptype);
1017 assert_eq!(v_non_null.as_::<Primitive>().ptype(), expected_ptype);
1018 }
1019
1020 #[test]
1021 fn test_float16_array_conversion() {
1022 let values = vec![
1023 Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5)),
1024 None,
1025 Some(<Float16Type as ArrowPrimitiveType>::Native::from_f32(3.5)),
1026 ];
1027 let arrow_array = arrow_array::PrimitiveArray::<Float16Type>::from(values);
1028 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1029
1030 let non_null_values = vec![
1031 <Float16Type as ArrowPrimitiveType>::Native::from_f32(1.5),
1032 <Float16Type as ArrowPrimitiveType>::Native::from_f32(2.5),
1033 ];
1034 let arrow_array_non_null =
1035 arrow_array::PrimitiveArray::<Float16Type>::from(non_null_values);
1036 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1037
1038 assert_eq!(vortex_array.len(), 3);
1039 assert_eq!(vortex_array_non_null.len(), 2);
1040
1041 let primitive_array = vortex_array.as_::<Primitive>();
1043 assert_eq!(primitive_array.ptype(), PType::F16);
1044
1045 let primitive_array_non_null = vortex_array_non_null.as_::<Primitive>();
1046 assert_eq!(primitive_array_non_null.ptype(), PType::F16);
1047 }
1048
1049 #[test]
1051 fn test_decimal128_array_conversion() {
1052 let mut builder = Decimal128Builder::with_capacity(4);
1053 builder.append_value(12345);
1054 builder.append_null();
1055 builder.append_value(67890);
1056 builder.append_value(11111);
1057 let decimal_array = builder.finish().with_precision_and_scale(10, 2).unwrap();
1058
1059 let vortex_array = ArrayRef::from_arrow(&decimal_array, true).unwrap();
1060 assert_eq!(vortex_array.len(), 4);
1061
1062 let mut builder_non_null = Decimal128Builder::with_capacity(3);
1063 builder_non_null.append_value(12345);
1064 builder_non_null.append_value(67890);
1065 builder_non_null.append_value(11111);
1066 let decimal_array_non_null = builder_non_null
1067 .finish()
1068 .with_precision_and_scale(10, 2)
1069 .unwrap();
1070
1071 let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false).unwrap();
1072 assert_eq!(vortex_array_non_null.len(), 3);
1073
1074 let decimal_vortex_array = vortex_array.as_::<Decimal>();
1076 assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 10);
1077 assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 2);
1078
1079 let decimal_vortex_array_non_null = vortex_array_non_null.as_::<Decimal>();
1080 assert_eq!(
1081 decimal_vortex_array_non_null.decimal_dtype().precision(),
1082 10
1083 );
1084 assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 2);
1085 }
1086
1087 #[test]
1088 fn test_decimal256_array_conversion() {
1089 let mut builder = Decimal256Builder::with_capacity(4);
1090 builder.append_value(arrow_buffer::i256::from_i128(12345));
1091 builder.append_null();
1092 builder.append_value(arrow_buffer::i256::from_i128(67890));
1093 builder.append_value(arrow_buffer::i256::from_i128(11111));
1094 let decimal_array = builder.finish().with_precision_and_scale(38, 10).unwrap();
1095
1096 let vortex_array = ArrayRef::from_arrow(&decimal_array, true).unwrap();
1097 assert_eq!(vortex_array.len(), 4);
1098
1099 let mut builder_non_null = Decimal256Builder::with_capacity(3);
1100 builder_non_null.append_value(arrow_buffer::i256::from_i128(12345));
1101 builder_non_null.append_value(arrow_buffer::i256::from_i128(67890));
1102 builder_non_null.append_value(arrow_buffer::i256::from_i128(11111));
1103 let decimal_array_non_null = builder_non_null
1104 .finish()
1105 .with_precision_and_scale(38, 10)
1106 .unwrap();
1107
1108 let vortex_array_non_null = ArrayRef::from_arrow(&decimal_array_non_null, false).unwrap();
1109 assert_eq!(vortex_array_non_null.len(), 3);
1110
1111 let decimal_vortex_array = vortex_array.as_::<Decimal>();
1113 assert_eq!(decimal_vortex_array.decimal_dtype().precision(), 38);
1114 assert_eq!(decimal_vortex_array.decimal_dtype().scale(), 10);
1115
1116 let decimal_vortex_array_non_null = vortex_array_non_null.as_::<Decimal>();
1117 assert_eq!(
1118 decimal_vortex_array_non_null.decimal_dtype().precision(),
1119 38
1120 );
1121 assert_eq!(decimal_vortex_array_non_null.decimal_dtype().scale(), 10);
1122 }
1123
1124 #[rstest]
1126 #[case::timestamp_second(
1127 Arc::new(TimestampSecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1128 Arc::new(TimestampSecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1129 )]
1130 #[case::timestamp_millisecond(
1131 Arc::new(TimestampMillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1132 Arc::new(TimestampMillisecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1133 )]
1134 #[case::timestamp_microsecond(
1135 Arc::new(TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1136 Arc::new(TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1137 )]
1138 #[case::timestamp_nanosecond(
1139 Arc::new(TimestampNanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1140 Arc::new(TimestampNanosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1141 )]
1142 #[case::time32_second(
1143 Arc::new(Time32SecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1144 Arc::new(Time32SecondArray::from(vec![1000_i32, 2000, 3000, 4000])),
1145 )]
1146 #[case::time32_millisecond(
1147 Arc::new(Time32MillisecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1148 Arc::new(Time32MillisecondArray::from(vec![1000_i32, 2000, 3000, 4000])),
1149 )]
1150 #[case::time64_microsecond(
1151 Arc::new(Time64MicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1152 Arc::new(Time64MicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1153 )]
1154 #[case::time64_nanosecond(
1155 Arc::new(Time64NanosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])),
1156 Arc::new(Time64NanosecondArray::from(vec![1000_i64, 2000, 3000, 4000])),
1157 )]
1158 #[case::date32(
1159 Arc::new(Date32Array::from(vec![Some(18000), None, Some(18002), Some(18003)])),
1160 Arc::new(Date32Array::from(vec![18000_i32, 18001, 18002, 18003])),
1161 )]
1162 #[case::date64(
1163 Arc::new(Date64Array::from(vec![Some(1555200000000), None, Some(1555286400000), Some(1555372800000)]
1164 )),
1165 Arc::new(Date64Array::from(vec![1555200000000_i64, 1555213600000, 1555286400000, 1555372800000]
1166 )),
1167 )]
1168 fn test_temporal_array_conversion(
1169 #[case] nullable: Arc<dyn ArrowArray>,
1170 #[case] non_nullable: Arc<dyn ArrowArray>,
1171 ) {
1172 let v_null = ArrayRef::from_arrow(nullable.as_ref(), true).unwrap();
1173 let v_non_null = ArrayRef::from_arrow(non_nullable.as_ref(), false).unwrap();
1174 assert_eq!(v_null.len(), 4);
1175 assert_eq!(v_non_null.len(), 4);
1176 }
1177
1178 #[test]
1179 fn test_timestamp_timezone_microsecond_array_conversion() {
1180 let arrow_array =
1181 TimestampMicrosecondArray::from(vec![Some(1000), None, Some(3000), Some(4000)])
1182 .with_timezone("UTC");
1183 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1184
1185 let arrow_array_non_null =
1186 TimestampMicrosecondArray::from(vec![1000_i64, 2000, 3000, 4000]).with_timezone("UTC");
1187 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1188
1189 assert_eq!(vortex_array.len(), 4);
1190 assert_eq!(
1191 vortex_array.dtype(),
1192 &DType::Extension(
1193 Timestamp::new_with_tz(
1194 TimeUnit::Microseconds,
1195 Some("UTC".into()),
1196 Nullability::Nullable
1197 )
1198 .erased()
1199 ),
1200 );
1201 assert_eq!(vortex_array_non_null.len(), 4);
1202 assert_eq!(
1203 vortex_array_non_null.dtype(),
1204 &DType::Extension(
1205 Timestamp::new_with_tz(
1206 TimeUnit::Microseconds,
1207 Some("UTC".into()),
1208 Nullability::NonNullable
1209 )
1210 .erased()
1211 )
1212 );
1213 }
1214
1215 #[rstest]
1217 #[case::utf8(
1218 Arc::new(StringArray::from(vec![Some("hello"), None, Some("world"), Some("test")])),
1219 Arc::new(StringArray::from(vec!["hello", "world", "test", "vortex"])),
1220 DType::Utf8(Nullability::NonNullable),
1221 )]
1222 #[case::large_utf8(
1223 Arc::new(LargeStringArray::from(vec![Some("hello"), None, Some("world"), Some("test")])),
1224 Arc::new(LargeStringArray::from(vec!["hello", "world", "test", "vortex"])),
1225 DType::Utf8(Nullability::NonNullable),
1226 )]
1227 #[case::binary(
1228 Arc::new(BinaryArray::from(vec![
1229 Some("hello".as_bytes()), None, Some("world".as_bytes()), Some("test".as_bytes()),
1230 ])),
1231 Arc::new(BinaryArray::from(vec![
1232 "hello".as_bytes(), "world".as_bytes(), "test".as_bytes(), "vortex".as_bytes(),
1233 ])),
1234 DType::Binary(Nullability::NonNullable),
1235 )]
1236 #[case::large_binary(
1237 Arc::new(LargeBinaryArray::from(vec![
1238 Some("hello".as_bytes()), None, Some("world".as_bytes()), Some("test".as_bytes()),
1239 ])),
1240 Arc::new(LargeBinaryArray::from(vec![
1241 "hello".as_bytes(), "world".as_bytes(), "test".as_bytes(), "vortex".as_bytes(),
1242 ])),
1243 DType::Binary(Nullability::NonNullable),
1244 )]
1245 fn test_string_binary_array_conversion(
1246 #[case] nullable: Arc<dyn ArrowArray>,
1247 #[case] non_nullable: Arc<dyn ArrowArray>,
1248 #[case] expected_non_nullable_dtype: DType,
1249 ) {
1250 let v_null = ArrayRef::from_arrow(nullable.as_ref(), true).unwrap();
1251 let v_non_null = ArrayRef::from_arrow(non_nullable.as_ref(), false).unwrap();
1252 assert_eq!(v_null.len(), 4);
1253 assert_eq!(v_non_null.len(), 4);
1254 assert_eq!(v_null.dtype(), &expected_non_nullable_dtype.as_nullable());
1255 assert_eq!(v_non_null.dtype(), &expected_non_nullable_dtype);
1256 }
1257
1258 #[test]
1259 fn test_utf8_view_array_conversion() {
1260 let mut builder = StringViewBuilder::new();
1261 builder.append_value("hello");
1262 builder.append_null();
1263 builder.append_value("world");
1264 builder.append_value("test");
1265 let arrow_array = builder.finish();
1266 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1267
1268 let mut builder_non_null = StringViewBuilder::new();
1269 builder_non_null.append_value("hello");
1270 builder_non_null.append_value("world");
1271 builder_non_null.append_value("test");
1272 builder_non_null.append_value("vortex");
1273 let arrow_array_non_null = builder_non_null.finish();
1274 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1275
1276 assert_eq!(vortex_array.len(), 4);
1277 assert_eq!(vortex_array_non_null.len(), 4);
1278
1279 let varbin_view_array = vortex_array.as_::<VarBinView>();
1281 assert_eq!(
1282 varbin_view_array.data_buffers().len(),
1283 arrow_array.data_buffers().len()
1284 );
1285 assert_eq!(varbin_view_array.dtype(), &DType::Utf8(true.into()));
1286
1287 let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinView>();
1288 assert_eq!(
1289 varbin_view_array_non_null.data_buffers().len(),
1290 arrow_array_non_null.data_buffers().len()
1291 );
1292 assert_eq!(
1293 varbin_view_array_non_null.dtype(),
1294 &DType::Utf8(false.into())
1295 );
1296 }
1297
1298 #[test]
1299 fn test_binary_view_array_conversion() {
1300 let mut builder = BinaryViewBuilder::new();
1301 builder.append_value(b"hello");
1302 builder.append_null();
1303 builder.append_value(b"world");
1304 builder.append_value(b"test");
1305 let arrow_array = builder.finish();
1306 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1307
1308 let mut builder_non_null = BinaryViewBuilder::new();
1309 builder_non_null.append_value(b"hello");
1310 builder_non_null.append_value(b"world");
1311 builder_non_null.append_value(b"test");
1312 builder_non_null.append_value(b"vortex");
1313 let arrow_array_non_null = builder_non_null.finish();
1314 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1315
1316 assert_eq!(vortex_array.len(), 4);
1317 assert_eq!(vortex_array_non_null.len(), 4);
1318
1319 let varbin_view_array = vortex_array.as_::<VarBinView>();
1321 assert_eq!(
1322 varbin_view_array.data_buffers().len(),
1323 arrow_array.data_buffers().len()
1324 );
1325 assert_eq!(varbin_view_array.dtype(), &DType::Binary(true.into()));
1326
1327 let varbin_view_array_non_null = vortex_array_non_null.as_::<VarBinView>();
1328 assert_eq!(
1329 varbin_view_array_non_null.data_buffers().len(),
1330 arrow_array_non_null.data_buffers().len()
1331 );
1332 assert_eq!(
1333 varbin_view_array_non_null.dtype(),
1334 &DType::Binary(false.into())
1335 );
1336 }
1337
1338 #[test]
1340 fn test_boolean_array_conversion() {
1341 let arrow_array = BooleanArray::from(vec![Some(true), None, Some(false), Some(true)]);
1342 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1343
1344 let arrow_array_non_null = BooleanArray::from(vec![true, false, true, false]);
1345 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1346
1347 assert_eq!(vortex_array.len(), 4);
1348 assert_eq!(vortex_array_non_null.len(), 4);
1349 }
1350
1351 #[test]
1353 fn test_struct_array_conversion() {
1354 let fields = vec![
1355 Field::new("field1", DataType::Int32, true),
1356 Field::new("field2", DataType::Utf8, false),
1357 ];
1358 let schema = Fields::from(fields);
1359
1360 let field1_data = Int32Array::from(vec![Some(1), None, Some(3)]);
1361 let field2_data = StringArray::from(vec!["a", "b", "c"]);
1362
1363 let arrow_array = StructArray::new(
1364 schema.clone(),
1365 vec![Arc::new(field1_data), Arc::new(field2_data)],
1366 None,
1367 );
1368
1369 let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1370 assert_eq!(vortex_array.len(), 3);
1371
1372 let struct_vortex_array = vortex_array.as_::<Struct>();
1374 assert_eq!(struct_vortex_array.names().len(), 2);
1375 assert_eq!(struct_vortex_array.names()[0], "field1");
1376 assert_eq!(struct_vortex_array.names()[1], "field2");
1377
1378 let nullable_array = StructArray::new(
1380 schema,
1381 vec![
1382 Arc::new(Int32Array::from(vec![Some(1), None, Some(3)])),
1383 Arc::new(StringArray::from(vec!["a", "b", "c"])),
1384 ],
1385 Some(arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![
1386 true, false, true,
1387 ]))),
1388 );
1389
1390 let vortex_nullable_array = ArrayRef::from_arrow(&nullable_array, true).unwrap();
1391 assert_eq!(vortex_nullable_array.len(), 3);
1392
1393 let struct_vortex_nullable_array = vortex_nullable_array.as_::<Struct>();
1395 assert_eq!(struct_vortex_nullable_array.names().len(), 2);
1396 assert_eq!(struct_vortex_nullable_array.names()[0], "field1");
1397 assert_eq!(struct_vortex_nullable_array.names()[1], "field2");
1398 }
1399
1400 #[test]
1402 fn test_list_array_conversion() {
1403 let mut builder = ListBuilder::new(Int32Builder::new());
1404 builder.append_value([Some(1), None, Some(3)]);
1405 builder.append_null();
1406 builder.append_value([Some(4), Some(5)]);
1407 let arrow_array = builder.finish();
1408
1409 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1410 assert_eq!(vortex_array.len(), 3);
1411
1412 let list_vortex_array = vortex_array.as_::<List>();
1414 let offsets_array = list_vortex_array.offsets().as_::<Primitive>();
1415 assert_eq!(offsets_array.len(), 4); assert_eq!(offsets_array.ptype(), PType::I32);
1417
1418 let mut builder_non_null = ListBuilder::new(Int32Builder::new());
1420 builder_non_null.append_value([Some(1), None, Some(3)]);
1421 builder_non_null.append_value([Some(4), Some(5)]);
1422 let arrow_array_non_null = builder_non_null.finish();
1423
1424 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1425 assert_eq!(vortex_array_non_null.len(), 2);
1426
1427 let list_vortex_array_non_null = vortex_array_non_null.as_::<List>();
1429 let offsets_array_non_null = list_vortex_array_non_null.offsets().as_::<Primitive>();
1430 assert_eq!(offsets_array_non_null.len(), 3); assert_eq!(offsets_array_non_null.ptype(), PType::I32);
1432 }
1433
1434 #[test]
1435 fn test_large_list_array_conversion() {
1436 let mut builder = LargeListBuilder::new(Int32Builder::new());
1437 builder.append_value([Some(1), None, Some(3)]);
1438 builder.append_null();
1439 builder.append_value([Some(4), Some(5)]);
1440 let arrow_array = builder.finish();
1441
1442 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1443 assert_eq!(vortex_array.len(), 3);
1444
1445 let list_vortex_array = vortex_array.as_::<List>();
1447 let offsets_array = list_vortex_array.offsets().as_::<Primitive>();
1448 assert_eq!(offsets_array.len(), 4); assert_eq!(offsets_array.ptype(), PType::I64); let mut builder_non_null = LargeListBuilder::new(Int32Builder::new());
1453 builder_non_null.append_value([Some(1), None, Some(3)]);
1454 builder_non_null.append_value([Some(4), Some(5)]);
1455 let arrow_array_non_null = builder_non_null.finish();
1456
1457 let vortex_array_non_null = ArrayRef::from_arrow(&arrow_array_non_null, false).unwrap();
1458 assert_eq!(vortex_array_non_null.len(), 2);
1459
1460 let list_vortex_array_non_null = vortex_array_non_null.as_::<List>();
1462 let offsets_array_non_null = list_vortex_array_non_null.offsets().as_::<Primitive>();
1463 assert_eq!(offsets_array_non_null.len(), 3); assert_eq!(offsets_array_non_null.ptype(), PType::I64); }
1466
1467 #[test]
1468 fn test_fixed_size_list_array_conversion() {
1469 let values = Int32Array::from(vec![
1471 Some(1),
1472 Some(2),
1473 Some(3), Some(4),
1475 None,
1476 Some(6), Some(7),
1478 Some(8),
1479 Some(9), Some(10),
1481 Some(11),
1482 Some(12), ]);
1484
1485 let field = Arc::new(Field::new("item", DataType::Int32, true));
1487 let arrow_array =
1488 ArrowFixedSizeListArray::try_new(Arc::clone(&field), 3, Arc::new(values), None)
1489 .unwrap();
1490 let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1491
1492 assert_eq!(vortex_array.len(), 4);
1493
1494 let fsl_vortex_array = vortex_array.as_::<FixedSizeList>();
1496 assert_eq!(fsl_vortex_array.list_size(), 3);
1497 assert_eq!(fsl_vortex_array.elements().len(), 12); let values_nullable = Int32Array::from(vec![
1501 Some(1),
1502 Some(2),
1503 Some(3), Some(4),
1505 None,
1506 Some(6), Some(7),
1508 Some(8),
1509 Some(9), ]);
1511
1512 let null_buffer =
1514 arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![true, false, true]));
1515
1516 let arrow_array_nullable = ArrowFixedSizeListArray::try_new(
1517 field,
1518 3,
1519 Arc::new(values_nullable),
1520 Some(null_buffer),
1521 )
1522 .unwrap();
1523 let vortex_array_nullable = ArrayRef::from_arrow(&arrow_array_nullable, true).unwrap();
1524
1525 assert_eq!(vortex_array_nullable.len(), 3);
1526
1527 let fsl_vortex_array_nullable = vortex_array_nullable.as_::<FixedSizeList>();
1529 assert_eq!(fsl_vortex_array_nullable.list_size(), 3);
1530 assert_eq!(fsl_vortex_array_nullable.elements().len(), 9); }
1532
1533 #[test]
1534 fn test_list_view_array_conversion() {
1535 let values = Int32Array::from(vec![
1537 Some(1),
1538 Some(2),
1539 Some(3), Some(4),
1541 Some(5), Some(6), Some(7),
1544 Some(8),
1545 Some(9),
1546 Some(10), ]);
1548
1549 let offsets = ScalarBuffer::from(vec![0i32, 3, 5, 6]);
1551 let sizes = ScalarBuffer::from(vec![3i32, 2, 1, 4]);
1552
1553 let field = Arc::new(Field::new("item", DataType::Int32, true));
1554 let arrow_array = GenericListViewArray::try_new(
1555 Arc::clone(&field),
1556 offsets.clone(),
1557 sizes.clone(),
1558 Arc::new(values.clone()),
1559 None,
1560 )
1561 .unwrap();
1562
1563 let vortex_array = ArrayRef::from_arrow(&arrow_array, false).unwrap();
1564 assert_eq!(vortex_array.len(), 4);
1565
1566 let list_view_vortex_array = vortex_array.as_::<ListView>();
1568 let offsets_array = list_view_vortex_array.offsets().as_::<Primitive>();
1569 let sizes_array = list_view_vortex_array.sizes().as_::<Primitive>();
1570
1571 assert_eq!(offsets_array.len(), 4);
1572 assert_eq!(offsets_array.ptype(), PType::I32);
1573 assert_eq!(sizes_array.len(), 4);
1574 assert_eq!(sizes_array.ptype(), PType::I32);
1575
1576 let null_buffer =
1578 arrow_buffer::NullBuffer::new(BooleanBuffer::from(vec![true, false, true, true]));
1579
1580 let arrow_array_nullable = GenericListViewArray::try_new(
1581 Arc::clone(&field),
1582 offsets,
1583 sizes,
1584 Arc::new(values.clone()),
1585 Some(null_buffer),
1586 )
1587 .unwrap();
1588
1589 let vortex_array_nullable = ArrayRef::from_arrow(&arrow_array_nullable, true).unwrap();
1590 assert_eq!(vortex_array_nullable.len(), 4);
1591
1592 let large_offsets = ScalarBuffer::from(vec![0i64, 3, 5, 6]);
1594 let large_sizes = ScalarBuffer::from(vec![3i64, 2, 1, 4]);
1595
1596 let large_arrow_array = GenericListViewArray::try_new(
1597 field,
1598 large_offsets,
1599 large_sizes,
1600 Arc::new(values),
1601 None,
1602 )
1603 .unwrap();
1604
1605 let large_vortex_array = ArrayRef::from_arrow(&large_arrow_array, false).unwrap();
1606 assert_eq!(large_vortex_array.len(), 4);
1607
1608 let large_list_view_vortex_array = large_vortex_array.as_::<ListView>();
1610 let large_offsets_array = large_list_view_vortex_array.offsets().as_::<Primitive>();
1611 let large_sizes_array = large_list_view_vortex_array.sizes().as_::<Primitive>();
1612
1613 assert_eq!(large_offsets_array.len(), 4);
1614 assert_eq!(large_offsets_array.ptype(), PType::I64); assert_eq!(large_sizes_array.len(), 4);
1616 assert_eq!(large_sizes_array.ptype(), PType::I64); }
1618
1619 #[test]
1621 fn test_null_array_conversion() {
1622 let arrow_array = NullArray::new(5);
1623 let vortex_array = ArrayRef::from_arrow(&arrow_array, true).unwrap();
1624 assert_eq!(vortex_array.len(), 5);
1625 }
1626
1627 #[test]
1629 fn test_arrow_buffer_conversion() {
1630 let data = vec![1u8, 2, 3, 4, 5];
1631 let arrow_buffer = ArrowBuffer::from_vec(data);
1632 let vortex_array = arrow_buffer.into_array();
1633 assert_eq!(vortex_array.len(), 5);
1634 }
1635
1636 #[test]
1637 fn test_boolean_buffer_conversion() {
1638 let data = vec![true, false, true, false, true];
1639 let boolean_buffer = BooleanBuffer::from(data);
1640 let vortex_array = boolean_buffer.into_array();
1641 assert_eq!(vortex_array.len(), 5);
1642 }
1643
1644 #[test]
1645 fn test_scalar_buffer_conversion() {
1646 let data = vec![1i32, 2, 3, 4, 5];
1647 let scalar_buffer = ScalarBuffer::from(data);
1648 let vortex_array = scalar_buffer.into_array();
1649 assert_eq!(vortex_array.len(), 5);
1650 }
1651
1652 #[test]
1653 fn test_offset_buffer_conversion() {
1654 let data = vec![0i32, 2, 5, 8, 10];
1655 let offset_buffer = OffsetBuffer::new(ScalarBuffer::from(data));
1656 let vortex_array = offset_buffer.into_array();
1657 assert_eq!(vortex_array.len(), 5);
1658 }
1659
1660 #[test]
1662 fn test_record_batch_conversion() {
1663 let schema = Arc::new(Schema::new(vec![
1664 Field::new("field1", DataType::Int32, false),
1665 Field::new("field2", DataType::Utf8, false),
1666 ]));
1667
1668 let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1669 let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1670
1671 let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1672
1673 let vortex_array = ArrayRef::from_arrow(record_batch, false).unwrap();
1674 assert_eq!(vortex_array.len(), 4);
1675
1676 let schema = Arc::new(Schema::new(vec![
1678 Field::new("field1", DataType::Int32, false),
1679 Field::new("field2", DataType::Utf8, false),
1680 ]));
1681
1682 let field1_data = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
1683 let field2_data = Arc::new(StringArray::from(vec!["a", "b", "c", "d"]));
1684
1685 let record_batch = RecordBatch::try_new(schema, vec![field1_data, field2_data]).unwrap();
1686
1687 let vortex_array = ArrayRef::from_arrow(&record_batch, false).unwrap();
1688 assert_eq!(vortex_array.len(), 4);
1689 }
1690
1691 #[test]
1693 fn test_dyn_array_conversion() {
1694 let int_array = Int32Array::from(vec![1, 2, 3, 4]);
1695 let dyn_array: &dyn ArrowArray = &int_array;
1696 let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1697 assert_eq!(vortex_array.len(), 4);
1698
1699 let string_array = StringArray::from(vec!["a", "b", "c"]);
1700 let dyn_array: &dyn ArrowArray = &string_array;
1701 let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1702 assert_eq!(vortex_array.len(), 3);
1703
1704 let bool_array = BooleanArray::from(vec![true, false, true]);
1705 let dyn_array: &dyn ArrowArray = &bool_array;
1706 let vortex_array = ArrayRef::from_arrow(dyn_array, false).unwrap();
1707 assert_eq!(vortex_array.len(), 3);
1708 }
1709
1710 #[test]
1712 pub fn nullable_may_contain_non_nullable() {
1713 let null_struct_array_with_non_nullable_field = new_null_array(
1714 &DataType::Struct(Fields::from(vec![Field::new(
1715 "non_nullable_inner",
1716 DataType::Int32,
1717 false,
1718 )])),
1719 1,
1720 );
1721 ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).unwrap();
1722 }
1723
1724 #[test]
1725 pub fn nullable_may_contain_deeply_nested_non_nullable() {
1726 let null_struct_array_with_non_nullable_field = new_null_array(
1727 &DataType::Struct(Fields::from(vec![Field::new(
1728 "non_nullable_inner",
1729 DataType::Struct(Fields::from(vec![Field::new(
1730 "non_nullable_deeper_inner",
1731 DataType::Int32,
1732 false,
1733 )])),
1734 false,
1735 )])),
1736 1,
1737 );
1738 ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).unwrap();
1739 }
1740
1741 #[test]
1742 fn dyn_dispatch_imports_map() -> VortexResult<()> {
1743 let mut builder = ArrowMapBuilder::new(None, StringBuilder::new(), Int32Builder::new());
1744 builder.keys().append_value("joe");
1745 builder.values().append_value(1);
1746 builder.append(true)?;
1747 builder.append(false)?;
1748 let arrow = builder.finish();
1749
1750 let expected = DType::map(
1751 DType::Utf8(Nullability::NonNullable),
1752 DType::Primitive(PType::I32, Nullability::Nullable),
1753 false,
1754 Nullability::Nullable,
1755 )?;
1756
1757 assert_eq!(from_arrow_dyn(&arrow, true)?.dtype(), &expected);
1759
1760 let batch = RecordBatch::try_from_iter_with_nullable([(
1762 "maps",
1763 Arc::new(arrow) as Arc<dyn ArrowArray>,
1764 true,
1765 )])?;
1766 let imported = from_arrow_batch(&batch, false)?;
1767 assert_eq!(
1768 imported.as_::<Struct>().unmasked_field(0).dtype(),
1769 &expected
1770 );
1771
1772 Ok(())
1773 }
1774
1775 #[test]
1776 fn non_nullable_request_rejects_nulls() {
1777 let arrow_array = Int32Array::from(vec![Some(1), None, Some(3)]);
1780 assert!(ArrayRef::from_arrow(&arrow_array, false).is_err());
1781 }
1782
1783 #[test]
1784 fn non_nullable_request_rejects_null_array() {
1785 let arrow_array = NullArray::new(5);
1788 assert!(ArrayRef::from_arrow(&arrow_array, false).is_err());
1789 }
1790
1791 #[test]
1792 fn non_nullable_struct_with_nulls_errors() {
1793 let struct_array = new_null_array(
1796 &DataType::Struct(Fields::from(vec![Field::new("a", DataType::Int32, true)])),
1797 3,
1798 );
1799 assert!(ArrayRef::from_arrow(struct_array.as_ref(), false).is_err());
1800 }
1801
1802 #[test]
1803 fn non_nullable_list_with_nulls_errors() {
1804 let mut builder = ListBuilder::new(Int32Builder::new());
1807 builder.append_value([Some(1), Some(2)]);
1808 builder.append_null();
1809 let list = builder.finish();
1810 assert!(ArrayRef::from_arrow(&list, false).is_err());
1811 }
1812
1813 #[test]
1814 pub fn nullable_struct_containing_non_nullable_dictionary_with_nulls_errors() {
1815 let null_struct_array_with_non_nullable_field = new_null_array(
1819 &DataType::Struct(Fields::from(vec![Field::new(
1820 "non_nullable_deeper_inner",
1821 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1822 false,
1823 )])),
1824 1,
1825 );
1826
1827 assert!(
1828 ArrayRef::from_arrow(null_struct_array_with_non_nullable_field.as_ref(), true).is_err()
1829 );
1830 }
1831}