1use arrow::{
18 array::{
19 self, Array, ArrayRef, GenericListArray, GenericListViewArray, ListLikeArray, StructArray,
20 UInt64Array, make_array,
21 },
22 buffer::NullBuffer,
23 compute::{CastOptions, take},
24 datatypes::Field,
25 error::Result,
26};
27use arrow_schema::{ArrowError, DataType, FieldRef};
28use parquet_variant::{VariantPath, VariantPathElement};
29
30use crate::ShreddingState;
31use crate::VariantArray;
32use crate::variant_to_arrow::make_variant_to_arrow_row_builder;
33
34use arrow::array::AsArray;
35use std::sync::Arc;
36
37pub(crate) enum ShreddedPathStep {
38 Success(ShreddingState),
40 Missing,
43 NotShredded,
47}
48
49fn take_list_like_index_as_shredding_state<L: ListLikeArray + 'static>(
52 typed_value: &dyn Array,
53 index: usize,
54) -> Result<Option<ShreddingState>> {
55 let list_array = typed_value.as_any().downcast_ref::<L>().ok_or_else(|| {
56 ArrowError::ComputeError(format!(
57 "Expected array type '{}' while handling list-like path step, got '{}'",
58 std::any::type_name::<L>(),
59 typed_value.data_type()
60 ))
61 })?;
62
63 let values = list_array.values();
64
65 let Some(struct_array) = values.as_struct_opt() else {
66 return Ok(None);
67 };
68 let shredding_state = ShreddingState::try_from(struct_array)?;
69
70 let value_array = shredding_state.value_field();
71 let typed_array = shredding_state.typed_value_field();
72
73 if value_array.is_none() && typed_array.is_none() {
75 return Ok(None);
76 }
77
78 let mut take_indices = Vec::with_capacity(list_array.len());
79 for row in 0..list_array.len() {
80 let row_range = list_array.element_range(row);
81 let take_index = (index < row_range.len()).then(|| (row_range.start + index) as u64);
82 take_indices.push(take_index);
83 }
84
85 let index_array = UInt64Array::from(take_indices);
86
87 let taken_value = value_array
89 .map(|value| take(value, &index_array, None))
90 .transpose()?;
91 let taken_typed = typed_array
92 .map(|typed| take(typed, &index_array, None))
93 .transpose()?;
94
95 Ok(Some(ShreddingState::new(taken_value, taken_typed)))
96}
97
98pub(crate) fn follow_shredded_path_element(
114 shredding_state: &ShreddingState,
115 path_element: &VariantPathElement<'_>,
116 _cast_options: &CastOptions,
117) -> Result<ShreddedPathStep> {
118 let missing_path_step = || match shredding_state.value_field() {
121 Some(_) => ShreddedPathStep::NotShredded,
122 None => ShreddedPathStep::Missing,
123 };
124
125 let Some(typed_value) = shredding_state.typed_value_field() else {
126 return Ok(missing_path_step());
127 };
128
129 match path_element {
130 VariantPathElement::Field { name } => {
131 let Some(struct_array) = typed_value.as_struct_opt() else {
134 return Ok(missing_path_step());
136 };
137
138 let Some(field) = struct_array.column_by_name(name) else {
140 return Ok(missing_path_step());
142 };
143
144 let struct_array = field.as_struct_opt().ok_or_else(|| {
145 ArrowError::InvalidArgumentError(format!(
149 "Expected Struct array while following path, got {}",
150 field.data_type(),
151 ))
152 })?;
153
154 let state = ShreddingState::try_from(struct_array)?;
155 Ok(ShreddedPathStep::Success(state))
156 }
157 VariantPathElement::Index { index } => {
158 let state = match typed_value.data_type() {
159 DataType::List(_) => take_list_like_index_as_shredding_state::<
160 GenericListArray<i32>,
161 >(typed_value.as_ref(), *index)?,
162 DataType::LargeList(_) => take_list_like_index_as_shredding_state::<
163 GenericListArray<i64>,
164 >(typed_value.as_ref(), *index)?,
165 DataType::ListView(_) => take_list_like_index_as_shredding_state::<
166 GenericListViewArray<i32>,
167 >(typed_value.as_ref(), *index)?,
168 DataType::LargeListView(_) => take_list_like_index_as_shredding_state::<
169 GenericListViewArray<i64>,
170 >(typed_value.as_ref(), *index)?,
171 _ => {
172 return Ok(missing_path_step());
174 }
175 };
176
177 match state {
178 Some(state) => Ok(ShreddedPathStep::Success(state)),
179 None => Ok(missing_path_step()),
180 }
181 }
182 }
183}
184
185fn shredded_get_path(
189 input: &VariantArray,
190 path: &[VariantPathElement<'_>],
191 as_field: Option<&Field>,
192 cast_options: &CastOptions,
193) -> Result<ArrayRef> {
194 let make_target_variant =
197 |value: Option<ArrayRef>,
198 typed_value: Option<ArrayRef>,
199 accumulated_nulls: Option<NullBuffer>| {
200 let metadata = input.metadata_field().clone();
201 VariantArray::from_parts(metadata, value, typed_value, accumulated_nulls)
202 };
203
204 let shred_basic_variant =
206 |target: VariantArray, path: VariantPath<'_>, as_field: Option<&Field>| {
207 let as_type = as_field.map(|f| f.data_type());
208 let mut builder = make_variant_to_arrow_row_builder(
209 target.metadata_field(),
210 path,
211 as_type,
212 cast_options,
213 target.len(),
214 )?;
215 for i in 0..target.len() {
216 if target.is_null(i) {
217 builder.append_null()?;
218 } else if !cast_options.safe {
219 let value = target.try_value(i)?;
220 builder.append_value(value)?;
221 } else {
222 let _ = match target.try_value(i) {
223 Ok(v) => builder.append_value(v)?,
224 Err(_) => {
225 builder.append_null()?;
226 false }
228 };
229 }
230 }
231 builder.finish()
232 };
233
234 let mut shredding_state = input.shredding_state().clone();
237 let mut accumulated_nulls = input.inner().nulls().cloned();
238 let mut path_index = 0;
239 for path_element in path {
240 match follow_shredded_path_element(&shredding_state, path_element, cast_options)? {
241 ShreddedPathStep::Success(state) => {
242 if let Some(typed_value) = shredding_state.typed_value_field() {
244 accumulated_nulls =
245 NullBuffer::union(accumulated_nulls.as_ref(), typed_value.nulls());
246 }
247 shredding_state = state;
248 path_index += 1;
249 continue;
250 }
251 ShreddedPathStep::Missing => {
252 let num_rows = input.len();
253 let arr = match as_field.map(|f| f.data_type()) {
254 Some(data_type) => array::new_null_array(data_type, num_rows),
255 None => Arc::new(array::NullArray::new(num_rows)) as _,
256 };
257 return Ok(arr);
258 }
259 ShreddedPathStep::NotShredded => {
260 let target = make_target_variant(
261 shredding_state.value_field().cloned(),
262 None,
263 accumulated_nulls,
264 );
265 return shred_basic_variant(target, path[path_index..].into(), as_field);
266 }
267 };
268 }
269
270 let target = make_target_variant(
272 shredding_state.value_field().cloned(),
273 shredding_state.typed_value_field().cloned(),
274 accumulated_nulls,
275 );
276
277 let Some(as_field) = as_field else {
279 return Ok(ArrayRef::from(target));
280 };
281
282 if let Some(shredded) = try_perfect_shredding(&target, as_field) {
284 return Ok(shredded);
285 }
286
287 if let DataType::Struct(fields) = as_field.data_type() {
297 if target.typed_value_field().is_none() {
298 return shred_basic_variant(target, VariantPath::default(), Some(as_field));
299 }
300
301 let children = fields
302 .iter()
303 .map(|field| {
304 shredded_get_path(
305 &target,
306 &[VariantPathElement::from(field.name().as_str())],
307 Some(field),
308 cast_options,
309 )
310 })
311 .collect::<Result<Vec<_>>>()?;
312
313 let struct_nulls = target.nulls().cloned();
314
315 return Ok(Arc::new(StructArray::try_new(
316 fields.clone(),
317 children,
318 struct_nulls,
319 )?));
320 }
321
322 shred_basic_variant(target, VariantPath::default(), Some(as_field))
324}
325
326fn try_perfect_shredding(variant_array: &VariantArray, as_field: &Field) -> Option<ArrayRef> {
327 if matches!(as_field.data_type(), DataType::Struct(_)) {
329 return None;
330 }
331 let typed_value = variant_array.typed_value_field()?;
332
333 if typed_value.data_type() == as_field.data_type()
334 && variant_array
335 .value_field()
336 .is_none_or(|v| v.null_count() == v.len())
337 {
338 let parent_nulls = variant_array.nulls();
345
346 let target_array = if parent_nulls.is_none() || typed_value.data_type().is_null() {
348 typed_value.clone()
349 } else {
350 let merged_nulls = NullBuffer::union(parent_nulls, typed_value.nulls());
351 let data = typed_value
352 .to_data()
353 .into_builder()
354 .nulls(merged_nulls)
355 .build()
356 .ok()?;
357 make_array(data)
358 };
359
360 return Some(target_array);
361 }
362
363 None
364}
365
366pub fn variant_get(input: &ArrayRef, options: GetOptions) -> Result<ArrayRef> {
378 let variant_array = VariantArray::try_new(input)?;
379
380 let GetOptions {
381 as_type,
382 path,
383 cast_options,
384 } = options;
385
386 shredded_get_path(&variant_array, &path, as_type.as_deref(), &cast_options)
387}
388
389#[derive(Debug, Clone, Default)]
391pub struct GetOptions<'a> {
392 pub path: VariantPath<'a>,
394 pub as_type: Option<FieldRef>,
398 pub cast_options: CastOptions<'a>,
400}
401
402impl<'a> GetOptions<'a> {
403 pub fn new() -> Self {
405 Default::default()
406 }
407
408 pub fn new_with_path(path: VariantPath<'a>) -> Self {
410 Self {
411 path,
412 as_type: None,
413 cast_options: Default::default(),
414 }
415 }
416
417 pub fn with_as_type(mut self, as_type: Option<FieldRef>) -> Self {
419 self.as_type = as_type;
420 self
421 }
422
423 pub fn with_cast_options(mut self, cast_options: CastOptions<'a>) -> Self {
425 self.cast_options = cast_options;
426 self
427 }
428}
429
430#[cfg(test)]
431mod test {
432 use std::str::FromStr;
433 use std::sync::Arc;
434
435 use super::{GetOptions, variant_get};
436 use crate::variant_array::{ShreddedVariantFieldArray, StructArrayBuilder};
437 use crate::{
438 ShreddedSchemaBuilder, VariantArray, VariantArrayBuilder, cast_to_variant, json_to_variant,
439 shred_variant,
440 };
441 use arrow::array::{
442 Array, ArrayRef, AsArray, BinaryArray, BinaryViewArray, BooleanArray, Date32Array,
443 Date64Array, Decimal32Array, Decimal64Array, Decimal128Array, Decimal256Array,
444 FixedSizeListArray, Float32Array, Float64Array, Int8Array, Int16Array, Int32Array,
445 Int64Array, LargeBinaryArray, LargeListArray, LargeListViewArray, LargeStringArray,
446 ListArray, ListViewArray, NullArray, NullBuilder, StringArray, StringViewArray,
447 StructArray, Time32MillisecondArray, Time32SecondArray, Time64MicrosecondArray,
448 Time64NanosecondArray,
449 };
450 use arrow::buffer::{NullBuffer, OffsetBuffer, ScalarBuffer};
451 use arrow::compute::{CastOptions, cast};
452 use arrow::datatypes::DataType::{Int16, Int32, Int64};
453 use arrow::datatypes::i256;
454 use arrow::util::display::FormatOptions;
455 use arrow_schema::DataType::{Boolean, Float32, Float64, Int8};
456 use arrow_schema::{DataType, Field, FieldRef, Fields, IntervalUnit, TimeUnit};
457 use chrono::DateTime;
458 use parquet_variant::{
459 EMPTY_VARIANT_METADATA_BYTES, Variant, VariantDecimal4, VariantDecimal8, VariantDecimal16,
460 VariantDecimalType, VariantPath,
461 };
462
463 fn single_variant_get_test(input_json: &str, path: VariantPath, expected_json: &str) {
464 let input_array_ref: ArrayRef = Arc::new(StringArray::from(vec![Some(input_json)]));
466 let input_variant_array_ref = ArrayRef::from(json_to_variant(&input_array_ref).unwrap());
467
468 let result =
469 variant_get(&input_variant_array_ref, GetOptions::new_with_path(path)).unwrap();
470
471 let expected_array_ref: ArrayRef = Arc::new(StringArray::from(vec![Some(expected_json)]));
473 let expected_variant_array = json_to_variant(&expected_array_ref).unwrap();
474
475 let result_array = VariantArray::try_new(&result).unwrap();
476 assert_eq!(
477 result_array.len(),
478 1,
479 "Expected result array to have length 1"
480 );
481 assert!(
482 result_array.nulls().is_none(),
483 "Expected no nulls in result array"
484 );
485 let result_variant = result_array.value(0);
486 let expected_variant = expected_variant_array.value(0);
487 assert_eq!(
488 result_variant, expected_variant,
489 "Result variant does not match expected variant"
490 );
491 }
492
493 #[test]
494 fn get_primitive_variant_field() {
495 single_variant_get_test(
496 r#"{"some_field": 1234}"#,
497 VariantPath::try_from("some_field").unwrap(),
498 "1234",
499 );
500 }
501
502 #[test]
503 fn get_primitive_variant_list_index() {
504 single_variant_get_test("[1234, 5678]", VariantPath::from(0), "1234");
505 }
506
507 #[test]
508 fn get_primitive_variant_inside_object_of_object() {
509 single_variant_get_test(
510 r#"{"top_level_field": {"inner_field": 1234}}"#,
511 VariantPath::try_from("top_level_field")
512 .unwrap()
513 .join("inner_field"),
514 "1234",
515 );
516 }
517
518 #[test]
519 fn get_primitive_variant_inside_list_of_object() {
520 single_variant_get_test(
521 r#"[{"some_field": 1234}]"#,
522 VariantPath::from(0).join("some_field"),
523 "1234",
524 );
525 }
526
527 #[test]
528 fn get_primitive_variant_inside_object_of_list() {
529 single_variant_get_test(
530 r#"{"some_field": [1234]}"#,
531 VariantPath::try_from("some_field[0]").unwrap(),
532 "1234",
533 );
534 }
535
536 #[test]
537 fn get_complex_variant() {
538 single_variant_get_test(
539 r#"{"top_level_field": {"inner_field": 1234}}"#,
540 VariantPath::try_from("top_level_field").unwrap(),
541 r#"{"inner_field": 1234}"#,
542 );
543 }
544
545 macro_rules! numeric_partially_shredded_test {
547 ($primitive_type:ty, $data_fn:ident) => {
548 let array = $data_fn();
549 let options = GetOptions::new();
550 let result = variant_get(&array, options).unwrap();
551
552 let result = VariantArray::try_new(&result).unwrap();
554 assert_eq!(result.len(), 4);
555
556 assert_eq!(
558 result.value(0),
559 Variant::from(<$primitive_type>::try_from(34u8).unwrap())
560 );
561 assert!(!result.is_valid(1));
562 assert_eq!(result.value(2), Variant::from("n/a"));
563 assert_eq!(
564 result.value(3),
565 Variant::from(<$primitive_type>::try_from(100u8).unwrap())
566 );
567 };
568 }
569
570 macro_rules! partially_shredded_variant_array_gen {
573 ($func_name:ident, $typed_value_array_gen: expr) => {
574 partially_shredded_variant_array_gen!(
575 $func_name,
576 $typed_value_array_gen,
577 Variant::from("n/a")
578 );
579 };
580 ($func_name:ident, $typed_value_array_gen: expr, $fallback_variant:expr) => {
581 fn $func_name() -> ArrayRef {
582 let typed_value: ArrayRef = Arc::new($typed_value_array_gen());
583 let typed_as_variant = cast_to_variant(typed_value.as_ref())
584 .expect("should cast typed array to variant");
585 let mut input_builder = VariantArrayBuilder::new(typed_as_variant.len());
586 input_builder.append_variant(typed_as_variant.value(0));
587 input_builder.append_null();
588 input_builder.append_variant($fallback_variant);
589 input_builder.append_variant(typed_as_variant.value(3));
590
591 let variant_array = shred_variant(&input_builder.build(), typed_value.data_type())
592 .expect("should shred variant array");
593 ArrayRef::from(variant_array)
594 }
595 };
596 }
597
598 macro_rules! numeric_partially_shredded_variant_array_fn {
600 ($func:ident, $array_type:ident, $primitive_type:ty) => {
601 partially_shredded_variant_array_gen!($func, || $array_type::from(vec![
602 Some(<$primitive_type>::try_from(34u8).unwrap()),
603 None,
604 None,
605 Some(<$primitive_type>::try_from(100u8).unwrap()),
606 ]));
607 };
608 }
609
610 numeric_partially_shredded_variant_array_fn!(
611 partially_shredded_int8_variant_array,
612 Int8Array,
613 i8
614 );
615 numeric_partially_shredded_variant_array_fn!(
616 partially_shredded_int16_variant_array,
617 Int16Array,
618 i16
619 );
620 numeric_partially_shredded_variant_array_fn!(
621 partially_shredded_int32_variant_array,
622 Int32Array,
623 i32
624 );
625 numeric_partially_shredded_variant_array_fn!(
626 partially_shredded_int64_variant_array,
627 Int64Array,
628 i64
629 );
630 numeric_partially_shredded_variant_array_fn!(
631 partially_shredded_float32_variant_array,
632 Float32Array,
633 f32
634 );
635 numeric_partially_shredded_variant_array_fn!(
636 partially_shredded_float64_variant_array,
637 Float64Array,
638 f64
639 );
640
641 partially_shredded_variant_array_gen!(partially_shredded_bool_variant_array, || {
642 arrow::array::BooleanArray::from(vec![Some(true), None, None, Some(false)])
643 });
644
645 partially_shredded_variant_array_gen!(
646 partially_shredded_utf8_variant_array,
647 || { StringArray::from(vec![Some("hello"), None, None, Some("world")]) },
648 Variant::from(42i32)
649 );
650
651 partially_shredded_variant_array_gen!(partially_shredded_date32_variant_array, || {
652 Date32Array::from(vec![
653 Some(20348), None,
655 None,
656 Some(20340), ])
658 });
659
660 #[test]
661 fn get_variant_partially_shredded_int8_as_variant() {
662 numeric_partially_shredded_test!(i8, partially_shredded_int8_variant_array);
663 }
664
665 #[test]
666 fn get_variant_partially_shredded_int16_as_variant() {
667 numeric_partially_shredded_test!(i16, partially_shredded_int16_variant_array);
668 }
669
670 #[test]
671 fn get_variant_partially_shredded_int32_as_variant() {
672 numeric_partially_shredded_test!(i32, partially_shredded_int32_variant_array);
673 }
674
675 #[test]
676 fn get_variant_partially_shredded_int64_as_variant() {
677 numeric_partially_shredded_test!(i64, partially_shredded_int64_variant_array);
678 }
679
680 #[test]
681 fn get_variant_partially_shredded_float32_as_variant() {
682 numeric_partially_shredded_test!(f32, partially_shredded_float32_variant_array);
683 }
684
685 #[test]
686 fn get_variant_partially_shredded_float64_as_variant() {
687 numeric_partially_shredded_test!(f64, partially_shredded_float64_variant_array);
688 }
689
690 #[test]
691 fn get_variant_partially_shredded_bool_as_variant() {
692 let array = partially_shredded_bool_variant_array();
693 let options = GetOptions::new();
694 let result = variant_get(&array, options).unwrap();
695
696 let result = VariantArray::try_new(&result).unwrap();
698 assert_eq!(result.len(), 4);
699
700 assert_eq!(result.value(0), Variant::from(true));
702 assert!(!result.is_valid(1));
703 assert_eq!(result.value(2), Variant::from("n/a"));
704 assert_eq!(result.value(3), Variant::from(false));
705 }
706
707 #[test]
708 fn get_variant_partially_shredded_utf8_as_variant() {
709 let array = partially_shredded_utf8_variant_array();
710 let options = GetOptions::new();
711 let result = variant_get(&array, options).unwrap();
712
713 let result = VariantArray::try_new(&result).unwrap();
715 assert_eq!(result.len(), 4);
716
717 assert_eq!(result.value(0), Variant::from("hello"));
719 assert!(!result.is_valid(1));
720 assert_eq!(result.value(2), Variant::from(42i32));
721 assert_eq!(result.value(3), Variant::from("world"));
722 }
723
724 partially_shredded_variant_array_gen!(partially_shredded_binary_view_variant_array, || {
725 BinaryViewArray::from(vec![
726 Some(&[1u8, 2u8, 3u8][..]), None, None, Some(&[4u8, 5u8, 6u8][..]), ])
731 });
732
733 #[test]
734 fn get_variant_partially_shredded_date32_as_variant() {
735 let array = partially_shredded_date32_variant_array();
736 let options = GetOptions::new();
737 let result = variant_get(&array, options).unwrap();
738
739 let result = VariantArray::try_new(&result).unwrap();
741 assert_eq!(result.len(), 4);
742
743 use chrono::NaiveDate;
745 let date1 = NaiveDate::from_ymd_opt(2025, 9, 17).unwrap();
746 let date2 = NaiveDate::from_ymd_opt(2025, 9, 9).unwrap();
747 assert_eq!(result.value(0), Variant::from(date1));
748 assert!(!result.is_valid(1));
749 assert_eq!(result.value(2), Variant::from("n/a"));
750 assert_eq!(result.value(3), Variant::from(date2));
751 }
752
753 #[test]
754 fn get_variant_partially_shredded_binary_view_as_variant() {
755 let array = partially_shredded_binary_view_variant_array();
756 let options = GetOptions::new();
757 let result = variant_get(&array, options).unwrap();
758
759 let result = VariantArray::try_new(&result).unwrap();
761 assert_eq!(result.len(), 4);
762
763 assert_eq!(result.value(0), Variant::from(&[1u8, 2u8, 3u8][..]));
765 assert!(!result.is_valid(1));
766 assert_eq!(result.value(2), Variant::from("n/a"));
767 assert_eq!(result.value(3), Variant::from(&[4u8, 5u8, 6u8][..]));
768 }
769
770 macro_rules! assert_variant_get_as_variant_array_with_default_option {
772 ($variant_array: expr, $array_expected: expr) => {{
773 let options = GetOptions::new();
774 let array = $variant_array;
775 let result = variant_get(&array, options).unwrap();
776 let result = VariantArray::try_new(&result).unwrap();
777
778 assert_eq!(result.len(), $array_expected.len());
779
780 for (idx, item) in $array_expected.into_iter().enumerate() {
781 match item {
782 Some(item) => assert_eq!(result.value(idx), item),
783 None => assert!(result.is_null(idx)),
784 }
785 }
786 }};
787 }
788
789 partially_shredded_variant_array_gen!(
790 partially_shredded_timestamp_micro_ntz_variant_array,
791 || {
792 arrow::array::TimestampMicrosecondArray::from(vec![
793 Some(-456000),
794 None,
795 None,
796 Some(1758602096000000),
797 ])
798 }
799 );
800
801 #[test]
802 fn get_variant_partial_shredded_timestamp_micro_ntz_as_variant() {
803 let array = partially_shredded_timestamp_micro_ntz_variant_array();
804 assert_variant_get_as_variant_array_with_default_option!(
805 array,
806 vec![
807 Some(Variant::from(
808 DateTime::from_timestamp_micros(-456000i64)
809 .unwrap()
810 .naive_utc(),
811 )),
812 None,
813 Some(Variant::from("n/a")),
814 Some(Variant::from(
815 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
816 .unwrap()
817 .naive_utc(),
818 )),
819 ]
820 )
821 }
822
823 partially_shredded_variant_array_gen!(partially_shredded_timestamp_micro_variant_array, || {
824 arrow::array::TimestampMicrosecondArray::from(vec![
825 Some(-456000),
826 None,
827 None,
828 Some(1758602096000000),
829 ])
830 .with_timezone("+00:00")
831 });
832
833 #[test]
834 fn get_variant_partial_shredded_timestamp_micro_as_variant() {
835 let array = partially_shredded_timestamp_micro_variant_array();
836 assert_variant_get_as_variant_array_with_default_option!(
837 array,
838 vec![
839 Some(Variant::from(
840 DateTime::from_timestamp_micros(-456000i64)
841 .unwrap()
842 .to_utc(),
843 )),
844 None,
845 Some(Variant::from("n/a")),
846 Some(Variant::from(
847 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
848 .unwrap()
849 .to_utc(),
850 )),
851 ]
852 )
853 }
854
855 partially_shredded_variant_array_gen!(
856 partially_shredded_timestamp_nano_ntz_variant_array,
857 || {
858 arrow::array::TimestampNanosecondArray::from(vec![
859 Some(-4999999561),
860 None,
861 None,
862 Some(1758602096000000000),
863 ])
864 }
865 );
866
867 #[test]
868 fn get_variant_partial_shredded_timestamp_nano_ntz_as_variant() {
869 let array = partially_shredded_timestamp_nano_ntz_variant_array();
870 assert_variant_get_as_variant_array_with_default_option!(
871 array,
872 vec![
873 Some(Variant::from(
874 DateTime::from_timestamp(-5, 439).unwrap().naive_utc()
875 )),
876 None,
877 Some(Variant::from("n/a")),
878 Some(Variant::from(
879 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
880 .unwrap()
881 .naive_utc()
882 )),
883 ]
884 )
885 }
886
887 partially_shredded_variant_array_gen!(partially_shredded_timestamp_nano_variant_array, || {
888 arrow::array::TimestampNanosecondArray::from(vec![
889 Some(-4999999561),
890 None,
891 None,
892 Some(1758602096000000000),
893 ])
894 .with_timezone("+00:00")
895 });
896
897 #[test]
898 fn get_variant_partial_shredded_timestamp_nano_as_variant() {
899 let array = partially_shredded_timestamp_nano_variant_array();
900 assert_variant_get_as_variant_array_with_default_option!(
901 array,
902 vec![
903 Some(Variant::from(
904 DateTime::from_timestamp(-5, 439).unwrap().to_utc()
905 )),
906 None,
907 Some(Variant::from("n/a")),
908 Some(Variant::from(
909 DateTime::parse_from_rfc3339("2025-09-23T12:34:56+08:00")
910 .unwrap()
911 .to_utc()
912 )),
913 ]
914 )
915 }
916
917 #[test]
919 fn get_variant_shredded_int32_as_int32_safe_cast() {
920 let array = partially_shredded_int32_variant_array();
922 let field = Field::new("typed_value", DataType::Int32, true);
924 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
925 let result = variant_get(&array, options).unwrap();
926 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
927 Some(34),
928 None,
929 None, Some(100),
931 ]));
932 assert_eq!(&result, &expected)
933 }
934
935 #[test]
937 fn get_variant_shredded_int32_as_int32_unsafe_cast() {
938 let array = partially_shredded_int32_variant_array();
940 let field = Field::new("typed_value", DataType::Int32, true);
941 let cast_options = CastOptions {
942 safe: false, ..Default::default()
944 };
945 let options = GetOptions::new()
946 .with_as_type(Some(FieldRef::from(field)))
947 .with_cast_options(cast_options);
948
949 let err = variant_get(&array, options).unwrap_err();
950 assert_eq!(
952 err.to_string(),
953 "Cast error: Failed to extract primitive of type Int32 from variant ShortString(ShortString(\"n/a\")) at path VariantPath([])"
954 );
955 }
956
957 macro_rules! numeric_perfectly_shredded_test {
959 ($primitive_type:ty, $data_fn:ident) => {
960 let array = $data_fn();
961 let options = GetOptions::new();
962 let result = variant_get(&array, options).unwrap();
963
964 let result = VariantArray::try_new(&result).unwrap();
966 assert_eq!(result.len(), 3);
967
968 assert_eq!(
970 result.value(0),
971 Variant::from(<$primitive_type>::try_from(1u8).unwrap())
972 );
973 assert_eq!(
974 result.value(1),
975 Variant::from(<$primitive_type>::try_from(2u8).unwrap())
976 );
977 assert_eq!(
978 result.value(2),
979 Variant::from(<$primitive_type>::try_from(3u8).unwrap())
980 );
981 };
982 }
983
984 #[test]
985 fn get_variant_perfectly_shredded_int8_as_variant() {
986 numeric_perfectly_shredded_test!(i8, perfectly_shredded_int8_variant_array);
987 }
988
989 #[test]
990 fn get_variant_perfectly_shredded_int16_as_variant() {
991 numeric_perfectly_shredded_test!(i16, perfectly_shredded_int16_variant_array);
992 }
993
994 #[test]
995 fn get_variant_perfectly_shredded_int32_as_variant() {
996 numeric_perfectly_shredded_test!(i32, perfectly_shredded_int32_variant_array);
997 }
998
999 #[test]
1000 fn get_variant_perfectly_shredded_int64_as_variant() {
1001 numeric_perfectly_shredded_test!(i64, perfectly_shredded_int64_variant_array);
1002 }
1003
1004 #[test]
1005 fn get_variant_perfectly_shredded_float32_as_variant() {
1006 numeric_perfectly_shredded_test!(f32, perfectly_shredded_float32_variant_array);
1007 }
1008
1009 #[test]
1010 fn get_variant_perfectly_shredded_float64_as_variant() {
1011 numeric_perfectly_shredded_test!(f64, perfectly_shredded_float64_variant_array);
1012 }
1013
1014 #[test]
1016 fn get_variant_all_null_as_variant() {
1017 let array = all_null_variant_array();
1018 let options = GetOptions::new();
1019 let result = variant_get(&array, options).unwrap();
1020
1021 let result = VariantArray::try_new(&result).unwrap();
1023 assert_eq!(result.len(), 3);
1024
1025 assert!(!result.is_valid(0));
1027 assert!(!result.is_valid(1));
1028 assert!(!result.is_valid(2));
1029 }
1030
1031 #[test]
1033 fn get_variant_all_null_as_int32() {
1034 let array = all_null_variant_array();
1035 let field = Field::new("typed_value", DataType::Int32, true);
1037 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
1038 let result = variant_get(&array, options).unwrap();
1039
1040 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
1041 Option::<i32>::None,
1042 Option::<i32>::None,
1043 Option::<i32>::None,
1044 ]));
1045 assert_eq!(&result, &expected)
1046 }
1047
1048 macro_rules! perfectly_shredded_to_arrow_primitive_test {
1049 ($name:ident, $primitive_type:expr, $perfectly_shredded_array_gen_fun:ident, $expected_array:expr) => {
1050 #[test]
1051 fn $name() {
1052 let array = $perfectly_shredded_array_gen_fun();
1053 let field = Field::new("typed_value", $primitive_type, true);
1054 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
1055 let result = variant_get(&array, options).unwrap();
1056 let expected_array: ArrayRef = Arc::new($expected_array);
1057 assert_eq!(&result, &expected_array);
1058 }
1059 };
1060 }
1061
1062 perfectly_shredded_to_arrow_primitive_test!(
1063 get_variant_perfectly_shredded_int18_as_int8,
1064 Int8,
1065 perfectly_shredded_int8_variant_array,
1066 Int8Array::from(vec![Some(1), Some(2), Some(3)])
1067 );
1068
1069 perfectly_shredded_to_arrow_primitive_test!(
1070 get_variant_perfectly_shredded_int16_as_int16,
1071 Int16,
1072 perfectly_shredded_int16_variant_array,
1073 Int16Array::from(vec![Some(1), Some(2), Some(3)])
1074 );
1075
1076 perfectly_shredded_to_arrow_primitive_test!(
1077 get_variant_perfectly_shredded_int32_as_int32,
1078 Int32,
1079 perfectly_shredded_int32_variant_array,
1080 Int32Array::from(vec![Some(1), Some(2), Some(3)])
1081 );
1082
1083 perfectly_shredded_to_arrow_primitive_test!(
1084 get_variant_perfectly_shredded_int64_as_int64,
1085 Int64,
1086 perfectly_shredded_int64_variant_array,
1087 Int64Array::from(vec![Some(1), Some(2), Some(3)])
1088 );
1089
1090 perfectly_shredded_to_arrow_primitive_test!(
1091 get_variant_perfectly_shredded_float32_as_float32,
1092 Float32,
1093 perfectly_shredded_float32_variant_array,
1094 Float32Array::from(vec![Some(1.0), Some(2.0), Some(3.0)])
1095 );
1096
1097 perfectly_shredded_to_arrow_primitive_test!(
1098 get_variant_perfectly_shredded_float64_as_float64,
1099 Float64,
1100 perfectly_shredded_float64_variant_array,
1101 Float64Array::from(vec![Some(1.0), Some(2.0), Some(3.0)])
1102 );
1103
1104 perfectly_shredded_to_arrow_primitive_test!(
1105 get_variant_perfectly_shredded_boolean_as_boolean,
1106 Boolean,
1107 perfectly_shredded_bool_variant_array,
1108 BooleanArray::from(vec![Some(true), Some(false), Some(true)])
1109 );
1110
1111 perfectly_shredded_to_arrow_primitive_test!(
1112 get_variant_perfectly_shredded_utf8_as_utf8,
1113 DataType::Utf8,
1114 perfectly_shredded_utf8_variant_array,
1115 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1116 );
1117
1118 perfectly_shredded_to_arrow_primitive_test!(
1119 get_variant_perfectly_shredded_large_utf8_as_utf8,
1120 DataType::Utf8,
1121 perfectly_shredded_large_utf8_variant_array,
1122 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1123 );
1124
1125 perfectly_shredded_to_arrow_primitive_test!(
1126 get_variant_perfectly_shredded_utf8_view_as_utf8,
1127 DataType::Utf8,
1128 perfectly_shredded_utf8_view_variant_array,
1129 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1130 );
1131
1132 macro_rules! perfectly_shredded_variant_array_fn {
1133 ($func:ident, $typed_value_gen:expr) => {
1134 fn $func() -> ArrayRef {
1135 let typed_value: ArrayRef = Arc::new($typed_value_gen());
1138 if let Some(shredded) = cast_to_variant(typed_value.as_ref())
1139 .ok()
1140 .and_then(|unshredded| shred_variant(&unshredded, typed_value.data_type()).ok())
1141 {
1142 return shredded.into();
1143 }
1144
1145 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(
1146 EMPTY_VARIANT_METADATA_BYTES,
1147 typed_value.len(),
1148 ));
1149 VariantArray::from_parts(Arc::new(metadata), None, Some(typed_value), None).into()
1150 }
1151 };
1152 }
1153
1154 perfectly_shredded_variant_array_fn!(perfectly_shredded_utf8_variant_array, || {
1155 StringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1156 });
1157
1158 perfectly_shredded_variant_array_fn!(perfectly_shredded_large_utf8_variant_array, || {
1159 LargeStringArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1160 });
1161
1162 perfectly_shredded_variant_array_fn!(perfectly_shredded_utf8_view_variant_array, || {
1163 StringViewArray::from(vec![Some("foo"), Some("bar"), Some("baz")])
1164 });
1165
1166 perfectly_shredded_variant_array_fn!(perfectly_shredded_bool_variant_array, || {
1167 BooleanArray::from(vec![Some(true), Some(false), Some(true)])
1168 });
1169
1170 macro_rules! numeric_perfectly_shredded_variant_array_fn {
1182 ($func:ident, $array_type:ident, $primitive_type:ty) => {
1183 perfectly_shredded_variant_array_fn!($func, || {
1184 $array_type::from(vec![
1185 Some(<$primitive_type>::try_from(1u8).unwrap()),
1186 Some(<$primitive_type>::try_from(2u8).unwrap()),
1187 Some(<$primitive_type>::try_from(3u8).unwrap()),
1188 ])
1189 });
1190 };
1191 }
1192
1193 numeric_perfectly_shredded_variant_array_fn!(
1194 perfectly_shredded_int8_variant_array,
1195 Int8Array,
1196 i8
1197 );
1198 numeric_perfectly_shredded_variant_array_fn!(
1199 perfectly_shredded_int16_variant_array,
1200 Int16Array,
1201 i16
1202 );
1203 numeric_perfectly_shredded_variant_array_fn!(
1204 perfectly_shredded_int32_variant_array,
1205 Int32Array,
1206 i32
1207 );
1208 numeric_perfectly_shredded_variant_array_fn!(
1209 perfectly_shredded_int64_variant_array,
1210 Int64Array,
1211 i64
1212 );
1213 numeric_perfectly_shredded_variant_array_fn!(
1214 perfectly_shredded_float32_variant_array,
1215 Float32Array,
1216 f32
1217 );
1218 numeric_perfectly_shredded_variant_array_fn!(
1219 perfectly_shredded_float64_variant_array,
1220 Float64Array,
1221 f64
1222 );
1223
1224 perfectly_shredded_variant_array_fn!(
1225 perfectly_shredded_timestamp_micro_ntz_variant_array,
1226 || {
1227 arrow::array::TimestampMicrosecondArray::from(vec![
1228 Some(-456000),
1229 Some(1758602096000001),
1230 Some(1758602096000002),
1231 ])
1232 }
1233 );
1234
1235 perfectly_shredded_to_arrow_primitive_test!(
1236 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_micro_ntz,
1237 DataType::Timestamp(TimeUnit::Microsecond, None),
1238 perfectly_shredded_timestamp_micro_ntz_variant_array,
1239 arrow::array::TimestampMicrosecondArray::from(vec![
1240 Some(-456000),
1241 Some(1758602096000001),
1242 Some(1758602096000002),
1243 ])
1244 );
1245
1246 perfectly_shredded_to_arrow_primitive_test!(
1248 get_variant_perfectly_shredded_timestamp_micro_ntz_as_nano_ntz,
1249 DataType::Timestamp(TimeUnit::Nanosecond, None),
1250 perfectly_shredded_timestamp_micro_ntz_variant_array,
1251 arrow::array::TimestampNanosecondArray::from(vec![
1252 Some(-456000000),
1253 Some(1758602096000001000),
1254 Some(1758602096000002000)
1255 ])
1256 );
1257
1258 perfectly_shredded_variant_array_fn!(perfectly_shredded_timestamp_micro_variant_array, || {
1259 arrow::array::TimestampMicrosecondArray::from(vec![
1260 Some(-456000),
1261 Some(1758602096000001),
1262 Some(1758602096000002),
1263 ])
1264 .with_timezone("+00:00")
1265 });
1266
1267 perfectly_shredded_to_arrow_primitive_test!(
1268 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_micro,
1269 DataType::Timestamp(TimeUnit::Microsecond, Some(Arc::from("+00:00"))),
1270 perfectly_shredded_timestamp_micro_variant_array,
1271 arrow::array::TimestampMicrosecondArray::from(vec![
1272 Some(-456000),
1273 Some(1758602096000001),
1274 Some(1758602096000002),
1275 ])
1276 .with_timezone("+00:00")
1277 );
1278
1279 perfectly_shredded_to_arrow_primitive_test!(
1281 get_variant_perfectly_shredded_timestamp_micro_as_nano,
1282 DataType::Timestamp(TimeUnit::Nanosecond, Some(Arc::from("+00:00"))),
1283 perfectly_shredded_timestamp_micro_variant_array,
1284 arrow::array::TimestampNanosecondArray::from(vec![
1285 Some(-456000000),
1286 Some(1758602096000001000),
1287 Some(1758602096000002000)
1288 ])
1289 .with_timezone("+00:00")
1290 );
1291
1292 perfectly_shredded_variant_array_fn!(
1293 perfectly_shredded_timestamp_nano_ntz_variant_array,
1294 || {
1295 arrow::array::TimestampNanosecondArray::from(vec![
1296 Some(-4999999561),
1297 Some(1758602096000000001),
1298 Some(1758602096000000002),
1299 ])
1300 }
1301 );
1302
1303 perfectly_shredded_variant_array_fn!(
1304 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1305 || {
1306 arrow::array::TimestampMicrosecondArray::from(vec![
1307 Some(1234), Some(1234000), Some(1234000000), ])
1311 .with_timezone("+00:00")
1312 }
1313 );
1314
1315 perfectly_shredded_to_arrow_primitive_test!(
1318 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_second,
1319 DataType::Timestamp(TimeUnit::Second, Some(Arc::from("+00:00"))),
1320 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1321 arrow::array::TimestampSecondArray::from(vec![
1322 None,
1323 None, Some(1234)
1325 ])
1326 .with_timezone("+00:00")
1327 );
1328
1329 perfectly_shredded_to_arrow_primitive_test!(
1330 get_variant_perfectly_shredded_timestamp_micro_as_timestamp_milli,
1331 DataType::Timestamp(TimeUnit::Millisecond, Some(Arc::from("+00:00"))),
1332 perfectly_shredded_timestamp_micro_variant_array_for_second_and_milli_second,
1333 arrow::array::TimestampMillisecondArray::from(vec![
1334 None, Some(1234),
1336 Some(1234000)
1337 ])
1338 .with_timezone("+00:00")
1339 );
1340
1341 perfectly_shredded_variant_array_fn!(
1342 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1343 || {
1344 arrow::array::TimestampMicrosecondArray::from(vec![
1345 Some(1234), Some(1234000), Some(1234000000), ])
1349 }
1350 );
1351
1352 perfectly_shredded_to_arrow_primitive_test!(
1355 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_second,
1356 DataType::Timestamp(TimeUnit::Second, None),
1357 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1358 arrow::array::TimestampSecondArray::from(vec![
1359 None,
1360 None, Some(1234)
1362 ])
1363 );
1364
1365 perfectly_shredded_to_arrow_primitive_test!(
1366 get_variant_perfectly_shredded_timestamp_micro_ntz_as_timestamp_milli,
1367 DataType::Timestamp(TimeUnit::Millisecond, None),
1368 perfectly_shredded_timestamp_micro_ntz_variant_array_for_second_and_milli_second,
1369 arrow::array::TimestampMillisecondArray::from(vec![
1370 None, Some(1234),
1372 Some(1234000)
1373 ])
1374 );
1375
1376 perfectly_shredded_variant_array_fn!(
1377 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1378 || {
1379 arrow::array::TimestampNanosecondArray::from(vec![
1380 Some(1234000), Some(1234000000), Some(1234000000000), ])
1384 .with_timezone("+00:00")
1385 }
1386 );
1387
1388 perfectly_shredded_to_arrow_primitive_test!(
1391 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_second,
1392 DataType::Timestamp(TimeUnit::Second, Some(Arc::from("+00:00"))),
1393 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1394 arrow::array::TimestampSecondArray::from(vec![
1395 None,
1396 None, Some(1234)
1398 ])
1399 .with_timezone("+00:00")
1400 );
1401
1402 perfectly_shredded_to_arrow_primitive_test!(
1403 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_milli,
1404 DataType::Timestamp(TimeUnit::Millisecond, Some(Arc::from("+00:00"))),
1405 perfectly_shredded_timestamp_nano_variant_array_for_second_and_milli_second,
1406 arrow::array::TimestampMillisecondArray::from(vec![
1407 None, Some(1234),
1409 Some(1234000)
1410 ])
1411 .with_timezone("+00:00")
1412 );
1413
1414 perfectly_shredded_variant_array_fn!(
1415 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1416 || {
1417 arrow::array::TimestampNanosecondArray::from(vec![
1418 Some(1234000), Some(1234000000), Some(1234000000000), ])
1422 }
1423 );
1424
1425 perfectly_shredded_to_arrow_primitive_test!(
1428 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_second,
1429 DataType::Timestamp(TimeUnit::Second, None),
1430 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1431 arrow::array::TimestampSecondArray::from(vec![
1432 None,
1433 None, Some(1234)
1435 ])
1436 );
1437
1438 perfectly_shredded_to_arrow_primitive_test!(
1439 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_milli,
1440 DataType::Timestamp(TimeUnit::Millisecond, None),
1441 perfectly_shredded_timestamp_nano_ntz_variant_array_for_second_and_milli_second,
1442 arrow::array::TimestampMillisecondArray::from(vec![
1443 None, Some(1234),
1445 Some(1234000)
1446 ])
1447 );
1448
1449 perfectly_shredded_to_arrow_primitive_test!(
1450 get_variant_perfectly_shredded_timestamp_nano_ntz_as_timestamp_nano_ntz,
1451 DataType::Timestamp(TimeUnit::Nanosecond, None),
1452 perfectly_shredded_timestamp_nano_ntz_variant_array,
1453 arrow::array::TimestampNanosecondArray::from(vec![
1454 Some(-4999999561),
1455 Some(1758602096000000001),
1456 Some(1758602096000000002),
1457 ])
1458 );
1459
1460 perfectly_shredded_variant_array_fn!(perfectly_shredded_timestamp_nano_variant_array, || {
1461 arrow::array::TimestampNanosecondArray::from(vec![
1462 Some(-4999999561),
1463 Some(1758602096000000001),
1464 Some(1758602096000000002),
1465 ])
1466 .with_timezone("+00:00")
1467 });
1468
1469 perfectly_shredded_to_arrow_primitive_test!(
1470 get_variant_perfectly_shredded_timestamp_nano_as_timestamp_nano,
1471 DataType::Timestamp(TimeUnit::Nanosecond, Some(Arc::from("+00:00"))),
1472 perfectly_shredded_timestamp_nano_variant_array,
1473 arrow::array::TimestampNanosecondArray::from(vec![
1474 Some(-4999999561),
1475 Some(1758602096000000001),
1476 Some(1758602096000000002),
1477 ])
1478 .with_timezone("+00:00")
1479 );
1480
1481 perfectly_shredded_variant_array_fn!(perfectly_shredded_date_variant_array, || {
1482 Date32Array::from(vec![Some(-12345), Some(17586), Some(20000)])
1483 });
1484
1485 perfectly_shredded_to_arrow_primitive_test!(
1486 get_variant_perfectly_shredded_date_as_date,
1487 DataType::Date32,
1488 perfectly_shredded_date_variant_array,
1489 Date32Array::from(vec![Some(-12345), Some(17586), Some(20000)])
1490 );
1491
1492 perfectly_shredded_to_arrow_primitive_test!(
1493 get_variant_perfectly_shredded_date_as_date64,
1494 DataType::Date64,
1495 perfectly_shredded_date_variant_array,
1496 Date64Array::from(vec![
1497 Some(-1066608000000),
1498 Some(1519430400000),
1499 Some(1728000000000)
1500 ])
1501 );
1502
1503 perfectly_shredded_variant_array_fn!(perfectly_shredded_time_variant_array, || {
1504 Time64MicrosecondArray::from(vec![Some(12345000), Some(87654000), Some(135792000)])
1505 });
1506
1507 perfectly_shredded_to_arrow_primitive_test!(
1508 get_variant_perfectly_shredded_time_as_time,
1509 DataType::Time64(TimeUnit::Microsecond),
1510 perfectly_shredded_time_variant_array,
1511 Time64MicrosecondArray::from(vec![Some(12345000), Some(87654000), Some(135792000)])
1512 );
1513
1514 perfectly_shredded_to_arrow_primitive_test!(
1515 get_variant_perfectly_shredded_time_as_time64_nano,
1516 DataType::Time64(TimeUnit::Nanosecond),
1517 perfectly_shredded_time_variant_array,
1518 Time64NanosecondArray::from(vec![
1519 Some(12345000000),
1520 Some(87654000000),
1521 Some(135792000000)
1522 ])
1523 );
1524
1525 perfectly_shredded_variant_array_fn!(perfectly_shredded_time_variant_array_for_time32, || {
1526 Time64MicrosecondArray::from(vec![
1527 Some(1234), Some(7654000), Some(35792000000), ])
1531 });
1532
1533 perfectly_shredded_to_arrow_primitive_test!(
1534 get_variant_perfectly_shredded_time_as_time32_second,
1535 DataType::Time32(TimeUnit::Second),
1536 perfectly_shredded_time_variant_array_for_time32,
1537 Time32SecondArray::from(vec![
1538 None,
1539 None, Some(35792)
1541 ])
1542 );
1543
1544 perfectly_shredded_to_arrow_primitive_test!(
1545 get_variant_perfectly_shredded_time_as_time32_milli,
1546 DataType::Time32(TimeUnit::Millisecond),
1547 perfectly_shredded_time_variant_array_for_time32,
1548 Time32MillisecondArray::from(vec![
1549 None, Some(7654),
1551 Some(35792000)
1552 ])
1553 );
1554
1555 perfectly_shredded_variant_array_fn!(perfectly_shredded_null_variant_array, || {
1556 let mut builder = NullBuilder::new();
1557 builder.append_nulls(3);
1558 builder.finish()
1559 });
1560
1561 perfectly_shredded_to_arrow_primitive_test!(
1562 get_variant_perfectly_shredded_null_as_null,
1563 DataType::Null,
1564 perfectly_shredded_null_variant_array,
1565 arrow::array::NullArray::new(3)
1566 );
1567
1568 perfectly_shredded_variant_array_fn!(perfectly_shredded_null_variant_array_with_int, || {
1569 Int32Array::from(vec![Some(32), Some(64), Some(48)])
1570 });
1571
1572 perfectly_shredded_to_arrow_primitive_test!(
1574 get_variant_perfectly_shredded_null_with_type_missmatch_in_safe_mode,
1575 DataType::Null,
1576 perfectly_shredded_null_variant_array_with_int,
1577 arrow::array::NullArray::new(3)
1578 );
1579
1580 #[test]
1582 fn get_variant_perfectly_shredded_null_as_null_with_type_missmatch_in_strict_mode() {
1583 let array = perfectly_shredded_null_variant_array_with_int();
1584 let field = Field::new("typed_value", DataType::Null, true);
1585 let options = GetOptions::new()
1586 .with_as_type(Some(FieldRef::from(field)))
1587 .with_cast_options(CastOptions {
1588 safe: false,
1589 format_options: FormatOptions::default(),
1590 });
1591
1592 let result = variant_get(&array, options);
1593
1594 assert!(result.is_err());
1595 let error_msg = format!("{}", result.unwrap_err());
1596 assert!(
1597 error_msg
1598 .contains("Cast error: Failed to extract primitive of type Null from variant Int32(32) at path VariantPath([])"),
1599 "Expected=[Cast error: Failed to extract primitive of type Null from variant Int32(32) at path VariantPath([])],\
1600 Got error message=[{}]",
1601 error_msg
1602 );
1603 }
1604
1605 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal4_variant_array, || {
1606 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
1607 .with_precision_and_scale(5, 2)
1608 .unwrap()
1609 });
1610
1611 perfectly_shredded_to_arrow_primitive_test!(
1612 get_variant_perfectly_shredded_decimal4_as_decimal4,
1613 DataType::Decimal32(5, 2),
1614 perfectly_shredded_decimal4_variant_array,
1615 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
1616 .with_precision_and_scale(5, 2)
1617 .unwrap()
1618 );
1619
1620 perfectly_shredded_variant_array_fn!(
1621 perfectly_shredded_decimal8_variant_array_cast2decimal32,
1622 || {
1623 Decimal64Array::from(vec![Some(123456), Some(145678), Some(-123456)])
1624 .with_precision_and_scale(6, 1)
1625 .unwrap()
1626 }
1627 );
1628
1629 perfectly_shredded_to_arrow_primitive_test!(
1633 get_variant_perfectly_shredded_decimal8_through_decimal32_as_decimal8,
1634 DataType::Decimal64(6, 1),
1635 perfectly_shredded_decimal8_variant_array_cast2decimal32,
1636 Decimal64Array::from(vec![Some(123456), Some(145678), Some(-123456)])
1637 .with_precision_and_scale(6, 1)
1638 .unwrap()
1639 );
1640
1641 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal8_variant_array, || {
1644 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1645 .with_precision_and_scale(10, 1)
1646 .unwrap()
1647 });
1648
1649 perfectly_shredded_to_arrow_primitive_test!(
1650 get_variant_perfectly_shredded_decimal8_as_decimal8,
1651 DataType::Decimal64(10, 1),
1652 perfectly_shredded_decimal8_variant_array,
1653 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1654 .with_precision_and_scale(10, 1)
1655 .unwrap()
1656 );
1657
1658 perfectly_shredded_variant_array_fn!(
1661 perfectly_shredded_decimal16_within_decimal4_variant_array,
1662 || {
1663 Decimal128Array::from(vec![
1664 Some(i128::from(1234589)),
1665 Some(i128::from(2344444)),
1666 Some(i128::from(-1234789)),
1667 ])
1668 .with_precision_and_scale(7, 3)
1669 .unwrap()
1670 }
1671 );
1672
1673 perfectly_shredded_to_arrow_primitive_test!(
1676 get_variant_perfectly_shredded_decimal16_within_decimal4_as_decimal16,
1677 DataType::Decimal128(7, 3),
1678 perfectly_shredded_decimal16_within_decimal4_variant_array,
1679 Decimal128Array::from(vec![
1680 Some(i128::from(1234589)),
1681 Some(i128::from(2344444)),
1682 Some(i128::from(-1234789)),
1683 ])
1684 .with_precision_and_scale(7, 3)
1685 .unwrap()
1686 );
1687
1688 perfectly_shredded_variant_array_fn!(
1689 perfectly_shredded_decimal16_within_decimal8_variant_array,
1690 || {
1691 Decimal128Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1692 .with_precision_and_scale(10, 1)
1693 .unwrap()
1694 }
1695 );
1696
1697 perfectly_shredded_to_arrow_primitive_test!(
1700 get_variant_perfectly_shredded_decimal16_within8_as_decimal16,
1701 DataType::Decimal128(10, 1),
1702 perfectly_shredded_decimal16_within_decimal8_variant_array,
1703 Decimal128Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
1704 .with_precision_and_scale(10, 1)
1705 .unwrap()
1706 );
1707
1708 perfectly_shredded_variant_array_fn!(perfectly_shredded_decimal16_variant_array, || {
1709 Decimal128Array::from(vec![
1710 Some(i128::from_str("12345678901234567899").unwrap()),
1711 Some(i128::from_str("23445677483748324300").unwrap()),
1712 Some(i128::from_str("-12345678901234567899").unwrap()),
1713 ])
1714 .with_precision_and_scale(20, 3)
1715 .unwrap()
1716 });
1717
1718 perfectly_shredded_to_arrow_primitive_test!(
1721 get_variant_perfectly_shredded_decimal16_as_decimal16,
1722 DataType::Decimal128(20, 3),
1723 perfectly_shredded_decimal16_variant_array,
1724 Decimal128Array::from(vec![
1725 Some(i128::from_str("12345678901234567899").unwrap()),
1726 Some(i128::from_str("23445677483748324300").unwrap()),
1727 Some(i128::from_str("-12345678901234567899").unwrap())
1728 ])
1729 .with_precision_and_scale(20, 3)
1730 .unwrap()
1731 );
1732
1733 perfectly_shredded_variant_array_fn!(perfectly_shredded_binary_variant_array, || {
1734 BinaryArray::from(vec![
1735 Some(b"Apache" as &[u8]),
1736 Some(b"Arrow-rs" as &[u8]),
1737 Some(b"Parquet-variant" as &[u8]),
1738 ])
1739 });
1740
1741 perfectly_shredded_to_arrow_primitive_test!(
1742 get_variant_perfectly_shredded_binary_as_binary,
1743 DataType::Binary,
1744 perfectly_shredded_binary_variant_array,
1745 BinaryArray::from(vec![
1746 Some(b"Apache" as &[u8]),
1747 Some(b"Arrow-rs" as &[u8]),
1748 Some(b"Parquet-variant" as &[u8]),
1749 ])
1750 );
1751
1752 perfectly_shredded_variant_array_fn!(perfectly_shredded_large_binary_variant_array, || {
1753 LargeBinaryArray::from(vec![
1754 Some(b"Apache" as &[u8]),
1755 Some(b"Arrow-rs" as &[u8]),
1756 Some(b"Parquet-variant" as &[u8]),
1757 ])
1758 });
1759
1760 perfectly_shredded_to_arrow_primitive_test!(
1761 get_variant_perfectly_shredded_large_binary_as_large_binary,
1762 DataType::LargeBinary,
1763 perfectly_shredded_large_binary_variant_array,
1764 LargeBinaryArray::from(vec![
1765 Some(b"Apache" as &[u8]),
1766 Some(b"Arrow-rs" as &[u8]),
1767 Some(b"Parquet-variant" as &[u8]),
1768 ])
1769 );
1770
1771 perfectly_shredded_variant_array_fn!(perfectly_shredded_binary_view_variant_array, || {
1772 BinaryViewArray::from(vec![
1773 Some(b"Apache" as &[u8]),
1774 Some(b"Arrow-rs" as &[u8]),
1775 Some(b"Parquet-variant" as &[u8]),
1776 ])
1777 });
1778
1779 perfectly_shredded_to_arrow_primitive_test!(
1780 get_variant_perfectly_shredded_binary_view_as_binary_view,
1781 DataType::BinaryView,
1782 perfectly_shredded_binary_view_variant_array,
1783 BinaryViewArray::from(vec![
1784 Some(b"Apache" as &[u8]),
1785 Some(b"Arrow-rs" as &[u8]),
1786 Some(b"Parquet-variant" as &[u8]),
1787 ])
1788 );
1789
1790 fn all_null_variant_array() -> ArrayRef {
1807 let nulls = NullBuffer::from(vec![
1808 false, false, false, ]);
1812
1813 let metadata =
1815 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 3));
1816
1817 ArrayRef::from(VariantArray::from_parts(
1818 Arc::new(metadata),
1819 None,
1820 None,
1821 Some(nulls),
1822 ))
1823 }
1824
1825 #[test]
1829 fn test_shredded_object_field_access() {
1830 let array = shredded_object_with_x_field_variant_array();
1831
1832 let options = GetOptions::new_with_path(VariantPath::try_from("x").unwrap());
1834 let result = variant_get(&array, options).unwrap();
1835
1836 let result_variant = VariantArray::try_new(&result).unwrap();
1837 assert_eq!(result_variant.len(), 2);
1838
1839 assert_eq!(result_variant.value(0), Variant::Int32(1));
1841 assert_eq!(result_variant.value(1), Variant::Int32(42));
1843 }
1844
1845 #[test]
1847 fn test_shredded_object_field_as_int32() {
1848 let array = shredded_object_with_x_field_variant_array();
1849
1850 let field = Field::new("x", DataType::Int32, false);
1852 let options = GetOptions::new_with_path(VariantPath::try_from("x").unwrap())
1853 .with_as_type(Some(FieldRef::from(field)));
1854 let result = variant_get(&array, options).unwrap();
1855
1856 let expected: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(42)]));
1858 assert_eq!(&result, &expected);
1859 }
1860
1861 type ShreddedListLikeArrayGen = fn() -> ArrayRef;
1862 type ShreddedListLikeCase = (&'static str, ShreddedListLikeArrayGen);
1863
1864 fn shredded_list_like_cases() -> [ShreddedListLikeCase; 4] {
1865 [
1866 ("list", shredded_list_variant_array),
1867 ("large_list", shredded_large_list_variant_array),
1868 ("list_view", shredded_list_view_variant_array),
1869 ("large_list_view", shredded_large_list_view_variant_array),
1870 ]
1871 }
1872
1873 #[test]
1874 fn test_shredded_list_like_index_access_from_value_field() {
1875 let options = GetOptions::new_with_path(VariantPath::from(1));
1876
1877 for (case, array_gen) in shredded_list_like_cases() {
1878 let array = array_gen();
1879 let result = variant_get(&array, options.clone()).unwrap();
1880 let result_variant = VariantArray::try_new(&result).unwrap();
1881
1882 assert_eq!(result_variant.value(0), Variant::from("drama"), "{case}");
1883 assert_eq!(result_variant.value(1).as_int64(), Some(123), "{case}");
1884 }
1885 }
1886
1887 #[test]
1888 fn test_shredded_list_like_index_out_of_bounds_unsafe_cast_returns_null() {
1889 let options =
1890 GetOptions::new_with_path(VariantPath::from(10)).with_cast_options(CastOptions {
1891 safe: false,
1892 ..Default::default()
1893 });
1894
1895 for (case, array_gen) in shredded_list_like_cases() {
1896 let result = variant_get(&array_gen(), options.clone()).unwrap();
1897 let result_variant = VariantArray::try_new(&result).unwrap();
1898 assert_eq!(result_variant.value(0), Variant::Null, "{case}");
1899 assert_eq!(result_variant.value(1), Variant::Null, "{case}");
1900 }
1901 }
1902
1903 #[test]
1905 fn test_shredded_list_like_as_string() {
1906 let field = Field::new("typed_value", DataType::Utf8, false);
1907 let options = GetOptions::new_with_path(VariantPath::from(0))
1908 .with_as_type(Some(FieldRef::from(field)));
1909 let expected: ArrayRef = Arc::new(StringArray::from(vec![Some("comedy"), Some("horror")]));
1910
1911 for (case, array_gen) in shredded_list_like_cases() {
1912 let result = variant_get(&array_gen(), options.clone()).unwrap();
1913 assert_eq!(&result, &expected, "{case}");
1914 }
1915 }
1916
1917 #[test]
1918 fn test_shredded_list_like_index_access_from_value_field_as_int64() {
1919 let field = Field::new("typed_value", DataType::Int64, true);
1920 let options = GetOptions::new_with_path(VariantPath::from(1))
1921 .with_as_type(Some(FieldRef::from(field)));
1922 let expected: ArrayRef = Arc::new(Int64Array::from(vec![None, Some(123)]));
1923
1924 for (case, array_gen) in shredded_list_like_cases() {
1925 let result = variant_get(&array_gen(), options.clone()).unwrap();
1926 assert_eq!(&result, &expected, "{case}");
1928 }
1929 }
1930
1931 #[test]
1932 fn test_shredded_list_in_struct_index_access() {
1933 let array = shredded_struct_with_list_variant_array();
1934 let options = GetOptions::new_with_path(VariantPath::try_from("a[1]").unwrap());
1935 let result = variant_get(&array, options).unwrap();
1936 let result_variant = VariantArray::try_new(&result).unwrap();
1937
1938 assert_eq!(result_variant.value(0), Variant::from("drama"));
1939 assert_eq!(result_variant.value(1).as_int64(), Some(123));
1940 }
1941
1942 #[test]
1943 fn test_shredded_struct_in_list_field_access() {
1944 let array = shredded_list_of_struct_variant_array();
1945 let field = Field::new("x", DataType::Int32, true);
1946 let path = VariantPath::from(0).join("x");
1947 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
1948 let result = variant_get(&array, options).unwrap();
1949
1950 let expected: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(3)]));
1951 assert_eq!(&result, &expected);
1952 }
1953
1954 #[test]
1955 fn test_shredded_list_of_lists_index_access() {
1956 let array = shredded_list_of_lists_variant_array();
1957 let path = VariantPath::from(0).join(1);
1958
1959 let result = variant_get(&array, GetOptions::new_with_path(path.clone())).unwrap();
1960 let result_variant = VariantArray::try_new(&result).unwrap();
1961 assert_eq!(result_variant.value(0), Variant::from("b"));
1962 assert_eq!(result_variant.value(1).as_int64(), Some(123));
1963
1964 let field = Field::new("typed_value", DataType::Int64, true);
1965 let casted = variant_get(
1966 &array,
1967 GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field))),
1968 )
1969 .unwrap();
1970 let expected: ArrayRef = Arc::new(Int64Array::from(vec![None, Some(123)]));
1971 assert_eq!(&casted, &expected);
1972 }
1973
1974 fn shredded_list_like_variant_array(list_schema: DataType) -> ArrayRef {
1980 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
1981 Some(r#"["comedy", "drama"]"#),
1982 Some(r#"["horror", 123]"#),
1983 ]));
1984 let input = json_to_variant(&json_rows).unwrap();
1985
1986 let shredded = shred_variant(&input, &list_schema).unwrap();
1987 ArrayRef::from(shredded)
1988 }
1989
1990 fn shredded_list_of_lists_variant_array() -> ArrayRef {
1991 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
1992 Some(r#"[["a", "b"], ["c", "d"]]"#),
1993 Some(r#"[["x", 123], ["y", "z"]]"#),
1994 ]));
1995 let input = json_to_variant(&json_rows).unwrap();
1996
1997 let inner_list = DataType::List(Arc::new(Field::new("item", DataType::Utf8, true)));
1998 let outer_list = DataType::List(Arc::new(Field::new("item", inner_list, true)));
1999 let shredded = shred_variant(&input, &outer_list).unwrap();
2000 ArrayRef::from(shredded)
2001 }
2002
2003 fn shredded_list_variant_array() -> ArrayRef {
2004 shredded_list_like_variant_array(DataType::List(Arc::new(Field::new(
2005 "item",
2006 DataType::Utf8,
2007 true,
2008 ))))
2009 }
2010
2011 fn shredded_large_list_variant_array() -> ArrayRef {
2012 shredded_list_like_variant_array(DataType::LargeList(Arc::new(Field::new(
2013 "item",
2014 DataType::Utf8,
2015 true,
2016 ))))
2017 }
2018
2019 fn shredded_list_view_variant_array() -> ArrayRef {
2020 shredded_list_like_variant_array(DataType::ListView(Arc::new(Field::new(
2021 "item",
2022 DataType::Utf8,
2023 true,
2024 ))))
2025 }
2026
2027 fn shredded_large_list_view_variant_array() -> ArrayRef {
2028 shredded_list_like_variant_array(DataType::LargeListView(Arc::new(Field::new(
2029 "item",
2030 DataType::Utf8,
2031 true,
2032 ))))
2033 }
2034
2035 fn shredded_struct_with_list_variant_array() -> ArrayRef {
2036 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
2037 Some(r#"{"a": ["comedy", "drama"]}"#),
2038 Some(r#"{"a": ["horror", 123]}"#),
2039 ]));
2040 let input = json_to_variant(&json_rows).unwrap();
2041
2042 let list_schema = DataType::List(Arc::new(Field::new("item", DataType::Utf8, true)));
2043 let shredding_schema = ShreddedSchemaBuilder::default()
2044 .with_path("a", &list_schema)
2045 .unwrap()
2046 .build();
2047 let shredded = shred_variant(&input, &shredding_schema).unwrap();
2048 ArrayRef::from(shredded)
2049 }
2050
2051 fn shredded_list_of_struct_variant_array() -> ArrayRef {
2052 let json_rows: ArrayRef = Arc::new(StringArray::from(vec![
2053 Some(r#"[{"x": 1}, {"x": 2}]"#),
2054 Some(r#"[{"x": 3}, {"y": 4}]"#),
2055 ]));
2056 let input = json_to_variant(&json_rows).unwrap();
2057
2058 let struct_type =
2059 DataType::Struct(Fields::from(vec![Field::new("x", DataType::Int32, true)]));
2060 let list_schema = DataType::List(Arc::new(Field::new("item", struct_type, true)));
2061 let shredded = shred_variant(&input, &list_schema).unwrap();
2062 ArrayRef::from(shredded)
2063 }
2064
2065 fn shredded_object_with_x_field_variant_array() -> ArrayRef {
2077 let (metadata, y_field_value) = {
2079 let mut builder = parquet_variant::VariantBuilder::new();
2080 let mut obj = builder.new_object();
2081 obj.insert("x", Variant::Int32(42));
2082 obj.insert("y", Variant::from("foo"));
2083 obj.finish();
2084 builder.finish()
2085 };
2086
2087 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2089
2090 let empty_object_value = {
2095 let mut builder = parquet_variant::VariantBuilder::new();
2096 let obj = builder.new_object();
2097 obj.finish();
2098 let (_, value) = builder.finish();
2099 value
2100 };
2101
2102 let value_array = BinaryViewArray::from(vec![
2103 Some(y_field_value.as_slice()), Some(empty_object_value.as_slice()), ]);
2106
2107 let x_field_typed_value = Int32Array::from(vec![Some(1), Some(42)]);
2110
2111 let x_field_shredded = ShreddedVariantFieldArray::from_parts(
2113 None,
2114 Some(Arc::new(x_field_typed_value) as ArrayRef),
2115 None,
2116 );
2117
2118 let typed_value_fields = Fields::from(vec![Field::new(
2120 "x",
2121 x_field_shredded.data_type().clone(),
2122 true,
2123 )]);
2124 let typed_value_struct = StructArray::try_new(
2125 typed_value_fields,
2126 vec![ArrayRef::from(x_field_shredded)],
2127 None, )
2129 .unwrap();
2130
2131 ArrayRef::from(VariantArray::from_parts(
2133 Arc::new(metadata_array),
2134 Some(Arc::new(value_array)),
2135 Some(Arc::new(typed_value_struct)),
2136 None,
2137 ))
2138 }
2139
2140 #[test]
2142 fn test_simple_nested_path_support() {
2143 println!("Testing path parsing:");
2145
2146 let path_x = VariantPath::try_from("x").unwrap();
2147 let elements_x: Vec<_> = path_x.iter().collect();
2148 println!(" 'x' -> {} elements: {:?}", elements_x.len(), elements_x);
2149
2150 let path_ax = VariantPath::try_from("a.x").unwrap();
2151 let elements_ax: Vec<_> = path_ax.iter().collect();
2152 println!(
2153 " 'a.x' -> {} elements: {:?}",
2154 elements_ax.len(),
2155 elements_ax
2156 );
2157
2158 let path_ax_alt = VariantPath::try_from("$.a.x").unwrap();
2159 let elements_ax_alt: Vec<_> = path_ax_alt.iter().collect();
2160 println!(
2161 " '$.a.x' -> {} elements: {:?}",
2162 elements_ax_alt.len(),
2163 elements_ax_alt
2164 );
2165
2166 let path_nested = VariantPath::try_from("a").unwrap().join("x");
2167 let elements_nested: Vec<_> = path_nested.iter().collect();
2168 println!(
2169 " VariantPath::try_from('a').unwrap().join('x') -> {} elements: {:?}",
2170 elements_nested.len(),
2171 elements_nested
2172 );
2173
2174 let array = shredded_object_with_x_field_variant_array();
2176
2177 let real_nested_path = VariantPath::try_from("a").unwrap().join("x");
2179 let options = GetOptions::new_with_path(real_nested_path);
2180 let result = variant_get(&array, options);
2181
2182 match result {
2183 Ok(_) => {
2184 println!("Nested path 'a.x' works unexpectedly!");
2185 }
2186 Err(e) => {
2187 println!("Nested path 'a.x' error: {}", e);
2188 if e.to_string().contains("Not yet implemented")
2189 || e.to_string().contains("NotYetImplemented")
2190 {
2191 println!("This is expected - nested paths are not implemented");
2192 return;
2193 }
2194 println!("This shows nested paths need implementation");
2196 }
2197 }
2198 }
2199
2200 #[test]
2204 fn test_depth_0_int32_conversion() {
2205 println!("=== Testing Depth 0: Direct field access ===");
2206
2207 let unshredded_array = create_depth_0_test_data();
2209
2210 let field = Field::new("result", DataType::Int32, true);
2211 let path = VariantPath::try_from("x").unwrap();
2212 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2213 let result = variant_get(&unshredded_array, options).unwrap();
2214
2215 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2216 Some(42), None, None, ]));
2220 assert_eq!(&result, &expected);
2221 println!("Depth 0 (unshredded) passed");
2222
2223 let shredded_array = create_depth_0_shredded_test_data_simple();
2225
2226 let field = Field::new("result", DataType::Int32, true);
2227 let path = VariantPath::try_from("x").unwrap();
2228 let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2229 let result = variant_get(&shredded_array, options).unwrap();
2230
2231 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2232 Some(42), None, ]));
2235 assert_eq!(&result, &expected);
2236 println!("Depth 0 (shredded) passed");
2237 }
2238
2239 #[test]
2242 fn test_depth_1_int32_conversion() {
2243 println!("=== Testing Depth 1: Single nested field access ===");
2244
2245 let unshredded_array = create_nested_path_test_data();
2247
2248 let field = Field::new("result", DataType::Int32, true);
2249 let path = VariantPath::try_from("a.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2251 let result = variant_get(&unshredded_array, options).unwrap();
2252
2253 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2254 Some(55), None, ]));
2257 assert_eq!(&result, &expected);
2258 println!("Depth 1 (unshredded) passed");
2259
2260 let shredded_array = create_depth_1_shredded_test_data_working();
2262
2263 let field = Field::new("result", DataType::Int32, true);
2264 let path = VariantPath::try_from("a.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2266 let result = variant_get(&shredded_array, options).unwrap();
2267
2268 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2269 Some(55), None, ]));
2272 assert_eq!(&result, &expected);
2273 println!("Depth 1 (shredded) passed");
2274 }
2275
2276 #[test]
2279 fn test_depth_2_int32_conversion() {
2280 println!("=== Testing Depth 2: Double nested field access ===");
2281
2282 let unshredded_array = create_depth_2_test_data();
2284
2285 let field = Field::new("result", DataType::Int32, true);
2286 let path = VariantPath::try_from("a.b.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2288 let result = variant_get(&unshredded_array, options).unwrap();
2289
2290 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2291 Some(100), None, None, ]));
2295 assert_eq!(&result, &expected);
2296 println!("Depth 2 (unshredded) passed");
2297
2298 let shredded_array = create_depth_2_shredded_test_data_working();
2300
2301 let field = Field::new("result", DataType::Int32, true);
2302 let path = VariantPath::try_from("a.b.x").unwrap(); let options = GetOptions::new_with_path(path).with_as_type(Some(FieldRef::from(field)));
2304 let result = variant_get(&shredded_array, options).unwrap();
2305
2306 let expected: ArrayRef = Arc::new(Int32Array::from(vec![
2307 Some(100), None, None, ]));
2311 assert_eq!(&result, &expected);
2312 println!("Depth 2 (shredded) passed");
2313 }
2314
2315 #[test]
2320 fn test_current_nested_path_functionality() {
2321 let array = shredded_object_with_x_field_variant_array();
2322
2323 let single_path = VariantPath::try_from("x").unwrap();
2325 let field = Field::new("result", DataType::Int32, true);
2326 let options =
2327 GetOptions::new_with_path(single_path).with_as_type(Some(FieldRef::from(field)));
2328 let result = variant_get(&array, options).unwrap();
2329
2330 println!("Single path 'x' works - result: {:?}", result);
2331
2332 let nested_path = VariantPath::try_from("a").unwrap().join("x");
2334 let field = Field::new("result", DataType::Int32, true);
2335 let options =
2336 GetOptions::new_with_path(nested_path).with_as_type(Some(FieldRef::from(field)));
2337 let result = variant_get(&array, options).unwrap();
2338
2339 println!("Nested path 'a.x' result: {:?}", result);
2340 }
2341
2342 fn create_depth_0_test_data() -> ArrayRef {
2345 let mut builder = crate::VariantArrayBuilder::new(3);
2346
2347 {
2349 let json_str = r#"{"x": 42}"#;
2350 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2351 if let Ok(variant_array) = json_to_variant(&string_array) {
2352 builder.append_variant(variant_array.value(0));
2353 } else {
2354 builder.append_null();
2355 }
2356 }
2357
2358 {
2360 let json_str = r#"{"x": "foo"}"#;
2361 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2362 if let Ok(variant_array) = json_to_variant(&string_array) {
2363 builder.append_variant(variant_array.value(0));
2364 } else {
2365 builder.append_null();
2366 }
2367 }
2368
2369 {
2371 let json_str = r#"{"y": 10}"#;
2372 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2373 if let Ok(variant_array) = json_to_variant(&string_array) {
2374 builder.append_variant(variant_array.value(0));
2375 } else {
2376 builder.append_null();
2377 }
2378 }
2379
2380 ArrayRef::from(builder.build())
2381 }
2382
2383 fn create_nested_path_test_data() -> ArrayRef {
2386 let mut builder = crate::VariantArrayBuilder::new(2);
2387
2388 {
2390 let json_str = r#"{"a": {"x": 55}, "b": 42}"#;
2391 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2392 if let Ok(variant_array) = json_to_variant(&string_array) {
2393 builder.append_variant(variant_array.value(0));
2394 } else {
2395 builder.append_null();
2396 }
2397 }
2398
2399 {
2401 let json_str = r#"{"a": {"x": "foo"}, "b": 42}"#;
2402 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2403 if let Ok(variant_array) = json_to_variant(&string_array) {
2404 builder.append_variant(variant_array.value(0));
2405 } else {
2406 builder.append_null();
2407 }
2408 }
2409
2410 ArrayRef::from(builder.build())
2411 }
2412
2413 fn create_depth_2_test_data() -> ArrayRef {
2416 let mut builder = crate::VariantArrayBuilder::new(3);
2417
2418 {
2420 let json_str = r#"{"a": {"b": {"x": 100}}}"#;
2421 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2422 if let Ok(variant_array) = json_to_variant(&string_array) {
2423 builder.append_variant(variant_array.value(0));
2424 } else {
2425 builder.append_null();
2426 }
2427 }
2428
2429 {
2431 let json_str = r#"{"a": {"b": {"x": "bar"}}}"#;
2432 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2433 if let Ok(variant_array) = json_to_variant(&string_array) {
2434 builder.append_variant(variant_array.value(0));
2435 } else {
2436 builder.append_null();
2437 }
2438 }
2439
2440 {
2442 let json_str = r#"{"a": {"b": {"y": 200}}}"#;
2443 let string_array: ArrayRef = Arc::new(StringArray::from(vec![json_str]));
2444 if let Ok(variant_array) = json_to_variant(&string_array) {
2445 builder.append_variant(variant_array.value(0));
2446 } else {
2447 builder.append_null();
2448 }
2449 }
2450
2451 ArrayRef::from(builder.build())
2452 }
2453
2454 fn create_depth_0_shredded_test_data_simple() -> ArrayRef {
2457 let (metadata, string_x_value) = {
2459 let mut builder = parquet_variant::VariantBuilder::new();
2460 let mut obj = builder.new_object();
2461 obj.insert("x", Variant::from("foo"));
2462 obj.finish();
2463 builder.finish()
2464 };
2465
2466 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2468
2469 let empty_object_value = {
2473 let mut builder = parquet_variant::VariantBuilder::new();
2474 let obj = builder.new_object();
2475 obj.finish();
2476 let (_, value) = builder.finish();
2477 value
2478 };
2479
2480 let value_array = BinaryViewArray::from(vec![
2481 Some(empty_object_value.as_slice()), Some(string_x_value.as_slice()), ]);
2484
2485 let x_field_typed_value = Int32Array::from(vec![Some(42), None]);
2487
2488 let x_field_shredded = ShreddedVariantFieldArray::from_parts(
2490 None,
2491 Some(Arc::new(x_field_typed_value) as ArrayRef),
2492 None,
2493 );
2494
2495 let typed_value_fields = Fields::from(vec![Field::new(
2497 "x",
2498 x_field_shredded.data_type().clone(),
2499 true,
2500 )]);
2501 let typed_value_struct = StructArray::try_new(
2502 typed_value_fields,
2503 vec![ArrayRef::from(x_field_shredded)],
2504 None,
2505 )
2506 .unwrap();
2507
2508 ArrayRef::from(VariantArray::from_parts(
2510 Arc::new(metadata_array),
2511 Some(Arc::new(value_array)),
2512 Some(Arc::new(typed_value_struct)),
2513 None,
2514 ))
2515 }
2516
2517 fn create_depth_1_shredded_test_data_working() -> ArrayRef {
2522 let (metadata, _) = {
2524 let mut builder = parquet_variant::VariantBuilder::new();
2526 let mut obj = builder.new_object();
2527
2528 let mut a_obj = obj.new_object("a");
2530 a_obj.insert("x", Variant::Int32(55));
2531 a_obj.finish();
2532
2533 obj.insert("b", Variant::Int32(42));
2534 obj.finish();
2535 builder.finish()
2536 };
2537
2538 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 2));
2539
2540 let empty_object_value = {
2543 let mut builder = parquet_variant::VariantBuilder::new();
2544 let obj = builder.new_object();
2545 obj.finish();
2546 let (_, value) = builder.finish();
2547 value
2548 };
2549
2550 let row1_fallback = {
2553 let mut builder = parquet_variant::VariantBuilder::new();
2554 let mut obj = builder.new_object();
2555 obj.insert("fallback", Variant::from("data"));
2556 obj.finish();
2557 let (_, value) = builder.finish();
2558 value
2559 };
2560
2561 let value_array = BinaryViewArray::from(vec![
2562 Some(empty_object_value.as_slice()), Some(row1_fallback.as_slice()), ]);
2565
2566 let x_typed_value = Int32Array::from(vec![Some(55), None]);
2569 let x_field_shredded = ShreddedVariantFieldArray::from_parts(
2570 None,
2571 Some(Arc::new(x_typed_value) as ArrayRef),
2572 None,
2573 );
2574
2575 let a_value_data = {
2580 let mut builder = parquet_variant::VariantBuilder::new();
2581 let obj = builder.new_object();
2582 obj.finish();
2583 let (_, value) = builder.finish();
2584 value
2585 };
2586 let a_value_array = BinaryViewArray::from(vec![
2587 None, Some(a_value_data.as_slice()), ]);
2590
2591 let a_inner_fields = Fields::from(vec![Field::new(
2592 "x",
2593 x_field_shredded.data_type().clone(),
2594 true,
2595 )]);
2596 let a_inner_typed_value = Arc::new(
2597 StructArray::try_new(a_inner_fields, vec![ArrayRef::from(x_field_shredded)], None)
2598 .unwrap(),
2599 ) as ArrayRef;
2600 let a_field_shredded = ShreddedVariantFieldArray::from_parts(
2601 Some(Arc::new(a_value_array)),
2602 Some(a_inner_typed_value),
2603 None,
2604 );
2605
2606 let typed_value_fields = Fields::from(vec![Field::new(
2608 "a",
2609 a_field_shredded.data_type().clone(),
2610 true,
2611 )]);
2612 let typed_value_struct = StructArray::try_new(
2613 typed_value_fields,
2614 vec![ArrayRef::from(a_field_shredded)],
2615 None,
2616 )
2617 .unwrap();
2618
2619 ArrayRef::from(VariantArray::from_parts(
2621 Arc::new(metadata_array),
2622 Some(Arc::new(value_array)),
2623 Some(Arc::new(typed_value_struct)),
2624 None,
2625 ))
2626 }
2627
2628 fn create_depth_2_shredded_test_data_working() -> ArrayRef {
2634 let (metadata, _) = {
2636 let mut builder = parquet_variant::VariantBuilder::new();
2638 let mut obj = builder.new_object();
2639
2640 let mut a_obj = obj.new_object("a");
2642 let mut b_obj = a_obj.new_object("b");
2643 b_obj.insert("x", Variant::Int32(100));
2644 b_obj.finish();
2645 a_obj.finish();
2646
2647 obj.finish();
2648 builder.finish()
2649 };
2650
2651 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 3));
2652
2653 let empty_object_value = {
2655 let mut builder = parquet_variant::VariantBuilder::new();
2656 let obj = builder.new_object();
2657 obj.finish();
2658 let (_, value) = builder.finish();
2659 value
2660 };
2661
2662 let value_array = BinaryViewArray::from(vec![
2664 Some(empty_object_value.as_slice()), Some(empty_object_value.as_slice()), Some(empty_object_value.as_slice()), ]);
2668
2669 let x_typed_value = Int32Array::from(vec![Some(100), None, None]);
2673 let x_field_shredded = ShreddedVariantFieldArray::from_parts(
2674 None,
2675 Some(Arc::new(x_typed_value) as ArrayRef),
2676 None,
2677 );
2678
2679 let b_value_data = {
2681 let mut builder = parquet_variant::VariantBuilder::new();
2682 let obj = builder.new_object();
2683 obj.finish();
2684 let (_, value) = builder.finish();
2685 value
2686 };
2687 let b_value_array = BinaryViewArray::from(vec![
2688 None, Some(b_value_data.as_slice()), Some(b_value_data.as_slice()), ]);
2692
2693 let b_inner_fields = Fields::from(vec![Field::new(
2694 "x",
2695 x_field_shredded.data_type().clone(),
2696 true,
2697 )]);
2698 let b_inner_typed_value = Arc::new(
2699 StructArray::try_new(b_inner_fields, vec![ArrayRef::from(x_field_shredded)], None)
2700 .unwrap(),
2701 ) as ArrayRef;
2702 let b_field_shredded = ShreddedVariantFieldArray::from_parts(
2703 Some(Arc::new(b_value_array)),
2704 Some(b_inner_typed_value),
2705 None,
2706 );
2707
2708 let a_value_data = {
2710 let mut builder = parquet_variant::VariantBuilder::new();
2711 let obj = builder.new_object();
2712 obj.finish();
2713 let (_, value) = builder.finish();
2714 value
2715 };
2716 let a_value_array = BinaryViewArray::from(vec![
2717 None, Some(a_value_data.as_slice()), Some(a_value_data.as_slice()), ]);
2721
2722 let a_inner_fields = Fields::from(vec![Field::new(
2723 "b",
2724 b_field_shredded.data_type().clone(),
2725 true,
2726 )]);
2727 let a_inner_typed_value = Arc::new(
2728 StructArray::try_new(a_inner_fields, vec![ArrayRef::from(b_field_shredded)], None)
2729 .unwrap(),
2730 ) as ArrayRef;
2731 let a_field_shredded = ShreddedVariantFieldArray::from_parts(
2732 Some(Arc::new(a_value_array)),
2733 Some(a_inner_typed_value),
2734 None,
2735 );
2736
2737 let typed_value_fields = Fields::from(vec![Field::new(
2739 "a",
2740 a_field_shredded.data_type().clone(),
2741 true,
2742 )]);
2743 let typed_value_struct = StructArray::try_new(
2744 typed_value_fields,
2745 vec![ArrayRef::from(a_field_shredded)],
2746 None,
2747 )
2748 .unwrap();
2749
2750 ArrayRef::from(VariantArray::from_parts(
2752 Arc::new(metadata_array),
2753 Some(Arc::new(value_array)),
2754 Some(Arc::new(typed_value_struct)),
2755 None,
2756 ))
2757 }
2758
2759 #[test]
2760 fn test_field_path_non_struct_returns_missing_path_step() {
2761 let variant_array = perfectly_shredded_int32_variant_array();
2763
2764 for safe in [true, false] {
2765 let options = GetOptions {
2766 path: VariantPath::try_from("nonexistent_field").unwrap(),
2767 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
2768 cast_options: CastOptions {
2769 safe,
2770 ..Default::default()
2771 },
2772 };
2773
2774 let result_array = variant_get(&variant_array, options).unwrap();
2775 assert_eq!(result_array.len(), 3);
2776 assert!(result_array.is_null(0));
2777 assert!(result_array.is_null(1));
2778 assert!(result_array.is_null(2));
2779 }
2780 }
2781
2782 #[test]
2783 fn test_strict_cast_options_index_on_non_list_returns_null() {
2784 use arrow::compute::CastOptions;
2785 use arrow::datatypes::{DataType, Field};
2786 use parquet_variant::VariantPath;
2787 use std::sync::Arc;
2788
2789 let variant_array = perfectly_shredded_int32_variant_array();
2791 let options = GetOptions {
2792 path: VariantPath::from(0),
2793 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
2794 cast_options: CastOptions {
2795 safe: false,
2796 ..Default::default()
2797 },
2798 };
2799
2800 let variant_array_ref: Arc<dyn Array> = variant_array.clone();
2801 let result = variant_get(&variant_array_ref, options).unwrap();
2802
2803 assert_eq!(result.len(), 3);
2804 assert!(result.is_null(0));
2805 assert!(result.is_null(1));
2806 assert!(result.is_null(2));
2807 }
2808
2809 #[test]
2810 fn test_error_message_boolean_type_display() {
2811 let mut builder = VariantArrayBuilder::new(1);
2812 builder.append_variant(Variant::from("abcd"));
2813 let variant_array: ArrayRef = ArrayRef::from(builder.build());
2814
2815 let options = GetOptions {
2817 path: VariantPath::default(),
2818 as_type: Some(Arc::new(Field::new("result", DataType::Boolean, true))),
2819 cast_options: CastOptions {
2820 safe: false,
2821 ..Default::default()
2822 },
2823 };
2824
2825 let err = variant_get(&variant_array, options).unwrap_err();
2826 let msg = err.to_string();
2827 assert!(msg.contains("Failed to extract primitive of type Boolean"));
2828 }
2829
2830 #[test]
2831 fn test_error_message_numeric_type_display() {
2832 let mut builder = VariantArrayBuilder::new(1);
2833 builder.append_variant(Variant::from("abcd"));
2834 let variant_array: ArrayRef = ArrayRef::from(builder.build());
2835
2836 let options = GetOptions {
2838 path: VariantPath::default(),
2839 as_type: Some(Arc::new(Field::new("result", DataType::Float32, true))),
2840 cast_options: CastOptions {
2841 safe: false,
2842 ..Default::default()
2843 },
2844 };
2845
2846 let err = variant_get(&variant_array, options).unwrap_err();
2847 let msg = err.to_string();
2848 assert!(msg.contains("Failed to extract primitive of type Float32"));
2849 }
2850
2851 #[test]
2852 fn test_error_message_temporal_type_display() {
2853 let mut builder = VariantArrayBuilder::new(1);
2854 builder.append_variant(Variant::BooleanFalse);
2855 let variant_array: ArrayRef = ArrayRef::from(builder.build());
2856
2857 let options = GetOptions {
2859 path: VariantPath::default(),
2860 as_type: Some(Arc::new(Field::new(
2861 "result",
2862 DataType::Timestamp(TimeUnit::Nanosecond, None),
2863 true,
2864 ))),
2865 cast_options: CastOptions {
2866 safe: false,
2867 ..Default::default()
2868 },
2869 };
2870
2871 let err = variant_get(&variant_array, options).unwrap_err();
2872 let msg = err.to_string();
2873 assert!(msg.contains("Failed to extract primitive of type Timestamp(ns)"));
2874 }
2875
2876 #[test]
2877 fn test_null_buffer_union_for_shredded_paths() {
2878 let variant_array = create_depth_1_shredded_test_data_working();
2887
2888 let options = GetOptions {
2893 path: VariantPath::try_from("a.x").unwrap(),
2894 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
2895 cast_options: CastOptions::default(),
2896 };
2897
2898 let result = variant_get(&variant_array, options).unwrap();
2899
2900 assert_eq!(result.len(), variant_array.len());
2902
2903 assert!(!result.is_null(0), "Row 0 should have valid Int32 data");
2907 assert!(
2908 result.is_null(1),
2909 "Row 1 should be null due to type casting failure"
2910 );
2911
2912 let int32_result = result.as_any().downcast_ref::<Int32Array>().unwrap();
2914 assert_eq!(int32_result.value(0), 55); }
2916
2917 #[test]
2918 fn test_struct_null_mask_union_from_children() {
2919 let json_strings = vec![
2924 r#"{"a": 42, "b": "hello"}"#, r#"{"a": "world", "b": 100}"#, r#"{"a": 55, "b": 77}"#, ];
2928
2929 let string_array: Arc<dyn arrow::array::Array> = Arc::new(StringArray::from(json_strings));
2930 let variant_array = json_to_variant(&string_array).unwrap();
2931
2932 let struct_fields = Fields::from(vec![
2935 Field::new("a", DataType::Int32, true),
2936 Field::new("b", DataType::Int32, true),
2937 ]);
2938 let struct_type = DataType::Struct(struct_fields);
2939
2940 let options = GetOptions {
2941 path: VariantPath::default(), as_type: Some(Arc::new(Field::new("result", struct_type, true))),
2943 cast_options: CastOptions::default(),
2944 };
2945
2946 let variant_array_ref = ArrayRef::from(variant_array);
2947 let result = variant_get(&variant_array_ref, options).unwrap();
2948
2949 let struct_result = result.as_struct();
2951 assert_eq!(struct_result.len(), 3);
2952
2953 let field_a = struct_result
2955 .column(0)
2956 .as_any()
2957 .downcast_ref::<Int32Array>()
2958 .unwrap();
2959 let field_b = struct_result
2960 .column(1)
2961 .as_any()
2962 .downcast_ref::<Int32Array>()
2963 .unwrap();
2964
2965 assert!(!field_a.is_null(0));
2968 assert_eq!(field_a.value(0), 42);
2969 assert!(field_b.is_null(0)); assert!(field_a.is_null(1)); assert!(!field_b.is_null(1));
2974 assert_eq!(field_b.value(1), 100);
2975
2976 assert!(!field_a.is_null(2));
2978 assert_eq!(field_a.value(2), 55);
2979 assert!(!field_b.is_null(2));
2980 assert_eq!(field_b.value(2), 77);
2981
2982 assert!(!struct_result.is_null(0)); assert!(!struct_result.is_null(1)); assert!(!struct_result.is_null(2)); }
2989
2990 #[test]
2991 fn test_field_nullability_preservation() {
2992 let json_strings = vec![
2995 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}"#, ];
3005
3006 let string_array: Arc<dyn arrow::array::Array> = Arc::new(StringArray::from(json_strings));
3007 let variant_array = json_to_variant(&string_array).unwrap();
3008
3009 let nullable_field = Arc::new(Field::new("result", DataType::Int32, true));
3011 let options_nullable = GetOptions {
3012 path: VariantPath::try_from("x").unwrap(),
3013 as_type: Some(nullable_field.clone()),
3014 cast_options: CastOptions::default(),
3015 };
3016
3017 let variant_array_ref = ArrayRef::from(variant_array);
3018 let result_nullable = variant_get(&variant_array_ref, options_nullable).unwrap();
3019
3020 let int32_result = result_nullable
3022 .as_any()
3023 .downcast_ref::<Int32Array>()
3024 .unwrap();
3025 assert_eq!(int32_result.len(), 9);
3026
3027 assert!(!int32_result.is_null(0));
3029 assert_eq!(int32_result.value(0), 42);
3030
3031 assert!(int32_result.is_null(1));
3033
3034 assert!(int32_result.is_null(2));
3036
3037 assert!(int32_result.is_null(3));
3039
3040 assert!(int32_result.is_null(4));
3042
3043 assert!(!int32_result.is_null(5));
3046 assert_eq!(int32_result.value(5), 127);
3047
3048 assert!(!int32_result.is_null(6));
3051 assert_eq!(int32_result.value(6), 32767);
3052
3053 assert!(!int32_result.is_null(7));
3056 assert_eq!(int32_result.value(7), 2147483647);
3057
3058 assert!(int32_result.is_null(8));
3061
3062 let non_nullable_field = Arc::new(Field::new("result", DataType::Int32, false));
3064 let options_non_nullable = GetOptions {
3065 path: VariantPath::try_from("x").unwrap(),
3066 as_type: Some(non_nullable_field.clone()),
3067 cast_options: CastOptions::default(), };
3069
3070 let variant_array_2 = json_to_variant(&string_array).unwrap();
3072 let variant_array_ref_2 = ArrayRef::from(variant_array_2);
3073 let result_non_nullable = variant_get(&variant_array_ref_2, options_non_nullable).unwrap();
3074 let int32_result_2 = result_non_nullable
3075 .as_any()
3076 .downcast_ref::<Int32Array>()
3077 .unwrap();
3078
3079 assert_eq!(int32_result_2.len(), 9);
3081
3082 assert!(!int32_result_2.is_null(0));
3084 assert_eq!(int32_result_2.value(0), 42);
3085
3086 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);
3096 assert!(!int32_result_2.is_null(6)); assert_eq!(int32_result_2.value(6), 32767);
3098 assert!(!int32_result_2.is_null(7)); assert_eq!(int32_result_2.value(7), 2147483647);
3100
3101 assert!(int32_result_2.is_null(8)); }
3104
3105 #[test]
3106 fn test_struct_extraction_subset_superset_schema_perfectly_shredded() {
3107 let variant_array = create_comprehensive_shredded_variant();
3109
3110 let struct_fields = Fields::from(vec![
3112 Field::new("a", DataType::Int32, true),
3113 Field::new("b", DataType::Int32, true),
3114 Field::new("d", DataType::Int32, true),
3115 ]);
3116 let struct_type = DataType::Struct(struct_fields);
3117
3118 let options = GetOptions {
3119 path: VariantPath::default(),
3120 as_type: Some(Arc::new(Field::new("result", struct_type, true))),
3121 cast_options: CastOptions::default(),
3122 };
3123
3124 let result = variant_get(&variant_array, options).unwrap();
3125
3126 let struct_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3128 assert_eq!(struct_result.len(), 5);
3129 assert_eq!(struct_result.num_columns(), 3);
3130
3131 let field_a = struct_result
3132 .column(0)
3133 .as_any()
3134 .downcast_ref::<Int32Array>()
3135 .unwrap();
3136 let field_b = struct_result
3137 .column(1)
3138 .as_any()
3139 .downcast_ref::<Int32Array>()
3140 .unwrap();
3141 let field_d = struct_result
3142 .column(2)
3143 .as_any()
3144 .downcast_ref::<Int32Array>()
3145 .unwrap();
3146
3147 assert!(!struct_result.is_null(0));
3149 assert_eq!(field_a.value(0), 1);
3150 assert_eq!(field_b.value(0), 2);
3151 assert!(field_d.is_null(0)); assert!(struct_result.is_null(1));
3155
3156 assert!(!struct_result.is_null(2));
3158 assert!(field_a.is_null(2)); assert_eq!(field_b.value(2), 2);
3160 assert!(field_d.is_null(2)); assert!(!struct_result.is_null(3));
3164 assert_eq!(field_a.value(3), 1);
3165 assert!(field_b.is_null(3)); assert!(field_d.is_null(3)); assert!(!struct_result.is_null(4));
3170 assert!(field_a.is_null(4)); assert!(field_b.is_null(4)); assert!(field_d.is_null(4)); }
3174
3175 #[test]
3176 fn test_nested_struct_extraction_perfectly_shredded() {
3177 let variant_array = create_comprehensive_nested_shredded_variant();
3179 println!("variant_array: {variant_array:?}");
3180
3181 let inner_field = Field::new("inner", DataType::Int32, true);
3183 let inner_type = DataType::Struct(Fields::from(vec![inner_field]));
3184 let outer_field = Field::new("outer", inner_type, true);
3185 let result_type = DataType::Struct(Fields::from(vec![outer_field]));
3186
3187 let options = GetOptions {
3188 path: VariantPath::default(),
3189 as_type: Some(Arc::new(Field::new("result", result_type, true))),
3190 cast_options: CastOptions::default(),
3191 };
3192
3193 let result = variant_get(&variant_array, options).unwrap();
3194 println!("result: {result:?}");
3195
3196 let outer_struct = result.as_any().downcast_ref::<StructArray>().unwrap();
3198 assert_eq!(outer_struct.len(), 4);
3199 assert_eq!(outer_struct.num_columns(), 1);
3200
3201 let inner_struct = outer_struct
3203 .column(0)
3204 .as_any()
3205 .downcast_ref::<StructArray>()
3206 .unwrap();
3207 assert_eq!(inner_struct.num_columns(), 1);
3208
3209 let leaf_field = inner_struct
3211 .column(0)
3212 .as_any()
3213 .downcast_ref::<Int32Array>()
3214 .unwrap();
3215
3216 assert!(!outer_struct.is_null(0));
3218 assert!(!inner_struct.is_null(0));
3219 assert_eq!(leaf_field.value(0), 42);
3220
3221 assert!(!outer_struct.is_null(1));
3223 assert!(!inner_struct.is_null(1)); assert!(leaf_field.is_null(1)); assert!(!outer_struct.is_null(2));
3228 assert!(inner_struct.is_null(2)); assert!(outer_struct.is_null(3));
3232 }
3233
3234 #[test]
3235 fn test_path_based_null_masks_one_step() {
3236 let variant_array = create_comprehensive_nested_shredded_variant();
3238
3239 let path = VariantPath::try_from("outer").unwrap();
3241 let inner_field = Field::new("inner", DataType::Int32, true);
3242 let result_type = DataType::Struct(Fields::from(vec![inner_field]));
3243
3244 let options = GetOptions {
3245 path,
3246 as_type: Some(Arc::new(Field::new("result", result_type, true))),
3247 cast_options: CastOptions::default(),
3248 };
3249
3250 let result = variant_get(&variant_array, options).unwrap();
3251
3252 let outer_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3254 assert_eq!(outer_result.len(), 4);
3255 assert_eq!(outer_result.num_columns(), 1);
3256
3257 let inner_field = outer_result
3259 .column(0)
3260 .as_any()
3261 .downcast_ref::<Int32Array>()
3262 .unwrap();
3263
3264 assert!(!outer_result.is_null(0));
3266 assert_eq!(inner_field.value(0), 42);
3267
3268 assert!(!outer_result.is_null(1));
3270 assert!(inner_field.is_null(1));
3271
3272 assert!(outer_result.is_null(2));
3274
3275 assert!(outer_result.is_null(3));
3277 }
3278
3279 #[test]
3280 fn test_path_based_null_masks_two_steps() {
3281 let variant_array = create_comprehensive_nested_shredded_variant();
3283
3284 let path = VariantPath::try_from("outer").unwrap().join("inner");
3286
3287 let options = GetOptions {
3288 path,
3289 as_type: Some(Arc::new(Field::new("result", DataType::Int32, true))),
3290 cast_options: CastOptions::default(),
3291 };
3292
3293 let result = variant_get(&variant_array, options).unwrap();
3294
3295 let int_result = result.as_any().downcast_ref::<Int32Array>().unwrap();
3297 assert_eq!(int_result.len(), 4);
3298
3299 assert!(!int_result.is_null(0));
3301 assert_eq!(int_result.value(0), 42);
3302
3303 assert!(int_result.is_null(1));
3305
3306 assert!(int_result.is_null(2));
3308
3309 assert!(int_result.is_null(3));
3311 }
3312
3313 #[test]
3314 fn test_struct_extraction_mixed_and_unshredded() {
3315 let variant_array = create_mixed_and_unshredded_variant();
3317
3318 let struct_fields = Fields::from(vec![
3320 Field::new("x", DataType::Int32, true),
3321 Field::new("y", DataType::Int32, true),
3322 ]);
3323 let struct_type = DataType::Struct(struct_fields);
3324
3325 let options = GetOptions {
3326 path: VariantPath::default(),
3327 as_type: Some(Arc::new(Field::new("result", struct_type, true))),
3328 cast_options: CastOptions::default(),
3329 };
3330
3331 let result = variant_get(&variant_array, options).unwrap();
3332
3333 let struct_result = result.as_any().downcast_ref::<StructArray>().unwrap();
3335 assert_eq!(struct_result.len(), 4);
3336 assert_eq!(struct_result.num_columns(), 2);
3337
3338 let field_x = struct_result
3339 .column(0)
3340 .as_any()
3341 .downcast_ref::<Int32Array>()
3342 .unwrap();
3343 let field_y = struct_result
3344 .column(1)
3345 .as_any()
3346 .downcast_ref::<Int32Array>()
3347 .unwrap();
3348
3349 assert_eq!(field_x.value(0), 1);
3351 assert_eq!(field_y.value(0), 42);
3352
3353 assert_eq!(field_x.value(1), 2);
3355 assert!(field_y.is_null(1));
3356
3357 assert_eq!(field_x.value(2), 3);
3359 assert!(field_y.is_null(2));
3360
3361 assert!(struct_result.is_null(3));
3363 }
3364
3365 #[test]
3366 fn test_struct_row_builder_handles_unshredded_nested_structs() {
3367 let json_strings = vec![
3369 r#"{"outer": {"inner": 42}}"#,
3370 r#"{"outer": {"inner": 100}}"#,
3371 ];
3372 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(json_strings));
3373 let variant_array = json_to_variant(&string_array).unwrap();
3374
3375 let inner_fields = Fields::from(vec![Field::new("inner", DataType::Int32, true)]);
3377 let inner_struct_type = DataType::Struct(inner_fields);
3378 let outer_fields = Fields::from(vec![Field::new("outer", inner_struct_type, true)]);
3379 let outer_struct_type = DataType::Struct(outer_fields);
3380
3381 let options = GetOptions {
3382 path: VariantPath::default(),
3383 as_type: Some(Arc::new(Field::new("result", outer_struct_type, true))),
3384 cast_options: CastOptions::default(),
3385 };
3386
3387 let variant_array_ref = ArrayRef::from(variant_array);
3388 let result = variant_get(&variant_array_ref, options).unwrap();
3389
3390 let outer_struct = result.as_struct();
3391 assert_eq!(outer_struct.len(), 2);
3392 assert_eq!(outer_struct.num_columns(), 1);
3393
3394 let inner_struct = outer_struct.column(0).as_struct();
3395 assert_eq!(inner_struct.num_columns(), 1);
3396
3397 let inner_values = inner_struct
3398 .column(0)
3399 .as_any()
3400 .downcast_ref::<Int32Array>()
3401 .unwrap();
3402 assert_eq!(inner_values.value(0), 42);
3403 assert_eq!(inner_values.value(1), 100);
3404 }
3405
3406 #[test]
3407 fn test_unshredded_struct_safe_cast_non_object_rows_are_null() {
3408 let json_strings = vec![r#"{"a": 1, "b": 2}"#, "123", "{}"];
3409 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(json_strings));
3410 let variant_array_ref = ArrayRef::from(json_to_variant(&string_array).unwrap());
3411
3412 let struct_fields = Fields::from(vec![
3413 Field::new("a", DataType::Int32, true),
3414 Field::new("b", DataType::Int32, true),
3415 ]);
3416 let options = GetOptions {
3417 path: VariantPath::default(),
3418 as_type: Some(Arc::new(Field::new(
3419 "result",
3420 DataType::Struct(struct_fields),
3421 true,
3422 ))),
3423 cast_options: CastOptions::default(),
3424 };
3425
3426 let result = variant_get(&variant_array_ref, options).unwrap();
3427 let struct_result = result.as_struct();
3428 let field_a = struct_result
3429 .column(0)
3430 .as_primitive::<arrow::datatypes::Int32Type>();
3431 let field_b = struct_result
3432 .column(1)
3433 .as_primitive::<arrow::datatypes::Int32Type>();
3434
3435 assert!(!struct_result.is_null(0));
3437 assert_eq!(field_a.value(0), 1);
3438 assert_eq!(field_b.value(0), 2);
3439
3440 assert!(struct_result.is_null(1));
3442 assert!(field_a.is_null(1));
3443 assert!(field_b.is_null(1));
3444
3445 assert!(!struct_result.is_null(2));
3447 assert!(field_a.is_null(2));
3448 assert!(field_b.is_null(2));
3449 }
3450
3451 #[test]
3452 fn test_unshredded_struct_strict_cast_non_object_errors() {
3453 let json_strings = vec![r#"{"a": 1, "b": 2}"#, "123"];
3454 let string_array: Arc<dyn Array> = Arc::new(StringArray::from(json_strings));
3455 let variant_array_ref = ArrayRef::from(json_to_variant(&string_array).unwrap());
3456
3457 let struct_fields = Fields::from(vec![
3458 Field::new("a", DataType::Int32, true),
3459 Field::new("b", DataType::Int32, true),
3460 ]);
3461 let options = GetOptions {
3462 path: VariantPath::default(),
3463 as_type: Some(Arc::new(Field::new(
3464 "result",
3465 DataType::Struct(struct_fields),
3466 true,
3467 ))),
3468 cast_options: CastOptions {
3469 safe: false,
3470 ..Default::default()
3471 },
3472 };
3473
3474 let err = variant_get(&variant_array_ref, options).unwrap_err();
3475 assert!(
3476 err.to_string()
3477 .contains("Failed to extract struct from variant")
3478 );
3479 }
3480
3481 fn create_comprehensive_shredded_variant() -> ArrayRef {
3484 let (metadata, _) = {
3485 let mut builder = parquet_variant::VariantBuilder::new();
3486 let obj = builder.new_object();
3487 obj.finish();
3488 builder.finish()
3489 };
3490
3491 let nulls = NullBuffer::from(vec![
3493 true, false, true, true, true, ]);
3499
3500 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 5));
3501
3502 let a_field_typed_value = Int32Array::from(vec![Some(1), None, None, Some(1), None]);
3505 let a_field_shredded = ShreddedVariantFieldArray::from_parts(
3506 None,
3507 Some(Arc::new(a_field_typed_value) as ArrayRef),
3508 None,
3509 );
3510
3511 let b_field_typed_value = Int32Array::from(vec![Some(2), None, Some(2), None, None]);
3513 let b_field_shredded = ShreddedVariantFieldArray::from_parts(
3514 None,
3515 Some(Arc::new(b_field_typed_value) as ArrayRef),
3516 None,
3517 );
3518
3519 let c_field_typed_value = Int32Array::from(vec![Some(3), None, None, None, None]);
3521 let c_field_shredded = ShreddedVariantFieldArray::from_parts(
3522 None,
3523 Some(Arc::new(c_field_typed_value) as ArrayRef),
3524 None,
3525 );
3526
3527 let typed_value_fields = Fields::from(vec![
3529 Field::new("a", a_field_shredded.data_type().clone(), true),
3530 Field::new("b", b_field_shredded.data_type().clone(), true),
3531 Field::new("c", c_field_shredded.data_type().clone(), true),
3532 ]);
3533 let typed_value_struct = StructArray::try_new(
3534 typed_value_fields,
3535 vec![
3536 ArrayRef::from(a_field_shredded),
3537 ArrayRef::from(b_field_shredded),
3538 ArrayRef::from(c_field_shredded),
3539 ],
3540 None,
3541 )
3542 .unwrap();
3543
3544 ArrayRef::from(VariantArray::from_parts(
3546 Arc::new(metadata_array),
3547 None,
3548 Some(Arc::new(typed_value_struct)),
3549 Some(nulls),
3550 ))
3551 }
3552
3553 fn create_comprehensive_nested_shredded_variant() -> ArrayRef {
3558 let inner_typed_value = Int32Array::from(vec![Some(42), None, None, None]); let inner = ShreddedVariantFieldArray::from_parts(
3562 None,
3563 Some(Arc::new(inner_typed_value) as ArrayRef),
3564 None,
3565 );
3566
3567 let outer_typed_value_nulls = NullBuffer::from(vec![
3568 true, false, false, false, ]);
3573 let outer_typed_value = StructArrayBuilder::new()
3574 .with_field("inner", ArrayRef::from(inner), false)
3575 .with_nulls(outer_typed_value_nulls)
3576 .build();
3577
3578 let outer = ShreddedVariantFieldArray::from_parts(
3579 None,
3580 Some(Arc::new(outer_typed_value) as ArrayRef),
3581 None,
3582 );
3583
3584 let typed_value_nulls = NullBuffer::from(vec![
3585 true, true, false, false, ]);
3590 let typed_value = StructArrayBuilder::new()
3591 .with_field("outer", ArrayRef::from(outer), false)
3592 .with_nulls(typed_value_nulls)
3593 .build();
3594
3595 let metadata_array =
3597 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 4));
3598 let nulls = NullBuffer::from(vec![
3599 true, true, true, false, ]);
3604 ArrayRef::from(VariantArray::from_parts(
3605 Arc::new(metadata_array),
3606 None,
3607 Some(Arc::new(typed_value)),
3608 Some(nulls),
3609 ))
3610 }
3611
3612 fn create_mixed_and_unshredded_variant() -> ArrayRef {
3615 let (metadata, y_field_value) = {
3620 let mut builder = parquet_variant::VariantBuilder::new();
3621 let mut obj = builder.new_object();
3622 obj.insert("y", Variant::from(42));
3623 obj.finish();
3624 builder.finish()
3625 };
3626
3627 let metadata_array = BinaryViewArray::from_iter_values(std::iter::repeat_n(&metadata, 4));
3628
3629 let empty_object_value = {
3636 let mut builder = parquet_variant::VariantBuilder::new();
3637 builder.new_object().finish();
3638 let (_, value) = builder.finish();
3639 value
3640 };
3641
3642 let y_null_value = {
3643 let mut builder = parquet_variant::VariantBuilder::new();
3644 builder.new_object().with_field("y", Variant::Null).finish();
3645 let (_, value) = builder.finish();
3646 value
3647 };
3648
3649 let value_array = BinaryViewArray::from(vec![
3650 Some(y_field_value.as_slice()), Some(empty_object_value.as_slice()), Some(y_null_value.as_slice()), Some(empty_object_value.as_slice()), ]);
3655
3656 let x_field_typed_value = Int32Array::from(vec![Some(1), Some(2), Some(3), Some(0)]);
3659 let x_field_shredded = ShreddedVariantFieldArray::from_parts(
3660 None,
3661 Some(Arc::new(x_field_typed_value) as ArrayRef),
3662 None,
3663 );
3664
3665 let typed_value_struct = StructArrayBuilder::new()
3667 .with_field("x", ArrayRef::from(x_field_shredded), false)
3668 .build();
3669
3670 let variant_nulls = NullBuffer::from(vec![true, true, true, false]); ArrayRef::from(VariantArray::from_parts(
3674 Arc::new(metadata_array),
3675 Some(Arc::new(value_array)),
3676 Some(Arc::new(typed_value_struct)),
3677 Some(variant_nulls),
3678 ))
3679 }
3680
3681 #[test]
3682 fn get_decimal32_rescaled_to_scale2() {
3683 let mut builder = crate::VariantArrayBuilder::new(5);
3685 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();
3689 builder.append_variant(
3690 VariantDecimal8::try_new((VariantDecimal4::MAX_UNSCALED_VALUE as i64) + 1, 3)
3691 .unwrap()
3692 .into(),
3693 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3695
3696 let field = Field::new("result", DataType::Decimal32(9, 2), true);
3697 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3698 let result = variant_get(&variant_array, options).unwrap();
3699 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3700
3701 assert_eq!(result.precision(), 9);
3702 assert_eq!(result.scale(), 2);
3703 assert_eq!(result.value(0), 1234);
3704 assert_eq!(result.value(1), 123);
3705 assert_eq!(result.value(2), 123400);
3706 assert!(result.is_null(3));
3707 assert_eq!(
3708 result.value(4),
3709 VariantDecimal4::MAX_UNSCALED_VALUE / 10 + 1
3710 ); }
3712
3713 #[test]
3714 fn get_decimal32_scale_down_rounding() {
3715 let mut builder = crate::VariantArrayBuilder::new(7);
3716 builder.append_variant(VariantDecimal4::try_new(1235, 0).unwrap().into());
3717 builder.append_variant(VariantDecimal4::try_new(1245, 0).unwrap().into());
3718 builder.append_variant(VariantDecimal4::try_new(-1235, 0).unwrap().into());
3719 builder.append_variant(VariantDecimal4::try_new(-1245, 0).unwrap().into());
3720 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());
3724
3725 let field = Field::new("result", DataType::Decimal32(9, -1), true);
3726 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3727 let result = variant_get(&variant_array, options).unwrap();
3728 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3729
3730 assert_eq!(result.precision(), 9);
3731 assert_eq!(result.scale(), -1);
3732 assert_eq!(result.value(0), 124);
3733 assert_eq!(result.value(1), 125);
3734 assert_eq!(result.value(2), -124);
3735 assert_eq!(result.value(3), -125);
3736 assert_eq!(result.value(4), 1);
3737 assert!(result.is_valid(5));
3738 assert_eq!(result.value(5), 0);
3739 assert_eq!(result.value(6), 1);
3740 }
3741
3742 #[test]
3743 fn get_decimal32_large_scale_reduction() {
3744 let mut builder = crate::VariantArrayBuilder::new(2);
3745 builder.append_variant(
3746 VariantDecimal4::try_new(-VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3747 .unwrap()
3748 .into(),
3749 );
3750 builder.append_variant(
3751 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3752 .unwrap()
3753 .into(),
3754 );
3755 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3756
3757 let field = Field::new("result", DataType::Decimal32(9, -9), true);
3758 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3759 let result = variant_get(&variant_array, options).unwrap();
3760 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3761
3762 assert_eq!(result.precision(), 9);
3763 assert_eq!(result.scale(), -9);
3764 assert_eq!(result.value(0), -1);
3765 assert_eq!(result.value(1), 1);
3766
3767 let field = Field::new("result", DataType::Decimal32(9, -10), true);
3768 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3769 let result = variant_get(&variant_array, options).unwrap();
3770 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3771
3772 assert_eq!(result.precision(), 9);
3773 assert_eq!(result.scale(), -10);
3774 assert!(result.is_valid(0));
3775 assert_eq!(result.value(0), 0);
3776 assert!(result.is_valid(1));
3777 assert_eq!(result.value(1), 0);
3778 }
3779
3780 #[test]
3781 fn get_decimal32_precision_overflow_safe() {
3782 let mut builder = crate::VariantArrayBuilder::new(2);
3784 builder.append_variant(
3785 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3786 .unwrap()
3787 .into(),
3788 );
3789 builder.append_variant(
3790 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 9)
3791 .unwrap()
3792 .into(),
3793 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3795
3796 let field = Field::new("result", DataType::Decimal32(2, 2), true);
3797 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3798 let result = variant_get(&variant_array, options).unwrap();
3799 let result = result.as_any().downcast_ref::<Decimal32Array>().unwrap();
3800
3801 assert!(result.is_null(0));
3802 assert!(result.is_null(1)); }
3804
3805 #[test]
3806 fn get_decimal32_precision_overflow_unsafe_errors() {
3807 let mut builder = crate::VariantArrayBuilder::new(1);
3808 builder.append_variant(
3809 VariantDecimal4::try_new(VariantDecimal4::MAX_UNSCALED_VALUE, 0)
3810 .unwrap()
3811 .into(),
3812 );
3813 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3814
3815 let field = Field::new("result", DataType::Decimal32(9, 2), true);
3816 let cast_options = CastOptions {
3817 safe: false,
3818 ..Default::default()
3819 };
3820 let options = GetOptions::new()
3821 .with_as_type(Some(FieldRef::from(field)))
3822 .with_cast_options(cast_options);
3823 let err = variant_get(&variant_array, options).unwrap_err();
3824
3825 assert!(
3826 err.to_string().contains(
3827 "Failed to cast to Decimal32(precision=9, scale=2) from variant Decimal4"
3828 )
3829 );
3830 }
3831
3832 #[test]
3833 fn get_decimal64_rescaled_to_scale2() {
3834 let mut builder = crate::VariantArrayBuilder::new(5);
3835 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();
3839 builder.append_variant(
3840 VariantDecimal16::try_new((VariantDecimal8::MAX_UNSCALED_VALUE as i128) + 1, 3)
3841 .unwrap()
3842 .into(),
3843 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3845
3846 let field = Field::new("result", DataType::Decimal64(18, 2), true);
3847 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3848 let result = variant_get(&variant_array, options).unwrap();
3849 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3850
3851 assert_eq!(result.precision(), 18);
3852 assert_eq!(result.scale(), 2);
3853 assert_eq!(result.value(0), 1234);
3854 assert_eq!(result.value(1), 123);
3855 assert_eq!(result.value(2), 123400);
3856 assert!(result.is_null(3));
3857 assert_eq!(
3858 result.value(4),
3859 VariantDecimal8::MAX_UNSCALED_VALUE / 10 + 1
3860 ); }
3862
3863 #[test]
3864 fn get_decimal64_scale_down_rounding() {
3865 let mut builder = crate::VariantArrayBuilder::new(7);
3866 builder.append_variant(VariantDecimal8::try_new(1235, 0).unwrap().into());
3867 builder.append_variant(VariantDecimal8::try_new(1245, 0).unwrap().into());
3868 builder.append_variant(VariantDecimal8::try_new(-1235, 0).unwrap().into());
3869 builder.append_variant(VariantDecimal8::try_new(-1245, 0).unwrap().into());
3870 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());
3874
3875 let field = Field::new("result", DataType::Decimal64(18, -1), true);
3876 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3877 let result = variant_get(&variant_array, options).unwrap();
3878 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3879
3880 assert_eq!(result.precision(), 18);
3881 assert_eq!(result.scale(), -1);
3882 assert_eq!(result.value(0), 124);
3883 assert_eq!(result.value(1), 125);
3884 assert_eq!(result.value(2), -124);
3885 assert_eq!(result.value(3), -125);
3886 assert_eq!(result.value(4), 1);
3887 assert!(result.is_valid(5));
3888 assert_eq!(result.value(5), 0);
3889 assert_eq!(result.value(6), 1);
3890 }
3891
3892 #[test]
3893 fn get_decimal64_large_scale_reduction() {
3894 let mut builder = crate::VariantArrayBuilder::new(2);
3895 builder.append_variant(
3896 VariantDecimal8::try_new(-VariantDecimal8::MAX_UNSCALED_VALUE, 0)
3897 .unwrap()
3898 .into(),
3899 );
3900 builder.append_variant(
3901 VariantDecimal8::try_new(VariantDecimal8::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::Decimal64(18, -18), 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::<Decimal64Array>().unwrap();
3911
3912 assert_eq!(result.precision(), 18);
3913 assert_eq!(result.scale(), -18);
3914 assert_eq!(result.value(0), -1);
3915 assert_eq!(result.value(1), 1);
3916
3917 let field = Field::new("result", DataType::Decimal64(18, -19), true);
3918 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3919 let result = variant_get(&variant_array, options).unwrap();
3920 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3921
3922 assert_eq!(result.precision(), 18);
3923 assert_eq!(result.scale(), -19);
3924 assert!(result.is_valid(0));
3925 assert_eq!(result.value(0), 0);
3926 assert!(result.is_valid(1));
3927 assert_eq!(result.value(1), 0);
3928 }
3929
3930 #[test]
3931 fn get_decimal64_precision_overflow_safe() {
3932 let mut builder = crate::VariantArrayBuilder::new(2);
3934 builder.append_variant(
3935 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0)
3936 .unwrap()
3937 .into(),
3938 );
3939 builder.append_variant(
3940 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 18)
3941 .unwrap()
3942 .into(),
3943 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
3945
3946 let field = Field::new("result", DataType::Decimal64(2, 2), true);
3947 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3948 let result = variant_get(&variant_array, options).unwrap();
3949 let result = result.as_any().downcast_ref::<Decimal64Array>().unwrap();
3950
3951 assert!(result.is_null(0));
3952 assert!(result.is_null(1));
3953 }
3954
3955 #[test]
3956 fn get_decimal64_precision_overflow_unsafe_errors() {
3957 let mut builder = crate::VariantArrayBuilder::new(1);
3958 builder.append_variant(
3959 VariantDecimal8::try_new(VariantDecimal8::MAX_UNSCALED_VALUE, 0)
3960 .unwrap()
3961 .into(),
3962 );
3963 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3964
3965 let field = Field::new("result", DataType::Decimal64(18, 2), true);
3966 let cast_options = CastOptions {
3967 safe: false,
3968 ..Default::default()
3969 };
3970 let options = GetOptions::new()
3971 .with_as_type(Some(FieldRef::from(field)))
3972 .with_cast_options(cast_options);
3973 let err = variant_get(&variant_array, options).unwrap_err();
3974
3975 assert!(
3976 err.to_string().contains(
3977 "Failed to cast to Decimal64(precision=18, scale=2) from variant Decimal8"
3978 )
3979 );
3980 }
3981
3982 #[test]
3983 fn get_decimal128_rescaled_to_scale2() {
3984 let mut builder = crate::VariantArrayBuilder::new(4);
3985 builder.append_variant(VariantDecimal16::try_new(1234, 2).unwrap().into());
3986 builder.append_variant(VariantDecimal16::try_new(1234, 3).unwrap().into());
3987 builder.append_variant(VariantDecimal16::try_new(1234, 0).unwrap().into());
3988 builder.append_null();
3989 let variant_array: ArrayRef = ArrayRef::from(builder.build());
3990
3991 let field = Field::new("result", DataType::Decimal128(38, 2), true);
3992 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
3993 let result = variant_get(&variant_array, options).unwrap();
3994 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
3995
3996 assert_eq!(result.precision(), 38);
3997 assert_eq!(result.scale(), 2);
3998 assert_eq!(result.value(0), 1234);
3999 assert_eq!(result.value(1), 123);
4000 assert_eq!(result.value(2), 123400);
4001 assert!(result.is_null(3));
4002 }
4003
4004 #[test]
4005 fn get_decimal128_scale_down_rounding() {
4006 let mut builder = crate::VariantArrayBuilder::new(7);
4007 builder.append_variant(VariantDecimal16::try_new(1235, 0).unwrap().into());
4008 builder.append_variant(VariantDecimal16::try_new(1245, 0).unwrap().into());
4009 builder.append_variant(VariantDecimal16::try_new(-1235, 0).unwrap().into());
4010 builder.append_variant(VariantDecimal16::try_new(-1245, 0).unwrap().into());
4011 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());
4015
4016 let field = Field::new("result", DataType::Decimal128(38, -1), true);
4017 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4018 let result = variant_get(&variant_array, options).unwrap();
4019 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
4020
4021 assert_eq!(result.precision(), 38);
4022 assert_eq!(result.scale(), -1);
4023 assert_eq!(result.value(0), 124);
4024 assert_eq!(result.value(1), 125);
4025 assert_eq!(result.value(2), -124);
4026 assert_eq!(result.value(3), -125);
4027 assert_eq!(result.value(4), 1);
4028 assert!(result.is_valid(5));
4029 assert_eq!(result.value(5), 0);
4030 assert_eq!(result.value(6), 1);
4031 }
4032
4033 #[test]
4034 fn get_decimal128_precision_overflow_safe() {
4035 let mut builder = crate::VariantArrayBuilder::new(2);
4037 builder.append_variant(
4038 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
4039 .unwrap()
4040 .into(),
4041 );
4042 builder.append_variant(
4043 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 38)
4044 .unwrap()
4045 .into(),
4046 ); let variant_array: ArrayRef = ArrayRef::from(builder.build());
4048
4049 let field = Field::new("result", DataType::Decimal128(2, 2), true);
4050 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4051 let result = variant_get(&variant_array, options).unwrap();
4052 let result = result.as_any().downcast_ref::<Decimal128Array>().unwrap();
4053
4054 assert!(result.is_null(0));
4055 assert!(result.is_null(1)); }
4057
4058 #[test]
4059 fn get_decimal128_precision_overflow_unsafe_errors() {
4060 let mut builder = crate::VariantArrayBuilder::new(1);
4061 builder.append_variant(
4062 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
4063 .unwrap()
4064 .into(),
4065 );
4066 let variant_array: ArrayRef = ArrayRef::from(builder.build());
4067
4068 let field = Field::new("result", DataType::Decimal128(38, 2), true);
4069 let cast_options = CastOptions {
4070 safe: false,
4071 ..Default::default()
4072 };
4073 let options = GetOptions::new()
4074 .with_as_type(Some(FieldRef::from(field)))
4075 .with_cast_options(cast_options);
4076 let err = variant_get(&variant_array, options).unwrap_err();
4077
4078 assert!(err.to_string().contains(
4079 "Failed to cast to Decimal128(precision=38, scale=2) from variant Decimal16"
4080 ));
4081 }
4082
4083 #[test]
4084 fn get_decimal256_rescaled_to_scale2() {
4085 let mut builder = crate::VariantArrayBuilder::new(4);
4087 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();
4091 let variant_array: ArrayRef = ArrayRef::from(builder.build());
4092
4093 let field = Field::new("result", DataType::Decimal256(76, 2), true);
4094 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4095 let result = variant_get(&variant_array, options).unwrap();
4096 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
4097
4098 assert_eq!(result.precision(), 76);
4099 assert_eq!(result.scale(), 2);
4100 assert_eq!(result.value(0), i256::from_i128(1234));
4101 assert_eq!(result.value(1), i256::from_i128(123));
4102 assert_eq!(result.value(2), i256::from_i128(123400));
4103 assert!(result.is_null(3));
4104 }
4105
4106 #[test]
4107 fn get_decimal256_scale_down_rounding() {
4108 let mut builder = crate::VariantArrayBuilder::new(7);
4109 builder.append_variant(VariantDecimal16::try_new(1235, 0).unwrap().into());
4110 builder.append_variant(VariantDecimal16::try_new(1245, 0).unwrap().into());
4111 builder.append_variant(VariantDecimal16::try_new(-1235, 0).unwrap().into());
4112 builder.append_variant(VariantDecimal16::try_new(-1245, 0).unwrap().into());
4113 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());
4117
4118 let field = Field::new("result", DataType::Decimal256(76, -1), true);
4119 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4120 let result = variant_get(&variant_array, options).unwrap();
4121 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
4122
4123 assert_eq!(result.precision(), 76);
4124 assert_eq!(result.scale(), -1);
4125 assert_eq!(result.value(0), i256::from_i128(124));
4126 assert_eq!(result.value(1), i256::from_i128(125));
4127 assert_eq!(result.value(2), i256::from_i128(-124));
4128 assert_eq!(result.value(3), i256::from_i128(-125));
4129 assert_eq!(result.value(4), i256::from_i128(1));
4130 assert!(result.is_valid(5));
4131 assert_eq!(result.value(5), i256::from_i128(0));
4132 assert_eq!(result.value(6), i256::from_i128(1));
4133 }
4134
4135 #[test]
4136 fn get_decimal256_precision_overflow_safe() {
4137 let mut builder = crate::VariantArrayBuilder::new(2);
4139 builder.append_variant(
4140 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 1)
4141 .unwrap()
4142 .into(),
4143 );
4144 builder.append_variant(
4145 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
4146 .unwrap()
4147 .into(),
4148 );
4149 let variant_array: ArrayRef = ArrayRef::from(builder.build());
4150
4151 let field = Field::new("result", DataType::Decimal256(76, 39), true);
4152 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4153 let result = variant_get(&variant_array, options).unwrap();
4154 let result = result.as_any().downcast_ref::<Decimal256Array>().unwrap();
4155
4156 let base = i256::from_i128(10);
4159 let factor = base.checked_pow(38).unwrap();
4160 let expected = i256::from_i128(VariantDecimal16::MAX_UNSCALED_VALUE)
4161 .checked_mul(factor)
4162 .unwrap();
4163 assert_eq!(result.value(0), expected);
4164 assert!(result.is_null(1));
4165 }
4166
4167 #[test]
4168 fn get_decimal256_precision_overflow_unsafe_errors() {
4169 let mut builder = crate::VariantArrayBuilder::new(2);
4171 builder.append_variant(
4172 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 1)
4173 .unwrap()
4174 .into(),
4175 );
4176 builder.append_variant(
4177 VariantDecimal16::try_new(VariantDecimal16::MAX_UNSCALED_VALUE, 0)
4178 .unwrap()
4179 .into(),
4180 );
4181 let variant_array: ArrayRef = ArrayRef::from(builder.build());
4182
4183 let field = Field::new("result", DataType::Decimal256(76, 39), true);
4184 let cast_options = CastOptions {
4185 safe: false,
4186 ..Default::default()
4187 };
4188 let options = GetOptions::new()
4189 .with_as_type(Some(FieldRef::from(field)))
4190 .with_cast_options(cast_options);
4191 let err = variant_get(&variant_array, options).unwrap_err();
4192
4193 assert!(err.to_string().contains(
4194 "Failed to cast to Decimal256(precision=76, scale=39) from variant Decimal16"
4195 ));
4196 }
4197
4198 #[test]
4199 fn get_non_supported_temporal_types_error() {
4200 let values = vec![None, Some(Variant::Null), Some(Variant::BooleanFalse)];
4201 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter(values));
4202
4203 let test_cases = vec![
4204 FieldRef::from(Field::new(
4205 "result",
4206 DataType::Duration(TimeUnit::Microsecond),
4207 true,
4208 )),
4209 FieldRef::from(Field::new(
4210 "result",
4211 DataType::Interval(IntervalUnit::YearMonth),
4212 true,
4213 )),
4214 ];
4215
4216 for field in test_cases {
4217 let options = GetOptions::new().with_as_type(Some(field));
4218 let err = variant_get(&variant_array, options).unwrap_err();
4219 assert!(
4220 err.to_string()
4221 .contains("Casting Variant to duration/interval types is not supported")
4222 );
4223 }
4224 }
4225
4226 #[test]
4227 fn get_variant_as_dictionary() {
4228 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter(vec![
4229 Some(Variant::from("apple")),
4230 Some(Variant::from("banana")),
4231 None,
4232 Some(Variant::from("apple")),
4233 ]));
4234 let data_type = DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8));
4235 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4236 "dict",
4237 data_type.clone(),
4238 true,
4239 ))));
4240
4241 let result = variant_get(&variant_array, options).unwrap();
4242 assert_eq!(result.data_type(), &data_type);
4243
4244 let decoded = cast(result.as_ref(), &DataType::Utf8).unwrap();
4245 let expected = StringArray::from(vec![Some("apple"), Some("banana"), None, Some("apple")]);
4246 assert_eq!(decoded.as_ref(), &expected);
4247 }
4248
4249 #[test]
4250 fn get_variant_as_numeric_dictionary() {
4251 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter(vec![
4252 Some(Variant::from(42)),
4253 Some(Variant::from(7)),
4254 None,
4255 Some(Variant::from(42)),
4256 ]));
4257 let data_type = DataType::Dictionary(Box::new(DataType::Int16), Box::new(DataType::Int32));
4258 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4259 "dict",
4260 data_type.clone(),
4261 true,
4262 ))));
4263
4264 let result = variant_get(&variant_array, options).unwrap();
4265 assert_eq!(result.data_type(), &data_type);
4266
4267 let decoded = cast(result.as_ref(), &DataType::Int32).unwrap();
4268 let expected = Int32Array::from(vec![Some(42), Some(7), None, Some(42)]);
4269 assert_eq!(decoded.as_ref(), &expected);
4270 }
4271
4272 #[test]
4273 fn get_variant_as_run_end_encoded() {
4274 let variant_array: ArrayRef = ArrayRef::from(VariantArray::from_iter(vec![
4275 Some(Variant::from("apple")),
4276 Some(Variant::from("apple")),
4277 None,
4278 Some(Variant::from("banana")),
4279 Some(Variant::from("banana")),
4280 ]));
4281 let run_ends = Arc::new(Field::new("run_ends", DataType::Int32, false));
4282 let values = Arc::new(Field::new("values", DataType::Utf8, true));
4283 let data_type = DataType::RunEndEncoded(run_ends, values);
4284 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4285 "ree",
4286 data_type.clone(),
4287 true,
4288 ))));
4289
4290 let result = variant_get(&variant_array, options).unwrap();
4291 assert_eq!(result.data_type(), &data_type);
4292
4293 let decoded = cast(result.as_ref(), &DataType::Utf8).unwrap();
4294 let expected = StringArray::from(vec![
4295 Some("apple"),
4296 Some("apple"),
4297 None,
4298 Some("banana"),
4299 Some("banana"),
4300 ]);
4301 assert_eq!(decoded.as_ref(), &expected);
4302 }
4303
4304 fn invalid_time_variant_array() -> ArrayRef {
4305 let mut builder = VariantArrayBuilder::new(3);
4306 builder.append_variant(Variant::Int64(86401000000));
4308 builder.append_variant(Variant::Int64(86401000000));
4309 builder.append_variant(Variant::Int64(86401000000));
4310 Arc::new(builder.build().into_inner())
4311 }
4312
4313 #[test]
4314 fn test_variant_get_error_when_cast_failure_and_safe_false() {
4315 let variant_array = invalid_time_variant_array();
4316
4317 let field = Field::new("result", DataType::Time64(TimeUnit::Microsecond), true);
4318 let cast_options = CastOptions {
4319 safe: false, ..Default::default()
4321 };
4322 let options = GetOptions::new()
4323 .with_as_type(Some(FieldRef::from(field)))
4324 .with_cast_options(cast_options);
4325 let err = variant_get(&variant_array, options).unwrap_err();
4326 assert!(
4327 err.to_string().contains(
4328 "Cast error: Failed to extract primitive of type Time64(µs) from variant Int64(86401000000) at path VariantPath([])"
4329 ),
4330 "actual: {err}",
4331 );
4332 }
4333
4334 #[test]
4335 fn test_variant_get_return_null_when_cast_failure_and_safe_true() {
4336 let variant_array = invalid_time_variant_array();
4337
4338 let field = Field::new("result", DataType::Time64(TimeUnit::Microsecond), true);
4339 let cast_options = CastOptions {
4340 safe: true, ..Default::default()
4342 };
4343 let options = GetOptions::new()
4344 .with_as_type(Some(FieldRef::from(field)))
4345 .with_cast_options(cast_options);
4346 let result = variant_get(&variant_array, options).unwrap();
4347 assert_eq!(3, result.len());
4348
4349 for i in 0..3 {
4350 assert!(result.is_null(i));
4351 }
4352 }
4353
4354 #[test]
4355 fn test_perfect_shredding_returns_same_arc_ptr() {
4356 let variant_array = perfectly_shredded_int32_variant_array();
4357
4358 let variant_array_ref = VariantArray::try_new(&variant_array).unwrap();
4359 let typed_value_arc = variant_array_ref.typed_value_field().unwrap().clone();
4360
4361 let field = Field::new("result", DataType::Int32, true);
4362 let options = GetOptions::new().with_as_type(Some(FieldRef::from(field)));
4363 let result = variant_get(&variant_array, options).unwrap();
4364
4365 assert!(Arc::ptr_eq(&typed_value_arc, &result));
4366 }
4367
4368 #[test]
4369 fn test_perfect_shredding_three_typed_value_columns() {
4370 let all_nulls_values: Arc<Int32Array> = Arc::new(Int32Array::from(vec![
4372 Option::<i32>::None,
4373 Option::<i32>::None,
4374 Option::<i32>::None,
4375 ]));
4376 let all_nulls_erased: ArrayRef = all_nulls_values.clone();
4377 let all_nulls_field =
4378 ShreddedVariantFieldArray::from_parts(None, Some(all_nulls_erased.clone()), None);
4379 let all_nulls_type = all_nulls_field.data_type().clone();
4380 let all_nulls_struct: ArrayRef = ArrayRef::from(all_nulls_field);
4381
4382 let some_nulls_values: Arc<Int32Array> =
4384 Arc::new(Int32Array::from(vec![Some(10), None, Some(30)]));
4385 let some_nulls_erased: ArrayRef = some_nulls_values.clone();
4386 let some_nulls_field =
4387 ShreddedVariantFieldArray::from_parts(None, Some(some_nulls_erased.clone()), None);
4388 let some_nulls_type = some_nulls_field.data_type().clone();
4389 let some_nulls_struct: ArrayRef = ArrayRef::from(some_nulls_field);
4390
4391 let inner_values: Arc<Int32Array> =
4393 Arc::new(Int32Array::from(vec![Some(111), None, Some(333)]));
4394 let inner_erased: ArrayRef = inner_values.clone();
4395 let inner_field =
4396 ShreddedVariantFieldArray::from_parts(None, Some(inner_erased.clone()), None);
4397 let inner_field_type = inner_field.data_type().clone();
4398 let inner_struct_array: ArrayRef = ArrayRef::from(inner_field);
4399
4400 let nested_struct = Arc::new(
4401 StructArray::try_new(
4402 Fields::from(vec![Field::new("inner", inner_field_type, true)]),
4403 vec![inner_struct_array],
4404 None,
4405 )
4406 .unwrap(),
4407 );
4408 let nested_struct_erased: ArrayRef = nested_struct.clone();
4409 let struct_field =
4410 ShreddedVariantFieldArray::from_parts(None, Some(nested_struct_erased.clone()), None);
4411 let struct_field_type = struct_field.data_type().clone();
4412 let struct_field_struct: ArrayRef = ArrayRef::from(struct_field);
4413
4414 let typed_value_struct = StructArray::try_new(
4416 Fields::from(vec![
4417 Field::new("all_nulls", all_nulls_type, true),
4418 Field::new("some_nulls", some_nulls_type, true),
4419 Field::new("struct_field", struct_field_type, true),
4420 ]),
4421 vec![all_nulls_struct, some_nulls_struct, struct_field_struct],
4422 None,
4423 )
4424 .unwrap();
4425
4426 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(
4427 EMPTY_VARIANT_METADATA_BYTES,
4428 all_nulls_values.len(),
4429 ));
4430 let variant_array: ArrayRef = VariantArray::from_parts(
4431 Arc::new(metadata),
4432 None,
4433 Some(Arc::new(typed_value_struct)),
4434 None,
4435 )
4436 .into();
4437
4438 let all_nulls_field_ref = FieldRef::from(Field::new("result", DataType::Int32, true));
4440 let all_nulls_result = variant_get(
4441 &variant_array,
4442 GetOptions::new_with_path(VariantPath::try_from("all_nulls").unwrap())
4443 .with_as_type(Some(all_nulls_field_ref)),
4444 )
4445 .unwrap();
4446 assert!(Arc::ptr_eq(&all_nulls_result, &all_nulls_erased));
4447
4448 let some_nulls_field_ref = FieldRef::from(Field::new("result", DataType::Int32, true));
4450 let some_nulls_result = variant_get(
4451 &variant_array,
4452 GetOptions::new_with_path(VariantPath::try_from("some_nulls").unwrap())
4453 .with_as_type(Some(some_nulls_field_ref)),
4454 )
4455 .unwrap();
4456 assert!(Arc::ptr_eq(&some_nulls_result, &some_nulls_erased));
4457
4458 let struct_child_fields = Fields::from(vec![Field::new("inner", DataType::Int32, true)]);
4460 let struct_field_ref = FieldRef::from(Field::new(
4461 "result",
4462 DataType::Struct(struct_child_fields.clone()),
4463 true,
4464 ));
4465 let struct_result = variant_get(
4466 &variant_array,
4467 GetOptions::new_with_path(VariantPath::try_from("struct_field").unwrap())
4468 .with_as_type(Some(struct_field_ref)),
4469 )
4470 .unwrap();
4471 let struct_array = struct_result
4472 .as_any()
4473 .downcast_ref::<StructArray>()
4474 .unwrap();
4475 assert_eq!(struct_array.len(), 3);
4476 assert_eq!(struct_array.null_count(), 0);
4477
4478 let inner_values_result = struct_array
4479 .column(0)
4480 .as_any()
4481 .downcast_ref::<Int32Array>()
4482 .unwrap();
4483 assert_eq!(inner_values_result.len(), 3);
4484 assert_eq!(inner_values_result.value(0), 111);
4485 assert!(inner_values_result.is_null(1));
4486 assert_eq!(inner_values_result.value(2), 333);
4487 }
4488
4489 #[test]
4490 fn test_variant_get_list_like_safe_cast() {
4491 let string_array: ArrayRef = Arc::new(StringArray::from(vec![
4492 r#"{"outer":{"list":[1, "two", 3]}}"#,
4493 r#"{"outer":{"list":"not a list"}}"#,
4494 ]));
4495 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4496
4497 let element_array: ArrayRef = Arc::new(Int64Array::from(vec![Some(1), None, Some(3)]));
4498 let field = Arc::new(Field::new("item", Int64, true));
4499
4500 let expectations = vec![
4501 (
4502 DataType::List(field.clone()),
4503 Arc::new(ListArray::new(
4504 field.clone(),
4505 OffsetBuffer::new(ScalarBuffer::from(vec![0, 3, 3])),
4506 element_array.clone(),
4507 Some(NullBuffer::from(vec![true, false])),
4508 )) as ArrayRef,
4509 ),
4510 (
4511 DataType::LargeList(field.clone()),
4512 Arc::new(LargeListArray::new(
4513 field.clone(),
4514 OffsetBuffer::new(ScalarBuffer::from(vec![0, 3, 3])),
4515 element_array.clone(),
4516 Some(NullBuffer::from(vec![true, false])),
4517 )) as ArrayRef,
4518 ),
4519 (
4520 DataType::ListView(field.clone()),
4521 Arc::new(ListViewArray::new(
4522 field.clone(),
4523 ScalarBuffer::from(vec![0, 3]),
4524 ScalarBuffer::from(vec![3, 0]),
4525 element_array.clone(),
4526 Some(NullBuffer::from(vec![true, false])),
4527 )) as ArrayRef,
4528 ),
4529 (
4530 DataType::LargeListView(field.clone()),
4531 Arc::new(LargeListViewArray::new(
4532 field.clone(),
4533 ScalarBuffer::from(vec![0, 3]),
4534 ScalarBuffer::from(vec![3, 0]),
4535 element_array,
4536 Some(NullBuffer::from(vec![true, false])),
4537 )) as ArrayRef,
4538 ),
4539 (
4540 DataType::FixedSizeList(field.clone(), 3),
4541 Arc::new(FixedSizeListArray::new(
4542 field,
4543 3,
4544 Arc::new(Int64Array::from(vec![
4545 Some(1),
4546 None,
4547 Some(3),
4548 None,
4549 None,
4550 None,
4551 ])),
4552 Some(NullBuffer::from(vec![true, false])),
4553 )) as ArrayRef,
4554 ),
4555 ];
4556
4557 for (request_type, expected) in expectations {
4558 let options =
4559 GetOptions::new_with_path(VariantPath::try_from("outer").unwrap().join("list"))
4560 .with_as_type(Some(FieldRef::from(Field::new(
4561 "result",
4562 request_type.clone(),
4563 true,
4564 ))));
4565
4566 let result = variant_get(&variant_array, options).unwrap();
4567 assert_eq!(result.data_type(), expected.data_type());
4568 assert_eq!(&result, &expected);
4569 }
4570
4571 for (idx, expected) in [
4572 (0, vec![Some(1), None]),
4573 (1, vec![None, None]),
4574 (2, vec![Some(3), None]),
4575 ] {
4576 let index_options = GetOptions::new_with_path(
4577 VariantPath::try_from("outer")
4578 .unwrap()
4579 .join("list")
4580 .join(idx),
4581 )
4582 .with_as_type(Some(FieldRef::from(Field::new(
4583 "result",
4584 DataType::Int64,
4585 true,
4586 ))));
4587 let index_result = variant_get(&variant_array, index_options).unwrap();
4588 let index_expected: ArrayRef = Arc::new(Int64Array::from(expected));
4589 assert_eq!(&index_result, &index_expected);
4590 }
4591 }
4592
4593 #[test]
4594 fn test_variant_get_nested_list() {
4595 use arrow::datatypes::Int64Type;
4596
4597 let string_array: ArrayRef = Arc::new(StringArray::from(vec![
4598 r#"[[1, 2], [3]]"#,
4599 r#"[[4], "not a list", [5, 6]]"#,
4600 ]));
4601 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4602
4603 let inner_field = Arc::new(Field::new("item", Int64, true));
4604 let outer_field = Arc::new(Field::new(
4605 "item",
4606 DataType::List(inner_field.clone()),
4607 true,
4608 ));
4609 let request_type = DataType::List(outer_field.clone());
4610
4611 let options = GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4612 "result",
4613 request_type,
4614 true,
4615 ))));
4616 let result = variant_get(&variant_array, options).unwrap();
4617 let outer = result.as_list::<i32>();
4618
4619 let row0 = outer.value(0);
4621 let row0 = row0.as_list::<i32>();
4622 assert_eq!(row0.len(), 2);
4623 let elem0 = row0.value(0);
4624 assert_eq!(elem0.as_primitive::<Int64Type>().values(), &[1, 2]);
4625 let elem1 = row0.value(1);
4626 assert_eq!(elem1.as_primitive::<Int64Type>().values(), &[3]);
4627
4628 let row1 = outer.value(1);
4630 let row1 = row1.as_list::<i32>();
4631 assert_eq!(row1.len(), 3);
4632 let elem0 = row1.value(0);
4633 assert_eq!(elem0.as_primitive::<Int64Type>().values(), &[4]);
4634 assert!(row1.is_null(1));
4635 let elem2 = row1.value(2);
4636 assert_eq!(elem2.as_primitive::<Int64Type>().values(), &[5, 6]);
4637 }
4638
4639 #[test]
4640 fn test_variant_get_list_like_unsafe_cast_errors_on_element_mismatch() {
4641 let string_array: ArrayRef =
4642 Arc::new(StringArray::from(vec![r#"[1, "two", 3]"#, "[4, 5]"]));
4643 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4644 let cast_options = CastOptions {
4645 safe: false,
4646 ..Default::default()
4647 };
4648
4649 let item_field = Arc::new(Field::new("item", DataType::Int64, true));
4650 let request_types = vec![
4651 DataType::List(item_field.clone()),
4652 DataType::LargeList(item_field.clone()),
4653 DataType::ListView(item_field.clone()),
4654 DataType::LargeListView(item_field),
4655 ];
4656
4657 for request_type in request_types {
4658 let options = GetOptions::new()
4659 .with_as_type(Some(FieldRef::from(Field::new(
4660 "result",
4661 request_type.clone(),
4662 true,
4663 ))))
4664 .with_cast_options(cast_options.clone());
4665
4666 let err = variant_get(&variant_array, options).unwrap_err();
4667 assert!(
4668 err.to_string()
4669 .contains("Failed to extract primitive of type Int64")
4670 );
4671 }
4672 }
4673
4674 #[test]
4675 fn test_variant_get_list_like_unsafe_cast_preserves_null_elements() {
4676 let string_array: ArrayRef = Arc::new(StringArray::from(vec![r#"[1, null, 3]"#]));
4677 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4678 let cast_options = CastOptions {
4679 safe: false,
4680 ..Default::default()
4681 };
4682 let options = GetOptions::new()
4683 .with_as_type(Some(FieldRef::from(Field::new(
4684 "result",
4685 DataType::List(Arc::new(Field::new("item", DataType::Int64, true))),
4686 true,
4687 ))))
4688 .with_cast_options(cast_options);
4689
4690 let result = variant_get(&variant_array, options).unwrap();
4691 let list_array = result.as_any().downcast_ref::<ListArray>().unwrap();
4692 let values = list_array
4693 .values()
4694 .as_any()
4695 .downcast_ref::<Int64Array>()
4696 .unwrap();
4697
4698 assert_eq!(values.len(), 3);
4699 assert_eq!(values.value(0), 1);
4700 assert!(values.is_null(1));
4701 assert_eq!(values.value(2), 3);
4702 }
4703
4704 #[test]
4705 fn test_variant_get_list_like_unsafe_cast_errors_on_non_list() {
4706 let string_array: ArrayRef = Arc::new(StringArray::from(vec!["[1, 2]", "\"not a list\""]));
4707 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4708 let cast_options = CastOptions {
4709 safe: false,
4710 ..Default::default()
4711 };
4712 let item_field = Arc::new(Field::new("item", Int64, true));
4713 let data_types = vec![
4714 DataType::List(item_field.clone()),
4715 DataType::LargeList(item_field.clone()),
4716 DataType::ListView(item_field.clone()),
4717 DataType::LargeListView(item_field.clone()),
4718 DataType::FixedSizeList(item_field, 2),
4719 ];
4720
4721 for data_type in data_types {
4722 let options = GetOptions::new()
4723 .with_as_type(Some(FieldRef::from(Field::new("result", data_type, true))))
4724 .with_cast_options(cast_options.clone());
4725
4726 let err = variant_get(&variant_array, options).unwrap_err();
4727 assert!(
4728 err.to_string()
4729 .contains("Failed to extract list from variant"),
4730 );
4731 }
4732 }
4733
4734 #[test]
4735 fn test_variant_get_fixed_size_list_wrong_size() {
4736 let string_array: ArrayRef = Arc::new(StringArray::from(vec!["[1, 2, 3]"]));
4737 let variant_array = ArrayRef::from(json_to_variant(&string_array).unwrap());
4738 let item_field = Arc::new(Field::new("item", Int64, true));
4739
4740 let options = GetOptions::new()
4742 .with_as_type(Some(FieldRef::from(Field::new(
4743 "result",
4744 DataType::FixedSizeList(item_field.clone(), 2),
4745 true,
4746 ))))
4747 .with_cast_options(CastOptions {
4748 safe: true,
4749 ..Default::default()
4750 });
4751 let result = variant_get(&variant_array, options).unwrap();
4752 let fixed_size_list = result
4753 .as_any()
4754 .downcast_ref::<FixedSizeListArray>()
4755 .expect("Expected FixedSizeListArray");
4756 assert_eq!(fixed_size_list.len(), 1);
4757 assert!(fixed_size_list.is_null(0));
4758
4759 let options = GetOptions::new()
4761 .with_as_type(Some(FieldRef::from(Field::new(
4762 "result",
4763 DataType::FixedSizeList(item_field.clone(), 2),
4764 true,
4765 ))))
4766 .with_cast_options(CastOptions {
4767 safe: false,
4768 ..Default::default()
4769 });
4770 let err = variant_get(&variant_array, options).unwrap_err();
4771 assert!(
4772 err.to_string()
4773 .contains("Expected fixed size list of size 2, got size 3"),
4774 "got: {err}",
4775 );
4776 }
4777
4778 macro_rules! perfectly_shredded_preserves_top_level_nulls_test {
4779 ($name:ident, $result_type:expr, $typed_value:expr, $expected_array:expr) => {
4780 perfectly_shredded_preserves_top_level_nulls_test!(
4781 $name,
4782 $result_type,
4783 $typed_value,
4784 Some(NullBuffer::from(vec![true, false, true])),
4785 $expected_array
4786 );
4787 };
4788 ($name:ident, $result_type:expr, $typed_value:expr, $parent_nulls:expr, $expected_array:expr) => {
4789 #[test]
4790 fn $name() {
4791 let metadata = Arc::new(BinaryViewArray::from_iter_values(std::iter::repeat_n(
4792 EMPTY_VARIANT_METADATA_BYTES,
4793 3,
4794 )));
4795 let typed_value: ArrayRef = Arc::new($typed_value);
4796 let variant_array: ArrayRef =
4797 VariantArray::from_parts(metadata, None, Some(typed_value), $parent_nulls)
4798 .into();
4799
4800 let result = variant_get(
4801 &variant_array,
4802 GetOptions::new().with_as_type(Some(FieldRef::from(Field::new(
4803 "result",
4804 $result_type,
4805 true,
4806 )))),
4807 )
4808 .unwrap();
4809
4810 let expected_array: ArrayRef = Arc::new($expected_array);
4811 assert_eq!(&result, &expected_array);
4812 }
4813 };
4814 }
4815
4816 perfectly_shredded_preserves_top_level_nulls_test!(
4817 test_variant_get_perfectly_shredded_integer_preserves_top_level_nulls,
4818 DataType::Int32,
4819 Int32Array::from(vec![Some(0_i32), Some(1_i32), Some(2_i32)]),
4820 Int32Array::from(vec![Some(0_i32), None, Some(2_i32)])
4821 );
4822
4823 perfectly_shredded_preserves_top_level_nulls_test!(
4824 test_variant_get_perfectly_shredded_integer_unions_child_and_top_level_nulls,
4825 DataType::Int32,
4826 Int32Array::from(vec![None, Some(1_i32), Some(2_i32)]),
4827 Some(NullBuffer::from(vec![true, false, true])),
4828 Int32Array::from(vec![None, None, Some(2_i32)])
4829 );
4830
4831 perfectly_shredded_preserves_top_level_nulls_test!(
4832 test_variant_get_perfectly_shredded_null_preserves_top_level_nulls,
4833 DataType::Null,
4834 NullArray::new(3),
4835 NullArray::new(3)
4836 );
4837
4838 perfectly_shredded_preserves_top_level_nulls_test!(
4839 test_variant_get_perfectly_shredded_binary_view_preserves_top_level_nulls,
4840 DataType::BinaryView,
4841 BinaryViewArray::from(vec![
4842 Some(b"Apache" as &[u8]),
4843 Some(b"masked-null" as &[u8]),
4844 Some(b"Parquet-variant" as &[u8]),
4845 ]),
4846 BinaryViewArray::from(vec![
4847 Some(b"Apache" as &[u8]),
4848 None,
4849 Some(b"Parquet-variant" as &[u8]),
4850 ])
4851 );
4852
4853 perfectly_shredded_preserves_top_level_nulls_test!(
4854 test_variant_get_perfectly_shredded_binary_preserves_top_level_nulls,
4855 DataType::Binary,
4856 BinaryArray::from(vec![
4857 Some(b"Apache" as &[u8]),
4858 Some(b"masked-null" as &[u8]),
4859 Some(b"Parquet-variant" as &[u8]),
4860 ]),
4861 BinaryArray::from(vec![
4862 Some(b"Apache" as &[u8]),
4863 None,
4864 Some(b"Parquet-variant" as &[u8]),
4865 ])
4866 );
4867
4868 perfectly_shredded_preserves_top_level_nulls_test!(
4869 test_variant_get_perfectly_shredded_decimal4_preserves_top_level_nulls,
4870 DataType::Decimal32(5, 2),
4871 Decimal32Array::from(vec![Some(12345), Some(23400), Some(-12342)])
4872 .with_precision_and_scale(5, 2)
4873 .unwrap(),
4874 Decimal32Array::from(vec![Some(12345), None, Some(-12342)])
4875 .with_precision_and_scale(5, 2)
4876 .unwrap()
4877 );
4878
4879 perfectly_shredded_preserves_top_level_nulls_test!(
4880 test_variant_get_perfectly_shredded_decimal8_preserves_top_level_nulls,
4881 DataType::Decimal64(10, 1),
4882 Decimal64Array::from(vec![Some(1234567809), Some(1456787000), Some(-1234561203)])
4883 .with_precision_and_scale(10, 1)
4884 .unwrap(),
4885 Decimal64Array::from(vec![Some(1234567809), None, Some(-1234561203)])
4886 .with_precision_and_scale(10, 1)
4887 .unwrap()
4888 );
4889
4890 perfectly_shredded_preserves_top_level_nulls_test!(
4891 test_variant_get_perfectly_shredded_decimal16_preserves_top_level_nulls,
4892 DataType::Decimal128(20, 3),
4893 Decimal128Array::from(vec![
4894 Some(i128::from_str("12345678901234567899").unwrap()),
4895 Some(i128::from_str("23445677483748324300").unwrap()),
4896 Some(i128::from_str("-12345678901234567899").unwrap()),
4897 ])
4898 .with_precision_and_scale(20, 3)
4899 .unwrap(),
4900 Decimal128Array::from(vec![
4901 Some(i128::from_str("12345678901234567899").unwrap()),
4902 None,
4903 Some(i128::from_str("-12345678901234567899").unwrap()),
4904 ])
4905 .with_precision_and_scale(20, 3)
4906 .unwrap()
4907 );
4908}