1use arrow::{
18 array::{self, Array, ArrayRef, BinaryViewArray, StructArray},
19 compute::CastOptions,
20 datatypes::Field,
21 error::Result,
22};
23use arrow_schema::{ArrowError, DataType, FieldRef};
24use parquet_variant::{VariantPath, VariantPathElement};
25
26use crate::VariantArray;
27use crate::variant_array::BorrowedShreddingState;
28use crate::variant_to_arrow::make_variant_to_arrow_row_builder;
29
30use arrow::array::AsArray;
31use std::sync::Arc;
32
33pub(crate) enum ShreddedPathStep<'a> {
34 Success(BorrowedShreddingState<'a>),
36 Missing,
39 NotShredded,
43}
44
45pub(crate) fn follow_shredded_path_element<'a>(
51 shredding_state: &BorrowedShreddingState<'a>,
52 path_element: &VariantPathElement<'_>,
53 cast_options: &CastOptions,
54) -> Result<ShreddedPathStep<'a>> {
55 let missing_path_step = || match shredding_state.value_field() {
58 Some(_) => ShreddedPathStep::NotShredded,
59 None => ShreddedPathStep::Missing,
60 };
61
62 let Some(typed_value) = shredding_state.typed_value_field() else {
63 return Ok(missing_path_step());
64 };
65
66 match path_element {
67 VariantPathElement::Field { name } => {
68 let Some(struct_array) = typed_value.as_any().downcast_ref::<StructArray>() else {
71 if !cast_options.safe {
73 return Err(ArrowError::CastError(format!(
74 "Cannot access field '{}' on non-struct type: {}",
75 name,
76 typed_value.data_type()
77 )));
78 }
79 return Ok(missing_path_step());
81 };
82
83 let Some(field) = struct_array.column_by_name(name) else {
85 return Ok(missing_path_step());
87 };
88
89 let struct_array = field.as_struct_opt().ok_or_else(|| {
90 ArrowError::InvalidArgumentError(format!(
94 "Expected Struct array while following path, got {}",
95 field.data_type(),
96 ))
97 })?;
98
99 let state = BorrowedShreddingState::try_from(struct_array)?;
100 Ok(ShreddedPathStep::Success(state))
101 }
102 VariantPathElement::Index { .. } => {
103 Err(ArrowError::NotYetImplemented(
106 "Pathing into shredded variant array index".into(),
107 ))
108 }
109 }
110}
111
112fn shredded_get_path(
116 input: &VariantArray,
117 path: &[VariantPathElement<'_>],
118 as_field: Option<&Field>,
119 cast_options: &CastOptions,
120) -> Result<ArrayRef> {
121 let make_target_variant =
124 |value: Option<BinaryViewArray>,
125 typed_value: Option<ArrayRef>,
126 accumulated_nulls: Option<arrow::buffer::NullBuffer>| {
127 let metadata = input.metadata_field().clone();
128 VariantArray::from_parts(metadata, value, typed_value, accumulated_nulls)
129 };
130
131 let shred_basic_variant =
133 |target: VariantArray, path: VariantPath<'_>, as_field: Option<&Field>| {
134 let as_type = as_field.map(|f| f.data_type());
135 let mut builder = make_variant_to_arrow_row_builder(
136 target.metadata_field(),
137 path,
138 as_type,
139 cast_options,
140 target.len(),
141 )?;
142 for i in 0..target.len() {
143 if target.is_null(i) {
144 builder.append_null()?;
145 } else if !cast_options.safe {
146 let value = target.try_value(i)?;
147 builder.append_value(value)?;
148 } else {
149 let _ = match target.try_value(i) {
150 Ok(v) => builder.append_value(v)?,
151 Err(_) => {
152 builder.append_null()?;
153 false }
155 };
156 }
157 }
158 builder.finish()
159 };
160
161 let mut shredding_state = input.shredding_state().borrow();
164 let mut accumulated_nulls = input.inner().nulls().cloned();
165 let mut path_index = 0;
166 for path_element in path {
167 match follow_shredded_path_element(&shredding_state, path_element, cast_options)? {
168 ShreddedPathStep::Success(state) => {
169 if let Some(typed_value) = shredding_state.typed_value_field() {
171 accumulated_nulls = arrow::buffer::NullBuffer::union(
172 accumulated_nulls.as_ref(),
173 typed_value.nulls(),
174 );
175 }
176 shredding_state = state;
177 path_index += 1;
178 continue;
179 }
180 ShreddedPathStep::Missing => {
181 let num_rows = input.len();
182 let arr = match as_field.map(|f| f.data_type()) {
183 Some(data_type) => array::new_null_array(data_type, num_rows),
184 None => Arc::new(array::NullArray::new(num_rows)) as _,
185 };
186 return Ok(arr);
187 }
188 ShreddedPathStep::NotShredded => {
189 let target = make_target_variant(
190 shredding_state.value_field().cloned(),
191 None,
192 accumulated_nulls,
193 );
194 return shred_basic_variant(target, path[path_index..].into(), as_field);
195 }
196 };
197 }
198
199 let target = make_target_variant(
201 shredding_state.value_field().cloned(),
202 shredding_state.typed_value_field().cloned(),
203 accumulated_nulls,
204 );
205
206 let Some(as_field) = as_field else {
208 return Ok(ArrayRef::from(target));
209 };
210
211 if let Some(shredded) = try_perfect_shredding(&target, as_field) {
213 return Ok(shredded);
214 }
215
216 if let DataType::Struct(fields) = as_field.data_type() {
219 let children = fields
220 .iter()
221 .map(|field| {
222 shredded_get_path(
223 &target,
224 &[VariantPathElement::from(field.name().as_str())],
225 Some(field),
226 cast_options,
227 )
228 })
229 .collect::<Result<Vec<_>>>()?;
230
231 let struct_nulls = target.nulls().cloned();
232
233 return Ok(Arc::new(StructArray::try_new(
234 fields.clone(),
235 children,
236 struct_nulls,
237 )?));
238 }
239
240 shred_basic_variant(target, VariantPath::default(), Some(as_field))
242}
243
244fn try_perfect_shredding(variant_array: &VariantArray, as_field: &Field) -> Option<ArrayRef> {
245 if matches!(as_field.data_type(), DataType::Struct(_)) {
247 return None;
248 }
249 let typed_value = variant_array.typed_value_field()?;
250 if typed_value.data_type() == as_field.data_type()
251 && variant_array
252 .value_field()
253 .is_none_or(|v| v.null_count() == v.len())
254 {
255 return Some(typed_value.clone());
262 }
263 None
264}
265
266pub fn variant_get(input: &ArrayRef, options: GetOptions) -> Result<ArrayRef> {
278 let variant_array = VariantArray::try_new(input)?;
279
280 let GetOptions {
281 as_type,
282 path,
283 cast_options,
284 } = options;
285
286 shredded_get_path(&variant_array, &path, as_type.as_deref(), &cast_options)
287}
288
289#[derive(Debug, Clone, Default)]
291pub struct GetOptions<'a> {
292 pub path: VariantPath<'a>,
294 pub as_type: Option<FieldRef>,
298 pub cast_options: CastOptions<'a>,
300}
301
302impl<'a> GetOptions<'a> {
303 pub fn new() -> Self {
305 Default::default()
306 }
307
308 pub fn new_with_path(path: VariantPath<'a>) -> Self {
310 Self {
311 path,
312 as_type: None,
313 cast_options: Default::default(),
314 }
315 }
316
317 pub fn with_as_type(mut self, as_type: Option<FieldRef>) -> Self {
319 self.as_type = as_type;
320 self
321 }
322
323 pub fn with_cast_options(mut self, cast_options: CastOptions<'a>) -> Self {
325 self.cast_options = cast_options;
326 self
327 }
328}
329
330#[cfg(test)]
331mod test {
332 use std::str::FromStr;
333 use std::sync::Arc;
334
335 use super::{GetOptions, variant_get};
336 use crate::variant_array::{ShreddedVariantFieldArray, StructArrayBuilder};
337 use crate::{VariantArray, VariantArrayBuilder, json_to_variant};
338 use arrow::array::{
339 Array, ArrayRef, AsArray, BinaryArray, BinaryViewArray, BooleanArray, Date32Array,
340 Date64Array, Decimal32Array, Decimal64Array, Decimal128Array, Decimal256Array,
341 Float32Array, Float64Array, Int8Array, Int16Array, Int32Array, Int64Array,
342 LargeBinaryArray, LargeListArray, LargeListViewArray, LargeStringArray, ListArray,
343 ListViewArray, NullBuilder, StringArray, StringViewArray, StructArray,
344 Time32MillisecondArray, Time32SecondArray, Time64MicrosecondArray, Time64NanosecondArray,
345 };
346 use arrow::buffer::{NullBuffer, OffsetBuffer, ScalarBuffer};
347 use arrow::compute::CastOptions;
348 use arrow::datatypes::DataType::{Int16, Int32, Int64};
349 use arrow::datatypes::i256;
350 use arrow::util::display::FormatOptions;
351 use arrow_schema::DataType::{Boolean, Float32, Float64, Int8};
352 use arrow_schema::{DataType, Field, FieldRef, Fields, IntervalUnit, TimeUnit};
353 use chrono::DateTime;
354 use parquet_variant::{
355 EMPTY_VARIANT_METADATA_BYTES, Variant, VariantBuilder, VariantDecimal4, VariantDecimal8,
356 VariantDecimal16, VariantDecimalType, VariantPath,
357 };
358
359 fn single_variant_get_test(input_json: &str, path: VariantPath, expected_json: &str) {
360 let input_array_ref: ArrayRef = Arc::new(StringArray::from(vec![Some(input_json)]));
362 let input_variant_array_ref = ArrayRef::from(json_to_variant(&input_array_ref).unwrap());
363
364 let result =
365 variant_get(&input_variant_array_ref, GetOptions::new_with_path(path)).unwrap();
366
367 let expected_array_ref: ArrayRef = Arc::new(StringArray::from(vec![Some(expected_json)]));
369 let expected_variant_array = json_to_variant(&expected_array_ref).unwrap();
370
371 let result_array = VariantArray::try_new(&result).unwrap();
372 assert_eq!(
373 result_array.len(),
374 1,
375 "Expected result array to have length 1"
376 );
377 assert!(
378 result_array.nulls().is_none(),
379 "Expected no nulls in result array"
380 );
381 let result_variant = result_array.value(0);
382 let expected_variant = expected_variant_array.value(0);
383 assert_eq!(
384 result_variant, expected_variant,
385 "Result variant does not match expected variant"
386 );
387 }
388
389 #[test]
390 fn get_primitive_variant_field() {
391 single_variant_get_test(
392 r#"{"some_field": 1234}"#,
393 VariantPath::try_from("some_field").unwrap(),
394 "1234",
395 );
396 }
397
398 #[test]
399 fn get_primitive_variant_list_index() {
400 single_variant_get_test("[1234, 5678]", VariantPath::from(0), "1234");
401 }
402
403 #[test]
404 fn get_primitive_variant_inside_object_of_object() {
405 single_variant_get_test(
406 r#"{"top_level_field": {"inner_field": 1234}}"#,
407 VariantPath::try_from("top_level_field")
408 .unwrap()
409 .join("inner_field"),
410 "1234",
411 );
412 }
413
414 #[test]
415 fn get_primitive_variant_inside_list_of_object() {
416 single_variant_get_test(
417 r#"[{"some_field": 1234}]"#,
418 VariantPath::from(0).join("some_field"),
419 "1234",
420 );
421 }
422
423 #[test]
424 fn get_primitive_variant_inside_object_of_list() {
425 single_variant_get_test(
426 r#"{"some_field": [1234]}"#,
427 VariantPath::try_from("some_field").unwrap().join(0),
428 "1234",
429 );
430 }
431
432 #[test]
433 fn get_complex_variant() {
434 single_variant_get_test(
435 r#"{"top_level_field": {"inner_field": 1234}}"#,
436 VariantPath::try_from("top_level_field").unwrap(),
437 r#"{"inner_field": 1234}"#,
438 );
439 }
440
441 macro_rules! numeric_partially_shredded_test {
443 ($primitive_type:ty, $data_fn:ident) => {
444 let array = $data_fn();
445 let options = GetOptions::new();
446 let result = variant_get(&array, options).unwrap();
447
448 let result = VariantArray::try_new(&result).unwrap();
450 assert_eq!(result.len(), 4);
451
452 assert_eq!(
454 result.value(0),
455 Variant::from(<$primitive_type>::try_from(34u8).unwrap())
456 );
457 assert!(!result.is_valid(1));
458 assert_eq!(result.value(2), Variant::from("n/a"));
459 assert_eq!(
460 result.value(3),
461 Variant::from(<$primitive_type>::try_from(100u8).unwrap())
462 );
463 };
464 }
465
466 macro_rules! partially_shredded_variant_array_gen {
467 ($func_name:ident, $typed_value_array_gen: expr) => {
468 fn $func_name() -> ArrayRef {
469 let (metadata, string_value) = {
470 let mut builder = parquet_variant::VariantBuilder::new();
471 builder.append_value("n/a");
472 builder.finish()
473 };
474
475 let nulls = NullBuffer::from(vec![
476 true, false, true, true, ]);
481
482 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 4));
484
485 let values = BinaryViewArray::from(vec![
488 None, Some(b"" as &[u8]), Some(&string_value), None, ]);
493
494 let typed_value = $typed_value_array_gen();
495
496 let struct_array = StructArrayBuilder::new()
497 .with_field("metadata", Arc::new(metadata), false)
498 .with_field("typed_value", Arc::new(typed_value), true)
499 .with_field("value", Arc::new(values), true)
500 .with_nulls(nulls)
501 .build();
502 ArrayRef::from(
503 VariantArray::try_new(&struct_array).expect("should create variant array"),
504 )
505 }
506 };
507 }
508
509 #[test]
510 fn get_variant_partially_shredded_int8_as_variant() {
511 numeric_partially_shredded_test!(i8, partially_shredded_int8_variant_array);
512 }
513
514 #[test]
515 fn get_variant_partially_shredded_int16_as_variant() {
516 numeric_partially_shredded_test!(i16, partially_shredded_int16_variant_array);
517 }
518
519 #[test]
520 fn get_variant_partially_shredded_int32_as_variant() {
521 numeric_partially_shredded_test!(i32, partially_shredded_int32_variant_array);
522 }
523
524 #[test]
525 fn get_variant_partially_shredded_int64_as_variant() {
526 numeric_partially_shredded_test!(i64, partially_shredded_int64_variant_array);
527 }
528
529 #[test]
530 fn get_variant_partially_shredded_float32_as_variant() {
531 numeric_partially_shredded_test!(f32, partially_shredded_float32_variant_array);
532 }
533
534 #[test]
535 fn get_variant_partially_shredded_float64_as_variant() {
536 numeric_partially_shredded_test!(f64, partially_shredded_float64_variant_array);
537 }
538
539 #[test]
540 fn get_variant_partially_shredded_bool_as_variant() {
541 let array = partially_shredded_bool_variant_array();
542 let options = GetOptions::new();
543 let result = variant_get(&array, options).unwrap();
544
545 let result = VariantArray::try_new(&result).unwrap();
547 assert_eq!(result.len(), 4);
548
549 assert_eq!(result.value(0), Variant::from(true));
551 assert!(!result.is_valid(1));
552 assert_eq!(result.value(2), Variant::from("n/a"));
553 assert_eq!(result.value(3), Variant::from(false));
554 }
555
556 #[test]
557 fn get_variant_partially_shredded_utf8_as_variant() {
558 let array = partially_shredded_utf8_variant_array();
559 let options = GetOptions::new();
560 let result = variant_get(&array, options).unwrap();
561
562 let result = VariantArray::try_new(&result).unwrap();
564 assert_eq!(result.len(), 4);
565
566 assert_eq!(result.value(0), Variant::from("hello"));
568 assert!(!result.is_valid(1));
569 assert_eq!(result.value(2), Variant::from("n/a"));
570 assert_eq!(result.value(3), Variant::from("world"));
571 }
572
573 partially_shredded_variant_array_gen!(partially_shredded_binary_view_variant_array, || {
574 BinaryViewArray::from(vec![
575 Some(&[1u8, 2u8, 3u8][..]), None, None, Some(&[4u8, 5u8, 6u8][..]), ])
580 });
581
582 #[test]
583 fn get_variant_partially_shredded_date32_as_variant() {
584 let array = partially_shredded_date32_variant_array();
585 let options = GetOptions::new();
586 let result = variant_get(&array, options).unwrap();
587
588 let result = VariantArray::try_new(&result).unwrap();
590 assert_eq!(result.len(), 4);
591
592 use chrono::NaiveDate;
594 let date1 = NaiveDate::from_ymd_opt(2025, 9, 17).unwrap();
595 let date2 = NaiveDate::from_ymd_opt(2025, 9, 9).unwrap();
596 assert_eq!(result.value(0), Variant::from(date1));
597 assert!(!result.is_valid(1));
598 assert_eq!(result.value(2), Variant::from("n/a"));
599 assert_eq!(result.value(3), Variant::from(date2));
600 }
601
602 #[test]
603 fn get_variant_partially_shredded_binary_view_as_variant() {
604 let array = partially_shredded_binary_view_variant_array();
605 let options = GetOptions::new();
606 let result = variant_get(&array, options).unwrap();
607
608 let result = VariantArray::try_new(&result).unwrap();
610 assert_eq!(result.len(), 4);
611
612 assert_eq!(result.value(0), Variant::from(&[1u8, 2u8, 3u8][..]));
614 assert!(!result.is_valid(1));
615 assert_eq!(result.value(2), Variant::from("n/a"));
616 assert_eq!(result.value(3), Variant::from(&[4u8, 5u8, 6u8][..]));
617 }
618
619 #[test]
621 fn get_variant_shredded_int32_as_int32_safe_cast() {
622 let array = partially_shredded_int32_variant_array();
624 let field = Field::new("typed_value", DataType::Int32, true);
626 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
627 let result = variant_get(&array, options).unwrap();
628 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
629 Some(34),
630 None,
631 None, Some(100),
633 ]));
634 assert_eq!(&result, &expected)
635 }
636
637 #[test]
639 fn get_variant_shredded_int32_as_int32_unsafe_cast() {
640 let array = partially_shredded_int32_variant_array();
642 let field = Field::new("typed_value", DataType::Int32, true);
643 let cast_options = CastOptions {
644 safe: false, ..Default::default()
646 };
647 let options = GetOptions::new()
648 .with_as_type(Some(FieldRef::from(field)))
649 .with_cast_options(cast_options);
650
651 let err = variant_get(&array, options).unwrap_err();
652 assert_eq!(
654 err.to_string(),
655 "Cast error: Failed to extract primitive of type Int32 from variant ShortString(ShortString(\"n/a\")) at path VariantPath([])"
656 );
657 }
658
659 macro_rules! numeric_perfectly_shredded_test {
661 ($primitive_type:ty, $data_fn:ident) => {
662 let array = $data_fn();
663 let options = GetOptions::new();
664 let result = variant_get(&array, options).unwrap();
665
666 let result = VariantArray::try_new(&result).unwrap();
668 assert_eq!(result.len(), 3);
669
670 assert_eq!(
672 result.value(0),
673 Variant::from(<$primitive_type>::try_from(1u8).unwrap())
674 );
675 assert_eq!(
676 result.value(1),
677 Variant::from(<$primitive_type>::try_from(2u8).unwrap())
678 );
679 assert_eq!(
680 result.value(2),
681 Variant::from(<$primitive_type>::try_from(3u8).unwrap())
682 );
683 };
684 }
685
686 #[test]
687 fn get_variant_perfectly_shredded_int8_as_variant() {
688 numeric_perfectly_shredded_test!(i8, perfectly_shredded_int8_variant_array);
689 }
690
691 #[test]
692 fn get_variant_perfectly_shredded_int16_as_variant() {
693 numeric_perfectly_shredded_test!(i16, perfectly_shredded_int16_variant_array);
694 }
695
696 #[test]
697 fn get_variant_perfectly_shredded_int32_as_variant() {
698 numeric_perfectly_shredded_test!(i32, perfectly_shredded_int32_variant_array);
699 }
700
701 #[test]
702 fn get_variant_perfectly_shredded_int64_as_variant() {
703 numeric_perfectly_shredded_test!(i64, perfectly_shredded_int64_variant_array);
704 }
705
706 #[test]
707 fn get_variant_perfectly_shredded_float32_as_variant() {
708 numeric_perfectly_shredded_test!(f32, perfectly_shredded_float32_variant_array);
709 }
710
711 #[test]
712 fn get_variant_perfectly_shredded_float64_as_variant() {
713 numeric_perfectly_shredded_test!(f64, perfectly_shredded_float64_variant_array);
714 }
715
716 #[test]
718 fn get_variant_all_null_as_variant() {
719 let array = all_null_variant_array();
720 let options = GetOptions::new();
721 let result = variant_get(&array, options).unwrap();
722
723 let result = VariantArray::try_new(&result).unwrap();
725 assert_eq!(result.len(), 3);
726
727 assert!(!result.is_valid(0));
729 assert!(!result.is_valid(1));
730 assert!(!result.is_valid(2));
731 }
732
733 #[test]
735 fn get_variant_all_null_as_int32() {
736 let array = all_null_variant_array();
737 let field = Field::new("typed_value", DataType::Int32, true);
739 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
740 let result = variant_get(&array, options).unwrap();
741
742 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
743 Option::<i32>::None,
744 Option::<i32>::None,
745 Option::<i32>::None,
746 ]));
747 assert_eq!(&result, &expected)
748 }
749
750 macro_rules! perfectly_shredded_to_arrow_primitive_test {
751 ($name:ident, $primitive_type:expr, $perfectly_shredded_array_gen_fun:ident, $expected_array:expr) => {
752 #[test]
753 fn $name() {
754 let array = $perfectly_shredded_array_gen_fun();
755 let field = Field::new("typed_value", $primitive_type, true);
756 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
757 let result = variant_get(&array, options).unwrap();
758 let expected_array: ArrayRef = Arc::new($expected_array);
759 assert_eq!(&result, &expected_array);
760 }
761 };
762 }
763
764 perfectly_shredded_to_arrow_primitive_test!(
765 get_variant_perfectly_shredded_int18_as_int8,
766 Int8,
767 perfectly_shredded_int8_variant_array,
768 Int8Array::from(vec![Some(1), Some(2), Some(3)])
769 );
770
771 perfectly_shredded_to_arrow_primitive_test!(
772 get_variant_perfectly_shredded_int16_as_int16,
773 Int16,
774 perfectly_shredded_int16_variant_array,
775 Int16Array::from(vec![Some(1), Some(2), Some(3)])
776 );
777
778 perfectly_shredded_to_arrow_primitive_test!(
779 get_variant_perfectly_shredded_int32_as_int32,
780 Int32,
781 perfectly_shredded_int32_variant_array,
782 Int32Array::from(vec![Some(1), Some(2), Some(3)])
783 );
784
785 perfectly_shredded_to_arrow_primitive_test!(
786 get_variant_perfectly_shredded_int64_as_int64,
787 Int64,
788 perfectly_shredded_int64_variant_array,
789 Int64Array::from(vec![Some(1), Some(2), Some(3)])
790 );
791
792 perfectly_shredded_to_arrow_primitive_test!(
793 get_variant_perfectly_shredded_float32_as_float32,
794 Float32,
795 perfectly_shredded_float32_variant_array,
796 Float32Array::from(vec![Some(1.0), Some(2.0), Some(3.0)])
797 );
798
799 perfectly_shredded_to_arrow_primitive_test!(
800 get_variant_perfectly_shredded_float64_as_float64,
801 Float64,
802 perfectly_shredded_float64_variant_array,
803 Float64Array::from(vec![Some(1.0), Some(2.0), Some(3.0)])
804 );
805
806 perfectly_shredded_to_arrow_primitive_test!(
807 get_variant_perfectly_shredded_boolean_as_boolean,
808 Boolean,
809 perfectly_shredded_bool_variant_array,
810 BooleanArray::from(vec![Some(true), Some(false), Some(true)])
811 );
812
813 perfectly_shredded_to_arrow_primitive_test!(
814 get_variant_perfectly_shredded_utf8_as_utf8,
815 DataType::Utf8,
816 perfectly_shredded_utf8_variant_array,
817 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
818 );
819
820 perfectly_shredded_to_arrow_primitive_test!(
821 get_variant_perfectly_shredded_large_utf8_as_utf8,
822 DataType::Utf8,
823 perfectly_shredded_large_utf8_variant_array,
824 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
825 );
826
827 perfectly_shredded_to_arrow_primitive_test!(
828 get_variant_perfectly_shredded_utf8_view_as_utf8,
829 DataType::Utf8,
830 perfectly_shredded_utf8_view_variant_array,
831 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
832 );
833
834 macro_rules! perfectly_shredded_variant_array_fn {
835 ($func:ident, $typed_value_gen:expr) => {
836 fn $func() -> ArrayRef {
837 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(
840 EMPTY_VARIANT_METADATA_BYTES,
841 3,
842 ));
843 let typed_value = $typed_value_gen();
844
845 let struct_array = StructArrayBuilder::new()
846 .with_field("metadata", Arc::new(metadata), false)
847 .with_field("typed_value", Arc::new(typed_value), true)
848 .build();
849
850 VariantArray::try_new(&struct_array)
851 .expect("should create variant array")
852 .into()
853 }
854 };
855 }
856
857 perfectly_shredded_variant_array_fn!(perfectly_shredded_utf8_variant_array, || {
858 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
859 });
860
861 perfectly_shredded_variant_array_fn!(perfectly_shredded_large_utf8_variant_array, || {
862 LargeStringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
863 });
864
865 perfectly_shredded_variant_array_fn!(perfectly_shredded_utf8_view_variant_array, || {
866 StringViewArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
867 });
868
869 perfectly_shredded_variant_array_fn!(perfectly_shredded_bool_variant_array, || {
870 BooleanArray::from(vec![Some(true), Some(false), Some(true)])
871 });
872
873 macro_rules! numeric_perfectly_shredded_variant_array_fn {
885 ($func:ident, $array_type:ident, $primitive_type:ty) => {
886 perfectly_shredded_variant_array_fn!($func, || {
887 $array_type::from(vec![
888 Some(<$primitive_type>::try_from(1u8).unwrap()),
889 Some(<$primitive_type>::try_from(2u8).unwrap()),
890 Some(<$primitive_type>::try_from(3u8).unwrap()),
891 ])
892 });
893 };
894 }
895
896 numeric_perfectly_shredded_variant_array_fn!(
897 perfectly_shredded_int8_variant_array,
898 Int8Array,
899 i8
900 );
901 numeric_perfectly_shredded_variant_array_fn!(
902 perfectly_shredded_int16_variant_array,
903 Int16Array,
904 i16
905 );
906 numeric_perfectly_shredded_variant_array_fn!(
907 perfectly_shredded_int32_variant_array,
908 Int32Array,
909 i32
910 );
911 numeric_perfectly_shredded_variant_array_fn!(
912 perfectly_shredded_int64_variant_array,
913 Int64Array,
914 i64
915 );
916 numeric_perfectly_shredded_variant_array_fn!(
917 perfectly_shredded_float32_variant_array,
918 Float32Array,
919 f32
920 );
921 numeric_perfectly_shredded_variant_array_fn!(
922 perfectly_shredded_float64_variant_array,
923 Float64Array,
924 f64
925 );
926
927 perfectly_shredded_variant_array_fn!(
928 perfectly_shredded_timestamp_micro_ntz_variant_array,
929 || {
930 arrow::array::TimestampMicrosecondArray::from(vec![
931 Some(-456000),
932 Some(1758602096000001),
933 Some(1758602096000002),
934 ])
935 }
936 );
937
938 perfectly_shredded_to_arrow_primitive_test!(
939 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_micro_ntz,
940 DataType::Timestamp(TimeUnit::Microsecond, None),
941 perfectly_shredded_timestamp_micro_ntz_variant_array,
942 arrow::array::TimestampMicrosecondArray::from(vec![
943 Some(-456000),
944 Some(1758602096000001),
945 Some(1758602096000002),
946 ])
947 );
948
949 perfectly_shredded_to_arrow_primitive_test!(
951 get_variant_perfectly_shredded_timestamp_micro_ntz_as_nano_ntz,
952 DataType::Timestamp(TimeUnit::Nanosecond, None),
953 perfectly_shredded_timestamp_micro_ntz_variant_array,
954 arrow::array::TimestampNanosecondArray::from(vec![
955 Some(-456000000),
956 Some(1758602096000001000),
957 Some(1758602096000002000)
958 ])
959 );
960
961 perfectly_shredded_variant_array_fn!(perfectly_shredded_timestamp_micro_variant_array, || {
962 arrow::array::TimestampMicrosecondArray::from(vec![
963 Some(-456000),
964 Some(1758602096000001),
965 Some(1758602096000002),
966 ])
967 .with_timezone("+00:00")
968 });
969
970 perfectly_shredded_to_arrow_primitive_test!(
971 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_micro,
972 DataType::Timestamp(TimeUnit::Microsecond, Some(Arc::from("+00:00"))),
973 perfectly_shredded_timestamp_micro_variant_array,
974 arrow::array::TimestampMicrosecondArray::from(vec![
975 Some(-456000),
976 Some(1758602096000001),
977 Some(1758602096000002),
978 ])
979 .with_timezone("+00:00")
980 );
981
982 perfectly_shredded_to_arrow_primitive_test!(
984 get_variant_perfectly_shredded_timestamp_micro_as_nano,
985 DataType::Timestamp(TimeUnit::Nanosecond, Some(Arc::from("+00:00"))),
986 perfectly_shredded_timestamp_micro_variant_array,
987 arrow::array::TimestampNanosecondArray::from(vec![
988 Some(-456000000),
989 Some(1758602096000001000),
990 Some(1758602096000002000)
991 ])
992 .with_timezone("+00:00")
993 );
994
995 perfectly_shredded_variant_array_fn!(
996 perfectly_shredded_timestamp_nano_ntz_variant_array,
997 || {
998 arrow::array::TimestampNanosecondArray::from(vec![
999 Some(-4999999561),
1000 Some(1758602096000000001),
1001 Some(1758602096000000002),
1002 ])
1003 }
1004 );
1005
1006 perfectly_shredded_variant_array_fn!(
1007 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1008 || {
1009 arrow::array::TimestampMicrosecondArray::from(vec![
1010 Some(1234), Some(1234000), Some(1234000000), ])
1014 .with_timezone("+00:00")
1015 }
1016 );
1017
1018 perfectly_shredded_to_arrow_primitive_test!(
1021 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_second,
1022 DataType::Timestamp(TimeUnit::Second, Some(Arc::from("+00:00"))),
1023 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1024 arrow::array::TimestampSecondArray::from(vec![
1025 None,
1026 None, Some(1234)
1028 ])
1029 .with_timezone("+00:00")
1030 );
1031
1032 perfectly_shredded_to_arrow_primitive_test!(
1033 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_milli,
1034 DataType::Timestamp(TimeUnit::Millisecond, Some(Arc::from("+00:00"))),
1035 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1036 arrow::array::TimestampMillisecondArray::from(vec![
1037 None, Some(1234),
1039 Some(1234000)
1040 ])
1041 .with_timezone("+00:00")
1042 );
1043
1044 perfectly_shredded_variant_array_fn!(
1045 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1046 || {
1047 arrow::array::TimestampMicrosecondArray::from(vec![
1048 Some(1234), Some(1234000), Some(1234000000), ])
1052 }
1053 );
1054
1055 perfectly_shredded_to_arrow_primitive_test!(
1058 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_second,
1059 DataType::Timestamp(TimeUnit::Second, None),
1060 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1061 arrow::array::TimestampSecondArray::from(vec![
1062 None,
1063 None, Some(1234)
1065 ])
1066 );
1067
1068 perfectly_shredded_to_arrow_primitive_test!(
1069 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_milli,
1070 DataType::Timestamp(TimeUnit::Millisecond, None),
1071 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1072 arrow::array::TimestampMillisecondArray::from(vec![
1073 None, Some(1234),
1075 Some(1234000)
1076 ])
1077 );
1078
1079 perfectly_shredded_variant_array_fn!(
1080 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1081 || {
1082 arrow::array::TimestampNanosecondArray::from(vec![
1083 Some(1234000), Some(1234000000), Some(1234000000000), ])
1087 .with_timezone("+00:00")
1088 }
1089 );
1090
1091 perfectly_shredded_to_arrow_primitive_test!(
1094 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_second,
1095 DataType::Timestamp(TimeUnit::Second, Some(Arc::from("+00:00"))),
1096 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1097 arrow::array::TimestampSecondArray::from(vec![
1098 None,
1099 None, Some(1234)
1101 ])
1102 .with_timezone("+00:00")
1103 );
1104
1105 perfectly_shredded_to_arrow_primitive_test!(
1106 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_milli,
1107 DataType::Timestamp(TimeUnit::Millisecond, Some(Arc::from("+00:00"))),
1108 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1109 arrow::array::TimestampMillisecondArray::from(vec![
1110 None, Some(1234),
1112 Some(1234000)
1113 ])
1114 .with_timezone("+00:00")
1115 );
1116
1117 perfectly_shredded_variant_array_fn!(
1118 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1119 || {
1120 arrow::array::TimestampNanosecondArray::from(vec![
1121 Some(1234000), Some(1234000000), Some(1234000000000), ])
1125 }
1126 );
1127
1128 perfectly_shredded_to_arrow_primitive_test!(
1131 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_second,
1132 DataType::Timestamp(TimeUnit::Second, None),
1133 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1134 arrow::array::TimestampSecondArray::from(vec![
1135 None,
1136 None, Some(1234)
1138 ])
1139 );
1140
1141 perfectly_shredded_to_arrow_primitive_test!(
1142 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_milli,
1143 DataType::Timestamp(TimeUnit::Millisecond, None),
1144 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1145 arrow::array::TimestampMillisecondArray::from(vec![
1146 None, Some(1234),
1148 Some(1234000)
1149 ])
1150 );
1151
1152 perfectly_shredded_to_arrow_primitive_test!(
1153 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_nano_ntz,
1154 DataType::Timestamp(TimeUnit::Nanosecond, None),
1155 perfectly_shredded_timestamp_nano_ntz_variant_array,
1156 arrow::array::TimestampNanosecondArray::from(vec![
1157 Some(-4999999561),
1158 Some(1758602096000000001),
1159 Some(1758602096000000002),
1160 ])
1161 );
1162
1163 perfectly_shredded_variant_array_fn!(perfectly_shredded_timestamp_nano_variant_array, || {
1164 arrow::array::TimestampNanosecondArray::from(vec![
1165 Some(-4999999561),
1166 Some(1758602096000000001),
1167 Some(1758602096000000002),
1168 ])
1169 .with_timezone("+00:00")
1170 });
1171
1172 perfectly_shredded_to_arrow_primitive_test!(
1173 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_nano,
1174 DataType::Timestamp(TimeUnit::Nanosecond, Some(Arc::from("+00:00"))),
1175 perfectly_shredded_timestamp_nano_variant_array,
1176 arrow::array::TimestampNanosecondArray::from(vec![
1177 Some(-4999999561),
1178 Some(1758602096000000001),
1179 Some(1758602096000000002),
1180 ])
1181 .with_timezone("+00:00")
1182 );
1183
1184 perfectly_shredded_variant_array_fn!(perfectly_shredded_date_variant_array, || {
1185 Date32Array::from(vec![Some(-12345), Some(17586), Some(20000)])
1186 });
1187
1188 perfectly_shredded_to_arrow_primitive_test!(
1189 get_variant_perfectly_shredded_date_as_date,
1190 DataType::Date32,
1191 perfectly_shredded_date_variant_array,
1192 Date32Array::from(vec![Some(-12345), Some(17586), Some(20000)])
1193 );
1194
1195 perfectly_shredded_to_arrow_primitive_test!(
1196 get_variant_perfectly_shredded_date_as_date64,
1197 DataType::Date64,
1198 perfectly_shredded_date_variant_array,
1199 Date64Array::from(vec![
1200 Some(-1066608000000),
1201 Some(1519430400000),
1202 Some(1728000000000)
1203 ])
1204 );
1205
1206 perfectly_shredded_variant_array_fn!(perfectly_shredded_time_variant_array, || {
1207 Time64MicrosecondArray::from(vec![Some(12345000), Some(87654000), Some(135792000)])
1208 });
1209
1210 perfectly_shredded_to_arrow_primitive_test!(
1211 get_variant_perfectly_shredded_time_as_time,
1212 DataType::Time64(TimeUnit::Microsecond),
1213 perfectly_shredded_time_variant_array,
1214 Time64MicrosecondArray::from(vec![Some(12345000), Some(87654000), Some(135792000)])
1215 );
1216
1217 perfectly_shredded_to_arrow_primitive_test!(
1218 get_variant_perfectly_shredded_time_as_time64_nano,
1219 DataType::Time64(TimeUnit::Nanosecond),
1220 perfectly_shredded_time_variant_array,
1221 Time64NanosecondArray::from(vec![
1222 Some(12345000000),
1223 Some(87654000000),
1224 Some(135792000000)
1225 ])
1226 );
1227
1228 perfectly_shredded_variant_array_fn!(perfectly_shredded_time_variant_array_for_time32, || {
1229 Time64MicrosecondArray::from(vec![
1230 Some(1234), Some(7654000), Some(35792000000), ])
1234 });
1235
1236 perfectly_shredded_to_arrow_primitive_test!(
1237 get_variant_perfectly_shredded_time_as_time32_second,
1238 DataType::Time32(TimeUnit::Second),
1239 perfectly_shredded_time_variant_array_for_time32,
1240 Time32SecondArray::from(vec![
1241 None,
1242 None, Some(35792)
1244 ])
1245 );
1246
1247 perfectly_shredded_to_arrow_primitive_test!(
1248 get_variant_perfectly_shredded_time_as_time32_milli,
1249 DataType::Time32(TimeUnit::Millisecond),
1250 perfectly_shredded_time_variant_array_for_time32,
1251 Time32MillisecondArray::from(vec![
1252 None, Some(7654),
1254 Some(35792000)
1255 ])
1256 );
1257
1258 perfectly_shredded_variant_array_fn!(perfectly_shredded_null_variant_array, || {
1259 let mut builder = NullBuilder::new();
1260 builder.append_nulls(3);
1261 builder.finish()
1262 });
1263
1264 perfectly_shredded_to_arrow_primitive_test!(
1265 get_variant_perfectly_shredded_null_as_null,
1266 DataType::Null,
1267 perfectly_shredded_null_variant_array,
1268 arrow::array::NullArray::new(3)
1269 );
1270
1271 perfectly_shredded_variant_array_fn!(perfectly_shredded_null_variant_array_with_int, || {
1272 Int32Array::from(vec![Some(32), Some(64), Some(48)])
1273 });
1274
1275 perfectly_shredded_to_arrow_primitive_test!(
1277 get_variant_perfectly_shredded_null_with_type_missmatch_in_safe_mode,
1278 DataType::Null,
1279 perfectly_shredded_null_variant_array_with_int,
1280 arrow::array::NullArray::new(3)
1281 );
1282
1283 #[test]
1285 fn get_variant_perfectly_shredded_null_as_null_with_type_missmatch_in_strict_mode() {
1286 let array = perfectly_shredded_null_variant_array_with_int();
1287 let field = Field::new("typed_value", DataType::Null, true);
1288 let options = GetOptions::new()
1289 .with_as_type(Some(FieldRef::from(field)))
1290 .with_cast_options(CastOptions {
1291 safe: false,
1292 format_options: FormatOptions::default(),
1293 });
1294
1295 let result = variant_get(&array, options);
1296
1297 assert!(result.is_err());
1298 let error_msg = format!("{}", result.unwrap_err());
1299 assert!(
1300 error_msg
1301 .contains("Cast error: Failed to extract primitive of type Null from variant Int32(32) at path VariantPath([])"),
1302 "Expected=[Cast error: Failed to extract primitive of type Null from variant Int32(32) at path VariantPath([])],\
1303 Got error message=[{}]",
1304 error_msg
1305 );
1306 }
1307
1308 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal4_variant_array, || {
1309 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
1310 .with_precision_and_scale(5, 2)
1311 .unwrap()
1312 });
1313
1314 perfectly_shredded_to_arrow_primitive_test!(
1315 get_variant_perfectly_shredded_decimal4_as_decimal4,
1316 DataType::Decimal32(5, 2),
1317 perfectly_shredded_decimal4_variant_array,
1318 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
1319 .with_precision_and_scale(5, 2)
1320 .unwrap()
1321 );
1322
1323 perfectly_shredded_variant_array_fn!(
1324 perfectly_shredded_decimal8_variant_array_cast2decimal32,
1325 || {
1326 Decimal64Array::from(vec![Some(123456), Some(145678), Some(-123456)])
1327 .with_precision_and_scale(6, 1)
1328 .unwrap()
1329 }
1330 );
1331
1332 perfectly_shredded_to_arrow_primitive_test!(
1336 get_variant_perfectly_shredded_decimal8_through_decimal32_as_decimal8,
1337 DataType::Decimal64(6, 1),
1338 perfectly_shredded_decimal8_variant_array_cast2decimal32,
1339 Decimal64Array::from(vec![Some(123456), Some(145678), Some(-123456)])
1340 .with_precision_and_scale(6, 1)
1341 .unwrap()
1342 );
1343
1344 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal8_variant_array, || {
1347 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1348 .with_precision_and_scale(10, 1)
1349 .unwrap()
1350 });
1351
1352 perfectly_shredded_to_arrow_primitive_test!(
1353 get_variant_perfectly_shredded_decimal8_as_decimal8,
1354 DataType::Decimal64(10, 1),
1355 perfectly_shredded_decimal8_variant_array,
1356 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1357 .with_precision_and_scale(10, 1)
1358 .unwrap()
1359 );
1360
1361 perfectly_shredded_variant_array_fn!(
1364 perfectly_shredded_decimal16_within_decimal4_variant_array,
1365 || {
1366 Decimal128Array::from(vec![
1367 Some(i128::from(1234589)),
1368 Some(i128::from(2344444)),
1369 Some(i128::from(-1234789)),
1370 ])
1371 .with_precision_and_scale(7, 3)
1372 .unwrap()
1373 }
1374 );
1375
1376 perfectly_shredded_to_arrow_primitive_test!(
1379 get_variant_perfectly_shredded_decimal16_within_decimal4_as_decimal16,
1380 DataType::Decimal128(7, 3),
1381 perfectly_shredded_decimal16_within_decimal4_variant_array,
1382 Decimal128Array::from(vec![
1383 Some(i128::from(1234589)),
1384 Some(i128::from(2344444)),
1385 Some(i128::from(-1234789)),
1386 ])
1387 .with_precision_and_scale(7, 3)
1388 .unwrap()
1389 );
1390
1391 perfectly_shredded_variant_array_fn!(
1392 perfectly_shredded_decimal16_within_decimal8_variant_array,
1393 || {
1394 Decimal128Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1395 .with_precision_and_scale(10, 1)
1396 .unwrap()
1397 }
1398 );
1399
1400 perfectly_shredded_to_arrow_primitive_test!(
1403 get_variant_perfectly_shredded_decimal16_within8_as_decimal16,
1404 DataType::Decimal128(10, 1),
1405 perfectly_shredded_decimal16_within_decimal8_variant_array,
1406 Decimal128Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1407 .with_precision_and_scale(10, 1)
1408 .unwrap()
1409 );
1410
1411 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal16_variant_array, || {
1412 Decimal128Array::from(vec![
1413 Some(i128::from_str("12345678901234567899").unwrap()),
1414 Some(i128::from_str("23445677483748324300").unwrap()),
1415 Some(i128::from_str("-12345678901234567899").unwrap()),
1416 ])
1417 .with_precision_and_scale(20, 3)
1418 .unwrap()
1419 });
1420
1421 perfectly_shredded_to_arrow_primitive_test!(
1424 get_variant_perfectly_shredded_decimal16_as_decimal16,
1425 DataType::Decimal128(20, 3),
1426 perfectly_shredded_decimal16_variant_array,
1427 Decimal128Array::from(vec![
1428 Some(i128::from_str("12345678901234567899").unwrap()),
1429 Some(i128::from_str("23445677483748324300").unwrap()),
1430 Some(i128::from_str("-12345678901234567899").unwrap())
1431 ])
1432 .with_precision_and_scale(20, 3)
1433 .unwrap()
1434 );
1435
1436 macro_rules! assert_variant_get_as_variant_array_with_default_option {
1437 ($variant_array: expr, $array_expected: expr) => {{
1438 let options = GetOptions::new();
1439 let array = $variant_array;
1440 let result = variant_get(&array, options).unwrap();
1441
1442 let result = VariantArray::try_new(&result).unwrap();
1444
1445 assert_eq!(result.len(), $array_expected.len());
1446
1447 for (idx, item) in $array_expected.into_iter().enumerate() {
1448 match item {
1449 Some(item) => assert_eq!(result.value(idx), item),
1450 None => assert!(result.is_null(idx)),
1451 }
1452 }
1453 }};
1454 }
1455
1456 partially_shredded_variant_array_gen!(
1457 partially_shredded_timestamp_micro_ntz_variant_array,
1458 || {
1459 arrow::array::TimestampMicrosecondArray::from(vec![
1460 Some(-456000),
1461 None,
1462 None,
1463 Some(1758602096000000),
1464 ])
1465 }
1466 );
1467
1468 #[test]
1469 fn get_variant_partial_shredded_timestamp_micro_ntz_as_variant() {
1470 let array = partially_shredded_timestamp_micro_ntz_variant_array();
1471 assert_variant_get_as_variant_array_with_default_option!(
1472 array,
1473 vec![
1474 Some(Variant::from(
1475 DateTime::from_timestamp_micros(-456000i64)
1476 .unwrap()
1477 .naive_utc(),
1478 )),
1479 None,
1480 Some(Variant::from("n/a")),
1481 Some(Variant::from(
1482 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
1483 .unwrap()
1484 .naive_utc(),
1485 )),
1486 ]
1487 )
1488 }
1489
1490 partially_shredded_variant_array_gen!(partially_shredded_timestamp_micro_variant_array, || {
1491 arrow::array::TimestampMicrosecondArray::from(vec![
1492 Some(-456000),
1493 None,
1494 None,
1495 Some(1758602096000000),
1496 ])
1497 .with_timezone("+00:00")
1498 });
1499
1500 #[test]
1501 fn get_variant_partial_shredded_timestamp_micro_as_variant() {
1502 let array = partially_shredded_timestamp_micro_variant_array();
1503 assert_variant_get_as_variant_array_with_default_option!(
1504 array,
1505 vec![
1506 Some(Variant::from(
1507 DateTime::from_timestamp_micros(-456000i64)
1508 .unwrap()
1509 .to_utc(),
1510 )),
1511 None,
1512 Some(Variant::from("n/a")),
1513 Some(Variant::from(
1514 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
1515 .unwrap()
1516 .to_utc(),
1517 )),
1518 ]
1519 )
1520 }
1521
1522 partially_shredded_variant_array_gen!(
1523 partially_shredded_timestamp_nano_ntz_variant_array,
1524 || {
1525 arrow::array::TimestampNanosecondArray::from(vec![
1526 Some(-4999999561),
1527 None,
1528 None,
1529 Some(1758602096000000000),
1530 ])
1531 }
1532 );
1533
1534 #[test]
1535 fn get_variant_partial_shredded_timestamp_nano_ntz_as_variant() {
1536 let array = partially_shredded_timestamp_nano_ntz_variant_array();
1537
1538 assert_variant_get_as_variant_array_with_default_option!(
1539 array,
1540 vec![
1541 Some(Variant::from(
1542 DateTime::from_timestamp(-5, 439).unwrap().naive_utc()
1543 )),
1544 None,
1545 Some(Variant::from("n/a")),
1546 Some(Variant::from(
1547 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
1548 .unwrap()
1549 .naive_utc()
1550 )),
1551 ]
1552 )
1553 }
1554
1555 partially_shredded_variant_array_gen!(partially_shredded_timestamp_nano_variant_array, || {
1556 arrow::array::TimestampNanosecondArray::from(vec![
1557 Some(-4999999561),
1558 None,
1559 None,
1560 Some(1758602096000000000),
1561 ])
1562 .with_timezone("+00:00")
1563 });
1564
1565 #[test]
1566 fn get_variant_partial_shredded_timestamp_nano_as_variant() {
1567 let array = partially_shredded_timestamp_nano_variant_array();
1568
1569 assert_variant_get_as_variant_array_with_default_option!(
1570 array,
1571 vec![
1572 Some(Variant::from(
1573 DateTime::from_timestamp(-5, 439).unwrap().to_utc()
1574 )),
1575 None,
1576 Some(Variant::from("n/a")),
1577 Some(Variant::from(
1578 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
1579 .unwrap()
1580 .to_utc()
1581 )),
1582 ]
1583 )
1584 }
1585
1586 perfectly_shredded_variant_array_fn!(perfectly_shredded_binary_variant_array, || {
1587 BinaryArray::from(vec![
1588 Some(b"Apache" as &[u8]),
1589 Some(b"Arrow-rs" as &[u8]),
1590 Some(b"Parquet-variant" as &[u8]),
1591 ])
1592 });
1593
1594 perfectly_shredded_to_arrow_primitive_test!(
1595 get_variant_perfectly_shredded_binary_as_binary,
1596 DataType::Binary,
1597 perfectly_shredded_binary_variant_array,
1598 BinaryArray::from(vec![
1599 Some(b"Apache" as &[u8]),
1600 Some(b"Arrow-rs" as &[u8]),
1601 Some(b"Parquet-variant" as &[u8]),
1602 ])
1603 );
1604
1605 perfectly_shredded_variant_array_fn!(perfectly_shredded_large_binary_variant_array, || {
1606 LargeBinaryArray::from(vec![
1607 Some(b"Apache" as &[u8]),
1608 Some(b"Arrow-rs" as &[u8]),
1609 Some(b"Parquet-variant" as &[u8]),
1610 ])
1611 });
1612
1613 perfectly_shredded_to_arrow_primitive_test!(
1614 get_variant_perfectly_shredded_large_binary_as_large_binary,
1615 DataType::LargeBinary,
1616 perfectly_shredded_large_binary_variant_array,
1617 LargeBinaryArray::from(vec![
1618 Some(b"Apache" as &[u8]),
1619 Some(b"Arrow-rs" as &[u8]),
1620 Some(b"Parquet-variant" as &[u8]),
1621 ])
1622 );
1623
1624 perfectly_shredded_variant_array_fn!(perfectly_shredded_binary_view_variant_array, || {
1625 BinaryViewArray::from(vec![
1626 Some(b"Apache" as &[u8]),
1627 Some(b"Arrow-rs" as &[u8]),
1628 Some(b"Parquet-variant" as &[u8]),
1629 ])
1630 });
1631
1632 perfectly_shredded_to_arrow_primitive_test!(
1633 get_variant_perfectly_shredded_binary_view_as_binary_view,
1634 DataType::BinaryView,
1635 perfectly_shredded_binary_view_variant_array,
1636 BinaryViewArray::from(vec![
1637 Some(b"Apache" as &[u8]),
1638 Some(b"Arrow-rs" as &[u8]),
1639 Some(b"Parquet-variant" as &[u8]),
1640 ])
1641 );
1642
1643 macro_rules! numeric_partially_shredded_variant_array_fn {
1667 ($func:ident, $array_type:ident, $primitive_type:ty) => {
1668 partially_shredded_variant_array_gen!($func, || $array_type::from(vec![
1669 Some(<$primitive_type>::try_from(34u8).unwrap()), None, None, Some(<$primitive_type>::try_from(100u8).unwrap()), ]));
1674 };
1675 }
1676
1677 macro_rules! partially_shredded_variant_array_gen {
1678 ($func:ident, $typed_array_gen: expr) => {
1679 fn $func() -> ArrayRef {
1680 let (metadata, string_value) = {
1683 let mut builder = parquet_variant::VariantBuilder::new();
1684 builder.append_value("n/a");
1685 builder.finish()
1686 };
1687
1688 let nulls = NullBuffer::from(vec![
1689 true, false, true, true, ]);
1694
1695 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 4));
1697
1698 let values = BinaryViewArray::from(vec![
1701 None, Some(b"" as &[u8]), Some(&string_value), None, ]);
1706
1707 let typed_value = $typed_array_gen();
1708
1709 let struct_array = StructArrayBuilder::new()
1710 .with_field("metadata", Arc::new(metadata), false)
1711 .with_field("typed_value", Arc::new(typed_value), true)
1712 .with_field("value", Arc::new(values), true)
1713 .with_nulls(nulls)
1714 .build();
1715
1716 ArrayRef::from(
1717 VariantArray::try_new(&struct_array).expect("should create variant array"),
1718 )
1719 }
1720 };
1721 }
1722
1723 numeric_partially_shredded_variant_array_fn!(
1724 partially_shredded_int8_variant_array,
1725 Int8Array,
1726 i8
1727 );
1728 numeric_partially_shredded_variant_array_fn!(
1729 partially_shredded_int16_variant_array,
1730 Int16Array,
1731 i16
1732 );
1733 numeric_partially_shredded_variant_array_fn!(
1734 partially_shredded_int32_variant_array,
1735 Int32Array,
1736 i32
1737 );
1738 numeric_partially_shredded_variant_array_fn!(
1739 partially_shredded_int64_variant_array,
1740 Int64Array,
1741 i64
1742 );
1743 numeric_partially_shredded_variant_array_fn!(
1744 partially_shredded_float32_variant_array,
1745 Float32Array,
1746 f32
1747 );
1748 numeric_partially_shredded_variant_array_fn!(
1749 partially_shredded_float64_variant_array,
1750 Float64Array,
1751 f64
1752 );
1753
1754 partially_shredded_variant_array_gen!(partially_shredded_bool_variant_array, || {
1755 arrow::array::BooleanArray::from(vec![
1756 Some(true), None, None, Some(false), ])
1761 });
1762
1763 partially_shredded_variant_array_gen!(partially_shredded_utf8_variant_array, || {
1764 StringArray::from(vec![
1765 Some("hello"), None, None, Some("world"), ])
1770 });
1771
1772 partially_shredded_variant_array_gen!(partially_shredded_date32_variant_array, || {
1773 Date32Array::from(vec![
1774 Some(20348), None, None, Some(20340), ])
1779 });
1780
1781 fn all_null_variant_array() -> ArrayRef {
1798 let nulls = NullBuffer::from(vec![
1799 false, false, false, ]);
1803
1804 let metadata =
1806 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 3));
1807
1808 let struct_array = StructArrayBuilder::new()
1809 .with_field("metadata", Arc::new(metadata), false)
1810 .with_nulls(nulls)
1811 .build();
1812
1813 Arc::new(struct_array)
1814 }
1815 #[test]
1819 fn test_shredded_object_field_access() {
1820 let array = shredded_object_with_x_field_variant_array();
1821
1822 let options = GetOptions::new_with_path(VariantPath::try_from("x").unwrap());
1824 let result = variant_get(&array, options).unwrap();
1825
1826 let result_variant = VariantArray::try_new(&result).unwrap();
1827 assert_eq!(result_variant.len(), 2);
1828
1829 assert_eq!(result_variant.value(0), Variant::Int32(1));
1831 assert_eq!(result_variant.value(1), Variant::Int32(42));
1833 }
1834
1835 #[test]
1837 fn test_shredded_object_field_as_int32() {
1838 let array = shredded_object_with_x_field_variant_array();
1839
1840 let field = Field::new("x", DataType::Int32, false);
1842 let options = GetOptions::new_with_path(VariantPath::try_from("x").unwrap())
1843 .with_as_type(Some(FieldRef::from(field)));
1844 let result = variant_get(&array, options).unwrap();
1845
1846 let expected: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(42)]));
1848 assert_eq!(&result, &expected);
1849 }
1850
1851 fn shredded_object_with_x_field_variant_array() -> ArrayRef {
1863 let (metadata, y_field_value) = {
1865 let mut builder = parquet_variant::VariantBuilder::new();
1866 let mut obj = builder.new_object();
1867 obj.insert("x", Variant::Int32(42));
1868 obj.insert("y", Variant::from("foo"));
1869 obj.finish();
1870 builder.finish()
1871 };
1872
1873 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
1875
1876 let empty_object_value = {
1881 let mut builder = parquet_variant::VariantBuilder::new();
1882 let obj = builder.new_object();
1883 obj.finish();
1884 let (_, value) = builder.finish();
1885 value
1886 };
1887
1888 let value_array = BinaryViewArray::from(vec![
1889 Some(y_field_value.as_slice()), Some(empty_object_value.as_slice()), ]);
1892
1893 let x_field_typed_value = Int32Array::from(vec![Some(1), Some(42)]);
1896
1897 let x_field_struct = StructArrayBuilder::new()
1899 .with_field("typed_value", Arc::new(x_field_typed_value), true)
1900 .build();
1901
1902 let x_field_shredded = ShreddedVariantFieldArray::try_new(&x_field_struct)
1904 .expect("should create ShreddedVariantFieldArray");
1905
1906 let typed_value_fields = Fields::from(vec![Field::new(
1908 "x",
1909 x_field_shredded.data_type().clone(),
1910 true,
1911 )]);
1912 let typed_value_struct = StructArray::try_new(
1913 typed_value_fields,
1914 vec![ArrayRef::from(x_field_shredded)],
1915 None, )
1917 .unwrap();
1918
1919 let main_struct = StructArrayBuilder::new()
1921 .with_field("metadata", Arc::new(metadata_array), false)
1922 .with_field("value", Arc::new(value_array), true)
1923 .with_field("typed_value", Arc::new(typed_value_struct), true)
1924 .build();
1925
1926 Arc::new(main_struct)
1927 }
1928
1929 #[test]
1931 fn test_simple_nested_path_support() {
1932 println!("Testing path parsing:");
1934
1935 let path_x = VariantPath::try_from("x").unwrap();
1936 let elements_x: Vec<_> = path_x.iter().collect();
1937 println!(" 'x' -> {} elements: {:?}", elements_x.len(), elements_x);
1938
1939 let path_ax = VariantPath::try_from("a.x").unwrap();
1940 let elements_ax: Vec<_> = path_ax.iter().collect();
1941 println!(
1942 " 'a.x' -> {} elements: {:?}",
1943 elements_ax.len(),
1944 elements_ax
1945 );
1946
1947 let path_ax_alt = VariantPath::try_from("$.a.x").unwrap();
1948 let elements_ax_alt: Vec<_> = path_ax_alt.iter().collect();
1949 println!(
1950 " '$.a.x' -> {} elements: {:?}",
1951 elements_ax_alt.len(),
1952 elements_ax_alt
1953 );
1954
1955 let path_nested = VariantPath::try_from("a").unwrap().join("x");
1956 let elements_nested: Vec<_> = path_nested.iter().collect();
1957 println!(
1958 " VariantPath::try_from('a').unwrap().join('x') -> {} elements: {:?}",
1959 elements_nested.len(),
1960 elements_nested
1961 );
1962
1963 let array = shredded_object_with_x_field_variant_array();
1965
1966 let real_nested_path = VariantPath::try_from("a").unwrap().join("x");
1968 let options = GetOptions::new_with_path(real_nested_path);
1969 let result = variant_get(&array, options);
1970
1971 match result {
1972 Ok(_) => {
1973 println!("Nested path 'a.x' works unexpectedly!");
1974 }
1975 Err(e) => {
1976 println!("Nested path 'a.x' error: {}", e);
1977 if e.to_string().contains("Not yet implemented")
1978 || e.to_string().contains("NotYetImplemented")
1979 {
1980 println!("This is expected - nested paths are not implemented");
1981 return;
1982 }
1983 println!("This shows nested paths need implementation");
1985 }
1986 }
1987 }
1988
1989 #[test]
1993 fn test_depth_0_int32_conversion() {
1994 println!("=== Testing Depth 0: Direct field access ===");
1995
1996 let unshredded_array = create_depth_0_test_data();
1998
1999 let field = Field::new("result", DataType::Int32, true);
2000 let path = VariantPath::try_from("x").unwrap();
2001 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2002 let result = variant_get(&unshredded_array, options).unwrap();
2003
2004 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2005 Some(42), None, None, ]));
2009 assert_eq!(&result, &expected);
2010 println!("Depth 0 (unshredded) passed");
2011
2012 let shredded_array = create_depth_0_shredded_test_data_simple();
2014
2015 let field = Field::new("result", DataType::Int32, true);
2016 let path = VariantPath::try_from("x").unwrap();
2017 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2018 let result = variant_get(&shredded_array, options).unwrap();
2019
2020 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2021 Some(42), None, ]));
2024 assert_eq!(&result, &expected);
2025 println!("Depth 0 (shredded) passed");
2026 }
2027
2028 #[test]
2031 fn test_depth_1_int32_conversion() {
2032 println!("=== Testing Depth 1: Single nested field access ===");
2033
2034 let unshredded_array = create_nested_path_test_data();
2036
2037 let field = Field::new("result", DataType::Int32, true);
2038 let path = VariantPath::try_from("a.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2040 let result = variant_get(&unshredded_array, options).unwrap();
2041
2042 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2043 Some(55), None, ]));
2046 assert_eq!(&result, &expected);
2047 println!("Depth 1 (unshredded) passed");
2048
2049 let shredded_array = create_depth_1_shredded_test_data_working();
2051
2052 let field = Field::new("result", DataType::Int32, true);
2053 let path = VariantPath::try_from("a.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2055 let result = variant_get(&shredded_array, options).unwrap();
2056
2057 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2058 Some(55), None, ]));
2061 assert_eq!(&result, &expected);
2062 println!("Depth 1 (shredded) passed");
2063 }
2064
2065 #[test]
2068 fn test_depth_2_int32_conversion() {
2069 println!("=== Testing Depth 2: Double nested field access ===");
2070
2071 let unshredded_array = create_depth_2_test_data();
2073
2074 let field = Field::new("result", DataType::Int32, true);
2075 let path = VariantPath::try_from("a.b.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2077 let result = variant_get(&unshredded_array, options).unwrap();
2078
2079 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2080 Some(100), None, None, ]));
2084 assert_eq!(&result, &expected);
2085 println!("Depth 2 (unshredded) passed");
2086
2087 let shredded_array = create_depth_2_shredded_test_data_working();
2089
2090 let field = Field::new("result", DataType::Int32, true);
2091 let path = VariantPath::try_from("a.b.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2093 let result = variant_get(&shredded_array, options).unwrap();
2094
2095 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2096 Some(100), None, None, ]));
2100 assert_eq!(&result, &expected);
2101 println!("Depth 2 (shredded) passed");
2102 }
2103
2104 #[test]
2109 fn test_current_nested_path_functionality() {
2110 let array = shredded_object_with_x_field_variant_array();
2111
2112 let single_path = VariantPath::try_from("x").unwrap();
2114 let field = Field::new("result", DataType::Int32, true);
2115 let options =
2116 GetOptions::new_with_path(single_path).with_as_type(Some(FieldRef::from(field)));
2117 let result = variant_get(&array, options).unwrap();
2118
2119 println!("Single path 'x' works - result: {:?}", result);
2120
2121 let nested_path = VariantPath::try_from("a").unwrap().join("x");
2123 let field = Field::new("result", DataType::Int32, true);
2124 let options =
2125 GetOptions::new_with_path(nested_path).with_as_type(Some(FieldRef::from(field)));
2126 let result = variant_get(&array, options).unwrap();
2127
2128 println!("Nested path 'a.x' result: {:?}", result);
2129 }
2130
2131 fn create_depth_0_test_data() -> ArrayRef {
2134 let mut builder = crate::VariantArrayBuilder::new(3);
2135
2136 {
2138 let json_str = r#"{"x": 42}"#;
2139 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2140 if let Ok(variant_array) = json_to_variant(&string_array) {
2141 builder.append_variant(variant_array.value(0));
2142 } else {
2143 builder.append_null();
2144 }
2145 }
2146
2147 {
2149 let json_str = r#"{"x": "foo"}"#;
2150 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2151 if let Ok(variant_array) = json_to_variant(&string_array) {
2152 builder.append_variant(variant_array.value(0));
2153 } else {
2154 builder.append_null();
2155 }
2156 }
2157
2158 {
2160 let json_str = r#"{"y": 10}"#;
2161 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2162 if let Ok(variant_array) = json_to_variant(&string_array) {
2163 builder.append_variant(variant_array.value(0));
2164 } else {
2165 builder.append_null();
2166 }
2167 }
2168
2169 ArrayRef::from(builder.build())
2170 }
2171
2172 fn create_nested_path_test_data() -> ArrayRef {
2175 let mut builder = crate::VariantArrayBuilder::new(2);
2176
2177 {
2179 let json_str = r#"{"a": {"x": 55}, "b": 42}"#;
2180 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2181 if let Ok(variant_array) = json_to_variant(&string_array) {
2182 builder.append_variant(variant_array.value(0));
2183 } else {
2184 builder.append_null();
2185 }
2186 }
2187
2188 {
2190 let json_str = r#"{"a": {"x": "foo"}, "b": 42}"#;
2191 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2192 if let Ok(variant_array) = json_to_variant(&string_array) {
2193 builder.append_variant(variant_array.value(0));
2194 } else {
2195 builder.append_null();
2196 }
2197 }
2198
2199 ArrayRef::from(builder.build())
2200 }
2201
2202 fn create_depth_2_test_data() -> ArrayRef {
2205 let mut builder = crate::VariantArrayBuilder::new(3);
2206
2207 {
2209 let json_str = r#"{"a": {"b": {"x": 100}}}"#;
2210 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2211 if let Ok(variant_array) = json_to_variant(&string_array) {
2212 builder.append_variant(variant_array.value(0));
2213 } else {
2214 builder.append_null();
2215 }
2216 }
2217
2218 {
2220 let json_str = r#"{"a": {"b": {"x": "bar"}}}"#;
2221 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2222 if let Ok(variant_array) = json_to_variant(&string_array) {
2223 builder.append_variant(variant_array.value(0));
2224 } else {
2225 builder.append_null();
2226 }
2227 }
2228
2229 {
2231 let json_str = r#"{"a": {"b": {"y": 200}}}"#;
2232 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2233 if let Ok(variant_array) = json_to_variant(&string_array) {
2234 builder.append_variant(variant_array.value(0));
2235 } else {
2236 builder.append_null();
2237 }
2238 }
2239
2240 ArrayRef::from(builder.build())
2241 }
2242
2243 fn create_depth_0_shredded_test_data_simple() -> ArrayRef {
2246 let (metadata, string_x_value) = {
2248 let mut builder = parquet_variant::VariantBuilder::new();
2249 let mut obj = builder.new_object();
2250 obj.insert("x", Variant::from("foo"));
2251 obj.finish();
2252 builder.finish()
2253 };
2254
2255 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2257
2258 let empty_object_value = {
2262 let mut builder = parquet_variant::VariantBuilder::new();
2263 let obj = builder.new_object();
2264 obj.finish();
2265 let (_, value) = builder.finish();
2266 value
2267 };
2268
2269 let value_array = BinaryViewArray::from(vec![
2270 Some(empty_object_value.as_slice()), Some(string_x_value.as_slice()), ]);
2273
2274 let x_field_typed_value = Int32Array::from(vec![Some(42), None]);
2276
2277 let x_field_struct = StructArrayBuilder::new()
2279 .with_field("typed_value", Arc::new(x_field_typed_value), true)
2280 .build();
2281
2282 let x_field_shredded = ShreddedVariantFieldArray::try_new(&x_field_struct)
2283 .expect("should create ShreddedVariantFieldArray");
2284
2285 let typed_value_fields = Fields::from(vec![Field::new(
2287 "x",
2288 x_field_shredded.data_type().clone(),
2289 true,
2290 )]);
2291 let typed_value_struct = StructArray::try_new(
2292 typed_value_fields,
2293 vec![ArrayRef::from(x_field_shredded)],
2294 None,
2295 )
2296 .unwrap();
2297
2298 let struct_array = StructArrayBuilder::new()
2300 .with_field("metadata", Arc::new(metadata_array), false)
2301 .with_field("value", Arc::new(value_array), true)
2302 .with_field("typed_value", Arc::new(typed_value_struct), true)
2303 .build();
2304
2305 Arc::new(struct_array)
2306 }
2307
2308 fn create_depth_1_shredded_test_data_working() -> ArrayRef {
2313 let (metadata, _) = {
2315 let mut builder = parquet_variant::VariantBuilder::new();
2317 let mut obj = builder.new_object();
2318
2319 let mut a_obj = obj.new_object("a");
2321 a_obj.insert("x", Variant::Int32(55));
2322 a_obj.finish();
2323
2324 obj.insert("b", Variant::Int32(42));
2325 obj.finish();
2326 builder.finish()
2327 };
2328
2329 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2330
2331 let empty_object_value = {
2334 let mut builder = parquet_variant::VariantBuilder::new();
2335 let obj = builder.new_object();
2336 obj.finish();
2337 let (_, value) = builder.finish();
2338 value
2339 };
2340
2341 let row1_fallback = {
2344 let mut builder = parquet_variant::VariantBuilder::new();
2345 let mut obj = builder.new_object();
2346 obj.insert("fallback", Variant::from("data"));
2347 obj.finish();
2348 let (_, value) = builder.finish();
2349 value
2350 };
2351
2352 let value_array = BinaryViewArray::from(vec![
2353 Some(empty_object_value.as_slice()), Some(row1_fallback.as_slice()), ]);
2356
2357 let x_typed_value = Int32Array::from(vec![Some(55), None]);
2360 let x_field_struct = StructArrayBuilder::new()
2361 .with_field("typed_value", Arc::new(x_typed_value), true)
2362 .build();
2363 let x_field_shredded = ShreddedVariantFieldArray::try_new(&x_field_struct)
2364 .expect("should create ShreddedVariantFieldArray for x");
2365
2366 let a_value_data = {
2371 let mut builder = parquet_variant::VariantBuilder::new();
2372 let obj = builder.new_object();
2373 obj.finish();
2374 let (_, value) = builder.finish();
2375 value
2376 };
2377 let a_value_array = BinaryViewArray::from(vec![
2378 None, Some(a_value_data.as_slice()), ]);
2381
2382 let a_inner_fields = Fields::from(vec![Field::new(
2383 "x",
2384 x_field_shredded.data_type().clone(),
2385 true,
2386 )]);
2387 let a_inner_struct = StructArrayBuilder::new()
2388 .with_field(
2389 "typed_value",
2390 Arc::new(
2391 StructArray::try_new(
2392 a_inner_fields,
2393 vec![ArrayRef::from(x_field_shredded)],
2394 None,
2395 )
2396 .unwrap(),
2397 ),
2398 true,
2399 )
2400 .with_field("value", Arc::new(a_value_array), true)
2401 .build();
2402 let a_field_shredded = ShreddedVariantFieldArray::try_new(&a_inner_struct)
2403 .expect("should create ShreddedVariantFieldArray for a");
2404
2405 let typed_value_fields = Fields::from(vec![Field::new(
2407 "a",
2408 a_field_shredded.data_type().clone(),
2409 true,
2410 )]);
2411 let typed_value_struct = StructArray::try_new(
2412 typed_value_fields,
2413 vec![ArrayRef::from(a_field_shredded)],
2414 None,
2415 )
2416 .unwrap();
2417
2418 let struct_array = StructArrayBuilder::new()
2420 .with_field("metadata", Arc::new(metadata_array), false)
2421 .with_field("value", Arc::new(value_array), true)
2422 .with_field("typed_value", Arc::new(typed_value_struct), true)
2423 .build();
2424
2425 Arc::new(struct_array)
2426 }
2427
2428 fn create_depth_2_shredded_test_data_working() -> ArrayRef {
2434 let (metadata, _) = {
2436 let mut builder = parquet_variant::VariantBuilder::new();
2438 let mut obj = builder.new_object();
2439
2440 let mut a_obj = obj.new_object("a");
2442 let mut b_obj = a_obj.new_object("b");
2443 b_obj.insert("x", Variant::Int32(100));
2444 b_obj.finish();
2445 a_obj.finish();
2446
2447 obj.finish();
2448 builder.finish()
2449 };
2450
2451 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 3));
2452
2453 let empty_object_value = {
2455 let mut builder = parquet_variant::VariantBuilder::new();
2456 let obj = builder.new_object();
2457 obj.finish();
2458 let (_, value) = builder.finish();
2459 value
2460 };
2461
2462 let value_array = BinaryViewArray::from(vec![
2464 Some(empty_object_value.as_slice()), Some(empty_object_value.as_slice()), Some(empty_object_value.as_slice()), ]);
2468
2469 let x_typed_value = Int32Array::from(vec![Some(100), None, None]);
2473 let x_field_struct = StructArrayBuilder::new()
2474 .with_field("typed_value", Arc::new(x_typed_value), true)
2475 .build();
2476 let x_field_shredded = ShreddedVariantFieldArray::try_new(&x_field_struct)
2477 .expect("should create ShreddedVariantFieldArray for x");
2478
2479 let b_value_data = {
2481 let mut builder = parquet_variant::VariantBuilder::new();
2482 let obj = builder.new_object();
2483 obj.finish();
2484 let (_, value) = builder.finish();
2485 value
2486 };
2487 let b_value_array = BinaryViewArray::from(vec![
2488 None, Some(b_value_data.as_slice()), Some(b_value_data.as_slice()), ]);
2492
2493 let b_inner_fields = Fields::from(vec![Field::new(
2494 "x",
2495 x_field_shredded.data_type().clone(),
2496 true,
2497 )]);
2498 let b_inner_struct = StructArrayBuilder::new()
2499 .with_field(
2500 "typed_value",
2501 Arc::new(
2502 StructArray::try_new(
2503 b_inner_fields,
2504 vec![ArrayRef::from(x_field_shredded)],
2505 None,
2506 )
2507 .unwrap(),
2508 ),
2509 true,
2510 )
2511 .with_field("value", Arc::new(b_value_array), true)
2512 .build();
2513 let b_field_shredded = ShreddedVariantFieldArray::try_new(&b_inner_struct)
2514 .expect("should create ShreddedVariantFieldArray for b");
2515
2516 let a_value_data = {
2518 let mut builder = parquet_variant::VariantBuilder::new();
2519 let obj = builder.new_object();
2520 obj.finish();
2521 let (_, value) = builder.finish();
2522 value
2523 };
2524 let a_value_array = BinaryViewArray::from(vec![
2525 None, Some(a_value_data.as_slice()), Some(a_value_data.as_slice()), ]);
2529
2530 let a_inner_fields = Fields::from(vec![Field::new(
2531 "b",
2532 b_field_shredded.data_type().clone(),
2533 true,
2534 )]);
2535 let a_inner_struct = StructArrayBuilder::new()
2536 .with_field(
2537 "typed_value",
2538 Arc::new(
2539 StructArray::try_new(
2540 a_inner_fields,
2541 vec![ArrayRef::from(b_field_shredded)],
2542 None,
2543 )
2544 .unwrap(),
2545 ),
2546 true,
2547 )
2548 .with_field("value", Arc::new(a_value_array), true)
2549 .build();
2550 let a_field_shredded = ShreddedVariantFieldArray::try_new(&a_inner_struct)
2551 .expect("should create ShreddedVariantFieldArray for a");
2552
2553 let typed_value_fields = Fields::from(vec![Field::new(
2555 "a",
2556 a_field_shredded.data_type().clone(),
2557 true,
2558 )]);
2559 let typed_value_struct = StructArray::try_new(
2560 typed_value_fields,
2561 vec![ArrayRef::from(a_field_shredded)],
2562 None,
2563 )
2564 .unwrap();
2565
2566 let struct_array = StructArrayBuilder::new()
2568 .with_field("metadata", Arc::new(metadata_array), false)
2569 .with_field("value", Arc::new(value_array), true)
2570 .with_field("typed_value", Arc::new(typed_value_struct), true)
2571 .build();
2572
2573 Arc::new(struct_array)
2574 }
2575
2576 #[test]
2577 fn test_strict_cast_options_downcast_failure() {
2578 use arrow::compute::CastOptions;
2579 use arrow::datatypes::{DataType, Field};
2580 use arrow::error::ArrowError;
2581 use parquet_variant::VariantPath;
2582 use std::sync::Arc;
2583
2584 let variant_array = perfectly_shredded_int32_variant_array();
2586
2587 let safe_options = GetOptions {
2589 path: VariantPath::try_from("nonexistent_field").unwrap(),
2590 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
2591 cast_options: CastOptions::default(), };
2593
2594 let variant_array_ref: Arc<dyn Array> = variant_array.clone();
2595 let result = variant_get(&variant_array_ref, safe_options);
2596 assert!(result.is_ok());
2598 let result_array = result.unwrap();
2599 assert_eq!(result_array.len(), 3);
2600 assert!(result_array.is_null(0));
2601 assert!(result_array.is_null(1));
2602 assert!(result_array.is_null(2));
2603
2604 let strict_options = GetOptions {
2606 path: VariantPath::try_from("nonexistent_field").unwrap(),
2607 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
2608 cast_options: CastOptions {
2609 safe: false,
2610 ..Default::default()
2611 },
2612 };
2613
2614 let result = variant_get(&variant_array_ref, strict_options);
2615 assert!(result.is_err());
2617 let error = result.unwrap_err();
2618 assert!(matches!(error, ArrowError::CastError(_)));
2619 assert!(
2620 error
2621 .to_string()
2622 .contains("Cannot access field 'nonexistent_field' on non-struct type")
2623 );
2624 }
2625
2626 #[test]
2627 fn test_error_message_boolean_type_display() {
2628 let mut builder = VariantArrayBuilder::new(1);
2629 builder.append_variant(Variant::Int32(123));
2630 let variant_array: ArrayRef = ArrayRef::from(builder.build());
2631
2632 let options = GetOptions {
2634 path: VariantPath::default(),
2635 as_type: Some(Arc::new(Field::new("result", DataType::Boolean, true))),
2636 cast_options: CastOptions {
2637 safe: false,
2638 ..Default::default()
2639 },
2640 };
2641
2642 let err = variant_get(&variant_array, options).unwrap_err();
2643 let msg = err.to_string();
2644 assert!(msg.contains("Failed to extract primitive of type Boolean"));
2645 }
2646
2647 #[test]
2648 fn test_error_message_numeric_type_display() {
2649 let mut builder = VariantArrayBuilder::new(1);
2650 builder.append_variant(Variant::BooleanTrue);
2651 let variant_array: ArrayRef = ArrayRef::from(builder.build());
2652
2653 let options = GetOptions {
2655 path: VariantPath::default(),
2656 as_type: Some(Arc::new(Field::new("result", DataType::Float32, true))),
2657 cast_options: CastOptions {
2658 safe: false,
2659 ..Default::default()
2660 },
2661 };
2662
2663 let err = variant_get(&variant_array, options).unwrap_err();
2664 let msg = err.to_string();
2665 assert!(msg.contains("Failed to extract primitive of type Float32"));
2666 }
2667
2668 #[test]
2669 fn test_error_message_temporal_type_display() {
2670 let mut builder = VariantArrayBuilder::new(1);
2671 builder.append_variant(Variant::BooleanFalse);
2672 let variant_array: ArrayRef = ArrayRef::from(builder.build());
2673
2674 let options = GetOptions {
2676 path: VariantPath::default(),
2677 as_type: Some(Arc::new(Field::new(
2678 "result",
2679 DataType::Timestamp(TimeUnit::Nanosecond, None),
2680 true,
2681 ))),
2682 cast_options: CastOptions {
2683 safe: false,
2684 ..Default::default()
2685 },
2686 };
2687
2688 let err = variant_get(&variant_array, options).unwrap_err();
2689 let msg = err.to_string();
2690 assert!(msg.contains("Failed to extract primitive of type Timestamp(ns)"));
2691 }
2692
2693 #[test]
2694 fn test_null_buffer_union_for_shredded_paths() {
2695 use arrow::compute::CastOptions;
2696 use arrow::datatypes::{DataType, Field};
2697 use parquet_variant::VariantPath;
2698 use std::sync::Arc;
2699
2700 let variant_array = create_depth_1_shredded_test_data_working();
2709
2710 let options = GetOptions {
2715 path: VariantPath::try_from("a.x").unwrap(),
2716 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
2717 cast_options: CastOptions::default(),
2718 };
2719
2720 let variant_array_ref: Arc<dyn Array> = variant_array.clone();
2721 let result = variant_get(&variant_array_ref, options).unwrap();
2722
2723 assert_eq!(result.len(), variant_array.len());
2725
2726 assert!(!result.is_null(0), "Row 0 should have valid Int32 data");
2730 assert!(
2731 result.is_null(1),
2732 "Row 1 should be null due to type casting failure"
2733 );
2734
2735 let int32_result = result.as_any().downcast_ref::<Int32Array>().unwrap();
2737 assert_eq!(int32_result.value(0), 55); }
2739
2740 #[test]
2741 fn test_struct_null_mask_union_from_children() {
2742 use arrow::compute::CastOptions;
2743 use arrow::datatypes::{DataType, Field, Fields};
2744 use parquet_variant::VariantPath;
2745 use std::sync::Arc;
2746
2747 use arrow::array::StringArray;
2748
2749 let json_strings = vec![
2754 r#"{"a": 42, "b": "hello"}"#, r#"{"a": "world", "b": 100}"#, r#"{"a": 55, "b": 77}"#, ];
2758
2759 let string_array: Arc<dyn arrow::array::Array> = Arc::new(StringArray::from(json_strings));
2760 let variant_array = json_to_variant(&string_array).unwrap();
2761
2762 let struct_fields = Fields::from(vec![
2765 Field::new("a", DataType::Int32, true),
2766 Field::new("b", DataType::Int32, true),
2767 ]);
2768 let struct_type = DataType::Struct(struct_fields);
2769
2770 let options = GetOptions {
2771 path: VariantPath::default(), as_type: Some(Arc::new(Field::new("result", struct_type, true))),
2773 cast_options: CastOptions::default(),
2774 };
2775
2776 let variant_array_ref = ArrayRef::from(variant_array);
2777 let result = variant_get(&variant_array_ref, options).unwrap();
2778
2779 let struct_result = result.as_struct();
2781 assert_eq!(struct_result.len(), 3);
2782
2783 let field_a = struct_result
2785 .column(0)
2786 .as_any()
2787 .downcast_ref::<Int32Array>()
2788 .unwrap();
2789 let field_b = struct_result
2790 .column(1)
2791 .as_any()
2792 .downcast_ref::<Int32Array>()
2793 .unwrap();
2794
2795 assert!(!field_a.is_null(0));
2798 assert_eq!(field_a.value(0), 42);
2799 assert!(field_b.is_null(0)); assert!(field_a.is_null(1)); assert!(!field_b.is_null(1));
2804 assert_eq!(field_b.value(1), 100);
2805
2806 assert!(!field_a.is_null(2));
2808 assert_eq!(field_a.value(2), 55);
2809 assert!(!field_b.is_null(2));
2810 assert_eq!(field_b.value(2), 77);
2811
2812 assert!(!struct_result.is_null(0)); assert!(!struct_result.is_null(1)); assert!(!struct_result.is_null(2)); }
2819
2820 #[test]
2821 fn test_field_nullability_preservation() {
2822 use arrow::compute::CastOptions;
2823 use arrow::datatypes::{DataType, Field};
2824 use parquet_variant::VariantPath;
2825 use std::sync::Arc;
2826
2827 use arrow::array::StringArray;
2828
2829 let json_strings = vec![
2832 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}"#, ];
2842
2843 let string_array: Arc<dyn arrow::array::Array> = Arc::new(StringArray::from(json_strings));
2844 let variant_array = json_to_variant(&string_array).unwrap();
2845
2846 let nullable_field = Arc::new(Field::new("result", DataType::Int32, true));
2848 let options_nullable = GetOptions {
2849 path: VariantPath::try_from("x").unwrap(),
2850 as_type: Some(nullable_field.clone()),
2851 cast_options: CastOptions::default(),
2852 };
2853
2854 let variant_array_ref = ArrayRef::from(variant_array);
2855 let result_nullable = variant_get(&variant_array_ref, options_nullable).unwrap();
2856
2857 let int32_result = result_nullable
2859 .as_any()
2860 .downcast_ref::<Int32Array>()
2861 .unwrap();
2862 assert_eq!(int32_result.len(), 9);
2863
2864 assert!(!int32_result.is_null(0));
2866 assert_eq!(int32_result.value(0), 42);
2867
2868 assert!(int32_result.is_null(1));
2870
2871 assert!(int32_result.is_null(2));
2873
2874 assert!(int32_result.is_null(3));
2876
2877 assert!(int32_result.is_null(4));
2879
2880 assert!(!int32_result.is_null(5));
2883 assert_eq!(int32_result.value(5), 127);
2884
2885 assert!(!int32_result.is_null(6));
2888 assert_eq!(int32_result.value(6), 32767);
2889
2890 assert!(!int32_result.is_null(7));
2893 assert_eq!(int32_result.value(7), 2147483647);
2894
2895 assert!(int32_result.is_null(8));
2898
2899 let non_nullable_field = Arc::new(Field::new("result", DataType::Int32, false));
2901 let options_non_nullable = GetOptions {
2902 path: VariantPath::try_from("x").unwrap(),
2903 as_type: Some(non_nullable_field.clone()),
2904 cast_options: CastOptions::default(), };
2906
2907 let variant_array_2 = json_to_variant(&string_array).unwrap();
2909 let variant_array_ref_2 = ArrayRef::from(variant_array_2);
2910 let result_non_nullable = variant_get(&variant_array_ref_2, options_non_nullable).unwrap();
2911 let int32_result_2 = result_non_nullable
2912 .as_any()
2913 .downcast_ref::<Int32Array>()
2914 .unwrap();
2915
2916 assert_eq!(int32_result_2.len(), 9);
2918
2919 assert!(!int32_result_2.is_null(0));
2921 assert_eq!(int32_result_2.value(0), 42);
2922
2923 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);
2933 assert!(!int32_result_2.is_null(6)); assert_eq!(int32_result_2.value(6), 32767);
2935 assert!(!int32_result_2.is_null(7)); assert_eq!(int32_result_2.value(7), 2147483647);
2937
2938 assert!(int32_result_2.is_null(8)); }
2941
2942 #[test]
2943 fn test_struct_extraction_subset_superset_schema_perfectly_shredded() {
2944 let variant_array = create_comprehensive_shredded_variant();
2946
2947 let struct_fields = Fields::from(vec![
2949 Field::new("a", DataType::Int32, true),
2950 Field::new("b", DataType::Int32, true),
2951 Field::new("d", DataType::Int32, true),
2952 ]);
2953 let struct_type = DataType::Struct(struct_fields);
2954
2955 let options = GetOptions {
2956 path: VariantPath::default(),
2957 as_type: Some(Arc::new(Field::new("result", struct_type, true))),
2958 cast_options: CastOptions::default(),
2959 };
2960
2961 let result = variant_get(&variant_array, options).unwrap();
2962
2963 let struct_result = result.as_any().downcast_ref::<StructArray>().unwrap();
2965 assert_eq!(struct_result.len(), 5);
2966 assert_eq!(struct_result.num_columns(), 3);
2967
2968 let field_a = struct_result
2969 .column(0)
2970 .as_any()
2971 .downcast_ref::<Int32Array>()
2972 .unwrap();
2973 let field_b = struct_result
2974 .column(1)
2975 .as_any()
2976 .downcast_ref::<Int32Array>()
2977 .unwrap();
2978 let field_d = struct_result
2979 .column(2)
2980 .as_any()
2981 .downcast_ref::<Int32Array>()
2982 .unwrap();
2983
2984 assert!(!struct_result.is_null(0));
2986 assert_eq!(field_a.value(0), 1);
2987 assert_eq!(field_b.value(0), 2);
2988 assert!(field_d.is_null(0)); assert!(struct_result.is_null(1));
2992
2993 assert!(!struct_result.is_null(2));
2995 assert!(field_a.is_null(2)); assert_eq!(field_b.value(2), 2);
2997 assert!(field_d.is_null(2)); assert!(!struct_result.is_null(3));
3001 assert_eq!(field_a.value(3), 1);
3002 assert!(field_b.is_null(3)); assert!(field_d.is_null(3)); assert!(!struct_result.is_null(4));
3007 assert!(field_a.is_null(4)); assert!(field_b.is_null(4)); assert!(field_d.is_null(4)); }
3011
3012 #[test]
3013 fn test_nested_struct_extraction_perfectly_shredded() {
3014 let variant_array = create_comprehensive_nested_shredded_variant();
3016 println!("variant_array: {variant_array:?}");
3017
3018 let inner_field = Field::new("inner", DataType::Int32, true);
3020 let inner_type = DataType::Struct(Fields::from(vec![inner_field]));
3021 let outer_field = Field::new("outer", inner_type, true);
3022 let result_type = DataType::Struct(Fields::from(vec![outer_field]));
3023
3024 let options = GetOptions {
3025 path: VariantPath::default(),
3026 as_type: Some(Arc::new(Field::new("result", result_type, true))),
3027 cast_options: CastOptions::default(),
3028 };
3029
3030 let result = variant_get(&variant_array, options).unwrap();
3031 println!("result: {result:?}");
3032
3033 let outer_struct = result.as_any().downcast_ref::<StructArray>().unwrap();
3035 assert_eq!(outer_struct.len(), 4);
3036 assert_eq!(outer_struct.num_columns(), 1);
3037
3038 let inner_struct = outer_struct
3040 .column(0)
3041 .as_any()
3042 .downcast_ref::<StructArray>()
3043 .unwrap();
3044 assert_eq!(inner_struct.num_columns(), 1);
3045
3046 let leaf_field = inner_struct
3048 .column(0)
3049 .as_any()
3050 .downcast_ref::<Int32Array>()
3051 .unwrap();
3052
3053 assert!(!outer_struct.is_null(0));
3055 assert!(!inner_struct.is_null(0));
3056 assert_eq!(leaf_field.value(0), 42);
3057
3058 assert!(!outer_struct.is_null(1));
3060 assert!(!inner_struct.is_null(1)); assert!(leaf_field.is_null(1)); assert!(!outer_struct.is_null(2));
3065 assert!(inner_struct.is_null(2)); assert!(outer_struct.is_null(3));
3069 }
3070
3071 #[test]
3072 fn test_path_based_null_masks_one_step() {
3073 let variant_array = create_comprehensive_nested_shredded_variant();
3075
3076 let path = VariantPath::try_from("outer").unwrap();
3078 let inner_field = Field::new("inner", DataType::Int32, true);
3079 let result_type = DataType::Struct(Fields::from(vec![inner_field]));
3080
3081 let options = GetOptions {
3082 path,
3083 as_type: Some(Arc::new(Field::new("result", result_type, true))),
3084 cast_options: CastOptions::default(),
3085 };
3086
3087 let result = variant_get(&variant_array, options).unwrap();
3088
3089 let outer_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3091 assert_eq!(outer_result.len(), 4);
3092 assert_eq!(outer_result.num_columns(), 1);
3093
3094 let inner_field = outer_result
3096 .column(0)
3097 .as_any()
3098 .downcast_ref::<Int32Array>()
3099 .unwrap();
3100
3101 assert!(!outer_result.is_null(0));
3103 assert_eq!(inner_field.value(0), 42);
3104
3105 assert!(!outer_result.is_null(1));
3107 assert!(inner_field.is_null(1));
3108
3109 assert!(outer_result.is_null(2));
3111
3112 assert!(outer_result.is_null(3));
3114 }
3115
3116 #[test]
3117 fn test_path_based_null_masks_two_steps() {
3118 let variant_array = create_comprehensive_nested_shredded_variant();
3120
3121 let path = VariantPath::try_from("outer").unwrap().join("inner");
3123
3124 let options = GetOptions {
3125 path,
3126 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
3127 cast_options: CastOptions::default(),
3128 };
3129
3130 let result = variant_get(&variant_array, options).unwrap();
3131
3132 let int_result = result.as_any().downcast_ref::<Int32Array>().unwrap();
3134 assert_eq!(int_result.len(), 4);
3135
3136 assert!(!int_result.is_null(0));
3138 assert_eq!(int_result.value(0), 42);
3139
3140 assert!(int_result.is_null(1));
3142
3143 assert!(int_result.is_null(2));
3145
3146 assert!(int_result.is_null(3));
3148 }
3149
3150 #[test]
3151 fn test_struct_extraction_mixed_and_unshredded() {
3152 let variant_array = create_mixed_and_unshredded_variant();
3154
3155 let struct_fields = Fields::from(vec![
3157 Field::new("x", DataType::Int32, true),
3158 Field::new("y", DataType::Int32, true),
3159 ]);
3160 let struct_type = DataType::Struct(struct_fields);
3161
3162 let options = GetOptions {
3163 path: VariantPath::default(),
3164 as_type: Some(Arc::new(Field::new("result", struct_type, true))),
3165 cast_options: CastOptions::default(),
3166 };
3167
3168 let result = variant_get(&variant_array, options).unwrap();
3169
3170 let struct_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3172 assert_eq!(struct_result.len(), 4);
3173 assert_eq!(struct_result.num_columns(), 2);
3174
3175 let field_x = struct_result
3176 .column(0)
3177 .as_any()
3178 .downcast_ref::<Int32Array>()
3179 .unwrap();
3180 let field_y = struct_result
3181 .column(1)
3182 .as_any()
3183 .downcast_ref::<Int32Array>()
3184 .unwrap();
3185
3186 assert_eq!(field_x.value(0), 1);
3188 assert_eq!(field_y.value(0), 42);
3189
3190 assert_eq!(field_x.value(1), 2);
3192 assert!(field_y.is_null(1));
3193
3194 assert_eq!(field_x.value(2), 3);
3196 assert!(field_y.is_null(2));
3197
3198 assert!(struct_result.is_null(3));
3200 }
3201
3202 #[test]
3205 fn test_struct_row_builder_gap_demonstration() {
3206 let json_strings = vec![
3208 r#"{"outer": {"inner": 42}}"#,
3209 r#"{"outer": {"inner": 100}}"#,
3210 ];
3211 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(json_strings));
3212 let variant_array = json_to_variant(&string_array).unwrap();
3213
3214 let inner_fields = Fields::from(vec![Field::new("inner", DataType::Int32, true)]);
3216 let inner_struct_type = DataType::Struct(inner_fields);
3217 let outer_fields = Fields::from(vec![Field::new("outer", inner_struct_type, true)]);
3218 let outer_struct_type = DataType::Struct(outer_fields);
3219
3220 let options = GetOptions {
3221 path: VariantPath::default(),
3222 as_type: Some(Arc::new(Field::new("result", outer_struct_type, true))),
3223 cast_options: CastOptions::default(),
3224 };
3225
3226 let variant_array_ref = ArrayRef::from(variant_array);
3227 let result = variant_get(&variant_array_ref, options);
3228
3229 assert!(result.is_err());
3231 let error = result.unwrap_err();
3232 assert!(error.to_string().contains("Not yet implemented"));
3233 }
3234
3235 fn create_comprehensive_shredded_variant() -> ArrayRef {
3238 let (metadata, _) = {
3239 let mut builder = parquet_variant::VariantBuilder::new();
3240 let obj = builder.new_object();
3241 obj.finish();
3242 builder.finish()
3243 };
3244
3245 let nulls = NullBuffer::from(vec![
3247 true, false, true, true, true, ]);
3253
3254 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 5));
3255
3256 let a_field_typed_value = Int32Array::from(vec![Some(1), None, None, Some(1), None]);
3259 let a_field_struct = StructArrayBuilder::new()
3260 .with_field("typed_value", Arc::new(a_field_typed_value), true)
3261 .build();
3262 let a_field_shredded = ShreddedVariantFieldArray::try_new(&a_field_struct)
3263 .expect("should create ShreddedVariantFieldArray for a");
3264
3265 let b_field_typed_value = Int32Array::from(vec![Some(2), None, Some(2), None, None]);
3267 let b_field_struct = StructArrayBuilder::new()
3268 .with_field("typed_value", Arc::new(b_field_typed_value), true)
3269 .build();
3270 let b_field_shredded = ShreddedVariantFieldArray::try_new(&b_field_struct)
3271 .expect("should create ShreddedVariantFieldArray for b");
3272
3273 let c_field_typed_value = Int32Array::from(vec![Some(3), None, None, None, None]);
3275 let c_field_struct = StructArrayBuilder::new()
3276 .with_field("typed_value", Arc::new(c_field_typed_value), true)
3277 .build();
3278 let c_field_shredded = ShreddedVariantFieldArray::try_new(&c_field_struct)
3279 .expect("should create ShreddedVariantFieldArray for c");
3280
3281 let typed_value_fields = Fields::from(vec![
3283 Field::new("a", a_field_shredded.data_type().clone(), true),
3284 Field::new("b", b_field_shredded.data_type().clone(), true),
3285 Field::new("c", c_field_shredded.data_type().clone(), true),
3286 ]);
3287 let typed_value_struct = StructArray::try_new(
3288 typed_value_fields,
3289 vec![
3290 ArrayRef::from(a_field_shredded),
3291 ArrayRef::from(b_field_shredded),
3292 ArrayRef::from(c_field_shredded),
3293 ],
3294 None,
3295 )
3296 .unwrap();
3297
3298 let struct_array = StructArrayBuilder::new()
3300 .with_field("metadata", Arc::new(metadata_array), false)
3301 .with_field("typed_value", Arc::new(typed_value_struct), true)
3302 .with_nulls(nulls)
3303 .build();
3304
3305 Arc::new(struct_array)
3306 }
3307
3308 fn create_comprehensive_nested_shredded_variant() -> ArrayRef {
3313 let inner_typed_value = Int32Array::from(vec![Some(42), None, None, None]); let inner = StructArrayBuilder::new()
3317 .with_field("typed_value", Arc::new(inner_typed_value), true)
3318 .build();
3319 let inner = ShreddedVariantFieldArray::try_new(&inner).unwrap();
3320
3321 let outer_typed_value_nulls = NullBuffer::from(vec![
3322 true, false, false, false, ]);
3327 let outer_typed_value = StructArrayBuilder::new()
3328 .with_field("inner", ArrayRef::from(inner), false)
3329 .with_nulls(outer_typed_value_nulls)
3330 .build();
3331
3332 let outer = StructArrayBuilder::new()
3333 .with_field("typed_value", Arc::new(outer_typed_value), true)
3334 .build();
3335 let outer = ShreddedVariantFieldArray::try_new(&outer).unwrap();
3336
3337 let typed_value_nulls = NullBuffer::from(vec![
3338 true, true, false, false, ]);
3343 let typed_value = StructArrayBuilder::new()
3344 .with_field("outer", ArrayRef::from(outer), false)
3345 .with_nulls(typed_value_nulls)
3346 .build();
3347
3348 let metadata_array =
3350 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 4));
3351 let nulls = NullBuffer::from(vec![
3352 true, true, true, false, ]);
3357 let struct_array = StructArrayBuilder::new()
3358 .with_field("metadata", Arc::new(metadata_array), false)
3359 .with_field("typed_value", Arc::new(typed_value), true)
3360 .with_nulls(nulls)
3361 .build();
3362
3363 Arc::new(struct_array)
3364 }
3365
3366 fn create_mixed_and_unshredded_variant() -> ArrayRef {
3369 let (metadata, y_field_value) = {
3374 let mut builder = parquet_variant::VariantBuilder::new();
3375 let mut obj = builder.new_object();
3376 obj.insert("y", Variant::from(42));
3377 obj.finish();
3378 builder.finish()
3379 };
3380
3381 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 4));
3382
3383 let empty_object_value = {
3390 let mut builder = parquet_variant::VariantBuilder::new();
3391 builder.new_object().finish();
3392 let (_, value) = builder.finish();
3393 value
3394 };
3395
3396 let y_null_value = {
3397 let mut builder = parquet_variant::VariantBuilder::new();
3398 builder.new_object().with_field("y", Variant::Null).finish();
3399 let (_, value) = builder.finish();
3400 value
3401 };
3402
3403 let value_array = BinaryViewArray::from(vec![
3404 Some(y_field_value.as_slice()), Some(empty_object_value.as_slice()), Some(y_null_value.as_slice()), Some(empty_object_value.as_slice()), ]);
3409
3410 let x_field_typed_value = Int32Array::from(vec![Some(1), Some(2), Some(3), Some(0)]);
3413 let x_field_struct = StructArrayBuilder::new()
3414 .with_field("typed_value", Arc::new(x_field_typed_value), true)
3415 .build();
3416 let x_field_shredded = ShreddedVariantFieldArray::try_new(&x_field_struct)
3417 .expect("should create ShreddedVariantFieldArray for x");
3418
3419 let typed_value_struct = StructArrayBuilder::new()
3421 .with_field("x", ArrayRef::from(x_field_shredded), false)
3422 .build();
3423
3424 let variant_nulls = NullBuffer::from(vec![true, true, true, false]); let struct_array = StructArrayBuilder::new()
3428 .with_field("metadata", Arc::new(metadata_array), false)
3429 .with_field("value", Arc::new(value_array), true)
3430 .with_field("typed_value", Arc::new(typed_value_struct), true)
3431 .with_nulls(variant_nulls)
3432 .build();
3433
3434 Arc::new(struct_array)
3435 }
3436
3437 #[test]
3438 fn get_decimal32_rescaled_to_scale2() {
3439 let mut builder = crate::VariantArrayBuilder::new(5);
3441 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();
3445 builder.append_variant(
3446 VariantDecimal8::try_new((VariantDecimal4::MAX_UNSCALED_VALUE as i64) + 1, 3)
3447 .unwrap()
3448 .into(),
3449 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3451
3452 let field = Field::new("result", DataType::Decimal32(9, 2), true);
3453 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3454 let result = variant_get(&variant_array, options).unwrap();
3455 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3456
3457 assert_eq!(result.precision(), 9);
3458 assert_eq!(result.scale(), 2);
3459 assert_eq!(result.value(0), 1234);
3460 assert_eq!(result.value(1), 123);
3461 assert_eq!(result.value(2), 123400);
3462 assert!(result.is_null(3));
3463 assert_eq!(
3464 result.value(4),
3465 VariantDecimal4::MAX_UNSCALED_VALUE / 10 + 1
3466 ); }
3468
3469 #[test]
3470 fn get_decimal32_scale_down_rounding() {
3471 let mut builder = crate::VariantArrayBuilder::new(7);
3472 builder.append_variant(VariantDecimal4::try_new(1235, 0).unwrap().into());
3473 builder.append_variant(VariantDecimal4::try_new(1245, 0).unwrap().into());
3474 builder.append_variant(VariantDecimal4::try_new(-1235, 0).unwrap().into());
3475 builder.append_variant(VariantDecimal4::try_new(-1245, 0).unwrap().into());
3476 builder.append_variant(VariantDecimal4::try_new(1235, 2).unwrap().into()); builder.append_variant(VariantDecimal4::try_new(1235, 3).unwrap().into()); builder.append_variant(VariantDecimal4::try_new(5235, 3).unwrap().into()); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3480
3481 let field = Field::new("result", DataType::Decimal32(9, -1), true);
3482 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3483 let result = variant_get(&variant_array, options).unwrap();
3484 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3485
3486 assert_eq!(result.precision(), 9);
3487 assert_eq!(result.scale(), -1);
3488 assert_eq!(result.value(0), 124);
3489 assert_eq!(result.value(1), 125);
3490 assert_eq!(result.value(2), -124);
3491 assert_eq!(result.value(3), -125);
3492 assert_eq!(result.value(4), 1);
3493 assert!(result.is_valid(5));
3494 assert_eq!(result.value(5), 0);
3495 assert_eq!(result.value(6), 1);
3496 }
3497
3498 #[test]
3499 fn get_decimal32_large_scale_reduction() {
3500 let mut builder = crate::VariantArrayBuilder::new(2);
3501 builder.append_variant(
3502 VariantDecimal4::try_new(-VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3503 .unwrap()
3504 .into(),
3505 );
3506 builder.append_variant(
3507 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3508 .unwrap()
3509 .into(),
3510 );
3511 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3512
3513 let field = Field::new("result", DataType::Decimal32(9, -9), true);
3514 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3515 let result = variant_get(&variant_array, options).unwrap();
3516 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3517
3518 assert_eq!(result.precision(), 9);
3519 assert_eq!(result.scale(), -9);
3520 assert_eq!(result.value(0), -1);
3521 assert_eq!(result.value(1), 1);
3522
3523 let field = Field::new("result", DataType::Decimal32(9, -10), true);
3524 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3525 let result = variant_get(&variant_array, options).unwrap();
3526 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3527
3528 assert_eq!(result.precision(), 9);
3529 assert_eq!(result.scale(), -10);
3530 assert!(result.is_valid(0));
3531 assert_eq!(result.value(0), 0);
3532 assert!(result.is_valid(1));
3533 assert_eq!(result.value(1), 0);
3534 }
3535
3536 #[test]
3537 fn get_decimal32_precision_overflow_safe() {
3538 let mut builder = crate::VariantArrayBuilder::new(2);
3540 builder.append_variant(
3541 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3542 .unwrap()
3543 .into(),
3544 );
3545 builder.append_variant(
3546 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 9)
3547 .unwrap()
3548 .into(),
3549 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3551
3552 let field = Field::new("result", DataType::Decimal32(2, 2), true);
3553 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3554 let result = variant_get(&variant_array, options).unwrap();
3555 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3556
3557 assert!(result.is_null(0));
3558 assert!(result.is_null(1)); }
3560
3561 #[test]
3562 fn get_decimal32_precision_overflow_unsafe_errors() {
3563 let mut builder = crate::VariantArrayBuilder::new(1);
3564 builder.append_variant(
3565 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3566 .unwrap()
3567 .into(),
3568 );
3569 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3570
3571 let field = Field::new("result", DataType::Decimal32(9, 2), true);
3572 let cast_options = CastOptions {
3573 safe: false,
3574 ..Default::default()
3575 };
3576 let options = GetOptions::new()
3577 .with_as_type(Some(FieldRef::from(field)))
3578 .with_cast_options(cast_options);
3579 let err = variant_get(&variant_array, options).unwrap_err();
3580
3581 assert!(
3582 err.to_string().contains(
3583 "Failed to cast to Decimal32(precision=9, scale=2) from variant Decimal4"
3584 )
3585 );
3586 }
3587
3588 #[test]
3589 fn get_decimal64_rescaled_to_scale2() {
3590 let mut builder = crate::VariantArrayBuilder::new(5);
3591 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();
3595 builder.append_variant(
3596 VariantDecimal16::try_new((VariantDecimal8::MAX_UNSCALED_VALUE as i128) + 1, 3)
3597 .unwrap()
3598 .into(),
3599 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3601
3602 let field = Field::new("result", DataType::Decimal64(18, 2), true);
3603 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3604 let result = variant_get(&variant_array, options).unwrap();
3605 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3606
3607 assert_eq!(result.precision(), 18);
3608 assert_eq!(result.scale(), 2);
3609 assert_eq!(result.value(0), 1234);
3610 assert_eq!(result.value(1), 123);
3611 assert_eq!(result.value(2), 123400);
3612 assert!(result.is_null(3));
3613 assert_eq!(
3614 result.value(4),
3615 VariantDecimal8::MAX_UNSCALED_VALUE / 10 + 1
3616 ); }
3618
3619 #[test]
3620 fn get_decimal64_scale_down_rounding() {
3621 let mut builder = crate::VariantArrayBuilder::new(7);
3622 builder.append_variant(VariantDecimal8::try_new(1235, 0).unwrap().into());
3623 builder.append_variant(VariantDecimal8::try_new(1245, 0).unwrap().into());
3624 builder.append_variant(VariantDecimal8::try_new(-1235, 0).unwrap().into());
3625 builder.append_variant(VariantDecimal8::try_new(-1245, 0).unwrap().into());
3626 builder.append_variant(VariantDecimal8::try_new(1235, 2).unwrap().into()); builder.append_variant(VariantDecimal8::try_new(1235, 3).unwrap().into()); builder.append_variant(VariantDecimal8::try_new(5235, 3).unwrap().into()); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3630
3631 let field = Field::new("result", DataType::Decimal64(18, -1), true);
3632 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3633 let result = variant_get(&variant_array, options).unwrap();
3634 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3635
3636 assert_eq!(result.precision(), 18);
3637 assert_eq!(result.scale(), -1);
3638 assert_eq!(result.value(0), 124);
3639 assert_eq!(result.value(1), 125);
3640 assert_eq!(result.value(2), -124);
3641 assert_eq!(result.value(3), -125);
3642 assert_eq!(result.value(4), 1);
3643 assert!(result.is_valid(5));
3644 assert_eq!(result.value(5), 0);
3645 assert_eq!(result.value(6), 1);
3646 }
3647
3648 #[test]
3649 fn get_decimal64_large_scale_reduction() {
3650 let mut builder = crate::VariantArrayBuilder::new(2);
3651 builder.append_variant(
3652 VariantDecimal8::try_new(-VariantDecimal8::MAX_UNSCALED_VALUE, 0)
3653 .unwrap()
3654 .into(),
3655 );
3656 builder.append_variant(
3657 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0)
3658 .unwrap()
3659 .into(),
3660 );
3661 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3662
3663 let field = Field::new("result", DataType::Decimal64(18, -18), true);
3664 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3665 let result = variant_get(&variant_array, options).unwrap();
3666 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3667
3668 assert_eq!(result.precision(), 18);
3669 assert_eq!(result.scale(), -18);
3670 assert_eq!(result.value(0), -1);
3671 assert_eq!(result.value(1), 1);
3672
3673 let field = Field::new("result", DataType::Decimal64(18, -19), true);
3674 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3675 let result = variant_get(&variant_array, options).unwrap();
3676 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3677
3678 assert_eq!(result.precision(), 18);
3679 assert_eq!(result.scale(), -19);
3680 assert!(result.is_valid(0));
3681 assert_eq!(result.value(0), 0);
3682 assert!(result.is_valid(1));
3683 assert_eq!(result.value(1), 0);
3684 }
3685
3686 #[test]
3687 fn get_decimal64_precision_overflow_safe() {
3688 let mut builder = crate::VariantArrayBuilder::new(2);
3690 builder.append_variant(
3691 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0)
3692 .unwrap()
3693 .into(),
3694 );
3695 builder.append_variant(
3696 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 18)
3697 .unwrap()
3698 .into(),
3699 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3701
3702 let field = Field::new("result", DataType::Decimal64(2, 2), true);
3703 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3704 let result = variant_get(&variant_array, options).unwrap();
3705 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3706
3707 assert!(result.is_null(0));
3708 assert!(result.is_null(1));
3709 }
3710
3711 #[test]
3712 fn get_decimal64_precision_overflow_unsafe_errors() {
3713 let mut builder = crate::VariantArrayBuilder::new(1);
3714 builder.append_variant(
3715 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0)
3716 .unwrap()
3717 .into(),
3718 );
3719 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3720
3721 let field = Field::new("result", DataType::Decimal64(18, 2), true);
3722 let cast_options = CastOptions {
3723 safe: false,
3724 ..Default::default()
3725 };
3726 let options = GetOptions::new()
3727 .with_as_type(Some(FieldRef::from(field)))
3728 .with_cast_options(cast_options);
3729 let err = variant_get(&variant_array, options).unwrap_err();
3730
3731 assert!(
3732 err.to_string().contains(
3733 "Failed to cast to Decimal64(precision=18, scale=2) from variant Decimal8"
3734 )
3735 );
3736 }
3737
3738 #[test]
3739 fn get_decimal128_rescaled_to_scale2() {
3740 let mut builder = crate::VariantArrayBuilder::new(4);
3741 builder.append_variant(VariantDecimal16::try_new(1234, 2).unwrap().into());
3742 builder.append_variant(VariantDecimal16::try_new(1234, 3).unwrap().into());
3743 builder.append_variant(VariantDecimal16::try_new(1234, 0).unwrap().into());
3744 builder.append_null();
3745 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3746
3747 let field = Field::new("result", DataType::Decimal128(38, 2), true);
3748 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3749 let result = variant_get(&variant_array, options).unwrap();
3750 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
3751
3752 assert_eq!(result.precision(), 38);
3753 assert_eq!(result.scale(), 2);
3754 assert_eq!(result.value(0), 1234);
3755 assert_eq!(result.value(1), 123);
3756 assert_eq!(result.value(2), 123400);
3757 assert!(result.is_null(3));
3758 }
3759
3760 #[test]
3761 fn get_decimal128_scale_down_rounding() {
3762 let mut builder = crate::VariantArrayBuilder::new(7);
3763 builder.append_variant(VariantDecimal16::try_new(1235, 0).unwrap().into());
3764 builder.append_variant(VariantDecimal16::try_new(1245, 0).unwrap().into());
3765 builder.append_variant(VariantDecimal16::try_new(-1235, 0).unwrap().into());
3766 builder.append_variant(VariantDecimal16::try_new(-1245, 0).unwrap().into());
3767 builder.append_variant(VariantDecimal16::try_new(1235, 2).unwrap().into()); builder.append_variant(VariantDecimal16::try_new(1235, 3).unwrap().into()); builder.append_variant(VariantDecimal16::try_new(5235, 3).unwrap().into()); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3771
3772 let field = Field::new("result", DataType::Decimal128(38, -1), true);
3773 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3774 let result = variant_get(&variant_array, options).unwrap();
3775 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
3776
3777 assert_eq!(result.precision(), 38);
3778 assert_eq!(result.scale(), -1);
3779 assert_eq!(result.value(0), 124);
3780 assert_eq!(result.value(1), 125);
3781 assert_eq!(result.value(2), -124);
3782 assert_eq!(result.value(3), -125);
3783 assert_eq!(result.value(4), 1);
3784 assert!(result.is_valid(5));
3785 assert_eq!(result.value(5), 0);
3786 assert_eq!(result.value(6), 1);
3787 }
3788
3789 #[test]
3790 fn get_decimal128_precision_overflow_safe() {
3791 let mut builder = crate::VariantArrayBuilder::new(2);
3793 builder.append_variant(
3794 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
3795 .unwrap()
3796 .into(),
3797 );
3798 builder.append_variant(
3799 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 38)
3800 .unwrap()
3801 .into(),
3802 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3804
3805 let field = Field::new("result", DataType::Decimal128(2, 2), true);
3806 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3807 let result = variant_get(&variant_array, options).unwrap();
3808 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
3809
3810 assert!(result.is_null(0));
3811 assert!(result.is_null(1)); }
3813
3814 #[test]
3815 fn get_decimal128_precision_overflow_unsafe_errors() {
3816 let mut builder = crate::VariantArrayBuilder::new(1);
3817 builder.append_variant(
3818 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
3819 .unwrap()
3820 .into(),
3821 );
3822 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3823
3824 let field = Field::new("result", DataType::Decimal128(38, 2), true);
3825 let cast_options = CastOptions {
3826 safe: false,
3827 ..Default::default()
3828 };
3829 let options = GetOptions::new()
3830 .with_as_type(Some(FieldRef::from(field)))
3831 .with_cast_options(cast_options);
3832 let err = variant_get(&variant_array, options).unwrap_err();
3833
3834 assert!(err.to_string().contains(
3835 "Failed to cast to Decimal128(precision=38, scale=2) from variant Decimal16"
3836 ));
3837 }
3838
3839 #[test]
3840 fn get_decimal256_rescaled_to_scale2() {
3841 let mut builder = crate::VariantArrayBuilder::new(4);
3843 builder.append_variant(VariantDecimal16::try_new(1234, 2).unwrap().into()); builder.append_variant(VariantDecimal16::try_new(1234, 3).unwrap().into()); builder.append_variant(VariantDecimal16::try_new(1234, 0).unwrap().into()); builder.append_null();
3847 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3848
3849 let field = Field::new("result", DataType::Decimal256(76, 2), true);
3850 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3851 let result = variant_get(&variant_array, options).unwrap();
3852 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
3853
3854 assert_eq!(result.precision(), 76);
3855 assert_eq!(result.scale(), 2);
3856 assert_eq!(result.value(0), i256::from_i128(1234));
3857 assert_eq!(result.value(1), i256::from_i128(123));
3858 assert_eq!(result.value(2), i256::from_i128(123400));
3859 assert!(result.is_null(3));
3860 }
3861
3862 #[test]
3863 fn get_decimal256_scale_down_rounding() {
3864 let mut builder = crate::VariantArrayBuilder::new(7);
3865 builder.append_variant(VariantDecimal16::try_new(1235, 0).unwrap().into());
3866 builder.append_variant(VariantDecimal16::try_new(1245, 0).unwrap().into());
3867 builder.append_variant(VariantDecimal16::try_new(-1235, 0).unwrap().into());
3868 builder.append_variant(VariantDecimal16::try_new(-1245, 0).unwrap().into());
3869 builder.append_variant(VariantDecimal16::try_new(1235, 2).unwrap().into()); builder.append_variant(VariantDecimal16::try_new(1235, 3).unwrap().into()); builder.append_variant(VariantDecimal16::try_new(5235, 3).unwrap().into()); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3873
3874 let field = Field::new("result", DataType::Decimal256(76, -1), true);
3875 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3876 let result = variant_get(&variant_array, options).unwrap();
3877 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
3878
3879 assert_eq!(result.precision(), 76);
3880 assert_eq!(result.scale(), -1);
3881 assert_eq!(result.value(0), i256::from_i128(124));
3882 assert_eq!(result.value(1), i256::from_i128(125));
3883 assert_eq!(result.value(2), i256::from_i128(-124));
3884 assert_eq!(result.value(3), i256::from_i128(-125));
3885 assert_eq!(result.value(4), i256::from_i128(1));
3886 assert!(result.is_valid(5));
3887 assert_eq!(result.value(5), i256::from_i128(0));
3888 assert_eq!(result.value(6), i256::from_i128(1));
3889 }
3890
3891 #[test]
3892 fn get_decimal256_precision_overflow_safe() {
3893 let mut builder = crate::VariantArrayBuilder::new(2);
3895 builder.append_variant(
3896 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 1)
3897 .unwrap()
3898 .into(),
3899 );
3900 builder.append_variant(
3901 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
3902 .unwrap()
3903 .into(),
3904 );
3905 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3906
3907 let field = Field::new("result", DataType::Decimal256(76, 39), true);
3908 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3909 let result = variant_get(&variant_array, options).unwrap();
3910 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
3911
3912 let base = i256::from_i128(10);
3915 let factor = base.checked_pow(38).unwrap();
3916 let expected = i256::from_i128(VariantDecimal16::MAX_UNSCALED_VALUE)
3917 .checked_mul(factor)
3918 .unwrap();
3919 assert_eq!(result.value(0), expected);
3920 assert!(result.is_null(1));
3921 }
3922
3923 #[test]
3924 fn get_decimal256_precision_overflow_unsafe_errors() {
3925 let mut builder = crate::VariantArrayBuilder::new(2);
3927 builder.append_variant(
3928 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 1)
3929 .unwrap()
3930 .into(),
3931 );
3932 builder.append_variant(
3933 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
3934 .unwrap()
3935 .into(),
3936 );
3937 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3938
3939 let field = Field::new("result", DataType::Decimal256(76, 39), true);
3940 let cast_options = CastOptions {
3941 safe: false,
3942 ..Default::default()
3943 };
3944 let options = GetOptions::new()
3945 .with_as_type(Some(FieldRef::from(field)))
3946 .with_cast_options(cast_options);
3947 let err = variant_get(&variant_array, options).unwrap_err();
3948
3949 assert!(err.to_string().contains(
3950 "Failed to cast to Decimal256(precision=76, scale=39) from variant Decimal16"
3951 ));
3952 }
3953
3954 #[test]
3955 fn get_non_supported_temporal_types_error() {
3956 let values = vec![None, Some(Variant::Null), Some(Variant::BooleanFalse)];
3957 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter(values));
3958
3959 let test_cases = vec![
3960 FieldRef::from(Field::new(
3961 "result",
3962 DataType::Duration(TimeUnit::Microsecond),
3963 true,
3964 )),
3965 FieldRef::from(Field::new(
3966 "result",
3967 DataType::Interval(IntervalUnit::YearMonth),
3968 true,
3969 )),
3970 ];
3971
3972 for field in test_cases {
3973 let options = GetOptions::new().with_as_type(Some(field));
3974 let err = variant_get(&variant_array, options).unwrap_err();
3975 assert!(
3976 err.to_string()
3977 .contains("Casting Variant to duration/interval types is not supported")
3978 );
3979 }
3980 }
3981
3982 fn invalid_time_variant_array() -> ArrayRef {
3983 let mut builder = VariantArrayBuilder::new(3);
3984 builder.append_variant(Variant::Int64(86401000000));
3986 builder.append_variant(Variant::Int64(86401000000));
3987 builder.append_variant(Variant::Int64(86401000000));
3988 Arc::new(builder.build().into_inner())
3989 }
3990
3991 #[test]
3992 fn test_variant_get_error_when_cast_failure_and_safe_false() {
3993 let variant_array = invalid_time_variant_array();
3994
3995 let field = Field::new("result", DataType::Time64(TimeUnit::Microsecond), true);
3996 let cast_options = CastOptions {
3997 safe: false, ..Default::default()
3999 };
4000 let options = GetOptions::new()
4001 .with_as_type(Some(FieldRef::from(field)))
4002 .with_cast_options(cast_options);
4003 let err = variant_get(&variant_array, options).unwrap_err();
4004 assert!(
4005 err.to_string().contains(
4006 "Cast error: Failed to extract primitive of type Time64(µs) from variant Int64(86401000000) at path VariantPath([])"
4007 ),
4008 "actual: {err}",
4009 );
4010 }
4011
4012 #[test]
4013 fn test_variant_get_return_null_when_cast_failure_and_safe_true() {
4014 let variant_array = invalid_time_variant_array();
4015
4016 let field = Field::new("result", DataType::Time64(TimeUnit::Microsecond), true);
4017 let cast_options = CastOptions {
4018 safe: true, ..Default::default()
4020 };
4021 let options = GetOptions::new()
4022 .with_as_type(Some(FieldRef::from(field)))
4023 .with_cast_options(cast_options);
4024 let result = variant_get(&variant_array, options).unwrap();
4025 assert_eq!(3, result.len());
4026
4027 for i in 0..3 {
4028 assert!(result.is_null(i));
4029 }
4030 }
4031
4032 #[test]
4033 fn test_perfect_shredding_returns_same_arc_ptr() {
4034 let variant_array = perfectly_shredded_int32_variant_array();
4035
4036 let variant_array_ref = VariantArray::try_new(&variant_array).unwrap();
4037 let typed_value_arc = variant_array_ref.typed_value_field().unwrap().clone();
4038
4039 let field = Field::new("result", DataType::Int32, true);
4040 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4041 let result = variant_get(&variant_array, options).unwrap();
4042
4043 assert!(Arc::ptr_eq(&typed_value_arc, &result));
4044 }
4045
4046 #[test]
4047 fn test_perfect_shredding_three_typed_value_columns() {
4048 let all_nulls_values: Arc<Int32Array> = Arc::new(Int32Array::from(vec![
4050 Option::<i32>::None,
4051 Option::<i32>::None,
4052 Option::<i32>::None,
4053 ]));
4054 let all_nulls_erased: ArrayRef = all_nulls_values.clone();
4055 let all_nulls_field =
4056 ShreddedVariantFieldArray::from_parts(None, Some(all_nulls_erased.clone()), None);
4057 let all_nulls_type = all_nulls_field.data_type().clone();
4058 let all_nulls_struct: ArrayRef = ArrayRef::from(all_nulls_field);
4059
4060 let some_nulls_values: Arc<Int32Array> =
4062 Arc::new(Int32Array::from(vec![Some(10), None, Some(30)]));
4063 let some_nulls_erased: ArrayRef = some_nulls_values.clone();
4064 let some_nulls_field =
4065 ShreddedVariantFieldArray::from_parts(None, Some(some_nulls_erased.clone()), None);
4066 let some_nulls_type = some_nulls_field.data_type().clone();
4067 let some_nulls_struct: ArrayRef = ArrayRef::from(some_nulls_field);
4068
4069 let inner_values: Arc<Int32Array> =
4071 Arc::new(Int32Array::from(vec![Some(111), None, Some(333)]));
4072 let inner_erased: ArrayRef = inner_values.clone();
4073 let inner_field =
4074 ShreddedVariantFieldArray::from_parts(None, Some(inner_erased.clone()), None);
4075 let inner_field_type = inner_field.data_type().clone();
4076 let inner_struct_array: ArrayRef = ArrayRef::from(inner_field);
4077
4078 let nested_struct = Arc::new(
4079 StructArray::try_new(
4080 Fields::from(vec![Field::new("inner", inner_field_type, true)]),
4081 vec![inner_struct_array],
4082 None,
4083 )
4084 .unwrap(),
4085 );
4086 let nested_struct_erased: ArrayRef = nested_struct.clone();
4087 let struct_field =
4088 ShreddedVariantFieldArray::from_parts(None, Some(nested_struct_erased.clone()), None);
4089 let struct_field_type = struct_field.data_type().clone();
4090 let struct_field_struct: ArrayRef = ArrayRef::from(struct_field);
4091
4092 let typed_value_struct = StructArray::try_new(
4094 Fields::from(vec![
4095 Field::new("all_nulls", all_nulls_type, true),
4096 Field::new("some_nulls", some_nulls_type, true),
4097 Field::new("struct_field", struct_field_type, true),
4098 ]),
4099 vec![all_nulls_struct, some_nulls_struct, struct_field_struct],
4100 None,
4101 )
4102 .unwrap();
4103
4104 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(
4105 EMPTY_VARIANT_METADATA_BYTES,
4106 all_nulls_values.len(),
4107 ));
4108 let variant_struct = StructArrayBuilder::new()
4109 .with_field("metadata", Arc::new(metadata), false)
4110 .with_field("typed_value", Arc::new(typed_value_struct), true)
4111 .build();
4112 let variant_array: ArrayRef = VariantArray::try_new(&variant_struct).unwrap().into();
4113
4114 let all_nulls_field_ref = FieldRef::from(Field::new("result", DataType::Int32, true));
4116 let all_nulls_result = variant_get(
4117 &variant_array,
4118 GetOptions::new_with_path(VariantPath::try_from("all_nulls").unwrap())
4119 .with_as_type(Some(all_nulls_field_ref)),
4120 )
4121 .unwrap();
4122 assert!(Arc::ptr_eq(&all_nulls_result, &all_nulls_erased));
4123
4124 let some_nulls_field_ref = FieldRef::from(Field::new("result", DataType::Int32, true));
4126 let some_nulls_result = variant_get(
4127 &variant_array,
4128 GetOptions::new_with_path(VariantPath::try_from("some_nulls").unwrap())
4129 .with_as_type(Some(some_nulls_field_ref)),
4130 )
4131 .unwrap();
4132 assert!(Arc::ptr_eq(&some_nulls_result, &some_nulls_erased));
4133
4134 let struct_child_fields = Fields::from(vec![Field::new("inner", DataType::Int32, true)]);
4136 let struct_field_ref = FieldRef::from(Field::new(
4137 "result",
4138 DataType::Struct(struct_child_fields.clone()),
4139 true,
4140 ));
4141 let struct_result = variant_get(
4142 &variant_array,
4143 GetOptions::new_with_path(VariantPath::try_from("struct_field").unwrap())
4144 .with_as_type(Some(struct_field_ref)),
4145 )
4146 .unwrap();
4147 let struct_array = struct_result
4148 .as_any()
4149 .downcast_ref::<StructArray>()
4150 .unwrap();
4151 assert_eq!(struct_array.len(), 3);
4152 assert_eq!(struct_array.null_count(), 0);
4153
4154 let inner_values_result = struct_array
4155 .column(0)
4156 .as_any()
4157 .downcast_ref::<Int32Array>()
4158 .unwrap();
4159 assert_eq!(inner_values_result.len(), 3);
4160 assert_eq!(inner_values_result.value(0), 111);
4161 assert!(inner_values_result.is_null(1));
4162 assert_eq!(inner_values_result.value(2), 333);
4163 }
4164
4165 #[test]
4166 fn test_variant_get_list_like_safe_cast() {
4167 let string_array: ArrayRef = Arc::new(StringArray::from(vec![
4168 r#"{"outer":{"list":[1, "two", 3]}}"#,
4169 r#"{"outer":{"list":"not a list"}}"#,
4170 ]));
4171 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4172
4173 let value_array: ArrayRef = {
4174 let mut builder = VariantBuilder::new();
4175 builder.append_value("two");
4176 let (_, value_bytes) = builder.finish();
4177 Arc::new(BinaryViewArray::from(vec![
4178 None,
4179 Some(value_bytes.as_slice()),
4180 None,
4181 ]))
4182 };
4183 let typed_value_array: ArrayRef = Arc::new(Int64Array::from(vec![Some(1), None, Some(3)]));
4184 let struct_fields = Fields::from(vec![
4185 Field::new("value", DataType::BinaryView, true),
4186 Field::new("typed_value", DataType::Int64, true),
4187 ]);
4188 let struct_array: ArrayRef = Arc::new(
4189 StructArray::try_new(
4190 struct_fields.clone(),
4191 vec![value_array.clone(), typed_value_array.clone()],
4192 None,
4193 )
4194 .unwrap(),
4195 );
4196
4197 let request_field = Arc::new(Field::new("item", DataType::Int64, true));
4198 let result_field = Arc::new(Field::new("item", DataType::Struct(struct_fields), true));
4199
4200 let expectations = vec![
4201 (
4202 DataType::List(request_field.clone()),
4203 Arc::new(ListArray::new(
4204 result_field.clone(),
4205 OffsetBuffer::new(ScalarBuffer::from(vec![0, 3, 3])),
4206 struct_array.clone(),
4207 Some(NullBuffer::from(vec![true, false])),
4208 )) as ArrayRef,
4209 ),
4210 (
4211 DataType::LargeList(request_field.clone()),
4212 Arc::new(LargeListArray::new(
4213 result_field.clone(),
4214 OffsetBuffer::new(ScalarBuffer::from(vec![0, 3, 3])),
4215 struct_array.clone(),
4216 Some(NullBuffer::from(vec![true, false])),
4217 )) as ArrayRef,
4218 ),
4219 (
4220 DataType::ListView(request_field.clone()),
4221 Arc::new(ListViewArray::new(
4222 result_field.clone(),
4223 ScalarBuffer::from(vec![0, 3]),
4224 ScalarBuffer::from(vec![3, 0]),
4225 struct_array.clone(),
4226 Some(NullBuffer::from(vec![true, false])),
4227 )) as ArrayRef,
4228 ),
4229 (
4230 DataType::LargeListView(request_field),
4231 Arc::new(LargeListViewArray::new(
4232 result_field,
4233 ScalarBuffer::from(vec![0, 3]),
4234 ScalarBuffer::from(vec![3, 0]),
4235 struct_array,
4236 Some(NullBuffer::from(vec![true, false])),
4237 )) as ArrayRef,
4238 ),
4239 ];
4240
4241 for (request_type, expected) in expectations {
4242 let options =
4243 GetOptions::new_with_path(VariantPath::try_from("outer").unwrap().join("list"))
4244 .with_as_type(Some(FieldRef::from(Field::new(
4245 "result",
4246 request_type.clone(),
4247 true,
4248 ))));
4249
4250 let result = variant_get(&variant_array, options).unwrap();
4251 assert_eq!(result.data_type(), expected.data_type());
4252 assert_eq!(&result, &expected);
4253 }
4254
4255 for (idx, expected) in [
4256 (0, vec![Some(1), None]),
4257 (1, vec![None, None]),
4258 (2, vec![Some(3), None]),
4259 ] {
4260 let index_options = GetOptions::new_with_path(
4261 VariantPath::try_from("outer")
4262 .unwrap()
4263 .join("list")
4264 .join(idx),
4265 )
4266 .with_as_type(Some(FieldRef::from(Field::new(
4267 "result",
4268 DataType::Int64,
4269 true,
4270 ))));
4271 let index_result = variant_get(&variant_array, index_options).unwrap();
4272 let index_expected: ArrayRef = Arc::new(Int64Array::from(expected));
4273 assert_eq!(&index_result, &index_expected);
4274 }
4275 }
4276
4277 #[test]
4278 fn test_variant_get_list_like_unsafe_cast_errors_on_element_mismatch() {
4279 let string_array: ArrayRef =
4280 Arc::new(StringArray::from(vec![r#"[1, "two", 3]"#, "[4, 5]"]));
4281 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4282 let cast_options = CastOptions {
4283 safe: false,
4284 ..Default::default()
4285 };
4286
4287 let item_field = Arc::new(Field::new("item", DataType::Int64, true));
4288 let request_types = vec![
4289 DataType::List(item_field.clone()),
4290 DataType::LargeList(item_field.clone()),
4291 DataType::ListView(item_field.clone()),
4292 DataType::LargeListView(item_field),
4293 ];
4294
4295 for request_type in request_types {
4296 let options = GetOptions::new()
4297 .with_as_type(Some(FieldRef::from(Field::new(
4298 "result",
4299 request_type.clone(),
4300 true,
4301 ))))
4302 .with_cast_options(cast_options.clone());
4303
4304 let err = variant_get(&variant_array, options).unwrap_err();
4305 assert!(
4306 err.to_string()
4307 .contains("Failed to extract primitive of type Int64")
4308 );
4309 }
4310 }
4311
4312 #[test]
4313 fn test_variant_get_list_like_unsafe_cast_errors_on_non_list() {
4314 let string_array: ArrayRef = Arc::new(StringArray::from(vec!["[1, 2]", "\"not a list\""]));
4315 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4316 let cast_options = CastOptions {
4317 safe: false,
4318 ..Default::default()
4319 };
4320 let item_field = Arc::new(Field::new("item", Int64, true));
4321 let data_types = vec![
4322 DataType::List(item_field.clone()),
4323 DataType::LargeList(item_field.clone()),
4324 DataType::ListView(item_field.clone()),
4325 DataType::LargeListView(item_field),
4326 ];
4327
4328 for data_type in data_types {
4329 let options = GetOptions::new()
4330 .with_as_type(Some(FieldRef::from(Field::new("result", data_type, true))))
4331 .with_cast_options(cast_options.clone());
4332
4333 let err = variant_get(&variant_array, options).unwrap_err();
4334 assert!(
4335 err.to_string()
4336 .contains("Failed to extract list from variant"),
4337 );
4338 }
4339 }
4340
4341 #[test]
4342 fn test_variant_get_fixed_size_list_not_implemented() {
4343 let string_array: ArrayRef = Arc::new(StringArray::from(vec!["[1, 2]", "\"not a list\""]));
4344 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4345 let item_field = Arc::new(Field::new("item", Int64, true));
4346 for safe in [true, false] {
4347 let options = GetOptions::new()
4348 .with_as_type(Some(FieldRef::from(Field::new(
4349 "result",
4350 DataType::FixedSizeList(item_field.clone(), 2),
4351 true,
4352 ))))
4353 .with_cast_options(CastOptions {
4354 safe,
4355 ..Default::default()
4356 });
4357
4358 let err = variant_get(&variant_array, options).unwrap_err();
4359 assert!(
4360 err.to_string()
4361 .contains("Converting unshredded variant arrays to arrow fixed-size lists")
4362 );
4363 }
4364 }
4365}