1use arrow::{
6 array::{
7 self, Array, ArrayRef, GenericListArray, GenericListViewArray, ListLikeArray, StructArray,
8 UInt64Array, make_array,
9 },
10 buffer::NullBuffer,
11 compute::{CastOptions, take},
12 datatypes::Field,
13 error::Result,
14};
15use arrow_schema::{ArrowError, DataType, FieldRef};
16use parquet_variant::{VariantPath, VariantPathElement};
17
18use crate::ShreddingState;
19use crate::variant_array::all_null_value_column;
20use crate::variant_to_arrow::make_variant_to_arrow_row_builder;
21use crate::{VariantArray, VariantType, unshred_variant};
22
23use arrow::array::AsArray;
24use std::sync::Arc;
25
26pub(crate) enum ShreddedPathStep {
27 Success {
29 state: ShreddingState,
30 path_nulls: Option<NullBuffer>,
32 },
33 Missing,
36 NotShredded,
40}
41
42fn follow_list_like_index<L: ListLikeArray + 'static>(
47 typed_value: &dyn Array,
48 index: usize,
49) -> Result<ShreddedPathStep> {
50 let list_array = typed_value.as_any().downcast_ref::<L>().ok_or_else(|| {
51 ArrowError::ComputeError(format!(
52 "Expected array type '{}' while handling list-like path step, got '{}'",
53 std::any::type_name::<L>(),
54 typed_value.data_type()
55 ))
56 })?;
57
58 let values = list_array.values();
59
60 let Some(struct_array) = values.as_struct_opt() else {
61 return Ok(ShreddedPathStep::Missing);
62 };
63 let shredding_state = ShreddingState::try_from(struct_array)?;
64
65 let value_array = shredding_state.value_column();
66 let typed_array = shredding_state.typed_value_column();
67
68 if typed_array.is_none() && value_array.null_count() == value_array.len() {
70 return Ok(ShreddedPathStep::Missing);
71 }
72
73 let mut take_indices = Vec::with_capacity(list_array.len());
74 let mut any_in_bounds = false;
75 for row in 0..list_array.len() {
76 let row_range = list_array.element_range(row);
77 let take_index = (index < row_range.len()).then(|| (row_range.start + index) as u64);
78 any_in_bounds |= take_index.is_some();
79 take_indices.push(take_index);
80 }
81
82 if !any_in_bounds {
83 return Ok(ShreddedPathStep::Missing);
84 }
85
86 let index_array = UInt64Array::from(take_indices);
87 let path_nulls = index_array.nulls().cloned();
91
92 let taken_value = take(value_array, &index_array, None)?;
94 let taken_typed = typed_array
95 .map(|typed| take(typed, &index_array, None))
96 .transpose()?;
97
98 Ok(ShreddedPathStep::Success {
99 state: ShreddingState::new(taken_value, taken_typed),
100 path_nulls,
101 })
102}
103
104pub(crate) fn follow_shredded_path_element(
120 shredding_state: &ShreddingState,
121 path_element: &VariantPathElement<'_>,
122 _cast_options: &CastOptions,
123) -> Result<ShreddedPathStep> {
124 let missing_path_step = || {
127 let value = shredding_state.value_column();
128 if value.null_count() == value.len() {
129 ShreddedPathStep::Missing
130 } else {
131 ShreddedPathStep::NotShredded
132 }
133 };
134
135 let Some(typed_value) = shredding_state.typed_value_column() else {
136 return Ok(missing_path_step());
137 };
138
139 match path_element {
140 VariantPathElement::Field { name } => {
141 let Some(struct_array) = typed_value.as_struct_opt() else {
144 return Ok(missing_path_step());
146 };
147
148 let Some(field) = struct_array.column_by_name(name) else {
150 return Ok(missing_path_step());
152 };
153
154 let struct_array = field.as_struct_opt().ok_or_else(|| {
155 ArrowError::InvalidArgumentError(format!(
158 "Shredded object field '{name}' must be a Struct containing 'value' and/or \
159 'typed_value', got {}",
160 field.data_type(),
161 ))
162 })?;
163
164 let state = ShreddingState::try_from(struct_array)?;
165 Ok(ShreddedPathStep::Success {
166 state,
167 path_nulls: None,
168 })
169 }
170 VariantPathElement::Index { index } => {
171 let typed_value = typed_value.as_ref();
172 match typed_value.data_type() {
173 DataType::List(_) => {
174 follow_list_like_index::<GenericListArray<i32>>(typed_value, *index)
175 }
176 DataType::LargeList(_) => {
177 follow_list_like_index::<GenericListArray<i64>>(typed_value, *index)
178 }
179 DataType::ListView(_) => {
180 follow_list_like_index::<GenericListViewArray<i32>>(typed_value, *index)
181 }
182 DataType::LargeListView(_) => {
183 follow_list_like_index::<GenericListViewArray<i64>>(typed_value, *index)
184 }
185 _ => Ok(missing_path_step()),
187 }
188 }
189 VariantPathElement::ListElement => Err(ArrowError::InvalidArgumentError(
190 "variant_get does not support [*] path elements".to_string(),
191 )),
192 }
193}
194
195fn shredded_get_path(
199 input: &VariantArray,
200 path: &[VariantPathElement<'_>],
201 as_field: Option<&Field>,
202 cast_options: &CastOptions,
203) -> Result<ArrayRef> {
204 let make_target_variant =
207 |value: ArrayRef, typed_value: Option<ArrayRef>, accumulated_nulls: Option<NullBuffer>| {
208 let metadata = input.metadata_column().clone();
209 VariantArray::from_parts(metadata, value, typed_value, accumulated_nulls)
210 };
211
212 let shred_basic_variant =
215 |target: VariantArray, path: VariantPath<'_>, as_field: Option<&Field>| {
216 let requested_variant =
219 as_field.is_some_and(Field::has_valid_extension_type::<VariantType>);
220
221 if requested_variant && requested_field_is_shredded(as_field) {
226 return Err(ArrowError::NotYetImplemented(
227 "variant_get with shredded `Variant` output is not yet supported".to_string(),
228 ));
229 }
230
231 let target = if requested_variant {
237 unshred_variant(&target)?
238 } else {
239 target
240 };
241
242 if requested_variant && path.is_empty() {
244 return Ok(ArrayRef::from(target));
245 }
246
247 let as_type = if requested_variant {
248 None
249 } else {
250 as_field.map(|f| f.data_type())
251 };
252 let mut builder = make_variant_to_arrow_row_builder(
253 target.metadata_column(),
254 path,
255 as_type,
256 cast_options,
257 target.len(),
258 )?;
259 for i in 0..target.len() {
260 if target.is_null(i) {
261 builder.append_null()?;
262 } else if !cast_options.safe {
263 let value = target.try_value(i)?;
264 builder.append_value(value)?;
265 } else {
266 let _ = match target.try_value(i) {
267 Ok(v) => builder.append_value(v)?,
268 Err(_) => {
269 builder.append_null()?;
270 false }
272 };
273 }
274 }
275 builder.finish()
276 };
277
278 let mut shredding_state = input.shredding_state().clone();
281 let mut accumulated_nulls = input.inner().nulls().cloned();
282 let mut path_index = 0;
283 for path_element in path {
284 match follow_shredded_path_element(&shredding_state, path_element, cast_options)? {
285 ShreddedPathStep::Success { state, path_nulls } => {
286 if let Some(typed_value) = shredding_state.typed_value_column() {
288 accumulated_nulls =
289 NullBuffer::union(accumulated_nulls.as_ref(), typed_value.nulls());
290 }
291 accumulated_nulls =
292 NullBuffer::union(accumulated_nulls.as_ref(), path_nulls.as_ref());
293 shredding_state = state;
294 path_index += 1;
295 }
296 ShreddedPathStep::Missing => {
297 let num_rows = input.len();
298 if let Some(field) =
299 as_field.filter(|f| !f.has_valid_extension_type::<VariantType>())
300 {
301 return Ok(array::new_null_array(field.data_type(), num_rows));
302 }
303 let all_nulls = Some(arrow::buffer::NullBuffer::from(vec![false; num_rows]));
304 let metadata = input.metadata_column().clone();
307 let arr = VariantArray::from_parts_unshredded(
308 metadata,
309 all_null_value_column(num_rows),
310 all_nulls,
311 );
312 return Ok(ArrayRef::from(arr));
313 }
314 ShreddedPathStep::NotShredded => {
315 let target = make_target_variant(
316 shredding_state.value_column().clone(),
317 None,
318 accumulated_nulls,
319 );
320 return shred_basic_variant(target, path[path_index..].into(), as_field);
321 }
322 }
323 }
324
325 let target = make_target_variant(
327 shredding_state.value_column().clone(),
328 shredding_state.typed_value_column().cloned(),
329 accumulated_nulls,
330 );
331
332 let Some(as_field) = as_field else {
334 return Ok(ArrayRef::from(target));
335 };
336
337 if let Some(shredded) = try_perfect_shredding(&target, as_field) {
339 return Ok(shredded);
340 }
341
342 if !as_field.has_valid_extension_type::<VariantType>()
352 && let DataType::Struct(fields) = as_field.data_type()
353 {
354 if target.typed_value_column().is_none() {
355 return shred_basic_variant(target, VariantPath::default(), Some(as_field));
356 }
357
358 let children = fields
359 .iter()
360 .map(|field| {
361 let path = &[VariantPathElement::from(field.name().as_str())];
362 shredded_get_path(&target, path, Some(field), cast_options)
363 })
364 .collect::<Result<Vec<_>>>()?;
365
366 return Ok(Arc::new(StructArray::try_new(
367 fields.clone(),
368 children,
369 target.nulls().cloned(),
370 )?));
371 }
372
373 shred_basic_variant(target, VariantPath::default(), Some(as_field))
375}
376
377fn requested_field_is_shredded(as_field: Option<&Field>) -> bool {
382 as_field.is_some_and(|f| match f.data_type() {
383 DataType::Struct(fields) => fields.iter().any(|field| field.name() == "typed_value"),
384 _ => false,
385 })
386}
387
388fn try_perfect_shredding(variant_array: &VariantArray, as_field: &Field) -> Option<ArrayRef> {
389 if matches!(as_field.data_type(), DataType::Struct(_)) {
391 return None;
392 }
393 let typed_value = variant_array.typed_value_column()?;
394
395 let value = variant_array.value_column();
396 if typed_value.data_type() == as_field.data_type() && value.null_count() == value.len() {
397 let parent_nulls = variant_array.nulls();
404
405 let target_array = if parent_nulls.is_none() || typed_value.data_type().is_null() {
407 typed_value.clone()
408 } else {
409 let merged_nulls = NullBuffer::union(parent_nulls, typed_value.nulls());
410 let data = typed_value
411 .to_data()
412 .into_builder()
413 .nulls(merged_nulls)
414 .build()
415 .ok()?;
416 make_array(data)
417 };
418
419 return Some(target_array);
420 }
421
422 None
423}
424
425pub fn variant_get(input: &ArrayRef, options: GetOptions) -> Result<ArrayRef> {
457 let variant_array = VariantArray::try_new(input)?;
458
459 let GetOptions {
460 as_type,
461 path,
462 cast_options,
463 } = options;
464
465 if path
466 .iter()
467 .any(|element| matches!(element, VariantPathElement::ListElement))
468 {
469 return Err(ArrowError::InvalidArgumentError(
470 "variant_get does not support [*] path elements".to_string(),
471 ));
472 }
473
474 shredded_get_path(&variant_array, &path, as_type.as_deref(), &cast_options)
475}
476
477#[derive(Debug, Clone, Default)]
479pub struct GetOptions<'a> {
480 pub path: VariantPath<'a>,
482 pub as_type: Option<FieldRef>,
486 pub cast_options: CastOptions<'a>,
488}
489
490impl<'a> GetOptions<'a> {
491 pub fn new() -> Self {
493 Default::default()
494 }
495
496 pub fn new_with_path(path: VariantPath<'a>) -> Self {
498 Self {
499 path,
500 as_type: None,
501 cast_options: Default::default(),
502 }
503 }
504
505 pub fn with_as_type(mut self, as_type: Option<FieldRef>) -> Self {
507 self.as_type = as_type;
508 self
509 }
510
511 pub fn with_cast_options(mut self, cast_options: CastOptions<'a>) -> Self {
513 self.cast_options = cast_options;
514 self
515 }
516}
517
518#[cfg(test)]
519mod test {
520 use std::str::FromStr;
521 use std::sync::Arc;
522
523 use super::{GetOptions, requested_field_is_shredded, variant_get};
524 use crate::variant_array::{ShreddedVariantFieldArray, all_null_value_column};
525 use crate::{
526 ShreddedSchemaBuilder, VariantArray, VariantArrayBuilder, cast_to_variant, json_to_variant,
527 shred_variant,
528 };
529 use arrow::array::{
530 Array, ArrayRef, AsArray, BinaryArray, BinaryViewArray, BooleanArray, Date32Array,
531 Date64Array, Decimal32Array, Decimal64Array, Decimal128Array, Decimal256Array,
532 FixedSizeListArray, Float32Array, Float64Array, Int8Array, Int16Array, Int32Array,
533 Int64Array, Int64Builder, LargeBinaryArray, LargeListArray, LargeListViewArray,
534 LargeStringArray, ListArray, ListBuilder, ListViewArray, MapBuilder, NullArray,
535 NullBuilder, StringArray, StringBuilder, StringViewArray, StructArray,
536 StructArrayAssembler, Time32MillisecondArray, Time32SecondArray, Time64MicrosecondArray,
537 Time64NanosecondArray, UnionArray,
538 };
539 use arrow::buffer::{NullBuffer, OffsetBuffer, ScalarBuffer};
540 use arrow::compute::{CastOptions, cast};
541 use arrow::datatypes::DataType::{Int16, Int32, Int64};
542 use arrow::datatypes::i256;
543 use arrow::util::display::FormatOptions;
544 use arrow_schema::ArrowError;
545 use arrow_schema::DataType::{Boolean, Float32, Float64, Int8};
546 use arrow_schema::{
547 DataType, Field, FieldRef, Fields, IntervalUnit, TimeUnit, UnionFields, UnionMode,
548 };
549 use chrono::DateTime;
550 use parquet_variant::{
551 EMPTY_VARIANT_METADATA_BYTES, Variant, VariantDecimal4, VariantDecimal8, VariantDecimal16,
552 VariantDecimalType, VariantPath,
553 };
554
555 fn single_variant_get_test(input_json: &str, path: VariantPath, expected_json: &str) {
556 let input_array_ref: ArrayRef = Arc::new(StringArray::from(vec![Some(input_json)]));
558 let input_variant_array_ref = ArrayRef::from(json_to_variant(&input_array_ref).unwrap());
559
560 let result =
561 variant_get(&input_variant_array_ref, GetOptions::new_with_path(path)).unwrap();
562
563 let expected_array_ref: ArrayRef = Arc::new(StringArray::from(vec![Some(expected_json)]));
565 let expected_variant_array = json_to_variant(&expected_array_ref).unwrap();
566
567 let result_array = VariantArray::try_new(&result).unwrap();
568 assert_eq!(
569 result_array.len(),
570 1,
571 "Expected result array to have length 1"
572 );
573 assert!(
574 result_array.nulls().is_none(),
575 "Expected no nulls in result array"
576 );
577 let result_variant = result_array.value(0);
578 let expected_variant = expected_variant_array.value(0);
579 assert_eq!(
580 result_variant, expected_variant,
581 "Result variant does not match expected variant"
582 );
583 }
584
585 #[test]
586 fn get_primitive_variant_field() {
587 single_variant_get_test(
588 r#"{"some_field": 1234}"#,
589 VariantPath::try_from("some_field").unwrap(),
590 "1234",
591 );
592 }
593
594 #[test]
595 fn get_primitive_variant_list_index() {
596 single_variant_get_test("[1234, 5678]", VariantPath::from(0), "1234");
597 }
598
599 #[test]
600 fn get_primitive_variant_inside_object_of_object() {
601 single_variant_get_test(
602 r#"{"top_level_field": {"inner_field": 1234}}"#,
603 VariantPath::try_from("top_level_field")
604 .unwrap()
605 .join("inner_field"),
606 "1234",
607 );
608 }
609
610 #[test]
611 fn get_primitive_variant_inside_list_of_object() {
612 single_variant_get_test(
613 r#"[{"some_field": 1234}]"#,
614 VariantPath::from(0).join("some_field"),
615 "1234",
616 );
617 }
618
619 #[test]
620 fn get_primitive_variant_inside_object_of_list() {
621 single_variant_get_test(
622 r#"{"some_field": [1234]}"#,
623 VariantPath::try_from("some_field[0]").unwrap(),
624 "1234",
625 );
626 }
627
628 #[test]
629 fn get_complex_variant() {
630 single_variant_get_test(
631 r#"{"top_level_field": {"inner_field": 1234}}"#,
632 VariantPath::try_from("top_level_field").unwrap(),
633 r#"{"inner_field": 1234}"#,
634 );
635 }
636
637 macro_rules! numeric_partially_shredded_test {
639 ($primitive_type:ty, $data_fn:ident) => {
640 let array = $data_fn();
641 let options = GetOptions::new();
642 let result = variant_get(&array, options).unwrap();
643
644 let result = VariantArray::try_new(&result).unwrap();
646 assert_eq!(result.len(), 4);
647
648 assert_eq!(
650 result.value(0),
651 Variant::from(<$primitive_type>::try_from(34u8).unwrap())
652 );
653 assert!(!result.is_valid(1));
654 assert_eq!(result.value(2), Variant::from("n/a"));
655 assert_eq!(
656 result.value(3),
657 Variant::from(<$primitive_type>::try_from(100u8).unwrap())
658 );
659 };
660 }
661
662 macro_rules! partially_shredded_variant_array_gen {
665 ($func_name:ident, $typed_value_array_gen: expr) => {
666 partially_shredded_variant_array_gen!(
667 $func_name,
668 $typed_value_array_gen,
669 Variant::from("n/a")
670 );
671 };
672 ($func_name:ident, $typed_value_array_gen: expr, $fallback_variant:expr) => {
673 fn $func_name() -> ArrayRef {
674 let typed_value: ArrayRef = Arc::new($typed_value_array_gen());
675 let typed_as_variant = cast_to_variant(typed_value.as_ref())
676 .expect("should cast typed array to variant");
677 let mut input_builder = VariantArrayBuilder::new(typed_as_variant.len());
678 input_builder.append_variant(typed_as_variant.value(0));
679 input_builder.append_null();
680 input_builder.append_variant($fallback_variant);
681 input_builder.append_variant(typed_as_variant.value(3));
682
683 let variant_array = shred_variant(&input_builder.build(), typed_value.data_type())
684 .expect("should shred variant array");
685 ArrayRef::from(variant_array)
686 }
687 };
688 }
689
690 macro_rules! numeric_partially_shredded_variant_array_fn {
692 ($func:ident, $array_type:ident, $primitive_type:ty) => {
693 partially_shredded_variant_array_gen!($func, || $array_type::from(vec![
694 Some(<$primitive_type>::try_from(34u8).unwrap()),
695 None,
696 None,
697 Some(<$primitive_type>::try_from(100u8).unwrap()),
698 ]));
699 };
700 }
701
702 numeric_partially_shredded_variant_array_fn!(
703 partially_shredded_int8_variant_array,
704 Int8Array,
705 i8
706 );
707 numeric_partially_shredded_variant_array_fn!(
708 partially_shredded_int16_variant_array,
709 Int16Array,
710 i16
711 );
712 numeric_partially_shredded_variant_array_fn!(
713 partially_shredded_int32_variant_array,
714 Int32Array,
715 i32
716 );
717 numeric_partially_shredded_variant_array_fn!(
718 partially_shredded_int64_variant_array,
719 Int64Array,
720 i64
721 );
722 numeric_partially_shredded_variant_array_fn!(
723 partially_shredded_float32_variant_array,
724 Float32Array,
725 f32
726 );
727 numeric_partially_shredded_variant_array_fn!(
728 partially_shredded_float64_variant_array,
729 Float64Array,
730 f64
731 );
732
733 partially_shredded_variant_array_gen!(partially_shredded_bool_variant_array, || {
734 arrow::array::BooleanArray::from(vec![Some(true), None, None, Some(false)])
735 });
736
737 partially_shredded_variant_array_gen!(
738 partially_shredded_utf8_variant_array,
739 || { StringArray::from(vec![Some("hello"), None, None, Some("world")]) },
740 Variant::from(42i32)
741 );
742
743 partially_shredded_variant_array_gen!(partially_shredded_date32_variant_array, || {
744 Date32Array::from(vec![
745 Some(20348), None,
747 None,
748 Some(20340), ])
750 });
751
752 #[test]
753 fn get_variant_partially_shredded_int8_as_variant() {
754 numeric_partially_shredded_test!(i8, partially_shredded_int8_variant_array);
755 }
756
757 #[test]
758 fn get_variant_partially_shredded_int16_as_variant() {
759 numeric_partially_shredded_test!(i16, partially_shredded_int16_variant_array);
760 }
761
762 #[test]
763 fn get_variant_partially_shredded_int32_as_variant() {
764 numeric_partially_shredded_test!(i32, partially_shredded_int32_variant_array);
765 }
766
767 #[test]
768 fn get_variant_partially_shredded_int64_as_variant() {
769 numeric_partially_shredded_test!(i64, partially_shredded_int64_variant_array);
770 }
771
772 #[test]
773 fn get_variant_partially_shredded_float32_as_variant() {
774 numeric_partially_shredded_test!(f32, partially_shredded_float32_variant_array);
775 }
776
777 #[test]
778 fn get_variant_partially_shredded_float64_as_variant() {
779 numeric_partially_shredded_test!(f64, partially_shredded_float64_variant_array);
780 }
781
782 #[test]
783 fn get_variant_partially_shredded_bool_as_variant() {
784 let array = partially_shredded_bool_variant_array();
785 let options = GetOptions::new();
786 let result = variant_get(&array, options).unwrap();
787
788 let result = VariantArray::try_new(&result).unwrap();
790 assert_eq!(result.len(), 4);
791
792 assert_eq!(result.value(0), Variant::from(true));
794 assert!(!result.is_valid(1));
795 assert_eq!(result.value(2), Variant::from("n/a"));
796 assert_eq!(result.value(3), Variant::from(false));
797 }
798
799 #[test]
800 fn get_variant_partially_shredded_utf8_as_variant() {
801 let array = partially_shredded_utf8_variant_array();
802 let options = GetOptions::new();
803 let result = variant_get(&array, options).unwrap();
804
805 let result = VariantArray::try_new(&result).unwrap();
807 assert_eq!(result.len(), 4);
808
809 assert_eq!(result.value(0), Variant::from("hello"));
811 assert!(!result.is_valid(1));
812 assert_eq!(result.value(2), Variant::from(42i32));
813 assert_eq!(result.value(3), Variant::from("world"));
814 }
815
816 partially_shredded_variant_array_gen!(partially_shredded_binary_view_variant_array, || {
817 BinaryViewArray::from(vec![
818 Some(&[1u8, 2u8, 3u8][..]), None, None, Some(&[4u8, 5u8, 6u8][..]), ])
823 });
824
825 #[test]
826 fn get_variant_partially_shredded_date32_as_variant() {
827 let array = partially_shredded_date32_variant_array();
828 let options = GetOptions::new();
829 let result = variant_get(&array, options).unwrap();
830
831 let result = VariantArray::try_new(&result).unwrap();
833 assert_eq!(result.len(), 4);
834
835 use chrono::NaiveDate;
837 let date1 = NaiveDate::from_ymd_opt(2025, 9, 17).unwrap();
838 let date2 = NaiveDate::from_ymd_opt(2025, 9, 9).unwrap();
839 assert_eq!(result.value(0), Variant::from(date1));
840 assert!(!result.is_valid(1));
841 assert_eq!(result.value(2), Variant::from("n/a"));
842 assert_eq!(result.value(3), Variant::from(date2));
843 }
844
845 #[test]
846 fn get_variant_partially_shredded_binary_view_as_variant() {
847 let array = partially_shredded_binary_view_variant_array();
848 let options = GetOptions::new();
849 let result = variant_get(&array, options).unwrap();
850
851 let result = VariantArray::try_new(&result).unwrap();
853 assert_eq!(result.len(), 4);
854
855 assert_eq!(result.value(0), Variant::from(&[1u8, 2u8, 3u8][..]));
857 assert!(!result.is_valid(1));
858 assert_eq!(result.value(2), Variant::from("n/a"));
859 assert_eq!(result.value(3), Variant::from(&[4u8, 5u8, 6u8][..]));
860 }
861
862 macro_rules! assert_variant_get_as_variant_array_with_default_option {
864 ($variant_array: expr, $array_expected: expr) => {{
865 let options = GetOptions::new();
866 let array = $variant_array;
867 let result = variant_get(&array, options).unwrap();
868 let result = VariantArray::try_new(&result).unwrap();
869
870 assert_eq!(result.len(), $array_expected.len());
871
872 for (idx, item) in $array_expected.into_iter().enumerate() {
873 match item {
874 Some(item) => assert_eq!(result.value(idx), item),
875 None => assert!(result.is_null(idx)),
876 }
877 }
878 }};
879 }
880
881 partially_shredded_variant_array_gen!(
882 partially_shredded_timestamp_micro_ntz_variant_array,
883 || {
884 arrow::array::TimestampMicrosecondArray::from(vec![
885 Some(-456000),
886 None,
887 None,
888 Some(1758602096000000),
889 ])
890 }
891 );
892
893 #[test]
894 fn get_variant_partial_shredded_timestamp_micro_ntz_as_variant() {
895 let array = partially_shredded_timestamp_micro_ntz_variant_array();
896 assert_variant_get_as_variant_array_with_default_option!(
897 array,
898 vec![
899 Some(Variant::from(
900 DateTime::from_timestamp_micros(-456000i64)
901 .unwrap()
902 .naive_utc(),
903 )),
904 None,
905 Some(Variant::from("n/a")),
906 Some(Variant::from(
907 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
908 .unwrap()
909 .naive_utc(),
910 )),
911 ]
912 )
913 }
914
915 partially_shredded_variant_array_gen!(partially_shredded_timestamp_micro_variant_array, || {
916 arrow::array::TimestampMicrosecondArray::from(vec![
917 Some(-456000),
918 None,
919 None,
920 Some(1758602096000000),
921 ])
922 .with_timezone("+00:00")
923 });
924
925 #[test]
926 fn get_variant_partial_shredded_timestamp_micro_as_variant() {
927 let array = partially_shredded_timestamp_micro_variant_array();
928 assert_variant_get_as_variant_array_with_default_option!(
929 array,
930 vec![
931 Some(Variant::from(
932 DateTime::from_timestamp_micros(-456000i64)
933 .unwrap()
934 .to_utc(),
935 )),
936 None,
937 Some(Variant::from("n/a")),
938 Some(Variant::from(
939 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
940 .unwrap()
941 .to_utc(),
942 )),
943 ]
944 )
945 }
946
947 partially_shredded_variant_array_gen!(
948 partially_shredded_timestamp_nano_ntz_variant_array,
949 || {
950 arrow::array::TimestampNanosecondArray::from(vec![
951 Some(-4999999561),
952 None,
953 None,
954 Some(1758602096000000000),
955 ])
956 }
957 );
958
959 #[test]
960 fn get_variant_partial_shredded_timestamp_nano_ntz_as_variant() {
961 let array = partially_shredded_timestamp_nano_ntz_variant_array();
962 assert_variant_get_as_variant_array_with_default_option!(
963 array,
964 vec![
965 Some(Variant::from(
966 DateTime::from_timestamp(-5, 439).unwrap().naive_utc()
967 )),
968 None,
969 Some(Variant::from("n/a")),
970 Some(Variant::from(
971 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
972 .unwrap()
973 .naive_utc()
974 )),
975 ]
976 )
977 }
978
979 partially_shredded_variant_array_gen!(partially_shredded_timestamp_nano_variant_array, || {
980 arrow::array::TimestampNanosecondArray::from(vec![
981 Some(-4999999561),
982 None,
983 None,
984 Some(1758602096000000000),
985 ])
986 .with_timezone("+00:00")
987 });
988
989 #[test]
990 fn get_variant_partial_shredded_timestamp_nano_as_variant() {
991 let array = partially_shredded_timestamp_nano_variant_array();
992 assert_variant_get_as_variant_array_with_default_option!(
993 array,
994 vec![
995 Some(Variant::from(
996 DateTime::from_timestamp(-5, 439).unwrap().to_utc()
997 )),
998 None,
999 Some(Variant::from("n/a")),
1000 Some(Variant::from(
1001 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
1002 .unwrap()
1003 .to_utc()
1004 )),
1005 ]
1006 )
1007 }
1008
1009 #[test]
1011 fn get_variant_shredded_int32_as_int32_safe_cast() {
1012 let array = partially_shredded_int32_variant_array();
1014 let field = Field::new("typed_value", DataType::Int32, true);
1016 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
1017 let result = variant_get(&array, options).unwrap();
1018 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
1019 Some(34),
1020 None,
1021 None, Some(100),
1023 ]));
1024 assert_eq!(&result, &expected)
1025 }
1026
1027 #[test]
1029 fn get_variant_shredded_int32_as_int32_unsafe_cast() {
1030 let array = partially_shredded_int32_variant_array();
1032 let field = Field::new("typed_value", DataType::Int32, true);
1033 let cast_options = CastOptions {
1034 safe: false, ..Default::default()
1036 };
1037 let options = GetOptions::new()
1038 .with_as_type(Some(FieldRef::from(field)))
1039 .with_cast_options(cast_options);
1040
1041 let err = variant_get(&array, options).unwrap_err();
1042 assert_eq!(
1044 err.to_string(),
1045 "Cast error: Failed to extract primitive of type Int32 from variant ShortString(ShortString(\"n/a\")) at path VariantPath([])"
1046 );
1047 }
1048
1049 macro_rules! numeric_perfectly_shredded_test {
1051 ($primitive_type:ty, $data_fn:ident) => {
1052 let array = $data_fn();
1053 let options = GetOptions::new();
1054 let result = variant_get(&array, options).unwrap();
1055
1056 let result = VariantArray::try_new(&result).unwrap();
1058 assert_eq!(result.len(), 3);
1059
1060 assert_eq!(
1062 result.value(0),
1063 Variant::from(<$primitive_type>::try_from(1u8).unwrap())
1064 );
1065 assert_eq!(
1066 result.value(1),
1067 Variant::from(<$primitive_type>::try_from(2u8).unwrap())
1068 );
1069 assert_eq!(
1070 result.value(2),
1071 Variant::from(<$primitive_type>::try_from(3u8).unwrap())
1072 );
1073 };
1074 }
1075
1076 #[test]
1077 fn get_variant_perfectly_shredded_int8_as_variant() {
1078 numeric_perfectly_shredded_test!(i8, perfectly_shredded_int8_variant_array);
1079 }
1080
1081 #[test]
1082 fn get_variant_perfectly_shredded_int16_as_variant() {
1083 numeric_perfectly_shredded_test!(i16, perfectly_shredded_int16_variant_array);
1084 }
1085
1086 #[test]
1087 fn get_variant_perfectly_shredded_int32_as_variant() {
1088 numeric_perfectly_shredded_test!(i32, perfectly_shredded_int32_variant_array);
1089 }
1090
1091 #[test]
1092 fn get_variant_perfectly_shredded_int64_as_variant() {
1093 numeric_perfectly_shredded_test!(i64, perfectly_shredded_int64_variant_array);
1094 }
1095
1096 #[test]
1097 fn get_variant_perfectly_shredded_float32_as_variant() {
1098 numeric_perfectly_shredded_test!(f32, perfectly_shredded_float32_variant_array);
1099 }
1100
1101 #[test]
1102 fn get_variant_perfectly_shredded_float64_as_variant() {
1103 numeric_perfectly_shredded_test!(f64, perfectly_shredded_float64_variant_array);
1104 }
1105
1106 #[test]
1108 fn get_variant_all_null_as_variant() {
1109 let array = all_null_variant_array();
1110 let options = GetOptions::new();
1111 let result = variant_get(&array, options).unwrap();
1112
1113 let result = VariantArray::try_new(&result).unwrap();
1115 assert_eq!(result.len(), 3);
1116
1117 assert!(!result.is_valid(0));
1119 assert!(!result.is_valid(1));
1120 assert!(!result.is_valid(2));
1121 }
1122
1123 #[test]
1125 fn get_variant_all_null_as_int32() {
1126 let array = all_null_variant_array();
1127 let field = Field::new("typed_value", DataType::Int32, true);
1129 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
1130 let result = variant_get(&array, options).unwrap();
1131
1132 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
1133 Option::<i32>::None,
1134 Option::<i32>::None,
1135 Option::<i32>::None,
1136 ]));
1137 assert_eq!(&result, &expected)
1138 }
1139
1140 macro_rules! perfectly_shredded_to_arrow_primitive_test {
1141 ($name:ident, $primitive_type:expr, $perfectly_shredded_array_gen_fun:ident, $expected_array:expr) => {
1142 #[test]
1143 fn $name() {
1144 let array = $perfectly_shredded_array_gen_fun();
1145 let field = Field::new("typed_value", $primitive_type, true);
1146 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
1147 let result = variant_get(&array, options).unwrap();
1148 let expected_array: ArrayRef = Arc::new($expected_array);
1149 assert_eq!(&result, &expected_array);
1150 }
1151 };
1152 }
1153
1154 perfectly_shredded_to_arrow_primitive_test!(
1155 get_variant_perfectly_shredded_int18_as_int8,
1156 Int8,
1157 perfectly_shredded_int8_variant_array,
1158 Int8Array::from(vec![Some(1), Some(2), Some(3)])
1159 );
1160
1161 perfectly_shredded_to_arrow_primitive_test!(
1162 get_variant_perfectly_shredded_int16_as_int16,
1163 Int16,
1164 perfectly_shredded_int16_variant_array,
1165 Int16Array::from(vec![Some(1), Some(2), Some(3)])
1166 );
1167
1168 perfectly_shredded_to_arrow_primitive_test!(
1169 get_variant_perfectly_shredded_int32_as_int32,
1170 Int32,
1171 perfectly_shredded_int32_variant_array,
1172 Int32Array::from(vec![Some(1), Some(2), Some(3)])
1173 );
1174
1175 perfectly_shredded_to_arrow_primitive_test!(
1176 get_variant_perfectly_shredded_int64_as_int64,
1177 Int64,
1178 perfectly_shredded_int64_variant_array,
1179 Int64Array::from(vec![Some(1), Some(2), Some(3)])
1180 );
1181
1182 perfectly_shredded_to_arrow_primitive_test!(
1183 get_variant_perfectly_shredded_float32_as_float32,
1184 Float32,
1185 perfectly_shredded_float32_variant_array,
1186 Float32Array::from(vec![Some(1.0), Some(2.0), Some(3.0)])
1187 );
1188
1189 perfectly_shredded_to_arrow_primitive_test!(
1190 get_variant_perfectly_shredded_float64_as_float64,
1191 Float64,
1192 perfectly_shredded_float64_variant_array,
1193 Float64Array::from(vec![Some(1.0), Some(2.0), Some(3.0)])
1194 );
1195
1196 perfectly_shredded_to_arrow_primitive_test!(
1197 get_variant_perfectly_shredded_boolean_as_boolean,
1198 Boolean,
1199 perfectly_shredded_bool_variant_array,
1200 BooleanArray::from(vec![Some(true), Some(false), Some(true)])
1201 );
1202
1203 perfectly_shredded_to_arrow_primitive_test!(
1204 get_variant_perfectly_shredded_utf8_as_utf8,
1205 DataType::Utf8,
1206 perfectly_shredded_utf8_variant_array,
1207 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1208 );
1209
1210 perfectly_shredded_to_arrow_primitive_test!(
1211 get_variant_perfectly_shredded_large_utf8_as_utf8,
1212 DataType::Utf8,
1213 perfectly_shredded_large_utf8_variant_array,
1214 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1215 );
1216
1217 perfectly_shredded_to_arrow_primitive_test!(
1218 get_variant_perfectly_shredded_utf8_view_as_utf8,
1219 DataType::Utf8,
1220 perfectly_shredded_utf8_view_variant_array,
1221 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1222 );
1223
1224 macro_rules! perfectly_shredded_variant_array_fn {
1225 ($func:ident, $typed_value_gen:expr) => {
1226 fn $func() -> ArrayRef {
1227 let typed_value: ArrayRef = Arc::new($typed_value_gen());
1230 if let Some(shredded) = cast_to_variant(typed_value.as_ref())
1231 .ok()
1232 .and_then(|unshredded| shred_variant(&unshredded, typed_value.data_type()).ok())
1233 {
1234 return shredded.into();
1235 }
1236
1237 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(
1238 EMPTY_VARIANT_METADATA_BYTES,
1239 typed_value.len(),
1240 ));
1241 VariantArray::perfectly_shredded(Arc::new(metadata), typed_value, None).into()
1242 }
1243 };
1244 }
1245
1246 perfectly_shredded_variant_array_fn!(perfectly_shredded_utf8_variant_array, || {
1247 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1248 });
1249
1250 perfectly_shredded_variant_array_fn!(perfectly_shredded_large_utf8_variant_array, || {
1251 LargeStringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1252 });
1253
1254 perfectly_shredded_variant_array_fn!(perfectly_shredded_utf8_view_variant_array, || {
1255 StringViewArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1256 });
1257
1258 perfectly_shredded_variant_array_fn!(perfectly_shredded_bool_variant_array, || {
1259 BooleanArray::from(vec![Some(true), Some(false), Some(true)])
1260 });
1261
1262 macro_rules! numeric_perfectly_shredded_variant_array_fn {
1274 ($func:ident, $array_type:ident, $primitive_type:ty) => {
1275 perfectly_shredded_variant_array_fn!($func, || {
1276 $array_type::from(vec![
1277 Some(<$primitive_type>::try_from(1u8).unwrap()),
1278 Some(<$primitive_type>::try_from(2u8).unwrap()),
1279 Some(<$primitive_type>::try_from(3u8).unwrap()),
1280 ])
1281 });
1282 };
1283 }
1284
1285 numeric_perfectly_shredded_variant_array_fn!(
1286 perfectly_shredded_int8_variant_array,
1287 Int8Array,
1288 i8
1289 );
1290 numeric_perfectly_shredded_variant_array_fn!(
1291 perfectly_shredded_int16_variant_array,
1292 Int16Array,
1293 i16
1294 );
1295 numeric_perfectly_shredded_variant_array_fn!(
1296 perfectly_shredded_int32_variant_array,
1297 Int32Array,
1298 i32
1299 );
1300 numeric_perfectly_shredded_variant_array_fn!(
1301 perfectly_shredded_int64_variant_array,
1302 Int64Array,
1303 i64
1304 );
1305 numeric_perfectly_shredded_variant_array_fn!(
1306 perfectly_shredded_float32_variant_array,
1307 Float32Array,
1308 f32
1309 );
1310 numeric_perfectly_shredded_variant_array_fn!(
1311 perfectly_shredded_float64_variant_array,
1312 Float64Array,
1313 f64
1314 );
1315
1316 perfectly_shredded_variant_array_fn!(
1317 perfectly_shredded_timestamp_micro_ntz_variant_array,
1318 || {
1319 arrow::array::TimestampMicrosecondArray::from(vec![
1320 Some(-456000),
1321 Some(1758602096000001),
1322 Some(1758602096000002),
1323 ])
1324 }
1325 );
1326
1327 perfectly_shredded_to_arrow_primitive_test!(
1328 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_micro_ntz,
1329 DataType::Timestamp(TimeUnit::Microsecond, None),
1330 perfectly_shredded_timestamp_micro_ntz_variant_array,
1331 arrow::array::TimestampMicrosecondArray::from(vec![
1332 Some(-456000),
1333 Some(1758602096000001),
1334 Some(1758602096000002),
1335 ])
1336 );
1337
1338 perfectly_shredded_to_arrow_primitive_test!(
1340 get_variant_perfectly_shredded_timestamp_micro_ntz_as_nano_ntz,
1341 DataType::Timestamp(TimeUnit::Nanosecond, None),
1342 perfectly_shredded_timestamp_micro_ntz_variant_array,
1343 arrow::array::TimestampNanosecondArray::from(vec![
1344 Some(-456000000),
1345 Some(1758602096000001000),
1346 Some(1758602096000002000)
1347 ])
1348 );
1349
1350 perfectly_shredded_variant_array_fn!(perfectly_shredded_timestamp_micro_variant_array, || {
1351 arrow::array::TimestampMicrosecondArray::from(vec![
1352 Some(-456000),
1353 Some(1758602096000001),
1354 Some(1758602096000002),
1355 ])
1356 .with_timezone("+00:00")
1357 });
1358
1359 perfectly_shredded_to_arrow_primitive_test!(
1360 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_micro,
1361 DataType::Timestamp(TimeUnit::Microsecond, Some(Arc::from("+00:00"))),
1362 perfectly_shredded_timestamp_micro_variant_array,
1363 arrow::array::TimestampMicrosecondArray::from(vec![
1364 Some(-456000),
1365 Some(1758602096000001),
1366 Some(1758602096000002),
1367 ])
1368 .with_timezone("+00:00")
1369 );
1370
1371 perfectly_shredded_to_arrow_primitive_test!(
1373 get_variant_perfectly_shredded_timestamp_micro_as_nano,
1374 DataType::Timestamp(TimeUnit::Nanosecond, Some(Arc::from("+00:00"))),
1375 perfectly_shredded_timestamp_micro_variant_array,
1376 arrow::array::TimestampNanosecondArray::from(vec![
1377 Some(-456000000),
1378 Some(1758602096000001000),
1379 Some(1758602096000002000)
1380 ])
1381 .with_timezone("+00:00")
1382 );
1383
1384 perfectly_shredded_variant_array_fn!(
1385 perfectly_shredded_timestamp_nano_ntz_variant_array,
1386 || {
1387 arrow::array::TimestampNanosecondArray::from(vec![
1388 Some(-4999999561),
1389 Some(1758602096000000001),
1390 Some(1758602096000000002),
1391 ])
1392 }
1393 );
1394
1395 perfectly_shredded_variant_array_fn!(
1396 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1397 || {
1398 arrow::array::TimestampMicrosecondArray::from(vec![
1399 Some(1234), Some(1234000), Some(1234000000), ])
1403 .with_timezone("+00:00")
1404 }
1405 );
1406
1407 perfectly_shredded_to_arrow_primitive_test!(
1410 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_second,
1411 DataType::Timestamp(TimeUnit::Second, Some(Arc::from("+00:00"))),
1412 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1413 arrow::array::TimestampSecondArray::from(vec![
1414 None,
1415 None, Some(1234)
1417 ])
1418 .with_timezone("+00:00")
1419 );
1420
1421 perfectly_shredded_to_arrow_primitive_test!(
1422 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_milli,
1423 DataType::Timestamp(TimeUnit::Millisecond, Some(Arc::from("+00:00"))),
1424 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1425 arrow::array::TimestampMillisecondArray::from(vec![
1426 None, Some(1234),
1428 Some(1234000)
1429 ])
1430 .with_timezone("+00:00")
1431 );
1432
1433 perfectly_shredded_variant_array_fn!(
1434 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1435 || {
1436 arrow::array::TimestampMicrosecondArray::from(vec![
1437 Some(1234), Some(1234000), Some(1234000000), ])
1441 }
1442 );
1443
1444 perfectly_shredded_to_arrow_primitive_test!(
1447 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_second,
1448 DataType::Timestamp(TimeUnit::Second, None),
1449 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1450 arrow::array::TimestampSecondArray::from(vec![
1451 None,
1452 None, Some(1234)
1454 ])
1455 );
1456
1457 perfectly_shredded_to_arrow_primitive_test!(
1458 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_milli,
1459 DataType::Timestamp(TimeUnit::Millisecond, None),
1460 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1461 arrow::array::TimestampMillisecondArray::from(vec![
1462 None, Some(1234),
1464 Some(1234000)
1465 ])
1466 );
1467
1468 perfectly_shredded_variant_array_fn!(
1469 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1470 || {
1471 arrow::array::TimestampNanosecondArray::from(vec![
1472 Some(1234000), Some(1234000000), Some(1234000000000), ])
1476 .with_timezone("+00:00")
1477 }
1478 );
1479
1480 perfectly_shredded_to_arrow_primitive_test!(
1483 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_second,
1484 DataType::Timestamp(TimeUnit::Second, Some(Arc::from("+00:00"))),
1485 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1486 arrow::array::TimestampSecondArray::from(vec![
1487 None,
1488 None, Some(1234)
1490 ])
1491 .with_timezone("+00:00")
1492 );
1493
1494 perfectly_shredded_to_arrow_primitive_test!(
1495 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_milli,
1496 DataType::Timestamp(TimeUnit::Millisecond, Some(Arc::from("+00:00"))),
1497 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1498 arrow::array::TimestampMillisecondArray::from(vec![
1499 None, Some(1234),
1501 Some(1234000)
1502 ])
1503 .with_timezone("+00:00")
1504 );
1505
1506 perfectly_shredded_variant_array_fn!(
1507 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1508 || {
1509 arrow::array::TimestampNanosecondArray::from(vec![
1510 Some(1234000), Some(1234000000), Some(1234000000000), ])
1514 }
1515 );
1516
1517 perfectly_shredded_to_arrow_primitive_test!(
1520 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_second,
1521 DataType::Timestamp(TimeUnit::Second, None),
1522 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1523 arrow::array::TimestampSecondArray::from(vec![
1524 None,
1525 None, Some(1234)
1527 ])
1528 );
1529
1530 perfectly_shredded_to_arrow_primitive_test!(
1531 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_milli,
1532 DataType::Timestamp(TimeUnit::Millisecond, None),
1533 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1534 arrow::array::TimestampMillisecondArray::from(vec![
1535 None, Some(1234),
1537 Some(1234000)
1538 ])
1539 );
1540
1541 perfectly_shredded_to_arrow_primitive_test!(
1542 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_nano_ntz,
1543 DataType::Timestamp(TimeUnit::Nanosecond, None),
1544 perfectly_shredded_timestamp_nano_ntz_variant_array,
1545 arrow::array::TimestampNanosecondArray::from(vec![
1546 Some(-4999999561),
1547 Some(1758602096000000001),
1548 Some(1758602096000000002),
1549 ])
1550 );
1551
1552 perfectly_shredded_variant_array_fn!(perfectly_shredded_timestamp_nano_variant_array, || {
1553 arrow::array::TimestampNanosecondArray::from(vec![
1554 Some(-4999999561),
1555 Some(1758602096000000001),
1556 Some(1758602096000000002),
1557 ])
1558 .with_timezone("+00:00")
1559 });
1560
1561 perfectly_shredded_to_arrow_primitive_test!(
1562 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_nano,
1563 DataType::Timestamp(TimeUnit::Nanosecond, Some(Arc::from("+00:00"))),
1564 perfectly_shredded_timestamp_nano_variant_array,
1565 arrow::array::TimestampNanosecondArray::from(vec![
1566 Some(-4999999561),
1567 Some(1758602096000000001),
1568 Some(1758602096000000002),
1569 ])
1570 .with_timezone("+00:00")
1571 );
1572
1573 perfectly_shredded_variant_array_fn!(perfectly_shredded_date_variant_array, || {
1574 Date32Array::from(vec![Some(-12345), Some(17586), Some(20000)])
1575 });
1576
1577 perfectly_shredded_to_arrow_primitive_test!(
1578 get_variant_perfectly_shredded_date_as_date,
1579 DataType::Date32,
1580 perfectly_shredded_date_variant_array,
1581 Date32Array::from(vec![Some(-12345), Some(17586), Some(20000)])
1582 );
1583
1584 perfectly_shredded_to_arrow_primitive_test!(
1585 get_variant_perfectly_shredded_date_as_date64,
1586 DataType::Date64,
1587 perfectly_shredded_date_variant_array,
1588 Date64Array::from(vec![
1589 Some(-1066608000000),
1590 Some(1519430400000),
1591 Some(1728000000000)
1592 ])
1593 );
1594
1595 perfectly_shredded_variant_array_fn!(perfectly_shredded_time_variant_array, || {
1596 Time64MicrosecondArray::from(vec![Some(12345000), Some(87654000), Some(135792000)])
1597 });
1598
1599 perfectly_shredded_to_arrow_primitive_test!(
1600 get_variant_perfectly_shredded_time_as_time,
1601 DataType::Time64(TimeUnit::Microsecond),
1602 perfectly_shredded_time_variant_array,
1603 Time64MicrosecondArray::from(vec![Some(12345000), Some(87654000), Some(135792000)])
1604 );
1605
1606 perfectly_shredded_to_arrow_primitive_test!(
1607 get_variant_perfectly_shredded_time_as_time64_nano,
1608 DataType::Time64(TimeUnit::Nanosecond),
1609 perfectly_shredded_time_variant_array,
1610 Time64NanosecondArray::from(vec![
1611 Some(12345000000),
1612 Some(87654000000),
1613 Some(135792000000)
1614 ])
1615 );
1616
1617 perfectly_shredded_variant_array_fn!(perfectly_shredded_time_variant_array_for_time32, || {
1618 Time64MicrosecondArray::from(vec![
1619 Some(1234), Some(7654000), Some(35792000000), ])
1623 });
1624
1625 perfectly_shredded_to_arrow_primitive_test!(
1626 get_variant_perfectly_shredded_time_as_time32_second,
1627 DataType::Time32(TimeUnit::Second),
1628 perfectly_shredded_time_variant_array_for_time32,
1629 Time32SecondArray::from(vec![
1630 None,
1631 None, Some(35792)
1633 ])
1634 );
1635
1636 perfectly_shredded_to_arrow_primitive_test!(
1637 get_variant_perfectly_shredded_time_as_time32_milli,
1638 DataType::Time32(TimeUnit::Millisecond),
1639 perfectly_shredded_time_variant_array_for_time32,
1640 Time32MillisecondArray::from(vec![
1641 None, Some(7654),
1643 Some(35792000)
1644 ])
1645 );
1646
1647 perfectly_shredded_variant_array_fn!(perfectly_shredded_null_variant_array, || {
1648 let mut builder = NullBuilder::new();
1649 builder.append_nulls(3);
1650 builder.finish()
1651 });
1652
1653 perfectly_shredded_to_arrow_primitive_test!(
1654 get_variant_perfectly_shredded_null_as_null,
1655 DataType::Null,
1656 perfectly_shredded_null_variant_array,
1657 arrow::array::NullArray::new(3)
1658 );
1659
1660 perfectly_shredded_variant_array_fn!(perfectly_shredded_null_variant_array_with_int, || {
1661 Int32Array::from(vec![Some(32), Some(64), Some(48)])
1662 });
1663
1664 perfectly_shredded_to_arrow_primitive_test!(
1666 get_variant_perfectly_shredded_null_with_type_mismatch_in_safe_mode,
1667 DataType::Null,
1668 perfectly_shredded_null_variant_array_with_int,
1669 arrow::array::NullArray::new(3)
1670 );
1671
1672 #[test]
1674 fn get_variant_perfectly_shredded_null_as_null_with_type_mismatch_in_strict_mode() {
1675 let array = perfectly_shredded_null_variant_array_with_int();
1676 let field = Field::new("typed_value", DataType::Null, true);
1677 let options = GetOptions::new()
1678 .with_as_type(Some(FieldRef::from(field)))
1679 .with_cast_options(CastOptions {
1680 safe: false,
1681 format_options: FormatOptions::default(),
1682 });
1683
1684 let result = variant_get(&array, options);
1685
1686 assert!(result.is_err());
1687 let error_msg = format!("{}", result.unwrap_err());
1688 assert!(
1689 error_msg
1690 .contains("Cast error: Failed to extract primitive of type Null from variant Int32(32) at path VariantPath([])"),
1691 "Expected=[Cast error: Failed to extract primitive of type Null from variant Int32(32) at path VariantPath([])],\
1692 Got error message=[{error_msg}]"
1693 );
1694 }
1695
1696 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal4_variant_array, || {
1697 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
1698 .with_precision_and_scale(5, 2)
1699 .unwrap()
1700 });
1701
1702 perfectly_shredded_to_arrow_primitive_test!(
1703 get_variant_perfectly_shredded_decimal4_as_decimal4,
1704 DataType::Decimal32(5, 2),
1705 perfectly_shredded_decimal4_variant_array,
1706 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
1707 .with_precision_and_scale(5, 2)
1708 .unwrap()
1709 );
1710
1711 perfectly_shredded_variant_array_fn!(
1712 perfectly_shredded_decimal8_variant_array_cast2decimal32,
1713 || {
1714 Decimal64Array::from(vec![Some(123456), Some(145678), Some(-123456)])
1715 .with_precision_and_scale(6, 1)
1716 .unwrap()
1717 }
1718 );
1719
1720 perfectly_shredded_to_arrow_primitive_test!(
1724 get_variant_perfectly_shredded_decimal8_through_decimal32_as_decimal8,
1725 DataType::Decimal64(6, 1),
1726 perfectly_shredded_decimal8_variant_array_cast2decimal32,
1727 Decimal64Array::from(vec![Some(123456), Some(145678), Some(-123456)])
1728 .with_precision_and_scale(6, 1)
1729 .unwrap()
1730 );
1731
1732 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal8_variant_array, || {
1735 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1736 .with_precision_and_scale(10, 1)
1737 .unwrap()
1738 });
1739
1740 perfectly_shredded_to_arrow_primitive_test!(
1741 get_variant_perfectly_shredded_decimal8_as_decimal8,
1742 DataType::Decimal64(10, 1),
1743 perfectly_shredded_decimal8_variant_array,
1744 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1745 .with_precision_and_scale(10, 1)
1746 .unwrap()
1747 );
1748
1749 perfectly_shredded_variant_array_fn!(
1752 perfectly_shredded_decimal16_within_decimal4_variant_array,
1753 || {
1754 Decimal128Array::from(vec![
1755 Some(i128::from(1234589)),
1756 Some(i128::from(2344444)),
1757 Some(i128::from(-1234789)),
1758 ])
1759 .with_precision_and_scale(7, 3)
1760 .unwrap()
1761 }
1762 );
1763
1764 perfectly_shredded_to_arrow_primitive_test!(
1767 get_variant_perfectly_shredded_decimal16_within_decimal4_as_decimal16,
1768 DataType::Decimal128(7, 3),
1769 perfectly_shredded_decimal16_within_decimal4_variant_array,
1770 Decimal128Array::from(vec![
1771 Some(i128::from(1234589)),
1772 Some(i128::from(2344444)),
1773 Some(i128::from(-1234789)),
1774 ])
1775 .with_precision_and_scale(7, 3)
1776 .unwrap()
1777 );
1778
1779 perfectly_shredded_variant_array_fn!(
1780 perfectly_shredded_decimal16_within_decimal8_variant_array,
1781 || {
1782 Decimal128Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1783 .with_precision_and_scale(10, 1)
1784 .unwrap()
1785 }
1786 );
1787
1788 perfectly_shredded_to_arrow_primitive_test!(
1791 get_variant_perfectly_shredded_decimal16_within8_as_decimal16,
1792 DataType::Decimal128(10, 1),
1793 perfectly_shredded_decimal16_within_decimal8_variant_array,
1794 Decimal128Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1795 .with_precision_and_scale(10, 1)
1796 .unwrap()
1797 );
1798
1799 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal16_variant_array, || {
1800 Decimal128Array::from(vec![
1801 Some(i128::from_str("12345678901234567899").unwrap()),
1802 Some(i128::from_str("23445677483748324300").unwrap()),
1803 Some(i128::from_str("-12345678901234567899").unwrap()),
1804 ])
1805 .with_precision_and_scale(20, 3)
1806 .unwrap()
1807 });
1808
1809 perfectly_shredded_to_arrow_primitive_test!(
1812 get_variant_perfectly_shredded_decimal16_as_decimal16,
1813 DataType::Decimal128(20, 3),
1814 perfectly_shredded_decimal16_variant_array,
1815 Decimal128Array::from(vec![
1816 Some(i128::from_str("12345678901234567899").unwrap()),
1817 Some(i128::from_str("23445677483748324300").unwrap()),
1818 Some(i128::from_str("-12345678901234567899").unwrap())
1819 ])
1820 .with_precision_and_scale(20, 3)
1821 .unwrap()
1822 );
1823
1824 perfectly_shredded_variant_array_fn!(perfectly_shredded_binary_variant_array, || {
1825 BinaryArray::from(vec![
1826 Some(b"Apache" as &[u8]),
1827 Some(b"Arrow-rs" as &[u8]),
1828 Some(b"Parquet-variant" as &[u8]),
1829 ])
1830 });
1831
1832 perfectly_shredded_to_arrow_primitive_test!(
1833 get_variant_perfectly_shredded_binary_as_binary,
1834 DataType::Binary,
1835 perfectly_shredded_binary_variant_array,
1836 BinaryArray::from(vec![
1837 Some(b"Apache" as &[u8]),
1838 Some(b"Arrow-rs" as &[u8]),
1839 Some(b"Parquet-variant" as &[u8]),
1840 ])
1841 );
1842
1843 perfectly_shredded_variant_array_fn!(perfectly_shredded_large_binary_variant_array, || {
1844 LargeBinaryArray::from(vec![
1845 Some(b"Apache" as &[u8]),
1846 Some(b"Arrow-rs" as &[u8]),
1847 Some(b"Parquet-variant" as &[u8]),
1848 ])
1849 });
1850
1851 perfectly_shredded_to_arrow_primitive_test!(
1852 get_variant_perfectly_shredded_large_binary_as_large_binary,
1853 DataType::LargeBinary,
1854 perfectly_shredded_large_binary_variant_array,
1855 LargeBinaryArray::from(vec![
1856 Some(b"Apache" as &[u8]),
1857 Some(b"Arrow-rs" as &[u8]),
1858 Some(b"Parquet-variant" as &[u8]),
1859 ])
1860 );
1861
1862 perfectly_shredded_variant_array_fn!(perfectly_shredded_binary_view_variant_array, || {
1863 BinaryViewArray::from(vec![
1864 Some(b"Apache" as &[u8]),
1865 Some(b"Arrow-rs" as &[u8]),
1866 Some(b"Parquet-variant" as &[u8]),
1867 ])
1868 });
1869
1870 perfectly_shredded_to_arrow_primitive_test!(
1871 get_variant_perfectly_shredded_binary_view_as_binary_view,
1872 DataType::BinaryView,
1873 perfectly_shredded_binary_view_variant_array,
1874 BinaryViewArray::from(vec![
1875 Some(b"Apache" as &[u8]),
1876 Some(b"Arrow-rs" as &[u8]),
1877 Some(b"Parquet-variant" as &[u8]),
1878 ])
1879 );
1880
1881 fn all_null_variant_array() -> ArrayRef {
1898 let nulls = NullBuffer::from(vec![
1899 false, false, false, ]);
1903
1904 let metadata =
1906 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 3));
1907
1908 ArrayRef::from(VariantArray::from_parts(
1909 Arc::new(metadata),
1910 all_null_value_column(3),
1911 None,
1912 Some(nulls),
1913 ))
1914 }
1915
1916 #[test]
1920 fn test_shredded_object_field_access() {
1921 let array = shredded_object_with_x_field_variant_array();
1922
1923 let options = GetOptions::new_with_path(VariantPath::try_from("x").unwrap());
1925 let result = variant_get(&array, options).unwrap();
1926
1927 let result_variant = VariantArray::try_new(&result).unwrap();
1928 assert_eq!(result_variant.len(), 2);
1929
1930 assert_eq!(result_variant.value(0), Variant::Int32(1));
1932 assert_eq!(result_variant.value(1), Variant::Int32(42));
1934 }
1935
1936 #[test]
1937 fn test_malformed_shredded_object_field_reports_field_and_type() {
1938 let metadata =
1939 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 2));
1940 let typed_value = StructArray::try_new(
1941 Fields::from(vec![Field::new("x", DataType::Int32, true)]),
1942 vec![Arc::new(Int32Array::from(vec![Some(1), Some(42)]))],
1943 None,
1944 )
1945 .unwrap();
1946 let array = ArrayRef::from(VariantArray::from_parts(
1947 Arc::new(metadata),
1948 all_null_value_column(2),
1949 Some(Arc::new(typed_value)),
1950 None,
1951 ));
1952
1953 let options = GetOptions::new_with_path(VariantPath::try_from("x").unwrap());
1954 let err = variant_get(&array, options).unwrap_err();
1955
1956 assert_eq!(
1957 err.to_string(),
1958 "Invalid argument error: Shredded object field 'x' must be a Struct containing \
1959 'value' and/or 'typed_value', got Int32"
1960 );
1961 }
1962
1963 #[test]
1965 fn test_shredded_object_field_as_int32() {
1966 let array = shredded_object_with_x_field_variant_array();
1967
1968 let field = Field::new("x", DataType::Int32, false);
1970 let options = GetOptions::new_with_path(VariantPath::try_from("x").unwrap())
1971 .with_as_type(Some(FieldRef::from(field)));
1972 let result = variant_get(&array, options).unwrap();
1973
1974 let expected: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(42)]));
1976 assert_eq!(&result, &expected);
1977 }
1978
1979 type ShreddedListLikeArrayGen = fn() -> ArrayRef;
1980 type ShreddedListLikeCase = (&'static str, ShreddedListLikeArrayGen);
1981
1982 fn shredded_list_like_cases() -> [ShreddedListLikeCase; 4] {
1983 [
1984 ("list", shredded_list_variant_array),
1985 ("large_list", shredded_large_list_variant_array),
1986 ("list_view", shredded_list_view_variant_array),
1987 ("large_list_view", shredded_large_list_view_variant_array),
1988 ]
1989 }
1990
1991 #[test]
1992 fn test_shredded_list_like_index_access_from_value_field() {
1993 let options = GetOptions::new_with_path(VariantPath::from(1));
1994
1995 for (case, array_gen) in shredded_list_like_cases() {
1996 let array = array_gen();
1997 let result = variant_get(&array, options.clone()).unwrap();
1998 let result_variant = VariantArray::try_new(&result).unwrap();
1999
2000 assert_eq!(result_variant.value(0), Variant::from("drama"), "{case}");
2001 assert_eq!(result_variant.value(1).as_int64(), Some(123), "{case}");
2002 }
2003 }
2004
2005 #[test]
2006 fn test_shredded_list_like_index_out_of_bounds_unsafe_cast_returns_null() {
2007 let options =
2008 GetOptions::new_with_path(VariantPath::from(10)).with_cast_options(CastOptions {
2009 safe: false,
2010 ..Default::default()
2011 });
2012
2013 for (case, array_gen) in shredded_list_like_cases() {
2014 let result = variant_get(&array_gen(), options.clone()).unwrap();
2015 let result_variant = VariantArray::try_new(&result).unwrap();
2016 assert!(result_variant.is_null(0), "{case}");
2017 assert!(result_variant.is_null(1), "{case}");
2018 }
2019 }
2020
2021 #[test]
2023 fn test_shredded_list_like_as_string() {
2024 let field = Field::new("typed_value", DataType::Utf8, false);
2025 let options = GetOptions::new_with_path(VariantPath::from(0))
2026 .with_as_type(Some(FieldRef::from(field)));
2027 let expected: ArrayRef = Arc::new(StringArray::from(vec![Some("comedy"), Some("horror")]));
2028
2029 for (case, array_gen) in shredded_list_like_cases() {
2030 let result = variant_get(&array_gen(), options.clone()).unwrap();
2031 assert_eq!(&result, &expected, "{case}");
2032 }
2033 }
2034
2035 #[test]
2036 fn test_shredded_list_like_index_access_from_value_field_as_int64() {
2037 let field = Field::new("typed_value", DataType::Int64, true);
2038 let options = GetOptions::new_with_path(VariantPath::from(1))
2039 .with_as_type(Some(FieldRef::from(field)));
2040 let expected: ArrayRef = Arc::new(Int64Array::from(vec![None, Some(123)]));
2041
2042 for (case, array_gen) in shredded_list_like_cases() {
2043 let result = variant_get(&array_gen(), options.clone()).unwrap();
2044 assert_eq!(&result, &expected, "{case}");
2046 }
2047 }
2048
2049 #[test]
2050 fn test_shredded_list_in_struct_index_access() {
2051 let array = shredded_struct_with_list_variant_array();
2052 let options = GetOptions::new_with_path(VariantPath::try_from("a[1]").unwrap());
2053 let result = variant_get(&array, options).unwrap();
2054 let result_variant = VariantArray::try_new(&result).unwrap();
2055
2056 assert_eq!(result_variant.value(0), Variant::from("drama"));
2057 assert_eq!(result_variant.value(1).as_int64(), Some(123));
2058 }
2059
2060 #[test]
2061 fn test_shredded_struct_in_list_field_access() {
2062 let array = shredded_list_of_struct_variant_array();
2063 let field = Field::new("x", DataType::Int32, true);
2064 let path = VariantPath::from(0).join("x");
2065 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2066 let result = variant_get(&array, options).unwrap();
2067
2068 let expected: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(3)]));
2069 assert_eq!(&result, &expected);
2070 }
2071
2072 #[test]
2073 fn test_shredded_list_of_lists_index_access() {
2074 let array = shredded_list_of_lists_variant_array();
2075 let path = VariantPath::from(0).join(1);
2076
2077 let result = variant_get(&array, GetOptions::new_with_path(path.clone())).unwrap();
2078 let result_variant = VariantArray::try_new(&result).unwrap();
2079 assert_eq!(result_variant.value(0), Variant::from("b"));
2080 assert_eq!(result_variant.value(1).as_int64(), Some(123));
2081
2082 let field = Field::new("typed_value", DataType::Int64, true);
2083 let casted = variant_get(
2084 &array,
2085 GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field))),
2086 )
2087 .unwrap();
2088 let expected: ArrayRef = Arc::new(Int64Array::from(vec![None, Some(123)]));
2089 assert_eq!(&casted, &expected);
2090 }
2091
2092 #[test]
2093 fn test_shredded_list_out_of_bounds_is_null() {
2094 let json: ArrayRef = Arc::new(StringArray::from(vec!["[]", "[null]", "[1]", r#""x""#]));
2096 let input = json_to_variant(&json).unwrap();
2097 let list_schema = DataType::new_list(DataType::Int64, true);
2098 let shredded = ArrayRef::from(shred_variant(&input, &list_schema).unwrap());
2099
2100 let options = GetOptions::new_with_path(VariantPath::from(0));
2101 let result = variant_get(&shredded, options).unwrap();
2102 let result = VariantArray::try_new(&result).unwrap();
2103
2104 assert!(result.is_null(0));
2105 assert!(!result.is_null(1));
2106 assert_eq!(result.value(1), Variant::Null);
2107 assert_eq!(result.value(2), Variant::Int64(1));
2108 assert!(result.is_null(3));
2109
2110 let options = GetOptions::new_with_path(VariantPath::from(5));
2111 let result = variant_get(&shredded, options).unwrap();
2112 let result = VariantArray::try_new(&result).unwrap();
2113 assert!((0..4).all(|i| result.is_null(i)));
2114 }
2115
2116 fn shredded_list_like_variant_array(list_schema: DataType) -> ArrayRef {
2122 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
2123 Some(r#"["comedy", "drama"]"#),
2124 Some(r#"["horror", 123]"#),
2125 ]));
2126 let input = json_to_variant(&json_rows).unwrap();
2127
2128 let shredded = shred_variant(&input, &list_schema).unwrap();
2129 ArrayRef::from(shredded)
2130 }
2131
2132 fn shredded_list_of_lists_variant_array() -> ArrayRef {
2133 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
2134 Some(r#"[["a", "b"], ["c", "d"]]"#),
2135 Some(r#"[["x", 123], ["y", "z"]]"#),
2136 ]));
2137 let input = json_to_variant(&json_rows).unwrap();
2138
2139 let inner_list = DataType::List(Arc::new(Field::new("item", DataType::Utf8, true)));
2140 let outer_list = DataType::List(Arc::new(Field::new("item", inner_list, true)));
2141 let shredded = shred_variant(&input, &outer_list).unwrap();
2142 ArrayRef::from(shredded)
2143 }
2144
2145 fn shredded_list_variant_array() -> ArrayRef {
2146 shredded_list_like_variant_array(DataType::List(Arc::new(Field::new(
2147 "item",
2148 DataType::Utf8,
2149 true,
2150 ))))
2151 }
2152
2153 fn shredded_large_list_variant_array() -> ArrayRef {
2154 shredded_list_like_variant_array(DataType::LargeList(Arc::new(Field::new(
2155 "item",
2156 DataType::Utf8,
2157 true,
2158 ))))
2159 }
2160
2161 fn shredded_list_view_variant_array() -> ArrayRef {
2162 shredded_list_like_variant_array(DataType::ListView(Arc::new(Field::new(
2163 "item",
2164 DataType::Utf8,
2165 true,
2166 ))))
2167 }
2168
2169 fn shredded_large_list_view_variant_array() -> ArrayRef {
2170 shredded_list_like_variant_array(DataType::LargeListView(Arc::new(Field::new(
2171 "item",
2172 DataType::Utf8,
2173 true,
2174 ))))
2175 }
2176
2177 fn shredded_struct_with_list_variant_array() -> ArrayRef {
2178 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
2179 Some(r#"{"a": ["comedy", "drama"]}"#),
2180 Some(r#"{"a": ["horror", 123]}"#),
2181 ]));
2182 let input = json_to_variant(&json_rows).unwrap();
2183
2184 let list_schema = DataType::List(Arc::new(Field::new("item", DataType::Utf8, true)));
2185 let shredding_schema = ShreddedSchemaBuilder::default()
2186 .with_path("a", &list_schema)
2187 .unwrap()
2188 .build();
2189 let shredded = shred_variant(&input, &shredding_schema).unwrap();
2190 ArrayRef::from(shredded)
2191 }
2192
2193 fn shredded_list_of_struct_variant_array() -> ArrayRef {
2194 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
2195 Some(r#"[{"x": 1}, {"x": 2}]"#),
2196 Some(r#"[{"x": 3}, {"y": 4}]"#),
2197 ]));
2198 let input = json_to_variant(&json_rows).unwrap();
2199
2200 let struct_type =
2201 DataType::Struct(Fields::from(vec![Field::new("x", DataType::Int32, true)]));
2202 let list_schema = DataType::List(Arc::new(Field::new("item", struct_type, true)));
2203 let shredded = shred_variant(&input, &list_schema).unwrap();
2204 ArrayRef::from(shredded)
2205 }
2206
2207 fn shredded_object_with_x_field_variant_array() -> ArrayRef {
2219 let (metadata, y_field_value) = {
2221 let mut builder = parquet_variant::VariantBuilder::new();
2222 let mut obj = builder.new_object();
2223 obj.insert("x", Variant::Int32(42));
2224 obj.insert("y", Variant::from("foo"));
2225 obj.finish();
2226 builder.finish()
2227 };
2228
2229 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2231
2232 let empty_object_value = {
2237 let mut builder = parquet_variant::VariantBuilder::new();
2238 let obj = builder.new_object();
2239 obj.finish();
2240 let (_, value) = builder.finish();
2241 value
2242 };
2243
2244 let value_array = BinaryViewArray::from(vec![
2245 Some(y_field_value.as_slice()), Some(empty_object_value.as_slice()), ]);
2248
2249 let x_field_typed_value = Int32Array::from(vec![Some(1), Some(42)]);
2252
2253 let x_field_shredded = ShreddedVariantFieldArray::perfectly_shredded(Arc::new(
2255 x_field_typed_value,
2256 ) as ArrayRef);
2257
2258 let typed_value_fields = Fields::from(vec![Field::new(
2260 "x",
2261 x_field_shredded.data_type().clone(),
2262 true,
2263 )]);
2264 let typed_value_struct = StructArray::try_new(
2265 typed_value_fields,
2266 vec![ArrayRef::from(x_field_shredded)],
2267 None, )
2269 .unwrap();
2270
2271 ArrayRef::from(VariantArray::from_parts(
2273 Arc::new(metadata_array),
2274 Arc::new(value_array),
2275 Some(Arc::new(typed_value_struct)),
2276 None,
2277 ))
2278 }
2279
2280 #[test]
2282 fn test_simple_nested_path_support() {
2283 println!("Testing path parsing:");
2285
2286 let path_x = VariantPath::try_from("x").unwrap();
2287 let elements_x: Vec<_> = path_x.iter().collect();
2288 println!(" 'x' -> {} elements: {:?}", elements_x.len(), elements_x);
2289
2290 let path_ax = VariantPath::try_from("a.x").unwrap();
2291 let elements_ax: Vec<_> = path_ax.iter().collect();
2292 println!(
2293 " 'a.x' -> {} elements: {:?}",
2294 elements_ax.len(),
2295 elements_ax
2296 );
2297
2298 let path_ax_alt = VariantPath::try_from("$.a.x").unwrap();
2299 let elements_ax_alt: Vec<_> = path_ax_alt.iter().collect();
2300 println!(
2301 " '$.a.x' -> {} elements: {:?}",
2302 elements_ax_alt.len(),
2303 elements_ax_alt
2304 );
2305
2306 let path_nested = VariantPath::try_from("a").unwrap().join("x");
2307 let elements_nested: Vec<_> = path_nested.iter().collect();
2308 println!(
2309 " VariantPath::try_from('a').unwrap().join('x') -> {} elements: {:?}",
2310 elements_nested.len(),
2311 elements_nested
2312 );
2313
2314 let array = shredded_object_with_x_field_variant_array();
2316
2317 let real_nested_path = VariantPath::try_from("a").unwrap().join("x");
2319 let options = GetOptions::new_with_path(real_nested_path);
2320 let result = variant_get(&array, options);
2321
2322 match result {
2323 Ok(_) => {
2324 println!("Nested path 'a.x' works unexpectedly!");
2325 }
2326 Err(e) => {
2327 println!("Nested path 'a.x' error: {e}");
2328 if e.to_string().contains("Not yet implemented")
2329 || e.to_string().contains("NotYetImplemented")
2330 {
2331 println!("This is expected - nested paths are not implemented");
2332 return;
2333 }
2334 println!("This shows nested paths need implementation");
2336 }
2337 }
2338 }
2339
2340 #[test]
2344 fn test_depth_0_int32_conversion() {
2345 println!("=== Testing Depth 0: Direct field access ===");
2346
2347 let unshredded_array = create_depth_0_test_data();
2349
2350 let field = Field::new("result", DataType::Int32, true);
2351 let path = VariantPath::try_from("x").unwrap();
2352 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2353 let result = variant_get(&unshredded_array, options).unwrap();
2354
2355 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2356 Some(42), None, None, ]));
2360 assert_eq!(&result, &expected);
2361 println!("Depth 0 (unshredded) passed");
2362
2363 let shredded_array = create_depth_0_shredded_test_data_simple();
2365
2366 let field = Field::new("result", DataType::Int32, true);
2367 let path = VariantPath::try_from("x").unwrap();
2368 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2369 let result = variant_get(&shredded_array, options).unwrap();
2370
2371 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2372 Some(42), None, ]));
2375 assert_eq!(&result, &expected);
2376 println!("Depth 0 (shredded) passed");
2377 }
2378
2379 #[test]
2382 fn test_depth_1_int32_conversion() {
2383 println!("=== Testing Depth 1: Single nested field access ===");
2384
2385 let unshredded_array = create_nested_path_test_data();
2387
2388 let field = Field::new("result", DataType::Int32, true);
2389 let path = VariantPath::try_from("a.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2391 let result = variant_get(&unshredded_array, options).unwrap();
2392
2393 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2394 Some(55), None, ]));
2397 assert_eq!(&result, &expected);
2398 println!("Depth 1 (unshredded) passed");
2399
2400 let shredded_array = create_depth_1_shredded_test_data_working();
2402
2403 let field = Field::new("result", DataType::Int32, true);
2404 let path = VariantPath::try_from("a.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2406 let result = variant_get(&shredded_array, options).unwrap();
2407
2408 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2409 Some(55), None, ]));
2412 assert_eq!(&result, &expected);
2413 println!("Depth 1 (shredded) passed");
2414 }
2415
2416 #[test]
2419 fn test_depth_2_int32_conversion() {
2420 println!("=== Testing Depth 2: Double nested field access ===");
2421
2422 let unshredded_array = create_depth_2_test_data();
2424
2425 let field = Field::new("result", DataType::Int32, true);
2426 let path = VariantPath::try_from("a.b.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2428 let result = variant_get(&unshredded_array, options).unwrap();
2429
2430 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2431 Some(100), None, None, ]));
2435 assert_eq!(&result, &expected);
2436 println!("Depth 2 (unshredded) passed");
2437
2438 let shredded_array = create_depth_2_shredded_test_data_working();
2440
2441 let field = Field::new("result", DataType::Int32, true);
2442 let path = VariantPath::try_from("a.b.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2444 let result = variant_get(&shredded_array, options).unwrap();
2445
2446 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2447 Some(100), None, None, ]));
2451 assert_eq!(&result, &expected);
2452 println!("Depth 2 (shredded) passed");
2453 }
2454
2455 #[test]
2460 fn test_current_nested_path_functionality() {
2461 let array = shredded_object_with_x_field_variant_array();
2462
2463 let single_path = VariantPath::try_from("x").unwrap();
2465 let field = Field::new("result", DataType::Int32, true);
2466 let options =
2467 GetOptions::new_with_path(single_path).with_as_type(Some(FieldRef::from(field)));
2468 let result = variant_get(&array, options).unwrap();
2469
2470 println!("Single path 'x' works - result: {result:?}");
2471
2472 let nested_path = VariantPath::try_from("a").unwrap().join("x");
2474 let field = Field::new("result", DataType::Int32, true);
2475 let options =
2476 GetOptions::new_with_path(nested_path).with_as_type(Some(FieldRef::from(field)));
2477 let result = variant_get(&array, options).unwrap();
2478
2479 println!("Nested path 'a.x' result: {result:?}");
2480 }
2481
2482 #[test]
2483 fn test_variant_get_as_variant_from_unshredded_input() {
2484 let (unshredded, _) = create_variant_get_as_variant_test_data();
2485 let unshredded_field = VariantArray::try_new(&unshredded).unwrap().field("result");
2486 assert_variant_field_extraction_returns_unshredded_variant(&unshredded, &unshredded_field);
2487 }
2488
2489 #[test]
2490 fn test_variant_get_as_variant_from_shredded_input() {
2491 let (unshredded, shredded) = create_variant_get_as_variant_test_data();
2492 let unshredded_field = VariantArray::try_new(&unshredded).unwrap().field("result");
2493 assert_variant_field_extraction_returns_unshredded_variant(&shredded, &unshredded_field);
2494 }
2495
2496 #[test]
2497 fn test_variant_get_as_shredded_variant_is_not_yet_supported() {
2498 let (_, shredded) = create_variant_get_as_variant_test_data();
2499 let shredded_field = VariantArray::try_new(&shredded).unwrap().field("result");
2504 assert!(requested_field_is_shredded(Some(&shredded_field)));
2505
2506 let options = GetOptions::new_with_path(VariantPath::try_from("field_name").unwrap())
2507 .with_as_type(Some(FieldRef::from(shredded_field)));
2508 let err = variant_get(&shredded, options).unwrap_err();
2509 assert!(
2510 matches!(err, ArrowError::NotYetImplemented(_)),
2511 "expected NotYetImplemented, got {err:?}"
2512 );
2513 }
2514
2515 #[test]
2516 fn test_variant_get_list_element_wildcard_is_invalid_argument() {
2517 let (unshredded, _) = create_variant_get_as_variant_test_data();
2518 let options = GetOptions::new_with_path(VariantPath::try_from("field_name[*]").unwrap());
2519 let err = variant_get(&unshredded, options).unwrap_err();
2520 assert!(
2521 matches!(err, ArrowError::InvalidArgumentError(_)),
2522 "expected InvalidArgumentError, got {err:?}"
2523 );
2524 }
2525
2526 #[test]
2527 fn test_variant_get_missing_path_as_variant_annotates_value_non_nullable() {
2528 let (unshredded, shredded) = create_variant_get_as_variant_test_data();
2529 let variant_field = VariantArray::try_new(&unshredded).unwrap().field("result");
2530
2531 for as_type in [Some(FieldRef::from(variant_field)), None] {
2533 let options =
2534 GetOptions::new_with_path(VariantPath::try_from("field_name[0]").unwrap())
2535 .with_as_type(as_type);
2536 let result = variant_get(&shredded, options).unwrap();
2537 let result_variant = VariantArray::try_new(&result).unwrap();
2538
2539 assert_eq!(result_variant.inner().null_count(), result_variant.len());
2540 let value_field = result_variant.inner().field_by_name("value").unwrap();
2541 assert!(!value_field.is_nullable());
2542 }
2543 }
2544
2545 fn create_variant_get_as_variant_test_data() -> (ArrayRef, ArrayRef) {
2546 let input_json: ArrayRef = Arc::new(StringArray::from(vec![
2547 Some(r#"{"field_name": {"k": 100000}}"#),
2548 Some(r#"{"field_name": {"k": "s"}}"#),
2549 ]));
2550
2551 let unshredded = ArrayRef::from(json_to_variant(&input_json).unwrap());
2552 let unshredded_variant = VariantArray::try_new(&unshredded).unwrap();
2553
2554 let as_type = DataType::Struct(Fields::from(vec![Field::new(
2555 "field_name",
2556 DataType::Struct(Fields::from(vec![Field::new("k", DataType::Int32, true)])),
2557 true,
2558 )]));
2559 let shredded = ArrayRef::from(shred_variant(&unshredded_variant, &as_type).unwrap());
2560
2561 (unshredded, shredded)
2562 }
2563
2564 fn assert_variant_field_extraction_returns_unshredded_variant(
2565 input: &ArrayRef,
2566 variant_field: &Field,
2567 ) {
2568 let options = GetOptions::new_with_path(VariantPath::try_from("field_name").unwrap())
2569 .with_as_type(Some(FieldRef::from(variant_field.clone())));
2570
2571 let result = variant_get(input, options).unwrap();
2572 let result_variant = VariantArray::try_new(&result).unwrap();
2573
2574 assert!(result_variant.typed_value_column().is_none());
2575 assert!(result_variant.value_column().null_count() < result_variant.len());
2576 let value_field = result_variant.inner().field_by_name("value").unwrap();
2577 assert!(!value_field.is_nullable());
2578
2579 let expected_json: ArrayRef = Arc::new(StringArray::from(vec![
2580 Some(r#"{"k":100000}"#),
2581 Some(r#"{"k":"s"}"#),
2582 ]));
2583 let expected = json_to_variant(&expected_json).unwrap();
2584
2585 assert_eq!(result_variant.len(), expected.len());
2586 for i in 0..result_variant.len() {
2587 assert_eq!(result_variant.is_null(i), expected.is_null(i));
2588 if !result_variant.is_null(i) {
2589 assert_eq!(result_variant.value(i), expected.value(i));
2590 }
2591 }
2592 }
2593
2594 fn create_depth_0_test_data() -> ArrayRef {
2597 let mut builder = crate::VariantArrayBuilder::new(3);
2598
2599 {
2601 let json_str = r#"{"x": 42}"#;
2602 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2603 if let Ok(variant_array) = json_to_variant(&string_array) {
2604 builder.append_variant(variant_array.value(0));
2605 } else {
2606 builder.append_null();
2607 }
2608 }
2609
2610 {
2612 let json_str = r#"{"x": "foo"}"#;
2613 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2614 if let Ok(variant_array) = json_to_variant(&string_array) {
2615 builder.append_variant(variant_array.value(0));
2616 } else {
2617 builder.append_null();
2618 }
2619 }
2620
2621 {
2623 let json_str = r#"{"y": 10}"#;
2624 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2625 if let Ok(variant_array) = json_to_variant(&string_array) {
2626 builder.append_variant(variant_array.value(0));
2627 } else {
2628 builder.append_null();
2629 }
2630 }
2631
2632 ArrayRef::from(builder.build())
2633 }
2634
2635 fn create_nested_path_test_data() -> ArrayRef {
2638 let mut builder = crate::VariantArrayBuilder::new(2);
2639
2640 {
2642 let json_str = r#"{"a": {"x": 55}, "b": 42}"#;
2643 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2644 if let Ok(variant_array) = json_to_variant(&string_array) {
2645 builder.append_variant(variant_array.value(0));
2646 } else {
2647 builder.append_null();
2648 }
2649 }
2650
2651 {
2653 let json_str = r#"{"a": {"x": "foo"}, "b": 42}"#;
2654 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2655 if let Ok(variant_array) = json_to_variant(&string_array) {
2656 builder.append_variant(variant_array.value(0));
2657 } else {
2658 builder.append_null();
2659 }
2660 }
2661
2662 ArrayRef::from(builder.build())
2663 }
2664
2665 fn create_depth_2_test_data() -> ArrayRef {
2668 let mut builder = crate::VariantArrayBuilder::new(3);
2669
2670 {
2672 let json_str = r#"{"a": {"b": {"x": 100}}}"#;
2673 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2674 if let Ok(variant_array) = json_to_variant(&string_array) {
2675 builder.append_variant(variant_array.value(0));
2676 } else {
2677 builder.append_null();
2678 }
2679 }
2680
2681 {
2683 let json_str = r#"{"a": {"b": {"x": "bar"}}}"#;
2684 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2685 if let Ok(variant_array) = json_to_variant(&string_array) {
2686 builder.append_variant(variant_array.value(0));
2687 } else {
2688 builder.append_null();
2689 }
2690 }
2691
2692 {
2694 let json_str = r#"{"a": {"b": {"y": 200}}}"#;
2695 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2696 if let Ok(variant_array) = json_to_variant(&string_array) {
2697 builder.append_variant(variant_array.value(0));
2698 } else {
2699 builder.append_null();
2700 }
2701 }
2702
2703 ArrayRef::from(builder.build())
2704 }
2705
2706 fn create_depth_0_shredded_test_data_simple() -> ArrayRef {
2709 let (metadata, string_x_value) = {
2711 let mut builder = parquet_variant::VariantBuilder::new();
2712 let mut obj = builder.new_object();
2713 obj.insert("x", Variant::from("foo"));
2714 obj.finish();
2715 builder.finish()
2716 };
2717
2718 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2720
2721 let empty_object_value = {
2725 let mut builder = parquet_variant::VariantBuilder::new();
2726 let obj = builder.new_object();
2727 obj.finish();
2728 let (_, value) = builder.finish();
2729 value
2730 };
2731
2732 let value_array = BinaryViewArray::from(vec![
2733 Some(empty_object_value.as_slice()), Some(string_x_value.as_slice()), ]);
2736
2737 let x_field_typed_value = Int32Array::from(vec![Some(42), None]);
2739
2740 let x_field_shredded = ShreddedVariantFieldArray::perfectly_shredded(Arc::new(
2742 x_field_typed_value,
2743 ) as ArrayRef);
2744
2745 let typed_value_fields = Fields::from(vec![Field::new(
2747 "x",
2748 x_field_shredded.data_type().clone(),
2749 true,
2750 )]);
2751 let typed_value_struct = StructArray::try_new(
2752 typed_value_fields,
2753 vec![ArrayRef::from(x_field_shredded)],
2754 None,
2755 )
2756 .unwrap();
2757
2758 ArrayRef::from(VariantArray::from_parts(
2760 Arc::new(metadata_array),
2761 Arc::new(value_array),
2762 Some(Arc::new(typed_value_struct)),
2763 None,
2764 ))
2765 }
2766
2767 fn create_depth_1_shredded_test_data_working() -> ArrayRef {
2772 let (metadata, _) = {
2774 let mut builder = parquet_variant::VariantBuilder::new();
2776 let mut obj = builder.new_object();
2777
2778 let mut a_obj = obj.new_object("a");
2780 a_obj.insert("x", Variant::Int32(55));
2781 a_obj.finish();
2782
2783 obj.insert("b", Variant::Int32(42));
2784 obj.finish();
2785 builder.finish()
2786 };
2787
2788 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2789
2790 let empty_object_value = {
2793 let mut builder = parquet_variant::VariantBuilder::new();
2794 let obj = builder.new_object();
2795 obj.finish();
2796 let (_, value) = builder.finish();
2797 value
2798 };
2799
2800 let row1_fallback = {
2803 let mut builder = parquet_variant::VariantBuilder::new();
2804 let mut obj = builder.new_object();
2805 obj.insert("fallback", Variant::from("data"));
2806 obj.finish();
2807 let (_, value) = builder.finish();
2808 value
2809 };
2810
2811 let value_array = BinaryViewArray::from(vec![
2812 Some(empty_object_value.as_slice()), Some(row1_fallback.as_slice()), ]);
2815
2816 let x_typed_value = Int32Array::from(vec![Some(55), None]);
2819 let x_field_shredded =
2820 ShreddedVariantFieldArray::perfectly_shredded(Arc::new(x_typed_value) as ArrayRef);
2821
2822 let a_value_data = {
2827 let mut builder = parquet_variant::VariantBuilder::new();
2828 let obj = builder.new_object();
2829 obj.finish();
2830 let (_, value) = builder.finish();
2831 value
2832 };
2833 let a_value_array = BinaryViewArray::from(vec![
2834 None, Some(a_value_data.as_slice()), ]);
2837
2838 let a_inner_fields = Fields::from(vec![Field::new(
2839 "x",
2840 x_field_shredded.data_type().clone(),
2841 true,
2842 )]);
2843 let a_inner_typed_value = Arc::new(
2844 StructArray::try_new(a_inner_fields, vec![ArrayRef::from(x_field_shredded)], None)
2845 .unwrap(),
2846 ) as ArrayRef;
2847 let a_field_shredded = ShreddedVariantFieldArray::from_parts(
2848 Arc::new(a_value_array),
2849 Some(a_inner_typed_value),
2850 None,
2851 );
2852
2853 let typed_value_fields = Fields::from(vec![Field::new(
2855 "a",
2856 a_field_shredded.data_type().clone(),
2857 true,
2858 )]);
2859 let typed_value_struct = StructArray::try_new(
2860 typed_value_fields,
2861 vec![ArrayRef::from(a_field_shredded)],
2862 None,
2863 )
2864 .unwrap();
2865
2866 ArrayRef::from(VariantArray::from_parts(
2868 Arc::new(metadata_array),
2869 Arc::new(value_array),
2870 Some(Arc::new(typed_value_struct)),
2871 None,
2872 ))
2873 }
2874
2875 fn create_depth_2_shredded_test_data_working() -> ArrayRef {
2881 let (metadata, _) = {
2883 let mut builder = parquet_variant::VariantBuilder::new();
2885 let mut obj = builder.new_object();
2886
2887 let mut a_obj = obj.new_object("a");
2889 let mut b_obj = a_obj.new_object("b");
2890 b_obj.insert("x", Variant::Int32(100));
2891 b_obj.finish();
2892 a_obj.finish();
2893
2894 obj.finish();
2895 builder.finish()
2896 };
2897
2898 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 3));
2899
2900 let empty_object_value = {
2902 let mut builder = parquet_variant::VariantBuilder::new();
2903 let obj = builder.new_object();
2904 obj.finish();
2905 let (_, value) = builder.finish();
2906 value
2907 };
2908
2909 let value_array = BinaryViewArray::from(vec![
2911 Some(empty_object_value.as_slice()), Some(empty_object_value.as_slice()), Some(empty_object_value.as_slice()), ]);
2915
2916 let x_typed_value = Int32Array::from(vec![Some(100), None, None]);
2920 let x_field_shredded =
2921 ShreddedVariantFieldArray::perfectly_shredded(Arc::new(x_typed_value) as ArrayRef);
2922
2923 let b_value_data = {
2925 let mut builder = parquet_variant::VariantBuilder::new();
2926 let obj = builder.new_object();
2927 obj.finish();
2928 let (_, value) = builder.finish();
2929 value
2930 };
2931 let b_value_array = BinaryViewArray::from(vec![
2932 None, Some(b_value_data.as_slice()), Some(b_value_data.as_slice()), ]);
2936
2937 let b_inner_fields = Fields::from(vec![Field::new(
2938 "x",
2939 x_field_shredded.data_type().clone(),
2940 true,
2941 )]);
2942 let b_inner_typed_value = Arc::new(
2943 StructArray::try_new(b_inner_fields, vec![ArrayRef::from(x_field_shredded)], None)
2944 .unwrap(),
2945 ) as ArrayRef;
2946 let b_field_shredded = ShreddedVariantFieldArray::from_parts(
2947 Arc::new(b_value_array),
2948 Some(b_inner_typed_value),
2949 None,
2950 );
2951
2952 let a_value_data = {
2954 let mut builder = parquet_variant::VariantBuilder::new();
2955 let obj = builder.new_object();
2956 obj.finish();
2957 let (_, value) = builder.finish();
2958 value
2959 };
2960 let a_value_array = BinaryViewArray::from(vec![
2961 None, Some(a_value_data.as_slice()), Some(a_value_data.as_slice()), ]);
2965
2966 let a_inner_fields = Fields::from(vec![Field::new(
2967 "b",
2968 b_field_shredded.data_type().clone(),
2969 true,
2970 )]);
2971 let a_inner_typed_value = Arc::new(
2972 StructArray::try_new(a_inner_fields, vec![ArrayRef::from(b_field_shredded)], None)
2973 .unwrap(),
2974 ) as ArrayRef;
2975 let a_field_shredded = ShreddedVariantFieldArray::from_parts(
2976 Arc::new(a_value_array),
2977 Some(a_inner_typed_value),
2978 None,
2979 );
2980
2981 let typed_value_fields = Fields::from(vec![Field::new(
2983 "a",
2984 a_field_shredded.data_type().clone(),
2985 true,
2986 )]);
2987 let typed_value_struct = StructArray::try_new(
2988 typed_value_fields,
2989 vec![ArrayRef::from(a_field_shredded)],
2990 None,
2991 )
2992 .unwrap();
2993
2994 ArrayRef::from(VariantArray::from_parts(
2996 Arc::new(metadata_array),
2997 Arc::new(value_array),
2998 Some(Arc::new(typed_value_struct)),
2999 None,
3000 ))
3001 }
3002
3003 #[test]
3004 fn test_field_path_non_struct_returns_missing_path_step() {
3005 let variant_array = perfectly_shredded_int32_variant_array();
3007
3008 for safe in [true, false] {
3009 let options = GetOptions {
3010 path: VariantPath::try_from("nonexistent_field").unwrap(),
3011 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
3012 cast_options: CastOptions {
3013 safe,
3014 ..Default::default()
3015 },
3016 };
3017
3018 let result_array = variant_get(&variant_array, options).unwrap();
3019 assert_eq!(result_array.len(), 3);
3020 assert!(result_array.is_null(0));
3021 assert!(result_array.is_null(1));
3022 assert!(result_array.is_null(2));
3023 }
3024 }
3025
3026 #[test]
3027 fn test_strict_cast_options_index_on_non_list_returns_null() {
3028 use arrow::compute::CastOptions;
3029 use arrow::datatypes::{DataType, Field};
3030 use parquet_variant::VariantPath;
3031 use std::sync::Arc;
3032
3033 let variant_array = perfectly_shredded_int32_variant_array();
3035 let options = GetOptions {
3036 path: VariantPath::from(0),
3037 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
3038 cast_options: CastOptions {
3039 safe: false,
3040 ..Default::default()
3041 },
3042 };
3043
3044 let variant_array_ref: Arc<dyn Array> = variant_array.clone();
3045 let result = variant_get(&variant_array_ref, options).unwrap();
3046
3047 assert_eq!(result.len(), 3);
3048 assert!(result.is_null(0));
3049 assert!(result.is_null(1));
3050 assert!(result.is_null(2));
3051 }
3052
3053 #[test]
3054 fn test_error_message_boolean_type_display() {
3055 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([Some("abcd")]));
3056
3057 let options = GetOptions {
3059 path: VariantPath::default(),
3060 as_type: Some(Arc::new(Field::new("result", DataType::Boolean, true))),
3061 cast_options: CastOptions {
3062 safe: false,
3063 ..Default::default()
3064 },
3065 };
3066
3067 let err = variant_get(&variant_array, options).unwrap_err();
3068 let msg = err.to_string();
3069 assert!(msg.contains("Failed to extract primitive of type Boolean"));
3070 }
3071
3072 #[test]
3073 fn test_error_message_numeric_type_display() {
3074 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([Some("abcd")]));
3075
3076 let options = GetOptions {
3078 path: VariantPath::default(),
3079 as_type: Some(Arc::new(Field::new("result", DataType::Float32, true))),
3080 cast_options: CastOptions {
3081 safe: false,
3082 ..Default::default()
3083 },
3084 };
3085
3086 let err = variant_get(&variant_array, options).unwrap_err();
3087 let msg = err.to_string();
3088 assert!(msg.contains("Failed to extract primitive of type Float32"));
3089 }
3090
3091 #[test]
3092 fn test_error_message_temporal_type_display() {
3093 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([Some(false)]));
3094
3095 let options = GetOptions {
3097 path: VariantPath::default(),
3098 as_type: Some(Arc::new(Field::new(
3099 "result",
3100 DataType::Timestamp(TimeUnit::Nanosecond, None),
3101 true,
3102 ))),
3103 cast_options: CastOptions {
3104 safe: false,
3105 ..Default::default()
3106 },
3107 };
3108
3109 let err = variant_get(&variant_array, options).unwrap_err();
3110 let msg = err.to_string();
3111 assert!(msg.contains("Failed to extract primitive of type Timestamp(ns)"));
3112 }
3113
3114 #[test]
3115 fn test_null_buffer_union_for_shredded_paths() {
3116 let variant_array = create_depth_1_shredded_test_data_working();
3125
3126 let options = GetOptions {
3131 path: VariantPath::try_from("a.x").unwrap(),
3132 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
3133 cast_options: CastOptions::default(),
3134 };
3135
3136 let result = variant_get(&variant_array, options).unwrap();
3137
3138 assert_eq!(result.len(), variant_array.len());
3140
3141 assert!(!result.is_null(0), "Row 0 should have valid Int32 data");
3145 assert!(
3146 result.is_null(1),
3147 "Row 1 should be null due to type casting failure"
3148 );
3149
3150 let int32_result = result.as_any().downcast_ref::<Int32Array>().unwrap();
3152 assert_eq!(int32_result.value(0), 55); }
3154
3155 #[test]
3156 fn test_struct_null_mask_union_from_children() {
3157 let json_strings = vec![
3162 r#"{"a": 42, "b": "hello"}"#, r#"{"a": "world", "b": 100}"#, r#"{"a": 55, "b": 77}"#, ];
3166
3167 let string_array: Arc<dyn arrow::array::Array> = Arc::new(StringArray::from(json_strings));
3168 let variant_array = json_to_variant(&string_array).unwrap();
3169
3170 let struct_fields = Fields::from(vec![
3173 Field::new("a", DataType::Int32, true),
3174 Field::new("b", DataType::Int32, true),
3175 ]);
3176 let struct_type = DataType::Struct(struct_fields);
3177
3178 let options = GetOptions {
3179 path: VariantPath::default(), as_type: Some(Arc::new(Field::new("result", struct_type, true))),
3181 cast_options: CastOptions::default(),
3182 };
3183
3184 let variant_array_ref = ArrayRef::from(variant_array);
3185 let result = variant_get(&variant_array_ref, options).unwrap();
3186
3187 let struct_result = result.as_struct();
3189 assert_eq!(struct_result.len(), 3);
3190
3191 let field_a = struct_result
3193 .column(0)
3194 .as_any()
3195 .downcast_ref::<Int32Array>()
3196 .unwrap();
3197 let field_b = struct_result
3198 .column(1)
3199 .as_any()
3200 .downcast_ref::<Int32Array>()
3201 .unwrap();
3202
3203 assert!(!field_a.is_null(0));
3206 assert_eq!(field_a.value(0), 42);
3207 assert!(field_b.is_null(0)); assert!(field_a.is_null(1)); assert!(!field_b.is_null(1));
3212 assert_eq!(field_b.value(1), 100);
3213
3214 assert!(!field_a.is_null(2));
3216 assert_eq!(field_a.value(2), 55);
3217 assert!(!field_b.is_null(2));
3218 assert_eq!(field_b.value(2), 77);
3219
3220 assert!(!struct_result.is_null(0)); assert!(!struct_result.is_null(1)); assert!(!struct_result.is_null(2)); }
3227
3228 #[test]
3229 fn test_field_nullability_preservation() {
3230 let json_strings = vec![
3233 r#"{"x": 42}"#, r#"{"x": "not_a_number"}"#, r#"{"x": null}"#, r#"{"x": "hello"}"#, r#"{"y": 100}"#, r#"{"x": 127}"#, r#"{"x": 32767}"#, r#"{"x": 2147483647}"#, r#"{"x": 9223372036854775807}"#, ];
3243
3244 let string_array: Arc<dyn arrow::array::Array> = Arc::new(StringArray::from(json_strings));
3245 let variant_array = json_to_variant(&string_array).unwrap();
3246
3247 let nullable_field = Arc::new(Field::new("result", DataType::Int32, true));
3249 let options_nullable = GetOptions {
3250 path: VariantPath::try_from("x").unwrap(),
3251 as_type: Some(nullable_field.clone()),
3252 cast_options: CastOptions::default(),
3253 };
3254
3255 let variant_array_ref = ArrayRef::from(variant_array);
3256 let result_nullable = variant_get(&variant_array_ref, options_nullable).unwrap();
3257
3258 let int32_result = result_nullable
3260 .as_any()
3261 .downcast_ref::<Int32Array>()
3262 .unwrap();
3263 assert_eq!(int32_result.len(), 9);
3264
3265 assert!(!int32_result.is_null(0));
3267 assert_eq!(int32_result.value(0), 42);
3268
3269 assert!(int32_result.is_null(1));
3271
3272 assert!(int32_result.is_null(2));
3274
3275 assert!(int32_result.is_null(3));
3277
3278 assert!(int32_result.is_null(4));
3280
3281 assert!(!int32_result.is_null(5));
3284 assert_eq!(int32_result.value(5), 127);
3285
3286 assert!(!int32_result.is_null(6));
3289 assert_eq!(int32_result.value(6), 32767);
3290
3291 assert!(!int32_result.is_null(7));
3294 assert_eq!(int32_result.value(7), 2147483647);
3295
3296 assert!(int32_result.is_null(8));
3299
3300 let non_nullable_field = Arc::new(Field::new("result", DataType::Int32, false));
3302 let options_non_nullable = GetOptions {
3303 path: VariantPath::try_from("x").unwrap(),
3304 as_type: Some(non_nullable_field.clone()),
3305 cast_options: CastOptions::default(), };
3307
3308 let variant_array_2 = json_to_variant(&string_array).unwrap();
3310 let variant_array_ref_2 = ArrayRef::from(variant_array_2);
3311 let result_non_nullable = variant_get(&variant_array_ref_2, options_non_nullable).unwrap();
3312 let int32_result_2 = result_non_nullable
3313 .as_any()
3314 .downcast_ref::<Int32Array>()
3315 .unwrap();
3316
3317 assert_eq!(int32_result_2.len(), 9);
3319
3320 assert!(!int32_result_2.is_null(0));
3322 assert_eq!(int32_result_2.value(0), 42);
3323
3324 assert!(int32_result_2.is_null(1)); assert!(int32_result_2.is_null(2)); assert!(int32_result_2.is_null(3)); assert!(int32_result_2.is_null(4)); assert!(!int32_result_2.is_null(5)); assert_eq!(int32_result_2.value(5), 127);
3334 assert!(!int32_result_2.is_null(6)); assert_eq!(int32_result_2.value(6), 32767);
3336 assert!(!int32_result_2.is_null(7)); assert_eq!(int32_result_2.value(7), 2147483647);
3338
3339 assert!(int32_result_2.is_null(8)); }
3342
3343 #[test]
3344 fn test_struct_extraction_subset_superset_schema_perfectly_shredded() {
3345 let variant_array = create_comprehensive_shredded_variant();
3347
3348 let struct_fields = Fields::from(vec![
3350 Field::new("a", DataType::Int32, true),
3351 Field::new("b", DataType::Int32, true),
3352 Field::new("d", DataType::Int32, true),
3353 ]);
3354 let struct_type = DataType::Struct(struct_fields);
3355
3356 let options = GetOptions {
3357 path: VariantPath::default(),
3358 as_type: Some(Arc::new(Field::new("result", struct_type, true))),
3359 cast_options: CastOptions::default(),
3360 };
3361
3362 let result = variant_get(&variant_array, options).unwrap();
3363
3364 let struct_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3366 assert_eq!(struct_result.len(), 5);
3367 assert_eq!(struct_result.num_columns(), 3);
3368
3369 let field_a = struct_result
3370 .column(0)
3371 .as_any()
3372 .downcast_ref::<Int32Array>()
3373 .unwrap();
3374 let field_b = struct_result
3375 .column(1)
3376 .as_any()
3377 .downcast_ref::<Int32Array>()
3378 .unwrap();
3379 let field_d = struct_result
3380 .column(2)
3381 .as_any()
3382 .downcast_ref::<Int32Array>()
3383 .unwrap();
3384
3385 assert!(!struct_result.is_null(0));
3387 assert_eq!(field_a.value(0), 1);
3388 assert_eq!(field_b.value(0), 2);
3389 assert!(field_d.is_null(0)); assert!(struct_result.is_null(1));
3393
3394 assert!(!struct_result.is_null(2));
3396 assert!(field_a.is_null(2)); assert_eq!(field_b.value(2), 2);
3398 assert!(field_d.is_null(2)); assert!(!struct_result.is_null(3));
3402 assert_eq!(field_a.value(3), 1);
3403 assert!(field_b.is_null(3)); assert!(field_d.is_null(3)); assert!(!struct_result.is_null(4));
3408 assert!(field_a.is_null(4)); assert!(field_b.is_null(4)); assert!(field_d.is_null(4)); }
3412
3413 #[test]
3414 fn test_nested_struct_extraction_perfectly_shredded() {
3415 let variant_array = create_comprehensive_nested_shredded_variant();
3417 println!("variant_array: {variant_array:?}");
3418
3419 let inner_field = Field::new("inner", DataType::Int32, true);
3421 let inner_type = DataType::Struct(Fields::from(vec![inner_field]));
3422 let outer_field = Field::new("outer", inner_type, true);
3423 let result_type = DataType::Struct(Fields::from(vec![outer_field]));
3424
3425 let options = GetOptions {
3426 path: VariantPath::default(),
3427 as_type: Some(Arc::new(Field::new("result", result_type, true))),
3428 cast_options: CastOptions::default(),
3429 };
3430
3431 let result = variant_get(&variant_array, options).unwrap();
3432 println!("result: {result:?}");
3433
3434 let outer_struct = result.as_any().downcast_ref::<StructArray>().unwrap();
3436 assert_eq!(outer_struct.len(), 4);
3437 assert_eq!(outer_struct.num_columns(), 1);
3438
3439 let inner_struct = outer_struct
3441 .column(0)
3442 .as_any()
3443 .downcast_ref::<StructArray>()
3444 .unwrap();
3445 assert_eq!(inner_struct.num_columns(), 1);
3446
3447 let leaf_field = inner_struct
3449 .column(0)
3450 .as_any()
3451 .downcast_ref::<Int32Array>()
3452 .unwrap();
3453
3454 assert!(!outer_struct.is_null(0));
3456 assert!(!inner_struct.is_null(0));
3457 assert_eq!(leaf_field.value(0), 42);
3458
3459 assert!(!outer_struct.is_null(1));
3461 assert!(!inner_struct.is_null(1)); assert!(leaf_field.is_null(1)); assert!(!outer_struct.is_null(2));
3466 assert!(inner_struct.is_null(2)); assert!(outer_struct.is_null(3));
3470 }
3471
3472 #[test]
3473 fn test_path_based_null_masks_one_step() {
3474 let variant_array = create_comprehensive_nested_shredded_variant();
3476
3477 let path = VariantPath::try_from("outer").unwrap();
3479 let inner_field = Field::new("inner", DataType::Int32, true);
3480 let result_type = DataType::Struct(Fields::from(vec![inner_field]));
3481
3482 let options = GetOptions {
3483 path,
3484 as_type: Some(Arc::new(Field::new("result", result_type, true))),
3485 cast_options: CastOptions::default(),
3486 };
3487
3488 let result = variant_get(&variant_array, options).unwrap();
3489
3490 let outer_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3492 assert_eq!(outer_result.len(), 4);
3493 assert_eq!(outer_result.num_columns(), 1);
3494
3495 let inner_field = outer_result
3497 .column(0)
3498 .as_any()
3499 .downcast_ref::<Int32Array>()
3500 .unwrap();
3501
3502 assert!(!outer_result.is_null(0));
3504 assert_eq!(inner_field.value(0), 42);
3505
3506 assert!(!outer_result.is_null(1));
3508 assert!(inner_field.is_null(1));
3509
3510 assert!(outer_result.is_null(2));
3512
3513 assert!(outer_result.is_null(3));
3515 }
3516
3517 #[test]
3518 fn test_path_based_null_masks_two_steps() {
3519 let variant_array = create_comprehensive_nested_shredded_variant();
3521
3522 let path = VariantPath::try_from("outer").unwrap().join("inner");
3524
3525 let options = GetOptions {
3526 path,
3527 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
3528 cast_options: CastOptions::default(),
3529 };
3530
3531 let result = variant_get(&variant_array, options).unwrap();
3532
3533 let int_result = result.as_any().downcast_ref::<Int32Array>().unwrap();
3535 assert_eq!(int_result.len(), 4);
3536
3537 assert!(!int_result.is_null(0));
3539 assert_eq!(int_result.value(0), 42);
3540
3541 assert!(int_result.is_null(1));
3543
3544 assert!(int_result.is_null(2));
3546
3547 assert!(int_result.is_null(3));
3549 }
3550
3551 #[test]
3552 fn test_struct_extraction_mixed_and_unshredded() {
3553 let variant_array = create_mixed_and_unshredded_variant();
3555
3556 let struct_fields = Fields::from(vec![
3558 Field::new("x", DataType::Int32, true),
3559 Field::new("y", DataType::Int32, true),
3560 ]);
3561 let struct_type = DataType::Struct(struct_fields);
3562
3563 let options = GetOptions {
3564 path: VariantPath::default(),
3565 as_type: Some(Arc::new(Field::new("result", struct_type, true))),
3566 cast_options: CastOptions::default(),
3567 };
3568
3569 let result = variant_get(&variant_array, options).unwrap();
3570
3571 let struct_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3573 assert_eq!(struct_result.len(), 4);
3574 assert_eq!(struct_result.num_columns(), 2);
3575
3576 let field_x = struct_result
3577 .column(0)
3578 .as_any()
3579 .downcast_ref::<Int32Array>()
3580 .unwrap();
3581 let field_y = struct_result
3582 .column(1)
3583 .as_any()
3584 .downcast_ref::<Int32Array>()
3585 .unwrap();
3586
3587 assert_eq!(field_x.value(0), 1);
3589 assert_eq!(field_y.value(0), 42);
3590
3591 assert_eq!(field_x.value(1), 2);
3593 assert!(field_y.is_null(1));
3594
3595 assert_eq!(field_x.value(2), 3);
3597 assert!(field_y.is_null(2));
3598
3599 assert!(struct_result.is_null(3));
3601 }
3602
3603 #[test]
3604 fn test_struct_row_builder_handles_unshredded_nested_structs() {
3605 let json_strings = vec![
3607 r#"{"outer": {"inner": 42}}"#,
3608 r#"{"outer": {"inner": 100}}"#,
3609 ];
3610 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(json_strings));
3611 let variant_array = json_to_variant(&string_array).unwrap();
3612
3613 let inner_fields = Fields::from(vec![Field::new("inner", DataType::Int32, true)]);
3615 let inner_struct_type = DataType::Struct(inner_fields);
3616 let outer_fields = Fields::from(vec![Field::new("outer", inner_struct_type, true)]);
3617 let outer_struct_type = DataType::Struct(outer_fields);
3618
3619 let options = GetOptions {
3620 path: VariantPath::default(),
3621 as_type: Some(Arc::new(Field::new("result", outer_struct_type, true))),
3622 cast_options: CastOptions::default(),
3623 };
3624
3625 let variant_array_ref = ArrayRef::from(variant_array);
3626 let result = variant_get(&variant_array_ref, options).unwrap();
3627
3628 let outer_struct = result.as_struct();
3629 assert_eq!(outer_struct.len(), 2);
3630 assert_eq!(outer_struct.num_columns(), 1);
3631
3632 let inner_struct = outer_struct.column(0).as_struct();
3633 assert_eq!(inner_struct.num_columns(), 1);
3634
3635 let inner_values = inner_struct
3636 .column(0)
3637 .as_any()
3638 .downcast_ref::<Int32Array>()
3639 .unwrap();
3640 assert_eq!(inner_values.value(0), 42);
3641 assert_eq!(inner_values.value(1), 100);
3642 }
3643
3644 #[test]
3645 fn test_unshredded_struct_safe_cast_and_field_mismatches() {
3646 let json_strings = vec![r#"{"a": 1, "b": 2, "extra": 3}"#, "123", "{}"];
3647 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(json_strings));
3648 let variant_array_ref = ArrayRef::from(json_to_variant(&string_array).unwrap());
3649
3650 let struct_fields = Fields::from(vec![
3651 Field::new("a", DataType::Int32, true),
3652 Field::new("b", DataType::Int32, true),
3653 ]);
3654 let options = GetOptions {
3655 path: VariantPath::default(),
3656 as_type: Some(Arc::new(Field::new(
3657 "result",
3658 DataType::Struct(struct_fields),
3659 true,
3660 ))),
3661 cast_options: CastOptions::default(),
3662 };
3663
3664 let result = variant_get(&variant_array_ref, options).unwrap();
3665 let struct_result = result.as_struct();
3666 let field_a = struct_result
3667 .column(0)
3668 .as_primitive::<arrow::datatypes::Int32Type>();
3669 let field_b = struct_result
3670 .column(1)
3671 .as_primitive::<arrow::datatypes::Int32Type>();
3672
3673 assert!(!struct_result.is_null(0));
3676 assert_eq!(field_a.value(0), 1);
3677 assert_eq!(field_b.value(0), 2);
3678
3679 assert!(struct_result.is_null(1));
3681 assert!(field_a.is_null(1));
3682 assert!(field_b.is_null(1));
3683
3684 assert!(!struct_result.is_null(2));
3686 assert!(field_a.is_null(2));
3687 assert!(field_b.is_null(2));
3688 }
3689
3690 #[test]
3691 fn test_unshredded_struct_missing_non_nullable_field_errors() {
3692 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(vec![r#"{"a": 1}"#]));
3693 let variant_array_ref = ArrayRef::from(json_to_variant(&string_array).unwrap());
3694
3695 let struct_fields = Fields::from(vec![
3696 Field::new("a", DataType::Int32, false),
3697 Field::new("missing", DataType::Int32, false),
3698 ]);
3699 let options = GetOptions {
3700 path: VariantPath::default(),
3701 as_type: Some(Arc::new(Field::new(
3702 "result",
3703 DataType::Struct(struct_fields),
3704 true,
3705 ))),
3706 cast_options: CastOptions::default(),
3707 };
3708
3709 let err = variant_get(&variant_array_ref, options).unwrap_err();
3710 assert!(
3711 err.to_string()
3712 .contains("unmasked nulls for non-nullable StructArray field \"missing\""),
3713 "unexpected error: {err}"
3714 );
3715 }
3716
3717 #[test]
3718 fn test_unshredded_struct_strict_cast_non_object_errors() {
3719 let json_strings = vec![r#"{"a": 1, "b": 2}"#, "123"];
3720 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(json_strings));
3721 let variant_array_ref = ArrayRef::from(json_to_variant(&string_array).unwrap());
3722
3723 let struct_fields = Fields::from(vec![
3724 Field::new("a", DataType::Int32, true),
3725 Field::new("b", DataType::Int32, true),
3726 ]);
3727 let options = GetOptions {
3728 path: VariantPath::default(),
3729 as_type: Some(Arc::new(Field::new(
3730 "result",
3731 DataType::Struct(struct_fields),
3732 true,
3733 ))),
3734 cast_options: CastOptions {
3735 safe: false,
3736 ..Default::default()
3737 },
3738 };
3739
3740 let err = variant_get(&variant_array_ref, options).unwrap_err();
3741 assert!(
3742 err.to_string()
3743 .contains("Failed to extract struct from variant")
3744 );
3745 }
3746
3747 fn create_comprehensive_shredded_variant() -> ArrayRef {
3750 let (metadata, _) = {
3751 let mut builder = parquet_variant::VariantBuilder::new();
3752 let obj = builder.new_object();
3753 obj.finish();
3754 builder.finish()
3755 };
3756
3757 let nulls = NullBuffer::from(vec![
3759 true, false, true, true, true, ]);
3765
3766 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 5));
3767
3768 let a_field_typed_value = Int32Array::from(vec![Some(1), None, None, Some(1), None]);
3771 let a_field_shredded = ShreddedVariantFieldArray::perfectly_shredded(Arc::new(
3772 a_field_typed_value,
3773 ) as ArrayRef);
3774
3775 let b_field_typed_value = Int32Array::from(vec![Some(2), None, Some(2), None, None]);
3777 let b_field_shredded = ShreddedVariantFieldArray::perfectly_shredded(Arc::new(
3778 b_field_typed_value,
3779 ) as ArrayRef);
3780
3781 let c_field_typed_value = Int32Array::from(vec![Some(3), None, None, None, None]);
3783 let c_field_shredded = ShreddedVariantFieldArray::perfectly_shredded(Arc::new(
3784 c_field_typed_value,
3785 ) as ArrayRef);
3786
3787 let typed_value_fields = Fields::from(vec![
3789 Field::new("a", a_field_shredded.data_type().clone(), true),
3790 Field::new("b", b_field_shredded.data_type().clone(), true),
3791 Field::new("c", c_field_shredded.data_type().clone(), true),
3792 ]);
3793 let typed_value_struct = StructArray::try_new(
3794 typed_value_fields,
3795 vec![
3796 ArrayRef::from(a_field_shredded),
3797 ArrayRef::from(b_field_shredded),
3798 ArrayRef::from(c_field_shredded),
3799 ],
3800 None,
3801 )
3802 .unwrap();
3803
3804 ArrayRef::from(VariantArray::perfectly_shredded(
3806 Arc::new(metadata_array),
3807 Arc::new(typed_value_struct),
3808 Some(nulls),
3809 ))
3810 }
3811
3812 fn create_comprehensive_nested_shredded_variant() -> ArrayRef {
3817 let inner_typed_value = Int32Array::from(vec![Some(42), None, None, None]); let inner =
3821 ShreddedVariantFieldArray::perfectly_shredded(Arc::new(inner_typed_value) as ArrayRef);
3822
3823 let outer_typed_value_nulls = NullBuffer::from(vec![
3824 true, false, false, false, ]);
3829 let outer_typed_value = StructArrayAssembler::new()
3830 .with_field("inner", ArrayRef::from(inner), false)
3831 .with_nulls(outer_typed_value_nulls)
3832 .build()
3833 .unwrap();
3834
3835 let outer =
3836 ShreddedVariantFieldArray::perfectly_shredded(Arc::new(outer_typed_value) as ArrayRef);
3837
3838 let typed_value_nulls = NullBuffer::from(vec![
3839 true, true, false, false, ]);
3844 let typed_value = StructArrayAssembler::new()
3845 .with_field("outer", ArrayRef::from(outer), false)
3846 .with_nulls(typed_value_nulls)
3847 .build()
3848 .unwrap();
3849
3850 let metadata_array =
3852 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 4));
3853 let nulls = NullBuffer::from(vec![
3854 true, true, true, false, ]);
3859 ArrayRef::from(VariantArray::perfectly_shredded(
3860 Arc::new(metadata_array),
3861 Arc::new(typed_value),
3862 Some(nulls),
3863 ))
3864 }
3865
3866 fn create_mixed_and_unshredded_variant() -> ArrayRef {
3869 let (metadata, y_field_value) = {
3874 let mut builder = parquet_variant::VariantBuilder::new();
3875 let mut obj = builder.new_object();
3876 obj.insert("y", Variant::from(42));
3877 obj.finish();
3878 builder.finish()
3879 };
3880
3881 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 4));
3882
3883 let empty_object_value = {
3890 let mut builder = parquet_variant::VariantBuilder::new();
3891 builder.new_object().finish();
3892 let (_, value) = builder.finish();
3893 value
3894 };
3895
3896 let y_null_value = {
3897 let mut builder = parquet_variant::VariantBuilder::new();
3898 builder.new_object().with_field("y", Variant::Null).finish();
3899 let (_, value) = builder.finish();
3900 value
3901 };
3902
3903 let value_array = BinaryViewArray::from(vec![
3904 Some(y_field_value.as_slice()), Some(empty_object_value.as_slice()), Some(y_null_value.as_slice()), Some(empty_object_value.as_slice()), ]);
3909
3910 let x_field_typed_value = Int32Array::from(vec![Some(1), Some(2), Some(3), Some(0)]);
3913 let x_field_shredded = ShreddedVariantFieldArray::perfectly_shredded(Arc::new(
3914 x_field_typed_value,
3915 ) as ArrayRef);
3916
3917 let typed_value_struct = StructArrayAssembler::new()
3919 .with_field("x", ArrayRef::from(x_field_shredded), false)
3920 .build()
3921 .unwrap();
3922
3923 let variant_nulls = NullBuffer::from(vec![true, true, true, false]); ArrayRef::from(VariantArray::from_parts(
3927 Arc::new(metadata_array),
3928 Arc::new(value_array),
3929 Some(Arc::new(typed_value_struct)),
3930 Some(variant_nulls),
3931 ))
3932 }
3933
3934 #[test]
3935 fn get_decimal32_rescaled_to_scale2() {
3936 let mut builder = crate::VariantArrayBuilder::new(5);
3938 builder.append_variant(VariantDecimal4::try_new(1234, 2).unwrap().into()); builder.append_variant(VariantDecimal4::try_new(1234, 3).unwrap().into()); builder.append_variant(VariantDecimal4::try_new(1234, 0).unwrap().into()); builder.append_null();
3942 builder.append_variant(
3943 VariantDecimal8::try_new((VariantDecimal4::MAX_UNSCALED_VALUE as i64) + 1, 3)
3944 .unwrap()
3945 .into(),
3946 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3948
3949 let field = Field::new("result", DataType::Decimal32(9, 2), true);
3950 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3951 let result = variant_get(&variant_array, options).unwrap();
3952 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3953
3954 assert_eq!(result.precision(), 9);
3955 assert_eq!(result.scale(), 2);
3956 assert_eq!(result.value(0), 1234);
3957 assert_eq!(result.value(1), 123);
3958 assert_eq!(result.value(2), 123400);
3959 assert!(result.is_null(3));
3960 assert_eq!(
3961 result.value(4),
3962 VariantDecimal4::MAX_UNSCALED_VALUE / 10 + 1
3963 ); }
3965
3966 #[test]
3967 fn get_decimal32_scale_down_rounding() {
3968 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
3969 Some(VariantDecimal4::try_new(1235, 0).unwrap()),
3970 Some(VariantDecimal4::try_new(1245, 0).unwrap()),
3971 Some(VariantDecimal4::try_new(-1235, 0).unwrap()),
3972 Some(VariantDecimal4::try_new(-1245, 0).unwrap()),
3973 Some(VariantDecimal4::try_new(1235, 2).unwrap()), Some(VariantDecimal4::try_new(1235, 3).unwrap()), Some(VariantDecimal4::try_new(5235, 3).unwrap()), ]));
3977
3978 let field = Field::new("result", DataType::Decimal32(9, -1), true);
3979 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3980 let result = variant_get(&variant_array, options).unwrap();
3981 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3982
3983 assert_eq!(result.precision(), 9);
3984 assert_eq!(result.scale(), -1);
3985 assert_eq!(result.value(0), 124);
3986 assert_eq!(result.value(1), 125);
3987 assert_eq!(result.value(2), -124);
3988 assert_eq!(result.value(3), -125);
3989 assert_eq!(result.value(4), 1);
3990 assert!(result.is_valid(5));
3991 assert_eq!(result.value(5), 0);
3992 assert_eq!(result.value(6), 1);
3993 }
3994
3995 #[test]
3996 fn get_decimal32_large_scale_reduction() {
3997 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
3998 Some(VariantDecimal4::try_new(-VariantDecimal4::MAX_UNSCALED_VALUE, 0).unwrap()),
3999 Some(VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0).unwrap()),
4000 ]));
4001
4002 let field = Field::new("result", DataType::Decimal32(9, -9), true);
4003 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4004 let result = variant_get(&variant_array, options).unwrap();
4005 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
4006
4007 assert_eq!(result.precision(), 9);
4008 assert_eq!(result.scale(), -9);
4009 assert_eq!(result.value(0), -1);
4010 assert_eq!(result.value(1), 1);
4011
4012 let field = Field::new("result", DataType::Decimal32(9, -10), true);
4013 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4014 let result = variant_get(&variant_array, options).unwrap();
4015 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
4016
4017 assert_eq!(result.precision(), 9);
4018 assert_eq!(result.scale(), -10);
4019 assert!(result.is_valid(0));
4020 assert_eq!(result.value(0), 0);
4021 assert!(result.is_valid(1));
4022 assert_eq!(result.value(1), 0);
4023 }
4024
4025 #[test]
4026 fn get_decimal32_precision_overflow_safe() {
4027 let variant_array = ArrayRef::from(VariantArray::from_iter([
4029 Some(Variant::from(
4030 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0).unwrap(),
4031 )),
4032 Some(Variant::from(
4034 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 9).unwrap(),
4035 )),
4036 Some(Variant::Float(1.1)),
4038 Some(Variant::Double(1.1)),
4039 Some(Variant::Float(0.999)),
4040 Some(Variant::Double(0.999)),
4041 ]));
4042
4043 let field = Field::new("result", DataType::Decimal32(2, 2), true);
4044 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4045 let result = variant_get(&variant_array, options).unwrap();
4046 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
4047
4048 assert_eq!(result.null_count(), 6); }
4050
4051 #[test]
4052 fn get_decimal32_precision_overflow_unsafe_errors() {
4053 for (value, kind) in [
4054 (
4055 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0)
4056 .unwrap()
4057 .into(),
4058 "Decimal4",
4059 ),
4060 (Variant::Float(1.1), "Float"),
4061 (Variant::Double(1.1), "Double"),
4062 (Variant::Float(0.999), "Float"),
4063 (Variant::Double(0.999), "Double"),
4064 ] {
4065 let variant_array = ArrayRef::from(VariantArray::from_iter([Some(value)]));
4066 let field = Field::new("result", DataType::Decimal32(2, 2), true);
4067 let options = GetOptions::new()
4068 .with_as_type(Some(FieldRef::from(field)))
4069 .with_cast_options(CastOptions {
4070 safe: false,
4071 ..Default::default()
4072 });
4073 let err = variant_get(&variant_array, options).unwrap_err();
4074 assert!(err.to_string().contains(&format!(
4075 "Failed to cast to Decimal32(precision=2, scale=2) from variant {kind}"
4076 )));
4077 }
4078 }
4079
4080 #[test]
4081 fn get_decimal64_rescaled_to_scale2() {
4082 let mut builder = crate::VariantArrayBuilder::new(5);
4083 builder.append_variant(VariantDecimal8::try_new(1234, 2).unwrap().into()); builder.append_variant(VariantDecimal8::try_new(1234, 3).unwrap().into()); builder.append_variant(VariantDecimal8::try_new(1234, 0).unwrap().into()); builder.append_null();
4087 builder.append_variant(
4088 VariantDecimal16::try_new((VariantDecimal8::MAX_UNSCALED_VALUE as i128) + 1, 3)
4089 .unwrap()
4090 .into(),
4091 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
4093
4094 let field = Field::new("result", DataType::Decimal64(18, 2), true);
4095 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4096 let result = variant_get(&variant_array, options).unwrap();
4097 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
4098
4099 assert_eq!(result.precision(), 18);
4100 assert_eq!(result.scale(), 2);
4101 assert_eq!(result.value(0), 1234);
4102 assert_eq!(result.value(1), 123);
4103 assert_eq!(result.value(2), 123400);
4104 assert!(result.is_null(3));
4105 assert_eq!(
4106 result.value(4),
4107 VariantDecimal8::MAX_UNSCALED_VALUE / 10 + 1
4108 ); }
4110
4111 #[test]
4112 fn get_decimal64_scale_down_rounding() {
4113 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4114 Some(VariantDecimal8::try_new(1235, 0).unwrap()),
4115 Some(VariantDecimal8::try_new(1245, 0).unwrap()),
4116 Some(VariantDecimal8::try_new(-1235, 0).unwrap()),
4117 Some(VariantDecimal8::try_new(-1245, 0).unwrap()),
4118 Some(VariantDecimal8::try_new(1235, 2).unwrap()), Some(VariantDecimal8::try_new(1235, 3).unwrap()), Some(VariantDecimal8::try_new(5235, 3).unwrap()), ]));
4122
4123 let field = Field::new("result", DataType::Decimal64(18, -1), true);
4124 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4125 let result = variant_get(&variant_array, options).unwrap();
4126 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
4127
4128 assert_eq!(result.precision(), 18);
4129 assert_eq!(result.scale(), -1);
4130 assert_eq!(result.value(0), 124);
4131 assert_eq!(result.value(1), 125);
4132 assert_eq!(result.value(2), -124);
4133 assert_eq!(result.value(3), -125);
4134 assert_eq!(result.value(4), 1);
4135 assert!(result.is_valid(5));
4136 assert_eq!(result.value(5), 0);
4137 assert_eq!(result.value(6), 1);
4138 }
4139
4140 #[test]
4141 fn get_decimal64_large_scale_reduction() {
4142 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4143 Some(VariantDecimal8::try_new(-VariantDecimal8::MAX_UNSCALED_VALUE, 0).unwrap()),
4144 Some(VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0).unwrap()),
4145 ]));
4146
4147 let field = Field::new("result", DataType::Decimal64(18, -18), true);
4148 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4149 let result = variant_get(&variant_array, options).unwrap();
4150 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
4151
4152 assert_eq!(result.precision(), 18);
4153 assert_eq!(result.scale(), -18);
4154 assert_eq!(result.value(0), -1);
4155 assert_eq!(result.value(1), 1);
4156
4157 let field = Field::new("result", DataType::Decimal64(18, -19), true);
4158 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4159 let result = variant_get(&variant_array, options).unwrap();
4160 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
4161
4162 assert_eq!(result.precision(), 18);
4163 assert_eq!(result.scale(), -19);
4164 assert!(result.is_valid(0));
4165 assert_eq!(result.value(0), 0);
4166 assert!(result.is_valid(1));
4167 assert_eq!(result.value(1), 0);
4168 }
4169
4170 #[test]
4171 fn get_decimal64_precision_overflow_safe() {
4172 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4174 Some(VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0).unwrap()),
4175 Some(VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 18).unwrap()),
4177 ]));
4178
4179 let field = Field::new("result", DataType::Decimal64(2, 2), true);
4180 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4181 let result = variant_get(&variant_array, options).unwrap();
4182 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
4183
4184 assert!(result.is_null(0));
4185 assert!(result.is_null(1));
4186 }
4187
4188 #[test]
4189 fn get_decimal64_precision_overflow_unsafe_errors() {
4190 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([Some(
4191 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0).unwrap(),
4192 )]));
4193
4194 let field = Field::new("result", DataType::Decimal64(18, 2), true);
4195 let cast_options = CastOptions {
4196 safe: false,
4197 ..Default::default()
4198 };
4199 let options = GetOptions::new()
4200 .with_as_type(Some(FieldRef::from(field)))
4201 .with_cast_options(cast_options);
4202 let err = variant_get(&variant_array, options).unwrap_err();
4203
4204 assert!(
4205 err.to_string().contains(
4206 "Failed to cast to Decimal64(precision=18, scale=2) from variant Decimal8"
4207 )
4208 );
4209 }
4210
4211 #[test]
4212 fn get_decimal128_rescaled_to_scale2() {
4213 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4214 Some(VariantDecimal16::try_new(1234, 2).unwrap()),
4215 Some(VariantDecimal16::try_new(1234, 3).unwrap()),
4216 Some(VariantDecimal16::try_new(1234, 0).unwrap()),
4217 None,
4218 ]));
4219
4220 let field = Field::new("result", DataType::Decimal128(38, 2), true);
4221 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4222 let result = variant_get(&variant_array, options).unwrap();
4223 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
4224
4225 assert_eq!(result.precision(), 38);
4226 assert_eq!(result.scale(), 2);
4227 assert_eq!(result.value(0), 1234);
4228 assert_eq!(result.value(1), 123);
4229 assert_eq!(result.value(2), 123400);
4230 assert!(result.is_null(3));
4231 }
4232
4233 #[test]
4234 fn get_decimal128_scale_down_rounding() {
4235 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4236 Some(VariantDecimal16::try_new(1235, 0).unwrap()),
4237 Some(VariantDecimal16::try_new(1245, 0).unwrap()),
4238 Some(VariantDecimal16::try_new(-1235, 0).unwrap()),
4239 Some(VariantDecimal16::try_new(-1245, 0).unwrap()),
4240 Some(VariantDecimal16::try_new(1235, 2).unwrap()), Some(VariantDecimal16::try_new(1235, 3).unwrap()), Some(VariantDecimal16::try_new(5235, 3).unwrap()), ]));
4244
4245 let field = Field::new("result", DataType::Decimal128(38, -1), true);
4246 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4247 let result = variant_get(&variant_array, options).unwrap();
4248 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
4249
4250 assert_eq!(result.precision(), 38);
4251 assert_eq!(result.scale(), -1);
4252 assert_eq!(result.value(0), 124);
4253 assert_eq!(result.value(1), 125);
4254 assert_eq!(result.value(2), -124);
4255 assert_eq!(result.value(3), -125);
4256 assert_eq!(result.value(4), 1);
4257 assert!(result.is_valid(5));
4258 assert_eq!(result.value(5), 0);
4259 assert_eq!(result.value(6), 1);
4260 }
4261
4262 #[test]
4263 fn get_decimal128_precision_overflow_safe() {
4264 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4266 Some(VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0).unwrap()),
4267 Some(VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 38).unwrap()),
4269 ]));
4270
4271 let field = Field::new("result", DataType::Decimal128(2, 2), true);
4272 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4273 let result = variant_get(&variant_array, options).unwrap();
4274 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
4275
4276 assert!(result.is_null(0));
4277 assert!(result.is_null(1)); }
4279
4280 #[test]
4281 fn get_decimal128_precision_overflow_unsafe_errors() {
4282 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([Some(
4283 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0).unwrap(),
4284 )]));
4285
4286 let field = Field::new("result", DataType::Decimal128(38, 2), true);
4287 let cast_options = CastOptions {
4288 safe: false,
4289 ..Default::default()
4290 };
4291 let options = GetOptions::new()
4292 .with_as_type(Some(FieldRef::from(field)))
4293 .with_cast_options(cast_options);
4294 let err = variant_get(&variant_array, options).unwrap_err();
4295
4296 assert!(err.to_string().contains(
4297 "Failed to cast to Decimal128(precision=38, scale=2) from variant Decimal16"
4298 ));
4299 }
4300
4301 #[test]
4302 fn get_decimal256_rescaled_to_scale2() {
4303 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4305 Some(VariantDecimal16::try_new(1234, 2).unwrap()), Some(VariantDecimal16::try_new(1234, 3).unwrap()), Some(VariantDecimal16::try_new(1234, 0).unwrap()), None,
4309 ]));
4310
4311 let field = Field::new("result", DataType::Decimal256(76, 2), true);
4312 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4313 let result = variant_get(&variant_array, options).unwrap();
4314 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
4315
4316 assert_eq!(result.precision(), 76);
4317 assert_eq!(result.scale(), 2);
4318 assert_eq!(result.value(0), i256::from_i128(1234));
4319 assert_eq!(result.value(1), i256::from_i128(123));
4320 assert_eq!(result.value(2), i256::from_i128(123400));
4321 assert!(result.is_null(3));
4322 }
4323
4324 #[test]
4325 fn get_decimal256_scale_down_rounding() {
4326 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4327 Some(VariantDecimal16::try_new(1235, 0).unwrap()),
4328 Some(VariantDecimal16::try_new(1245, 0).unwrap()),
4329 Some(VariantDecimal16::try_new(-1235, 0).unwrap()),
4330 Some(VariantDecimal16::try_new(-1245, 0).unwrap()),
4331 Some(VariantDecimal16::try_new(1235, 2).unwrap()), Some(VariantDecimal16::try_new(1235, 3).unwrap()), Some(VariantDecimal16::try_new(5235, 3).unwrap()), ]));
4335
4336 let field = Field::new("result", DataType::Decimal256(76, -1), true);
4337 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4338 let result = variant_get(&variant_array, options).unwrap();
4339 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
4340
4341 assert_eq!(result.precision(), 76);
4342 assert_eq!(result.scale(), -1);
4343 assert_eq!(result.value(0), i256::from_i128(124));
4344 assert_eq!(result.value(1), i256::from_i128(125));
4345 assert_eq!(result.value(2), i256::from_i128(-124));
4346 assert_eq!(result.value(3), i256::from_i128(-125));
4347 assert_eq!(result.value(4), i256::from_i128(1));
4348 assert!(result.is_valid(5));
4349 assert_eq!(result.value(5), i256::from_i128(0));
4350 assert_eq!(result.value(6), i256::from_i128(1));
4351 }
4352
4353 #[test]
4354 fn get_decimal256_precision_overflow_safe() {
4355 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4357 Some(VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 1).unwrap()),
4358 Some(VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0).unwrap()),
4359 ]));
4360
4361 let field = Field::new("result", DataType::Decimal256(76, 39), true);
4362 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4363 let result = variant_get(&variant_array, options).unwrap();
4364 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
4365
4366 let base = i256::from_i128(10);
4369 let factor = base.checked_pow(38).unwrap();
4370 let expected = i256::from_i128(VariantDecimal16::MAX_UNSCALED_VALUE)
4371 .checked_mul(factor)
4372 .unwrap();
4373 assert_eq!(result.value(0), expected);
4374 assert!(result.is_null(1));
4375 }
4376
4377 #[test]
4378 fn get_decimal256_precision_overflow_unsafe_errors() {
4379 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4381 Some(VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 1).unwrap()),
4382 Some(VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0).unwrap()),
4383 ]));
4384
4385 let field = Field::new("result", DataType::Decimal256(76, 39), true);
4386 let cast_options = CastOptions {
4387 safe: false,
4388 ..Default::default()
4389 };
4390 let options = GetOptions::new()
4391 .with_as_type(Some(FieldRef::from(field)))
4392 .with_cast_options(cast_options);
4393 let err = variant_get(&variant_array, options).unwrap_err();
4394
4395 assert!(err.to_string().contains(
4396 "Failed to cast to Decimal256(precision=76, scale=39) from variant Decimal16"
4397 ));
4398 }
4399
4400 #[test]
4401 fn get_non_supported_temporal_types_error() {
4402 let values = vec![None, Some(Variant::Null), Some(Variant::BooleanFalse)];
4403 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter(values));
4404
4405 let test_cases = vec![
4406 FieldRef::from(Field::new(
4407 "result",
4408 DataType::Duration(TimeUnit::Microsecond),
4409 true,
4410 )),
4411 FieldRef::from(Field::new(
4412 "result",
4413 DataType::Interval(IntervalUnit::YearMonth),
4414 true,
4415 )),
4416 ];
4417
4418 for field in test_cases {
4419 let options = GetOptions::new().with_as_type(Some(field));
4420 let err = variant_get(&variant_array, options).unwrap_err();
4421 assert!(
4422 err.to_string()
4423 .contains("Casting Variant to duration/interval types is not supported")
4424 );
4425 }
4426 }
4427
4428 #[test]
4429 fn get_variant_as_dictionary() {
4430 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4431 Some("apple"),
4432 Some("banana"),
4433 None,
4434 Some("apple"),
4435 ]));
4436 let data_type = DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8));
4437 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4438 "dict",
4439 data_type.clone(),
4440 true,
4441 ))));
4442
4443 let result = variant_get(&variant_array, options).unwrap();
4444 assert_eq!(result.data_type(), &data_type);
4445
4446 let decoded = cast(result.as_ref(), &DataType::Utf8).unwrap();
4447 let expected = StringArray::from(vec![Some("apple"), Some("banana"), None, Some("apple")]);
4448 assert_eq!(decoded.as_ref(), &expected);
4449 }
4450
4451 #[test]
4452 fn get_variant_as_numeric_dictionary() {
4453 let variant_array: ArrayRef =
4454 ArrayRef::from(VariantArray::from_iter([Some(42), Some(7), None, Some(42)]));
4455 let data_type = DataType::Dictionary(Box::new(DataType::Int16), Box::new(DataType::Int32));
4456 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4457 "dict",
4458 data_type.clone(),
4459 true,
4460 ))));
4461
4462 let result = variant_get(&variant_array, options).unwrap();
4463 assert_eq!(result.data_type(), &data_type);
4464
4465 let decoded = cast(result.as_ref(), &DataType::Int32).unwrap();
4466 let expected = Int32Array::from(vec![Some(42), Some(7), None, Some(42)]);
4467 assert_eq!(decoded.as_ref(), &expected);
4468 }
4469
4470 #[test]
4471 fn get_variant_as_run_end_encoded() {
4472 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter([
4473 Some("apple"),
4474 Some("apple"),
4475 None,
4476 Some("banana"),
4477 Some("banana"),
4478 ]));
4479 let run_ends = Arc::new(Field::new(
4480 Field::REE_RUN_ENDS_FIELD_DEFAULT_NAME,
4481 DataType::Int32,
4482 false,
4483 ));
4484 let values = Arc::new(Field::new(
4485 Field::REE_VALUES_FIELD_DEFAULT_NAME,
4486 DataType::Utf8,
4487 true,
4488 ));
4489 let data_type = DataType::RunEndEncoded(run_ends, values);
4490 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4491 "ree",
4492 data_type.clone(),
4493 true,
4494 ))));
4495
4496 let result = variant_get(&variant_array, options).unwrap();
4497 assert_eq!(result.data_type(), &data_type);
4498
4499 let decoded = cast(result.as_ref(), &DataType::Utf8).unwrap();
4500 let expected = StringArray::from(vec![
4501 Some("apple"),
4502 Some("apple"),
4503 None,
4504 Some("banana"),
4505 Some("banana"),
4506 ]);
4507 assert_eq!(decoded.as_ref(), &expected);
4508 }
4509
4510 fn map_data_type(value_type: DataType) -> DataType {
4513 DataType::Map(
4514 Arc::new(Field::new(
4515 "entries",
4516 DataType::Struct(Fields::from(vec![
4517 Field::new("keys", DataType::Utf8, false),
4518 Field::new("values", value_type, true),
4519 ])),
4520 false,
4521 )),
4522 false,
4523 )
4524 }
4525
4526 fn map_get_options(data_type: &DataType) -> GetOptions<'static> {
4527 GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4528 "map",
4529 data_type.clone(),
4530 true,
4531 ))))
4532 }
4533
4534 #[test]
4535 fn get_variant_as_map() {
4536 let input: ArrayRef = Arc::new(StringArray::from(vec![
4537 Some(r#"{"a": 1, "b": 2}"#),
4538 Some(r#"{"c": 3}"#),
4539 None,
4540 Some("{}"),
4541 Some(r#"{"d": null}"#),
4542 ]));
4543 let variant_array = ArrayRef::from(json_to_variant(&input).unwrap());
4544
4545 let data_type = map_data_type(DataType::Int64);
4546 let result = variant_get(&variant_array, map_get_options(&data_type)).unwrap();
4547 assert_eq!(result.data_type(), &data_type);
4548
4549 let mut expected = MapBuilder::new(None, StringBuilder::new(), Int64Builder::new());
4550 expected.keys().append_value("a");
4551 expected.values().append_value(1);
4552 expected.keys().append_value("b");
4553 expected.values().append_value(2);
4554 expected.append(true).unwrap();
4555 expected.keys().append_value("c");
4556 expected.values().append_value(3);
4557 expected.append(true).unwrap();
4558 expected.append(false).unwrap(); expected.append(true).unwrap(); expected.keys().append_value("d");
4561 expected.values().append_null(); expected.append(true).unwrap();
4563 let expected = expected.finish();
4564 assert_eq!(result.as_ref(), &expected);
4565 }
4566
4567 #[test]
4568 fn get_variant_as_map_of_lists() {
4569 let input: ArrayRef = Arc::new(StringArray::from(vec![
4570 Some(r#"{"a": [1, 2], "b": []}"#),
4571 Some(r#"{"c": [3]}"#),
4572 ]));
4573 let variant_array = ArrayRef::from(json_to_variant(&input).unwrap());
4574
4575 let data_type = map_data_type(DataType::List(Arc::new(Field::new(
4576 "item",
4577 DataType::Int64,
4578 true,
4579 ))));
4580 let result = variant_get(&variant_array, map_get_options(&data_type)).unwrap();
4581 assert_eq!(result.data_type(), &data_type);
4582
4583 let mut expected = MapBuilder::new(
4584 None,
4585 StringBuilder::new(),
4586 ListBuilder::new(Int64Builder::new()),
4587 );
4588 expected.keys().append_value("a");
4589 expected.values().append_value([Some(1), Some(2)]);
4590 expected.keys().append_value("b");
4591 expected.values().append_value([]);
4592 expected.append(true).unwrap();
4593 expected.keys().append_value("c");
4594 expected.values().append_value([Some(3)]);
4595 expected.append(true).unwrap();
4596 let expected = expected.finish();
4597 assert_eq!(result.as_ref(), &expected);
4598 }
4599
4600 #[test]
4601 fn get_variant_as_map_non_object_rows() {
4602 let input: ArrayRef = Arc::new(StringArray::from(vec![
4603 Some(r#"{"a": 1}"#),
4604 Some("42"), ]));
4606 let variant_array = ArrayRef::from(json_to_variant(&input).unwrap());
4607 let data_type = map_data_type(DataType::Int64);
4608
4609 let result = variant_get(&variant_array, map_get_options(&data_type)).unwrap();
4611 let mut expected = MapBuilder::new(None, StringBuilder::new(), Int64Builder::new());
4612 expected.keys().append_value("a");
4613 expected.values().append_value(1);
4614 expected.append(true).unwrap();
4615 expected.append(false).unwrap();
4616 let expected = expected.finish();
4617 assert_eq!(result.as_ref(), &expected);
4618
4619 let options = map_get_options(&data_type).with_cast_options(CastOptions {
4621 safe: false,
4622 format_options: FormatOptions::default(),
4623 });
4624 let err = variant_get(&variant_array, options).unwrap_err();
4625 assert!(
4626 err.to_string().contains("Failed to extract object"),
4627 "unexpected error: {err}"
4628 );
4629 }
4630
4631 #[test]
4632 fn get_variant_as_map_invalid_entries() {
4633 let input: ArrayRef = Arc::new(StringArray::from(vec![Some(r#"{"a": 1}"#)]));
4634 let variant_array = ArrayRef::from(json_to_variant(&input).unwrap());
4635
4636 let data_type = DataType::Map(
4638 Arc::new(Field::new("entries", DataType::Int32, false)),
4639 false,
4640 );
4641 let err = variant_get(&variant_array, map_get_options(&data_type)).unwrap_err();
4642 assert!(
4643 err.to_string().contains("Map entries must be Struct"),
4644 "unexpected error: {err}"
4645 );
4646
4647 let data_type = DataType::Map(
4649 Arc::new(Field::new(
4650 "entries",
4651 DataType::Struct(Fields::from(vec![Field::new(
4652 "keys",
4653 DataType::Utf8,
4654 false,
4655 )])),
4656 false,
4657 )),
4658 false,
4659 );
4660 let err = variant_get(&variant_array, map_get_options(&data_type)).unwrap_err();
4661 assert!(
4662 err.to_string()
4663 .contains("Map entries must have exactly two fields"),
4664 "unexpected error: {err}"
4665 );
4666 }
4667
4668 fn invalid_time_variant_array() -> ArrayRef {
4669 ArrayRef::from(VariantArray::from_iter([Some(86401000000_i64); 3]))
4671 }
4672
4673 #[test]
4674 fn test_variant_get_error_when_cast_failure_and_safe_false() {
4675 let variant_array = invalid_time_variant_array();
4676
4677 let field = Field::new("result", DataType::Time64(TimeUnit::Microsecond), true);
4678 let cast_options = CastOptions {
4679 safe: false, ..Default::default()
4681 };
4682 let options = GetOptions::new()
4683 .with_as_type(Some(FieldRef::from(field)))
4684 .with_cast_options(cast_options);
4685 let err = variant_get(&variant_array, options).unwrap_err();
4686 assert!(
4687 err.to_string().contains(
4688 "Cast error: Failed to extract primitive of type Time64(µs) from variant Int64(86401000000) at path VariantPath([])"
4689 ),
4690 "actual: {err}",
4691 );
4692 }
4693
4694 #[test]
4695 fn test_variant_get_return_null_when_cast_failure_and_safe_true() {
4696 let variant_array = invalid_time_variant_array();
4697
4698 let field = Field::new("result", DataType::Time64(TimeUnit::Microsecond), true);
4699 let cast_options = CastOptions {
4700 safe: true, ..Default::default()
4702 };
4703 let options = GetOptions::new()
4704 .with_as_type(Some(FieldRef::from(field)))
4705 .with_cast_options(cast_options);
4706 let result = variant_get(&variant_array, options).unwrap();
4707 assert_eq!(3, result.len());
4708
4709 for i in 0..3 {
4710 assert!(result.is_null(i));
4711 }
4712 }
4713
4714 #[test]
4715 fn test_perfect_shredding_returns_same_arc_ptr() {
4716 let variant_array = perfectly_shredded_int32_variant_array();
4717
4718 let variant_array_ref = VariantArray::try_new(&variant_array).unwrap();
4719 let typed_value_arc = variant_array_ref.typed_value_column().unwrap().clone();
4720
4721 let field = Field::new("result", DataType::Int32, true);
4722 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4723 let result = variant_get(&variant_array, options).unwrap();
4724
4725 assert!(Arc::ptr_eq(&typed_value_arc, &result));
4726 }
4727
4728 #[test]
4729 fn test_perfect_shredding_three_typed_value_columns() {
4730 let all_nulls_values: Arc<Int32Array> = Arc::new(Int32Array::from(vec![
4732 Option::<i32>::None,
4733 Option::<i32>::None,
4734 Option::<i32>::None,
4735 ]));
4736 let all_nulls_erased: ArrayRef = all_nulls_values.clone();
4737 let all_nulls_field =
4738 ShreddedVariantFieldArray::perfectly_shredded(all_nulls_erased.clone());
4739 let all_nulls_type = all_nulls_field.data_type().clone();
4740 let all_nulls_struct: ArrayRef = ArrayRef::from(all_nulls_field);
4741
4742 let some_nulls_values: Arc<Int32Array> =
4744 Arc::new(Int32Array::from(vec![Some(10), None, Some(30)]));
4745 let some_nulls_erased: ArrayRef = some_nulls_values.clone();
4746 let some_nulls_field =
4747 ShreddedVariantFieldArray::perfectly_shredded(some_nulls_erased.clone());
4748 let some_nulls_type = some_nulls_field.data_type().clone();
4749 let some_nulls_struct: ArrayRef = ArrayRef::from(some_nulls_field);
4750
4751 let inner_values: Arc<Int32Array> =
4753 Arc::new(Int32Array::from(vec![Some(111), None, Some(333)]));
4754 let inner_erased: ArrayRef = inner_values.clone();
4755 let inner_field = ShreddedVariantFieldArray::perfectly_shredded(inner_erased.clone());
4756 let inner_field_type = inner_field.data_type().clone();
4757 let inner_struct_array: ArrayRef = ArrayRef::from(inner_field);
4758
4759 let nested_struct = Arc::new(
4760 StructArray::try_new(
4761 Fields::from(vec![Field::new("inner", inner_field_type, true)]),
4762 vec![inner_struct_array],
4763 None,
4764 )
4765 .unwrap(),
4766 );
4767 let nested_struct_erased: ArrayRef = nested_struct.clone();
4768 let struct_field =
4769 ShreddedVariantFieldArray::perfectly_shredded(nested_struct_erased.clone());
4770 let struct_field_type = struct_field.data_type().clone();
4771 let struct_field_struct: ArrayRef = ArrayRef::from(struct_field);
4772
4773 let typed_value_struct = StructArray::try_new(
4775 Fields::from(vec![
4776 Field::new("all_nulls", all_nulls_type, true),
4777 Field::new("some_nulls", some_nulls_type, true),
4778 Field::new("struct_field", struct_field_type, true),
4779 ]),
4780 vec![all_nulls_struct, some_nulls_struct, struct_field_struct],
4781 None,
4782 )
4783 .unwrap();
4784
4785 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(
4786 EMPTY_VARIANT_METADATA_BYTES,
4787 all_nulls_values.len(),
4788 ));
4789 let variant_array: ArrayRef = VariantArray::perfectly_shredded(
4790 Arc::new(metadata),
4791 Arc::new(typed_value_struct),
4792 None,
4793 )
4794 .into();
4795
4796 let all_nulls_field_ref = FieldRef::from(Field::new("result", DataType::Int32, true));
4798 let all_nulls_result = variant_get(
4799 &variant_array,
4800 GetOptions::new_with_path(VariantPath::try_from("all_nulls").unwrap())
4801 .with_as_type(Some(all_nulls_field_ref)),
4802 )
4803 .unwrap();
4804 assert!(Arc::ptr_eq(&all_nulls_result, &all_nulls_erased));
4805
4806 let some_nulls_field_ref = FieldRef::from(Field::new("result", DataType::Int32, true));
4808 let some_nulls_result = variant_get(
4809 &variant_array,
4810 GetOptions::new_with_path(VariantPath::try_from("some_nulls").unwrap())
4811 .with_as_type(Some(some_nulls_field_ref)),
4812 )
4813 .unwrap();
4814 assert!(Arc::ptr_eq(&some_nulls_result, &some_nulls_erased));
4815
4816 let struct_child_fields = Fields::from(vec![Field::new("inner", DataType::Int32, true)]);
4818 let struct_field_ref = FieldRef::from(Field::new(
4819 "result",
4820 DataType::Struct(struct_child_fields.clone()),
4821 true,
4822 ));
4823 let struct_result = variant_get(
4824 &variant_array,
4825 GetOptions::new_with_path(VariantPath::try_from("struct_field").unwrap())
4826 .with_as_type(Some(struct_field_ref)),
4827 )
4828 .unwrap();
4829 let struct_array = struct_result
4830 .as_any()
4831 .downcast_ref::<StructArray>()
4832 .unwrap();
4833 assert_eq!(struct_array.len(), 3);
4834 assert_eq!(struct_array.null_count(), 0);
4835
4836 let inner_values_result = struct_array
4837 .column(0)
4838 .as_any()
4839 .downcast_ref::<Int32Array>()
4840 .unwrap();
4841 assert_eq!(inner_values_result.len(), 3);
4842 assert_eq!(inner_values_result.value(0), 111);
4843 assert!(inner_values_result.is_null(1));
4844 assert_eq!(inner_values_result.value(2), 333);
4845 }
4846
4847 #[test]
4848 fn test_variant_get_list_like_safe_cast() {
4849 let string_array: ArrayRef = Arc::new(StringArray::from(vec![
4850 r#"{"outer":{"list":[1, "two", 3]}}"#,
4851 r#"{"outer":{"list":"not a list"}}"#,
4852 ]));
4853 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4854
4855 let element_array: ArrayRef = Arc::new(Int64Array::from(vec![Some(1), None, Some(3)]));
4856 let field = Arc::new(Field::new("item", Int64, true));
4857
4858 let expectations = vec![
4859 (
4860 DataType::List(field.clone()),
4861 Arc::new(ListArray::new(
4862 field.clone(),
4863 OffsetBuffer::new(ScalarBuffer::from(vec![0, 3, 3])),
4864 element_array.clone(),
4865 Some(NullBuffer::from(vec![true, false])),
4866 )) as ArrayRef,
4867 ),
4868 (
4869 DataType::LargeList(field.clone()),
4870 Arc::new(LargeListArray::new(
4871 field.clone(),
4872 OffsetBuffer::new(ScalarBuffer::from(vec![0, 3, 3])),
4873 element_array.clone(),
4874 Some(NullBuffer::from(vec![true, false])),
4875 )) as ArrayRef,
4876 ),
4877 (
4878 DataType::ListView(field.clone()),
4879 Arc::new(ListViewArray::new(
4880 field.clone(),
4881 ScalarBuffer::from(vec![0, 3]),
4882 ScalarBuffer::from(vec![3, 0]),
4883 element_array.clone(),
4884 Some(NullBuffer::from(vec![true, false])),
4885 )) as ArrayRef,
4886 ),
4887 (
4888 DataType::LargeListView(field.clone()),
4889 Arc::new(LargeListViewArray::new(
4890 field.clone(),
4891 ScalarBuffer::from(vec![0, 3]),
4892 ScalarBuffer::from(vec![3, 0]),
4893 element_array,
4894 Some(NullBuffer::from(vec![true, false])),
4895 )) as ArrayRef,
4896 ),
4897 (
4898 DataType::FixedSizeList(field.clone(), 3),
4899 Arc::new(FixedSizeListArray::new(
4900 field,
4901 3,
4902 Arc::new(Int64Array::from(vec![
4903 Some(1),
4904 None,
4905 Some(3),
4906 None,
4907 None,
4908 None,
4909 ])),
4910 Some(NullBuffer::from(vec![true, false])),
4911 )) as ArrayRef,
4912 ),
4913 ];
4914
4915 for (request_type, expected) in expectations {
4916 let options =
4917 GetOptions::new_with_path(VariantPath::try_from("outer").unwrap().join("list"))
4918 .with_as_type(Some(FieldRef::from(Field::new(
4919 "result",
4920 request_type.clone(),
4921 true,
4922 ))));
4923
4924 let result = variant_get(&variant_array, options).unwrap();
4925 assert_eq!(result.data_type(), expected.data_type());
4926 assert_eq!(&result, &expected);
4927 }
4928
4929 for (idx, expected) in [
4930 (0, vec![Some(1), None]),
4931 (1, vec![None, None]),
4932 (2, vec![Some(3), None]),
4933 ] {
4934 let index_options = GetOptions::new_with_path(
4935 VariantPath::try_from("outer")
4936 .unwrap()
4937 .join("list")
4938 .join(idx),
4939 )
4940 .with_as_type(Some(FieldRef::from(Field::new(
4941 "result",
4942 DataType::Int64,
4943 true,
4944 ))));
4945 let index_result = variant_get(&variant_array, index_options).unwrap();
4946 let index_expected: ArrayRef = Arc::new(Int64Array::from(expected));
4947 assert_eq!(&index_result, &index_expected);
4948 }
4949 }
4950
4951 #[test]
4952 fn test_variant_get_nested_list() {
4953 use arrow::datatypes::Int64Type;
4954
4955 let string_array: ArrayRef = Arc::new(StringArray::from(vec![
4956 "[[1, 2], [3]]",
4957 r#"[[4], "not a list", [5, 6]]"#,
4958 ]));
4959 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4960
4961 let inner_field = Arc::new(Field::new("item", Int64, true));
4962 let outer_field = Arc::new(Field::new(
4963 "item",
4964 DataType::List(inner_field.clone()),
4965 true,
4966 ));
4967 let request_type = DataType::List(outer_field.clone());
4968
4969 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4970 "result",
4971 request_type,
4972 true,
4973 ))));
4974 let result = variant_get(&variant_array, options).unwrap();
4975 let outer = result.as_list::<i32>();
4976
4977 let row0 = outer.value(0);
4979 let row0 = row0.as_list::<i32>();
4980 assert_eq!(row0.len(), 2);
4981 let elem0 = row0.value(0);
4982 assert_eq!(elem0.as_primitive::<Int64Type>().values(), &[1, 2]);
4983 let elem1 = row0.value(1);
4984 assert_eq!(elem1.as_primitive::<Int64Type>().values(), &[3]);
4985
4986 let row1 = outer.value(1);
4988 let row1 = row1.as_list::<i32>();
4989 assert_eq!(row1.len(), 3);
4990 let elem0 = row1.value(0);
4991 assert_eq!(elem0.as_primitive::<Int64Type>().values(), &[4]);
4992 assert!(row1.is_null(1));
4993 let elem2 = row1.value(2);
4994 assert_eq!(elem2.as_primitive::<Int64Type>().values(), &[5, 6]);
4995 }
4996
4997 #[test]
4998 fn test_variant_get_list_like_unsafe_cast_errors_on_element_mismatch() {
4999 let string_array: ArrayRef =
5000 Arc::new(StringArray::from(vec![r#"[1, "two", 3]"#, "[4, 5]"]));
5001 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
5002 let cast_options = CastOptions {
5003 safe: false,
5004 ..Default::default()
5005 };
5006
5007 let item_field = Arc::new(Field::new("item", DataType::Int64, true));
5008 let request_types = vec![
5009 DataType::List(item_field.clone()),
5010 DataType::LargeList(item_field.clone()),
5011 DataType::ListView(item_field.clone()),
5012 DataType::LargeListView(item_field),
5013 ];
5014
5015 for request_type in request_types {
5016 let options = GetOptions::new()
5017 .with_as_type(Some(FieldRef::from(Field::new(
5018 "result",
5019 request_type.clone(),
5020 true,
5021 ))))
5022 .with_cast_options(cast_options.clone());
5023
5024 let err = variant_get(&variant_array, options).unwrap_err();
5025 assert!(
5026 err.to_string()
5027 .contains("Failed to extract primitive of type Int64")
5028 );
5029 }
5030 }
5031
5032 #[test]
5033 fn test_variant_get_list_like_unsafe_cast_preserves_null_elements() {
5034 let string_array: ArrayRef = Arc::new(StringArray::from(vec!["[1, null, 3]"]));
5035 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
5036 let cast_options = CastOptions {
5037 safe: false,
5038 ..Default::default()
5039 };
5040 let options = GetOptions::new()
5041 .with_as_type(Some(FieldRef::from(Field::new(
5042 "result",
5043 DataType::List(Arc::new(Field::new("item", DataType::Int64, true))),
5044 true,
5045 ))))
5046 .with_cast_options(cast_options);
5047
5048 let result = variant_get(&variant_array, options).unwrap();
5049 let list_array = result.as_any().downcast_ref::<ListArray>().unwrap();
5050 let values = list_array
5051 .values()
5052 .as_any()
5053 .downcast_ref::<Int64Array>()
5054 .unwrap();
5055
5056 assert_eq!(values.len(), 3);
5057 assert_eq!(values.value(0), 1);
5058 assert!(values.is_null(1));
5059 assert_eq!(values.value(2), 3);
5060 }
5061
5062 #[test]
5063 fn test_variant_get_list_like_null_element_in_non_nullable_item() {
5064 let item_field = Arc::new(Field::new("item", Int64, false));
5065 let data_types = [
5066 (DataType::List(item_field.clone()), "ListArray"),
5067 (DataType::LargeList(item_field.clone()), "LargeListArray"),
5068 (DataType::ListView(item_field.clone()), "ListViewArray"),
5069 (DataType::LargeListView(item_field), "LargeListViewArray"),
5070 ];
5071 for json in ["[1, null, 3]", r#"[1, "two", 3]"#] {
5073 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json]));
5074 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
5075 for (data_type, array_name) in &data_types {
5076 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
5077 "result",
5078 data_type.clone(),
5079 true,
5080 ))));
5081 let err = variant_get(&variant_array, options).unwrap_err();
5082 assert_eq!(
5083 err.to_string(),
5084 format!(
5085 "Invalid argument error: Non-nullable field of {array_name} \"item\" cannot contain nulls"
5086 )
5087 );
5088 }
5089 }
5090 }
5091
5092 #[test]
5093 fn test_variant_get_list_like_unsafe_cast_errors_on_non_list() {
5094 let string_array: ArrayRef = Arc::new(StringArray::from(vec!["[1, 2]", "\"not a list\""]));
5095 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
5096 let cast_options = CastOptions {
5097 safe: false,
5098 ..Default::default()
5099 };
5100 let item_field = Arc::new(Field::new("item", Int64, true));
5101 let data_types = vec![
5102 DataType::List(item_field.clone()),
5103 DataType::LargeList(item_field.clone()),
5104 DataType::ListView(item_field.clone()),
5105 DataType::LargeListView(item_field.clone()),
5106 DataType::FixedSizeList(item_field, 2),
5107 ];
5108
5109 for data_type in data_types {
5110 let options = GetOptions::new()
5111 .with_as_type(Some(FieldRef::from(Field::new("result", data_type, true))))
5112 .with_cast_options(cast_options.clone());
5113
5114 let err = variant_get(&variant_array, options).unwrap_err();
5115 assert!(
5116 err.to_string()
5117 .contains("Failed to extract list from variant"),
5118 );
5119 }
5120 }
5121
5122 #[test]
5123 fn test_variant_get_fixed_size_list_wrong_size() {
5124 let string_array: ArrayRef = Arc::new(StringArray::from(vec!["[1, 2, 3]"]));
5125 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
5126 let item_field = Arc::new(Field::new("item", Int64, true));
5127
5128 let options = GetOptions::new()
5130 .with_as_type(Some(FieldRef::from(Field::new(
5131 "result",
5132 DataType::FixedSizeList(item_field.clone(), 2),
5133 true,
5134 ))))
5135 .with_cast_options(CastOptions {
5136 safe: true,
5137 ..Default::default()
5138 });
5139 let result = variant_get(&variant_array, options).unwrap();
5140 let fixed_size_list = result
5141 .as_any()
5142 .downcast_ref::<FixedSizeListArray>()
5143 .expect("Expected FixedSizeListArray");
5144 assert_eq!(fixed_size_list.len(), 1);
5145 assert!(fixed_size_list.is_null(0));
5146
5147 let options = GetOptions::new()
5149 .with_as_type(Some(FieldRef::from(Field::new(
5150 "result",
5151 DataType::FixedSizeList(item_field.clone(), 2),
5152 true,
5153 ))))
5154 .with_cast_options(CastOptions {
5155 safe: false,
5156 ..Default::default()
5157 });
5158 let err = variant_get(&variant_array, options).unwrap_err();
5159 assert!(
5160 err.to_string()
5161 .contains("Expected fixed size list of size 2, got size 3"),
5162 "got: {err}",
5163 );
5164 }
5165
5166 macro_rules! perfectly_shredded_preserves_top_level_nulls_test {
5167 ($name:ident, $result_type:expr, $typed_value:expr, $expected_array:expr) => {
5168 perfectly_shredded_preserves_top_level_nulls_test!(
5169 $name,
5170 $result_type,
5171 $typed_value,
5172 Some(NullBuffer::from(vec![true, false, true])),
5173 $expected_array
5174 );
5175 };
5176 ($name:ident, $result_type:expr, $typed_value:expr, $parent_nulls:expr, $expected_array:expr) => {
5177 #[test]
5178 fn $name() {
5179 let metadata = Arc::new(BinaryViewArray::from_iter_values(std::iter::repeat_n(
5180 EMPTY_VARIANT_METADATA_BYTES,
5181 3,
5182 )));
5183 let typed_value: ArrayRef = Arc::new($typed_value);
5184 let variant_array: ArrayRef =
5185 VariantArray::perfectly_shredded(metadata, typed_value, $parent_nulls).into();
5186
5187 let result = variant_get(
5188 &variant_array,
5189 GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
5190 "result",
5191 $result_type,
5192 true,
5193 )))),
5194 )
5195 .unwrap();
5196
5197 let expected_array: ArrayRef = Arc::new($expected_array);
5198 assert_eq!(&result, &expected_array);
5199 }
5200 };
5201 }
5202
5203 perfectly_shredded_preserves_top_level_nulls_test!(
5204 test_variant_get_perfectly_shredded_integer_preserves_top_level_nulls,
5205 DataType::Int32,
5206 Int32Array::from(vec![Some(0_i32), Some(1_i32), Some(2_i32)]),
5207 Int32Array::from(vec![Some(0_i32), None, Some(2_i32)])
5208 );
5209
5210 perfectly_shredded_preserves_top_level_nulls_test!(
5211 test_variant_get_perfectly_shredded_integer_unions_child_and_top_level_nulls,
5212 DataType::Int32,
5213 Int32Array::from(vec![None, Some(1_i32), Some(2_i32)]),
5214 Some(NullBuffer::from(vec![true, false, true])),
5215 Int32Array::from(vec![None, None, Some(2_i32)])
5216 );
5217
5218 perfectly_shredded_preserves_top_level_nulls_test!(
5219 test_variant_get_perfectly_shredded_null_preserves_top_level_nulls,
5220 DataType::Null,
5221 NullArray::new(3),
5222 NullArray::new(3)
5223 );
5224
5225 perfectly_shredded_preserves_top_level_nulls_test!(
5226 test_variant_get_perfectly_shredded_binary_view_preserves_top_level_nulls,
5227 DataType::BinaryView,
5228 BinaryViewArray::from(vec![
5229 Some(b"Apache" as &[u8]),
5230 Some(b"masked-null" as &[u8]),
5231 Some(b"Parquet-variant" as &[u8]),
5232 ]),
5233 BinaryViewArray::from(vec![
5234 Some(b"Apache" as &[u8]),
5235 None,
5236 Some(b"Parquet-variant" as &[u8]),
5237 ])
5238 );
5239
5240 perfectly_shredded_preserves_top_level_nulls_test!(
5241 test_variant_get_perfectly_shredded_binary_preserves_top_level_nulls,
5242 DataType::Binary,
5243 BinaryArray::from(vec![
5244 Some(b"Apache" as &[u8]),
5245 Some(b"masked-null" as &[u8]),
5246 Some(b"Parquet-variant" as &[u8]),
5247 ]),
5248 BinaryArray::from(vec![
5249 Some(b"Apache" as &[u8]),
5250 None,
5251 Some(b"Parquet-variant" as &[u8]),
5252 ])
5253 );
5254
5255 perfectly_shredded_preserves_top_level_nulls_test!(
5256 test_variant_get_perfectly_shredded_decimal4_preserves_top_level_nulls,
5257 DataType::Decimal32(5, 2),
5258 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
5259 .with_precision_and_scale(5, 2)
5260 .unwrap(),
5261 Decimal32Array::from(vec![Some(12345), None, Some(-12342)])
5262 .with_precision_and_scale(5, 2)
5263 .unwrap()
5264 );
5265
5266 perfectly_shredded_preserves_top_level_nulls_test!(
5267 test_variant_get_perfectly_shredded_decimal8_preserves_top_level_nulls,
5268 DataType::Decimal64(10, 1),
5269 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
5270 .with_precision_and_scale(10, 1)
5271 .unwrap(),
5272 Decimal64Array::from(vec![Some(1234567809), None, Some(-1234561203)])
5273 .with_precision_and_scale(10, 1)
5274 .unwrap()
5275 );
5276
5277 perfectly_shredded_preserves_top_level_nulls_test!(
5278 test_variant_get_perfectly_shredded_decimal16_preserves_top_level_nulls,
5279 DataType::Decimal128(20, 3),
5280 Decimal128Array::from(vec![
5281 Some(i128::from_str("12345678901234567899").unwrap()),
5282 Some(i128::from_str("23445677483748324300").unwrap()),
5283 Some(i128::from_str("-12345678901234567899").unwrap()),
5284 ])
5285 .with_precision_and_scale(20, 3)
5286 .unwrap(),
5287 Decimal128Array::from(vec![
5288 Some(i128::from_str("12345678901234567899").unwrap()),
5289 None,
5290 Some(i128::from_str("-12345678901234567899").unwrap()),
5291 ])
5292 .with_precision_and_scale(20, 3)
5293 .unwrap()
5294 );
5295
5296 fn union_get_options(fields: &UnionFields, mode: UnionMode) -> GetOptions<'static> {
5297 let field = Field::new("union", DataType::Union(fields.clone(), mode), true);
5298 GetOptions::new().with_as_type(Some(FieldRef::from(field)))
5299 }
5300
5301 fn int_str_bool_union_fields() -> UnionFields {
5302 UnionFields::try_new(
5303 vec![0, 1, 2],
5304 vec![
5305 Field::new("int", DataType::Int64, true),
5306 Field::new("str", DataType::Utf8, true),
5307 Field::new("bool", DataType::Boolean, true),
5308 ],
5309 )
5310 .unwrap()
5311 }
5312
5313 fn mixed_variant_array() -> ArrayRef {
5315 let mut builder = VariantArrayBuilder::new(7);
5316 builder.append_variant(Variant::Int8(1));
5317 builder.append_variant(Variant::from("hello"));
5318 builder.append_variant(Variant::from(true));
5319 builder.append_null();
5320 builder.append_variant(Variant::Null);
5321 builder.append_variant(Variant::Double(2.5));
5322 builder.append_variant(Variant::Int64(5_000_000_000));
5323 ArrayRef::from(builder.build())
5324 }
5325
5326 #[test]
5327 fn get_variant_as_dense_union() {
5328 let fields = int_str_bool_union_fields();
5329 let array = mixed_variant_array();
5330 let result = variant_get(&array, union_get_options(&fields, UnionMode::Dense)).unwrap();
5331
5332 let expected: ArrayRef = Arc::new(
5334 UnionArray::try_new(
5335 fields,
5336 ScalarBuffer::from(vec![0i8, 1, 2, 0, 0, 0, 0]),
5337 Some(ScalarBuffer::from(vec![0i32, 0, 0, 1, 2, 3, 4])),
5338 vec![
5339 Arc::new(Int64Array::from(vec![
5340 Some(1),
5341 None,
5342 None,
5343 None,
5344 Some(5_000_000_000),
5345 ])),
5346 Arc::new(StringArray::from(vec!["hello"])),
5347 Arc::new(BooleanArray::from(vec![true])),
5348 ],
5349 )
5350 .unwrap(),
5351 );
5352 assert_eq!(&result, &expected);
5353 }
5354
5355 #[test]
5356 fn get_variant_as_sparse_union() {
5357 let fields = int_str_bool_union_fields();
5358 let array = mixed_variant_array();
5359 let result = variant_get(&array, union_get_options(&fields, UnionMode::Sparse)).unwrap();
5360
5361 let expected: ArrayRef = Arc::new(
5362 UnionArray::try_new(
5363 fields,
5364 ScalarBuffer::from(vec![0i8, 1, 2, 0, 0, 0, 0]),
5365 None,
5366 vec![
5367 Arc::new(Int64Array::from(vec![
5368 Some(1),
5369 None,
5370 None,
5371 None,
5372 None,
5373 None,
5374 Some(5_000_000_000),
5375 ])),
5376 Arc::new(StringArray::from(vec![
5377 None,
5378 Some("hello"),
5379 None,
5380 None,
5381 None,
5382 None,
5383 None,
5384 ])),
5385 Arc::new(BooleanArray::from(vec![
5386 None,
5387 None,
5388 Some(true),
5389 None,
5390 None,
5391 None,
5392 None,
5393 ])),
5394 ],
5395 )
5396 .unwrap(),
5397 );
5398 assert_eq!(&result, &expected);
5399 }
5400
5401 #[test]
5402 fn get_variant_as_union_prefers_most_exact_field() {
5403 let fields = UnionFields::try_new(
5405 vec![0, 1],
5406 vec![
5407 Field::new("big", DataType::Int64, true),
5408 Field::new("small", DataType::Int32, true),
5409 ],
5410 )
5411 .unwrap();
5412 let mut builder = VariantArrayBuilder::new(3);
5413 builder.append_variant(Variant::Int8(1));
5414 builder.append_variant(Variant::Int32(2));
5415 builder.append_variant(Variant::Int64(3));
5416 let array = ArrayRef::from(builder.build());
5417
5418 let result = variant_get(&array, union_get_options(&fields, UnionMode::Dense)).unwrap();
5419
5420 let expected: ArrayRef = Arc::new(
5421 UnionArray::try_new(
5422 fields,
5423 ScalarBuffer::from(vec![1i8, 1, 0]),
5424 Some(ScalarBuffer::from(vec![0i32, 1, 0])),
5425 vec![
5426 Arc::new(Int64Array::from(vec![3])),
5427 Arc::new(Int32Array::from(vec![1, 2])),
5428 ],
5429 )
5430 .unwrap(),
5431 );
5432 assert_eq!(&result, &expected);
5433 }
5434
5435 #[test]
5436 fn get_variant_as_union_with_encoded_children() {
5437 let encoded_types = [
5438 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
5439 DataType::RunEndEncoded(
5440 Arc::new(Field::new(
5441 Field::REE_RUN_ENDS_FIELD_DEFAULT_NAME,
5442 DataType::Int32,
5443 false,
5444 )),
5445 Arc::new(Field::new(
5446 Field::REE_VALUES_FIELD_DEFAULT_NAME,
5447 DataType::Utf8,
5448 true,
5449 )),
5450 ),
5451 ];
5452
5453 for data_type in encoded_types {
5454 let fields = UnionFields::try_new(
5455 vec![0],
5456 vec![Field::new("encoded", data_type.clone(), true)],
5457 )
5458 .unwrap();
5459 let array = ArrayRef::from(VariantArray::from_iter([Some("apple"), Some("banana")]));
5460 let options =
5461 union_get_options(&fields, UnionMode::Dense).with_cast_options(CastOptions {
5462 safe: false,
5463 ..Default::default()
5464 });
5465
5466 let result = variant_get(&array, options).unwrap();
5467 let union = result.as_any().downcast_ref::<UnionArray>().unwrap();
5468 assert_eq!(union.type_ids(), &[0i8, 0]);
5469 assert_eq!(union.child(0).data_type(), &data_type);
5470
5471 let decoded = cast(union.child(0).as_ref(), &DataType::Utf8).unwrap();
5472 let expected = StringArray::from(vec!["apple", "banana"]);
5473 assert_eq!(decoded.as_ref(), &expected);
5474 }
5475 }
5476
5477 #[test]
5478 fn get_variant_as_union_with_fixed_size_list_child() {
5479 let item = Arc::new(Field::new("item", DataType::Int64, true));
5480 let fields = UnionFields::try_new(
5481 vec![0],
5482 vec![Field::new("fixed", DataType::FixedSizeList(item, 2), true)],
5483 )
5484 .unwrap();
5485 let json = StringArray::from(vec!["[1, 2]"]);
5486 let array = ArrayRef::from(json_to_variant(&(Arc::new(json) as ArrayRef)).unwrap());
5487
5488 for safe in [true, false] {
5489 let options =
5490 union_get_options(&fields, UnionMode::Dense).with_cast_options(CastOptions {
5491 safe,
5492 ..Default::default()
5493 });
5494 let result = variant_get(&array, options).unwrap();
5495 let union = result.as_any().downcast_ref::<UnionArray>().unwrap();
5496 assert_eq!(union.type_ids(), &[0i8]);
5497 let list = union
5498 .child(0)
5499 .as_any()
5500 .downcast_ref::<FixedSizeListArray>()
5501 .unwrap();
5502 assert_eq!(
5503 list.value(0)
5504 .as_primitive::<arrow::datatypes::Int64Type>()
5505 .values(),
5506 &[1, 2]
5507 );
5508 }
5509 }
5510
5511 #[test]
5512 fn get_variant_as_union_skips_decimal_that_cannot_fit() {
5513 let fields = UnionFields::try_new(
5514 vec![0, 1],
5515 vec![
5516 Field::new("too_narrow", DataType::Decimal32(3, 2), true),
5517 Field::new("fits", DataType::Decimal32(5, 2), true),
5518 ],
5519 )
5520 .unwrap();
5521 let array = ArrayRef::from(VariantArray::from_iter([Some(
5522 VariantDecimal4::try_new(12_345, 2).unwrap(),
5523 )]));
5524
5525 for safe in [true, false] {
5526 let options =
5527 union_get_options(&fields, UnionMode::Dense).with_cast_options(CastOptions {
5528 safe,
5529 ..Default::default()
5530 });
5531 let result = variant_get(&array, options).unwrap();
5532 let union = result.as_any().downcast_ref::<UnionArray>().unwrap();
5533 assert_eq!(union.type_ids(), &[1i8]);
5534 let decimal = union
5535 .child(1)
5536 .as_any()
5537 .downcast_ref::<Decimal32Array>()
5538 .unwrap();
5539 assert_eq!(decimal.value(0), 12_345);
5540 }
5541 }
5542
5543 #[test]
5544 fn get_variant_as_union_with_null_field() {
5545 let fields = UnionFields::try_new(
5547 vec![0, 1],
5548 vec![
5549 Field::new("int", DataType::Int64, true),
5550 Field::new("null", DataType::Null, true),
5551 ],
5552 )
5553 .unwrap();
5554 let mut builder = VariantArrayBuilder::new(4);
5555 builder.append_variant(Variant::Int8(1));
5556 builder.append_null();
5557 builder.append_variant(Variant::Null);
5558 builder.append_variant(Variant::from("no matching field"));
5559 let array = ArrayRef::from(builder.build());
5560
5561 let result = variant_get(&array, union_get_options(&fields, UnionMode::Dense)).unwrap();
5562
5563 let expected: ArrayRef = Arc::new(
5564 UnionArray::try_new(
5565 fields,
5566 ScalarBuffer::from(vec![0i8, 1, 1, 1]),
5567 Some(ScalarBuffer::from(vec![0i32, 0, 1, 2])),
5568 vec![
5569 Arc::new(Int64Array::from(vec![1])),
5570 Arc::new(NullArray::new(3)),
5571 ],
5572 )
5573 .unwrap(),
5574 );
5575 assert_eq!(&result, &expected);
5576 }
5577
5578 #[test]
5579 fn get_variant_as_union_of_nested_types() {
5580 let fields = UnionFields::try_new(
5581 vec![0, 1, 2],
5582 vec![
5583 Field::new(
5584 "struct",
5585 DataType::Struct(Fields::from(vec![Field::new("a", DataType::Int64, true)])),
5586 true,
5587 ),
5588 Field::new(
5589 "list",
5590 DataType::List(Arc::new(Field::new("item", DataType::Int64, true))),
5591 true,
5592 ),
5593 Field::new("str", DataType::Utf8, true),
5594 ],
5595 )
5596 .unwrap();
5597 let json = StringArray::from(vec![r#"{"a": 1}"#, "[1, 2, 3]", "\"s\""]);
5598 let array = ArrayRef::from(json_to_variant(&(Arc::new(json) as ArrayRef)).unwrap());
5599
5600 let result = variant_get(&array, union_get_options(&fields, UnionMode::Dense)).unwrap();
5601
5602 let mut list_builder = ListBuilder::new(Int64Builder::new());
5603 list_builder.append_value([Some(1), Some(2), Some(3)]);
5604 let expected: ArrayRef = Arc::new(
5605 UnionArray::try_new(
5606 fields,
5607 ScalarBuffer::from(vec![0i8, 1, 2]),
5608 Some(ScalarBuffer::from(vec![0i32, 0, 0])),
5609 vec![
5610 Arc::new(StructArray::from(vec![(
5611 Arc::new(Field::new("a", DataType::Int64, true)),
5612 Arc::new(Int64Array::from(vec![1])) as ArrayRef,
5613 )])),
5614 Arc::new(list_builder.finish()),
5615 Arc::new(StringArray::from(vec!["s"])),
5616 ],
5617 )
5618 .unwrap(),
5619 );
5620 assert_eq!(&result, &expected);
5621 }
5622
5623 #[test]
5624 fn get_variant_as_union_with_map_field() {
5625 let fields = UnionFields::try_new(
5627 vec![0, 1],
5628 vec![
5629 Field::new("map", map_data_type(DataType::Int64), true),
5630 Field::new("str", DataType::Utf8, true),
5631 ],
5632 )
5633 .unwrap();
5634 let json = StringArray::from(vec![r#"{"a": 1, "b": 2}"#, "\"hi\""]);
5635 let array = ArrayRef::from(json_to_variant(&(Arc::new(json) as ArrayRef)).unwrap());
5636
5637 let result = variant_get(&array, union_get_options(&fields, UnionMode::Dense)).unwrap();
5638
5639 let mut map_builder = MapBuilder::new(None, StringBuilder::new(), Int64Builder::new());
5640 map_builder.keys().append_value("a");
5641 map_builder.values().append_value(1);
5642 map_builder.keys().append_value("b");
5643 map_builder.values().append_value(2);
5644 map_builder.append(true).unwrap();
5645 let expected: ArrayRef = Arc::new(
5646 UnionArray::try_new(
5647 fields,
5648 ScalarBuffer::from(vec![0i8, 1]),
5649 Some(ScalarBuffer::from(vec![0i32, 0])),
5650 vec![
5651 Arc::new(map_builder.finish()),
5652 Arc::new(StringArray::from(vec!["hi"])),
5653 ],
5654 )
5655 .unwrap(),
5656 );
5657 assert_eq!(&result, &expected);
5658 }
5659
5660 #[test]
5661 fn get_variant_as_union_prefers_struct_over_map() {
5662 let fields = UnionFields::try_new(
5665 vec![0, 1],
5666 vec![
5667 Field::new("map", map_data_type(DataType::Int64), true),
5668 Field::new(
5669 "struct",
5670 DataType::Struct(Fields::from(vec![Field::new("a", DataType::Int64, true)])),
5671 true,
5672 ),
5673 ],
5674 )
5675 .unwrap();
5676 let json = StringArray::from(vec![r#"{"a": 1}"#]);
5677 let array = ArrayRef::from(json_to_variant(&(Arc::new(json) as ArrayRef)).unwrap());
5678
5679 let result = variant_get(&array, union_get_options(&fields, UnionMode::Dense)).unwrap();
5680 let union = result.as_any().downcast_ref::<UnionArray>().unwrap();
5681 assert_eq!(union.type_ids(), &[1i8]);
5683 }
5684
5685 #[test]
5686 fn get_variant_as_union_no_matching_field() {
5687 let fields =
5689 UnionFields::try_new(vec![0], vec![Field::new("str", DataType::Utf8, false)]).unwrap();
5690 let mut builder = VariantArrayBuilder::new(2);
5691 builder.append_variant(Variant::from("kept"));
5692 builder.append_variant(Variant::Int8(1));
5693 let array = ArrayRef::from(builder.build());
5694
5695 let result = variant_get(&array, union_get_options(&fields, UnionMode::Dense)).unwrap();
5697 let expected: ArrayRef = Arc::new(
5698 UnionArray::try_new(
5699 fields.clone(),
5700 ScalarBuffer::from(vec![0i8, 0]),
5701 Some(ScalarBuffer::from(vec![0i32, 1])),
5702 vec![Arc::new(StringArray::from(vec![Some("kept"), None]))],
5703 )
5704 .unwrap(),
5705 );
5706 assert_eq!(&result, &expected);
5707
5708 let options = union_get_options(&fields, UnionMode::Dense).with_cast_options(CastOptions {
5710 safe: false,
5711 ..Default::default()
5712 });
5713 let err = variant_get(&array, options).unwrap_err();
5714 assert!(
5715 err.to_string().contains("no field can represent it"),
5716 "unexpected error: {err}"
5717 );
5718 }
5719
5720 #[test]
5721 fn get_variant_as_union_empty_fields_errors() {
5722 let array = ArrayRef::from(VariantArray::from_iter([Some(1_i8)]));
5723
5724 let err = variant_get(
5725 &array,
5726 union_get_options(&UnionFields::empty(), UnionMode::Dense),
5727 )
5728 .unwrap_err();
5729 assert!(
5730 err.to_string().contains("at least one union field"),
5731 "unexpected error: {err}"
5732 );
5733 }
5734}