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