1use crate::VariantArrayBuilder;
21use crate::type_conversion::{
22 generic_conversion_single_value, generic_conversion_single_value_with_result,
23 primitive_conversion_single_value,
24};
25use arrow::array::{
26 Array, ArrayRef, AsArray, StructArray, downcast_dictionary_array, downcast_run_array,
27 new_null_array,
28};
29use arrow::buffer::NullBuffer;
30use arrow::compute::cast;
31use arrow::datatypes::{
32 Date32Type, Decimal32Type, Decimal64Type, Decimal128Type, Float16Type, Float32Type,
33 Float64Type, Int8Type, Int16Type, Int32Type, Int64Type, Time64MicrosecondType,
34 TimestampMicrosecondType, TimestampNanosecondType,
35};
36use arrow::error::Result;
37use arrow_schema::extension::{ExtensionType, Uuid as UuidExtension};
38use arrow_schema::{ArrowError, DataType, Field, FieldRef, Fields, TimeUnit};
39use chrono::{DateTime, NaiveTime};
40use parquet_variant::{
41 Uuid, Variant, VariantDecimal4, VariantDecimal8, VariantDecimal16, VariantDecimalType as _,
42};
43
44use std::borrow::Cow;
45use std::sync::Arc;
46
47pub(crate) fn binary_array_value(array: &dyn Array, index: usize) -> Option<&[u8]> {
50 if array.is_null(index) {
51 return None;
52 }
53 match array.data_type() {
54 DataType::Binary => Some(array.as_binary::<i32>().value(index)),
55 DataType::LargeBinary => Some(array.as_binary::<i64>().value(index)),
56 DataType::BinaryView => Some(array.as_binary_view().value(index)),
57 DataType::Dictionary(..) => downcast_dictionary_array! {
58 array => {
59 let index = array.key(index)?;
60 binary_array_value(array.values().as_ref(), index)
61 },
62 _ => unreachable!(),
63 },
64 DataType::RunEndEncoded(..) => downcast_run_array! {
65 array => {
66 let index = array.get_physical_index(index);
67 binary_array_value(array.values().as_ref(), index)
68 },
69 _ => unreachable!(),
70 },
71 _ => None,
72 }
73}
74
75pub(crate) fn variant_from_arrays_at<'m, 'v>(
78 metadata: &'m dyn Array,
79 value: &'v dyn Array,
80 index: usize,
81) -> Option<Variant<'m, 'v>> {
82 let metadata = binary_array_value(metadata, index)?;
83 let value = binary_array_value(value, index)?;
84 Some(Variant::new(metadata, value))
85}
86
87pub(crate) fn all_null_value_column(len: usize) -> ArrayRef {
93 new_null_array(&DataType::BinaryView, len)
94}
95
96pub(crate) fn validate_binary_array(array: &dyn Array, field_name: &str) -> Result<()> {
98 match array.data_type() {
99 DataType::Binary | DataType::LargeBinary | DataType::BinaryView => Ok(()),
100 _ => Err(ArrowError::InvalidArgumentError(format!(
101 "VariantArray '{field_name}' field must be Binary, LargeBinary, or BinaryView, got {}",
102 array.data_type()
103 ))),
104 }
105}
106
107fn validate_metadata_array(array: &dyn Array) -> Result<()> {
109 let is_binary = |data_type: &DataType| {
110 matches!(
111 data_type,
112 DataType::Binary | DataType::LargeBinary | DataType::BinaryView
113 )
114 };
115 match array.data_type() {
116 data_type if is_binary(data_type) => Ok(()),
117 DataType::Dictionary(_, values) if is_binary(values) => Ok(()),
118 DataType::RunEndEncoded(_, values) if is_binary(values.data_type()) => Ok(()),
119 _ => Err(ArrowError::InvalidArgumentError(format!(
120 "VariantArray 'metadata' field must be Binary, LargeBinary, BinaryView, or a Dictionary or RunEndEncoded array of one of those types, got {}",
121 array.data_type()
122 ))),
123 }
124}
125
126pub struct VariantType;
131
132impl ExtensionType for VariantType {
133 const NAME: &'static str = "arrow.parquet.variant";
134
135 type Metadata = &'static str;
138
139 fn metadata(&self) -> &Self::Metadata {
140 &""
141 }
142
143 fn serialize_metadata(&self) -> Option<String> {
144 Some(String::new())
145 }
146
147 fn deserialize_metadata(_metadata: Option<&str>) -> Result<Self::Metadata> {
148 Ok("")
149 }
150
151 fn supports_data_type(&self, data_type: &DataType) -> Result<()> {
152 if matches!(data_type, DataType::Struct(_)) {
153 Ok(())
154 } else {
155 Err(ArrowError::InvalidArgumentError(format!(
156 "VariantType only supports StructArray, got {data_type}"
157 )))
158 }
159 }
160
161 fn try_new(data_type: &DataType, _metadata: Self::Metadata) -> Result<Self> {
162 Self.supports_data_type(data_type)?;
163 Ok(Self)
164 }
165
166 fn validate(data_type: &DataType, _metadata: Self::Metadata) -> Result<()> {
167 Self.supports_data_type(data_type)
168 }
169}
170
171#[derive(Debug, Clone)]
302pub struct VariantArray {
303 inner: StructArray,
305
306 metadata: ArrayRef,
308
309 shredding_state: ShreddingState,
311}
312
313impl VariantArray {
314 pub fn try_new(inner: &dyn Array) -> Result<Self> {
337 let inner = canonicalize_shredded_types(inner)?;
339
340 let Some(inner) = inner.as_struct_opt() else {
341 return Err(ArrowError::InvalidArgumentError(
342 "Invalid VariantArray: requires StructArray as input".to_string(),
343 ));
344 };
345
346 let Some(metadata_col) = inner.column_by_name("metadata") else {
350 return Err(ArrowError::InvalidArgumentError(
351 "Invalid VariantArray: StructArray must contain a 'metadata' field".to_string(),
352 ));
353 };
354 validate_metadata_array(metadata_col.as_ref())?;
355
356 let shredding_state = ShreddingState::try_from(inner)?;
357
358 if inner.column_by_name("value").is_none() {
361 return Ok(Self::from_parts(
362 metadata_col.clone(),
363 shredding_state.value_column().clone(),
364 shredding_state.typed_value_column().cloned(),
365 inner.nulls().cloned(),
366 ));
367 }
368
369 Ok(Self {
371 inner: inner.clone(),
372 metadata: metadata_col.clone(),
373 shredding_state,
374 })
375 }
376
377 pub(crate) fn from_parts(
382 metadata: ArrayRef,
383 value: ArrayRef,
384 typed_value: Option<ArrayRef>,
385 nulls: Option<NullBuffer>,
386 ) -> Self {
387 Self::from_parts_with_nullable_value(metadata, value, typed_value, nulls, true)
388 }
389
390 pub(crate) fn from_parts_unshredded(
396 metadata: ArrayRef,
397 value: ArrayRef,
398 nulls: Option<NullBuffer>,
399 ) -> Self {
400 Self::from_parts_with_nullable_value(metadata, value, None, nulls, false)
401 }
402
403 fn from_parts_with_nullable_value(
404 metadata: ArrayRef,
405 value: ArrayRef,
406 typed_value: Option<ArrayRef>,
407 nulls: Option<NullBuffer>,
408 value_nullable: bool,
409 ) -> Self {
410 let mut builder = StructArrayBuilder::new()
411 .with_field("metadata", metadata.clone(), false)
412 .with_field("value", value.clone(), value_nullable);
413 if let Some(typed_value) = typed_value.clone() {
414 builder = builder.with_field_ref(typed_value_field(&typed_value), typed_value);
415 }
416 if let Some(nulls) = nulls {
417 builder = builder.with_nulls(nulls);
418 }
419
420 Self {
421 inner: builder.build(),
422 metadata,
423 shredding_state: ShreddingState::new(value, typed_value),
424 }
425 }
426
427 pub fn inner(&self) -> &StructArray {
429 &self.inner
430 }
431
432 pub fn into_inner(self) -> StructArray {
434 self.inner
435 }
436
437 pub fn shredding_state(&self) -> &ShreddingState {
439 &self.shredding_state
440 }
441
442 pub fn value(&self, index: usize) -> Variant<'_, '_> {
453 self.try_value(index)
454 .unwrap_or_else(|err| panic!("VariantArray::value({index}) failed: {err}"))
455 }
456
457 pub fn try_value(&self, index: usize) -> Result<Variant<'_, '_>> {
486 if self.len() <= index {
487 return Err(ArrowError::InvalidArgumentError(format!(
488 "Index {index} out of bounds for VariantArray of length {}",
489 self.len()
490 )));
491 }
492
493 let value = self.value_column();
494 match self.typed_value_column() {
495 Some(typed_value) if typed_value.is_valid(index) => {
497 if !matches!(typed_value.data_type(), DataType::Struct(_)) && value.is_valid(index) {
498 return Err(ArrowError::InvalidArgumentError(
500 "Invalid variant, conflicting value and typed_value".to_owned(),
501 ));
502 }
503 typed_value_to_variant(typed_value, index)
504 }
505 _ if value.is_valid(index) => variant_from_arrays_at(&self.metadata, value, index)
507 .ok_or_else(|| {
508 ArrowError::InvalidArgumentError(format!(
509 "metadata and value fields must be binary-like arrays, instead got {} and {}",
510 self.metadata.data_type(),
511 value.data_type()
512 ))
513 }),
514 _ => Ok(Variant::Null),
517 }
518 }
519
520 pub fn metadata_column(&self) -> &ArrayRef {
522 &self.metadata
523 }
524
525 pub fn value_column(&self) -> &ArrayRef {
527 self.shredding_state.value_column()
528 }
529
530 pub fn typed_value_column(&self) -> Option<&ArrayRef> {
532 self.shredding_state.typed_value_column()
533 }
534
535 pub fn field(&self, name: impl Into<String>) -> Field {
538 Field::new(
539 name.into(),
540 self.data_type().clone(),
541 self.inner.is_nullable(),
542 )
543 .with_extension_type(VariantType)
544 }
545
546 pub fn data_type(&self) -> &DataType {
548 self.inner.data_type()
549 }
550
551 pub fn slice(&self, offset: usize, length: usize) -> Self {
552 let inner = self.inner.slice(offset, length);
553 let metadata = self.metadata.slice(offset, length);
554 let shredding_state = self.shredding_state.slice(offset, length);
555 Self {
556 inner,
557 metadata,
558 shredding_state,
559 }
560 }
561
562 pub fn len(&self) -> usize {
563 self.inner.len()
564 }
565
566 pub fn is_empty(&self) -> bool {
567 self.inner.is_empty()
568 }
569
570 pub fn nulls(&self) -> Option<&NullBuffer> {
571 self.inner.nulls()
572 }
573
574 pub fn is_null(&self, index: usize) -> bool {
576 self.nulls().is_some_and(|n| n.is_null(index))
577 }
578
579 pub fn is_valid(&self, index: usize) -> bool {
581 !self.is_null(index)
582 }
583
584 pub fn iter(&self) -> VariantArrayIter<'_> {
586 VariantArrayIter::new(self)
587 }
588}
589
590impl<'a> IntoIterator for &'a VariantArray {
591 type Item = Option<Variant<'a, 'a>>;
592 type IntoIter = VariantArrayIter<'a>;
593
594 fn into_iter(self) -> Self::IntoIter {
595 VariantArrayIter::new(self)
596 }
597}
598
599impl PartialEq for VariantArray {
600 fn eq(&self, other: &Self) -> bool {
601 self.inner == other.inner
602 }
603}
604
605impl From<VariantArray> for StructArray {
606 fn from(variant_array: VariantArray) -> Self {
607 variant_array.into_inner()
608 }
609}
610
611impl From<VariantArray> for ArrayRef {
612 fn from(variant_array: VariantArray) -> Self {
613 Arc::new(variant_array.into_inner())
614 }
615}
616
617impl<'m, 'v> FromIterator<Option<Variant<'m, 'v>>> for VariantArray {
618 fn from_iter<T: IntoIterator<Item = Option<Variant<'m, 'v>>>>(iter: T) -> Self {
619 let iter = iter.into_iter();
620
621 let mut b = VariantArrayBuilder::new(iter.size_hint().0);
622 b.extend(iter);
623 b.build()
624 }
625}
626
627impl<'m, 'v> FromIterator<Variant<'m, 'v>> for VariantArray {
628 fn from_iter<T: IntoIterator<Item = Variant<'m, 'v>>>(iter: T) -> Self {
629 Self::from_iter(iter.into_iter().map(Some))
630 }
631}
632
633#[derive(Debug)]
658pub struct VariantArrayIter<'a> {
659 array: &'a VariantArray,
660 head_i: usize,
661 tail_i: usize,
662}
663
664impl<'a> VariantArrayIter<'a> {
665 pub fn new(array: &'a VariantArray) -> Self {
667 Self {
668 array,
669 head_i: 0,
670 tail_i: array.len(),
671 }
672 }
673
674 fn value_opt(&self, i: usize) -> Option<Variant<'a, 'a>> {
675 self.array.is_valid(i).then(|| self.array.value(i))
676 }
677}
678
679impl<'a> Iterator for VariantArrayIter<'a> {
680 type Item = Option<Variant<'a, 'a>>;
681
682 #[inline]
683 fn next(&mut self) -> Option<Self::Item> {
684 if self.head_i == self.tail_i {
685 return None;
686 }
687
688 let out = self.value_opt(self.head_i);
689
690 self.head_i += 1;
691
692 Some(out)
693 }
694
695 fn size_hint(&self) -> (usize, Option<usize>) {
696 let remainder = self.tail_i - self.head_i;
697
698 (remainder, Some(remainder))
699 }
700}
701
702impl DoubleEndedIterator for VariantArrayIter<'_> {
703 fn next_back(&mut self) -> Option<Self::Item> {
704 if self.head_i == self.tail_i {
705 return None;
706 }
707
708 self.tail_i -= 1;
709
710 Some(self.value_opt(self.tail_i))
711 }
712}
713
714impl ExactSizeIterator for VariantArrayIter<'_> {}
715
716#[derive(Debug)]
751pub struct ShreddedVariantFieldArray {
752 inner: StructArray,
754 shredding_state: ShreddingState,
755}
756
757impl ShreddedVariantFieldArray {
758 pub fn try_new(inner: &dyn Array) -> Result<Self> {
778 let Some(inner_struct) = inner.as_struct_opt() else {
779 return Err(ArrowError::InvalidArgumentError(
780 "Invalid ShreddedVariantFieldArray: requires StructArray as input".to_string(),
781 ));
782 };
783
784 let shredding_state = ShreddingState::try_from(inner_struct)?;
785
786 if inner_struct.column_by_name("value").is_none() {
789 return Ok(Self::from_parts(
790 shredding_state.value_column().clone(),
791 shredding_state.typed_value_column().cloned(),
792 inner_struct.nulls().cloned(),
793 ));
794 }
795
796 Ok(Self {
798 inner: inner_struct.clone(),
799 shredding_state,
800 })
801 }
802
803 pub fn shredding_state(&self) -> &ShreddingState {
805 &self.shredding_state
806 }
807
808 pub fn value_column(&self) -> &ArrayRef {
810 self.shredding_state.value_column()
811 }
812
813 pub fn typed_value_column(&self) -> Option<&ArrayRef> {
815 self.shredding_state.typed_value_column()
816 }
817
818 pub fn inner(&self) -> &StructArray {
820 &self.inner
821 }
822
823 pub(crate) fn from_parts(
824 value: ArrayRef,
825 typed_value: Option<ArrayRef>,
826 nulls: Option<NullBuffer>,
827 ) -> Self {
828 let mut builder = StructArrayBuilder::new().with_field("value", value.clone(), true);
829 if let Some(typed_value) = typed_value.clone() {
830 builder = builder.with_field_ref(typed_value_field(&typed_value), typed_value);
831 }
832 if let Some(nulls) = nulls {
833 builder = builder.with_nulls(nulls);
834 }
835
836 Self {
837 inner: builder.build(),
838 shredding_state: ShreddingState::new(value, typed_value),
839 }
840 }
841
842 pub fn into_inner(self) -> StructArray {
844 self.inner
845 }
846
847 pub fn data_type(&self) -> &DataType {
848 self.inner.data_type()
849 }
850
851 pub fn len(&self) -> usize {
852 self.inner.len()
853 }
854
855 pub fn is_empty(&self) -> bool {
856 self.inner.is_empty()
857 }
858
859 pub fn offset(&self) -> usize {
860 self.inner.offset()
861 }
862
863 pub fn nulls(&self) -> Option<&NullBuffer> {
864 None
868 }
869 pub fn is_null(&self, index: usize) -> bool {
871 self.nulls().is_some_and(|n| n.is_null(index))
872 }
873
874 pub fn is_valid(&self, index: usize) -> bool {
876 !self.is_null(index)
877 }
878}
879
880impl From<ShreddedVariantFieldArray> for ArrayRef {
881 fn from(array: ShreddedVariantFieldArray) -> Self {
882 Arc::new(array.into_inner())
883 }
884}
885
886impl From<ShreddedVariantFieldArray> for StructArray {
887 fn from(array: ShreddedVariantFieldArray) -> Self {
888 array.into_inner()
889 }
890}
891
892#[derive(Debug, Clone)]
929pub struct ShreddingState {
930 value: ArrayRef,
931 typed_value: Option<ArrayRef>,
932}
933
934impl ShreddingState {
935 pub fn new(value: ArrayRef, typed_value: Option<ArrayRef>) -> Self {
950 Self { value, typed_value }
951 }
952
953 pub fn value_column(&self) -> &ArrayRef {
955 &self.value
956 }
957
958 pub fn typed_value_column(&self) -> Option<&ArrayRef> {
960 self.typed_value.as_ref()
961 }
962
963 pub fn slice(&self, offset: usize, length: usize) -> Self {
965 Self {
966 value: self.value.slice(offset, length),
967 typed_value: self.typed_value.as_ref().map(|tv| tv.slice(offset, length)),
968 }
969 }
970}
971
972impl TryFrom<&StructArray> for ShreddingState {
973 type Error = ArrowError;
974
975 fn try_from(inner_struct: &StructArray) -> Result<Self> {
976 let typed_value = inner_struct.column_by_name("typed_value").cloned();
977 let value = match inner_struct.column_by_name("value") {
978 Some(value) => {
979 validate_binary_array(value.as_ref(), "value")?;
980 value.clone()
981 }
982 None if typed_value.is_some() => all_null_value_column(inner_struct.len()),
985 None => {
986 return Err(ArrowError::InvalidArgumentError(
987 "Invalid VariantArray: StructArray must contain a 'value' field".to_string(),
988 ));
989 }
990 };
991 Ok(ShreddingState::new(value, typed_value))
992 }
993}
994
995fn typed_value_field(array: &ArrayRef) -> FieldRef {
1001 let mut field = Field::new("typed_value", array.data_type().clone(), true);
1002 if matches!(array.data_type(), DataType::FixedSizeBinary(16)) {
1003 field = field.with_extension_type(UuidExtension);
1004 }
1005 Arc::new(field)
1006}
1007
1008#[derive(Debug, Default, Clone)]
1012pub(crate) struct StructArrayBuilder {
1013 fields: Vec<FieldRef>,
1014 arrays: Vec<ArrayRef>,
1015 nulls: Option<NullBuffer>,
1016}
1017
1018impl StructArrayBuilder {
1019 pub fn new() -> Self {
1020 Default::default()
1021 }
1022
1023 pub fn with_field(mut self, field_name: &str, array: ArrayRef, nullable: bool) -> Self {
1025 let field = Field::new(field_name, array.data_type().clone(), nullable);
1026 self.fields.push(Arc::new(field));
1027 self.arrays.push(array);
1028 self
1029 }
1030
1031 pub fn with_field_ref(mut self, field: FieldRef, array: ArrayRef) -> Self {
1036 self.fields.push(field);
1037 self.arrays.push(array);
1038 self
1039 }
1040
1041 pub fn with_nulls(mut self, nulls: NullBuffer) -> Self {
1043 self.nulls = Some(nulls);
1044 self
1045 }
1046
1047 pub fn build(self) -> StructArray {
1048 let Self {
1049 fields,
1050 arrays,
1051 nulls,
1052 } = self;
1053 StructArray::new(Fields::from(fields), arrays, nulls)
1054 }
1055}
1056
1057fn typed_value_to_variant(typed_value: &ArrayRef, index: usize) -> Result<Variant<'_, '_>> {
1059 let data_type = typed_value.data_type();
1060 match data_type {
1061 DataType::Null => Ok(Variant::Null),
1062 DataType::Boolean => {
1063 let boolean_array = typed_value.as_boolean();
1064 let value = boolean_array.value(index);
1065 Ok(Variant::from(value))
1066 }
1067 DataType::FixedSizeBinary(16) => {
1069 let array = typed_value.as_fixed_size_binary();
1070 let value = array.value(index);
1071 Ok(Uuid::from_slice(value).unwrap().into()) }
1073 DataType::Binary => {
1074 let array = typed_value.as_binary::<i32>();
1075 let value = array.value(index);
1076 Ok(Variant::from(value))
1077 }
1078 DataType::LargeBinary => {
1079 let array = typed_value.as_binary::<i64>();
1080 let value = array.value(index);
1081 Ok(Variant::from(value))
1082 }
1083 DataType::BinaryView => {
1084 let array = typed_value.as_binary_view();
1085 let value = array.value(index);
1086 Ok(Variant::from(value))
1087 }
1088 DataType::Utf8 => {
1089 let array = typed_value.as_string::<i32>();
1090 let value = array.value(index);
1091 Ok(Variant::from(value))
1092 }
1093 DataType::LargeUtf8 => {
1094 let array = typed_value.as_string::<i64>();
1095 let value = array.value(index);
1096 Ok(Variant::from(value))
1097 }
1098 DataType::Utf8View => {
1099 let array = typed_value.as_string_view();
1100 let value = array.value(index);
1101 Ok(Variant::from(value))
1102 }
1103 DataType::Int8 => {
1104 primitive_conversion_single_value!(Int8Type, typed_value, index)
1105 }
1106 DataType::Int16 => {
1107 primitive_conversion_single_value!(Int16Type, typed_value, index)
1108 }
1109 DataType::Int32 => {
1110 primitive_conversion_single_value!(Int32Type, typed_value, index)
1111 }
1112 DataType::Int64 => {
1113 primitive_conversion_single_value!(Int64Type, typed_value, index)
1114 }
1115 DataType::Float16 => {
1116 primitive_conversion_single_value!(Float16Type, typed_value, index)
1117 }
1118 DataType::Float32 => {
1119 primitive_conversion_single_value!(Float32Type, typed_value, index)
1120 }
1121 DataType::Float64 => {
1122 primitive_conversion_single_value!(Float64Type, typed_value, index)
1123 }
1124 DataType::Decimal32(_, s) => {
1125 generic_conversion_single_value_with_result!(
1126 Decimal32Type,
1127 as_primitive,
1128 |v| VariantDecimal4::try_new(v, *s as u8),
1129 typed_value,
1130 index
1131 )
1132 }
1133 DataType::Decimal64(_, s) => {
1134 generic_conversion_single_value_with_result!(
1135 Decimal64Type,
1136 as_primitive,
1137 |v| VariantDecimal8::try_new(v, *s as u8),
1138 typed_value,
1139 index
1140 )
1141 }
1142 DataType::Decimal128(_, s) => {
1143 generic_conversion_single_value_with_result!(
1144 Decimal128Type,
1145 as_primitive,
1146 |v| VariantDecimal16::try_new(v, *s as u8),
1147 typed_value,
1148 index
1149 )
1150 }
1151 DataType::Date32 => {
1152 generic_conversion_single_value!(
1153 Date32Type,
1154 as_primitive,
1155 |v| Date32Type::to_naive_date_opt(v).unwrap(),
1156 typed_value,
1157 index
1158 )
1159 }
1160 DataType::Time64(TimeUnit::Microsecond) => {
1161 generic_conversion_single_value_with_result!(
1162 Time64MicrosecondType,
1163 as_primitive,
1164 |v| NaiveTime::from_num_seconds_from_midnight_opt(
1165 (v / 1_000_000) as u32,
1166 (v % 1_000_000) as u32 * 1000
1167 )
1168 .ok_or_else(|| format!("Invalid microsecond from midnight: {v}")),
1169 typed_value,
1170 index
1171 )
1172 }
1173 DataType::Timestamp(TimeUnit::Microsecond, Some(_)) => {
1174 generic_conversion_single_value!(
1175 TimestampMicrosecondType,
1176 as_primitive,
1177 |v| DateTime::from_timestamp_micros(v).unwrap(),
1178 typed_value,
1179 index
1180 )
1181 }
1182 DataType::Timestamp(TimeUnit::Microsecond, None) => {
1183 generic_conversion_single_value!(
1184 TimestampMicrosecondType,
1185 as_primitive,
1186 |v| DateTime::from_timestamp_micros(v).unwrap().naive_utc(),
1187 typed_value,
1188 index
1189 )
1190 }
1191 DataType::Timestamp(TimeUnit::Nanosecond, Some(_)) => {
1192 generic_conversion_single_value!(
1193 TimestampNanosecondType,
1194 as_primitive,
1195 DateTime::from_timestamp_nanos,
1196 typed_value,
1197 index
1198 )
1199 }
1200 DataType::Timestamp(TimeUnit::Nanosecond, None) => {
1201 generic_conversion_single_value!(
1202 TimestampNanosecondType,
1203 as_primitive,
1204 |v| DateTime::from_timestamp_nanos(v).naive_utc(),
1205 typed_value,
1206 index
1207 )
1208 }
1209 _ => Err(ArrowError::NotYetImplemented(format!(
1216 "VariantArray::try_value cannot materialize typed_value of type {} \
1217 as a borrowed Variant; call unshred_variant first",
1218 typed_value.data_type()
1219 ))),
1220 }
1221}
1222
1223fn canonicalize_shredded_types(array: &dyn Array) -> Result<ArrayRef> {
1226 let new_type = canonicalize_and_verify_data_type_impl(array.data_type(), true)?;
1227 if let Cow::Borrowed(_) = new_type
1228 && let Some(array) = array.as_struct_opt()
1229 {
1230 return Ok(Arc::new(array.clone())); }
1232 cast(array, new_type.as_ref())
1233}
1234
1235fn canonicalize_and_verify_data_type(data_type: &DataType) -> Result<Cow<'_, DataType>> {
1239 canonicalize_and_verify_data_type_impl(data_type, false)
1240}
1241
1242fn canonicalize_and_verify_data_type_impl(
1243 data_type: &DataType,
1244 skip_top_level_metadata: bool,
1245) -> Result<Cow<'_, DataType>> {
1246 use DataType::*;
1247
1248 macro_rules! fail {
1250 () => {
1251 return Err(ArrowError::InvalidArgumentError(format!(
1252 "Illegal shredded value type: {data_type}"
1253 )))
1254 };
1255 }
1256 macro_rules! borrow {
1257 () => {
1258 Cow::Borrowed(data_type)
1259 };
1260 }
1261
1262 let new_data_type = match data_type {
1263 Null | Boolean => borrow!(),
1265 Int8 | Int16 | Int32 | Int64 | Float32 | Float64 => borrow!(),
1266
1267 UInt8 | UInt16 | UInt32 | UInt64 | Float16 => fail!(),
1269
1270 Decimal64(p, s) | Decimal128(p, s)
1275 if VariantDecimal4::is_valid_precision_and_scale(p, s) =>
1276 {
1277 Cow::Owned(Decimal32(*p, *s))
1278 }
1279 Decimal128(p, s) if VariantDecimal8::is_valid_precision_and_scale(p, s) => {
1280 Cow::Owned(Decimal64(*p, *s))
1281 }
1282 Decimal32(p, s) if VariantDecimal4::is_valid_precision_and_scale(p, s) => borrow!(),
1283 Decimal64(p, s) if VariantDecimal8::is_valid_precision_and_scale(p, s) => borrow!(),
1284 Decimal128(p, s) if VariantDecimal16::is_valid_precision_and_scale(p, s) => borrow!(),
1285 Decimal32(..) | Decimal64(..) | Decimal128(..) | Decimal256(..) => fail!(),
1286
1287 Timestamp(TimeUnit::Microsecond | TimeUnit::Nanosecond, _) => borrow!(),
1289 Timestamp(TimeUnit::Millisecond | TimeUnit::Second, _) => fail!(),
1290
1291 Date32 | Time64(TimeUnit::Microsecond) => borrow!(),
1293 Date64 | Time32(_) | Time64(_) | Duration(_) | Interval(_) => fail!(),
1294
1295 Binary | LargeBinary | BinaryView | Utf8 | LargeUtf8 | Utf8View => borrow!(),
1297
1298 FixedSizeBinary(16) => borrow!(),
1300 FixedSizeBinary(_) | FixedSizeList(..) => fail!(),
1301
1302 List(field) => match canonicalize_and_verify_field(field)? {
1304 Cow::Borrowed(_) => borrow!(),
1305 Cow::Owned(new_field) => Cow::Owned(DataType::List(new_field)),
1306 },
1307 LargeList(field) => match canonicalize_and_verify_field(field)? {
1308 Cow::Borrowed(_) => borrow!(),
1309 Cow::Owned(new_field) => Cow::Owned(DataType::LargeList(new_field)),
1310 },
1311 ListView(field) => match canonicalize_and_verify_field(field)? {
1312 Cow::Borrowed(_) => borrow!(),
1313 Cow::Owned(new_field) => Cow::Owned(DataType::ListView(new_field)),
1314 },
1315 LargeListView(field) => match canonicalize_and_verify_field(field)? {
1316 Cow::Borrowed(_) => borrow!(),
1317 Cow::Owned(new_field) => Cow::Owned(DataType::LargeListView(new_field)),
1318 },
1319 Struct(fields) => {
1321 let mut new_fields = std::collections::HashMap::new();
1324 for (i, field) in fields.iter().enumerate() {
1325 if skip_top_level_metadata && field.name() == "metadata" {
1326 continue;
1327 }
1328 if let Cow::Owned(new_field) = canonicalize_and_verify_field(field)? {
1329 new_fields.insert(i, new_field);
1330 }
1331 }
1332
1333 if new_fields.is_empty() {
1334 borrow!()
1335 } else {
1336 let new_fields = fields
1337 .iter()
1338 .enumerate()
1339 .map(|(i, field)| new_fields.remove(&i).unwrap_or_else(|| field.clone()));
1340 Cow::Owned(DataType::Struct(new_fields.collect()))
1341 }
1342 }
1343 Map(..) | Union(..) => fail!(),
1344
1345 Dictionary(..) | RunEndEncoded(..) => fail!(),
1347 };
1348 Ok(new_data_type)
1349}
1350
1351fn canonicalize_and_verify_field(field: &Arc<Field>) -> Result<Cow<'_, Arc<Field>>> {
1352 let new_data_type = canonicalize_and_verify_data_type(field.data_type())?;
1353
1354 if matches!(new_data_type.as_ref(), DataType::FixedSizeBinary(16))
1358 && !field.has_valid_extension_type::<UuidExtension>()
1359 {
1360 let new_field = field.as_ref().clone().with_extension_type(UuidExtension);
1361 return Ok(Cow::Owned(Arc::new(new_field)));
1362 }
1363
1364 let Cow::Owned(new_data_type) = new_data_type else {
1365 return Ok(Cow::Borrowed(field));
1366 };
1367 let new_field = field.as_ref().clone().with_data_type(new_data_type);
1368 Ok(Cow::Owned(Arc::new(new_field)))
1369}
1370
1371#[cfg(test)]
1374impl VariantArray {
1375 pub(crate) fn perfectly_shredded(
1376 metadata: ArrayRef,
1377 typed_value: ArrayRef,
1378 nulls: Option<NullBuffer>,
1379 ) -> Self {
1380 let value = all_null_value_column(typed_value.len());
1381 Self::from_parts(metadata, value, Some(typed_value), nulls)
1382 }
1383}
1384
1385#[cfg(test)]
1386impl ShreddedVariantFieldArray {
1387 pub(crate) fn perfectly_shredded(typed_value: ArrayRef) -> Self {
1388 let value = all_null_value_column(typed_value.len());
1389 Self::from_parts(value, Some(typed_value), None)
1390 }
1391}
1392
1393#[cfg(test)]
1394mod test {
1395 use crate::{GetOptions, VariantArrayBuilder, json_to_variant, variant_get, variant_to_json};
1396 use std::str::FromStr;
1397
1398 use super::*;
1399 use arrow::array::{
1400 BinaryArray, BinaryDictionaryBuilder, BinaryRunBuilder, BinaryViewArray, Decimal32Array,
1401 Decimal64Array, Decimal128Array, FixedSizeBinaryArray, Int8Array, Int32Array, Int64Array,
1402 LargeBinaryArray, LargeListArray, LargeListViewArray, ListArray, ListViewArray,
1403 StringArray, Time64MicrosecondArray,
1404 };
1405 use arrow::buffer::{OffsetBuffer, ScalarBuffer};
1406 use arrow_schema::{Field, Fields};
1407 use parquet_variant::{EMPTY_VARIANT_METADATA_BYTES, ShortString};
1408
1409 #[test]
1410 fn invalid_not_a_struct_array() {
1411 let array = make_binary_view_array();
1412 let err = VariantArray::try_new(&array);
1414 assert_eq!(
1415 err.unwrap_err().to_string(),
1416 "Invalid argument error: Invalid VariantArray: requires StructArray as input"
1417 );
1418 }
1419
1420 #[test]
1421 fn invalid_missing_metadata() {
1422 let fields = Fields::from(vec![Field::new("value", DataType::BinaryView, true)]);
1423 let array = StructArray::new(fields, vec![make_binary_view_array()], None);
1424 let err = VariantArray::try_new(&array);
1426 assert_eq!(
1427 err.unwrap_err().to_string(),
1428 "Invalid argument error: Invalid VariantArray: StructArray must contain a 'metadata' field"
1429 );
1430 }
1431
1432 #[test]
1433 fn read_missing_value_column() {
1434 let typed_value = Arc::new(Int64Array::from(vec![Some(1), None, Some(3)])) as ArrayRef;
1438 let metadata =
1439 BinaryViewArray::from_iter_values(std::iter::repeat_n(EMPTY_VARIANT_METADATA_BYTES, 3));
1440 let struct_array = StructArrayBuilder::new()
1441 .with_field("metadata", Arc::new(metadata), false)
1442 .with_field("typed_value", typed_value, true)
1443 .build();
1444 assert!(struct_array.column_by_name("value").is_none());
1445
1446 let variant_array = VariantArray::try_new(&struct_array).unwrap();
1447 assert_eq!(variant_array.value_column().len(), 3);
1448 assert_eq!(variant_array.value_column().null_count(), 3);
1449 assert!(variant_array.inner().column_by_name("value").is_some());
1450 assert!(variant_array.typed_value_column().is_some());
1451 assert_eq!(variant_array.value(0), Variant::from(1i64));
1452 assert_eq!(variant_array.value(1), Variant::Null);
1453 assert_eq!(variant_array.value(2), Variant::from(3i64));
1454
1455 let fields = Fields::from(vec![Field::new("metadata", DataType::BinaryView, false)]);
1457 let metadata_only = StructArray::new(fields, vec![make_binary_view_array()], None);
1458 let err = VariantArray::try_new(&metadata_only);
1459 assert_eq!(
1460 err.unwrap_err().to_string(),
1461 "Invalid argument error: Invalid VariantArray: StructArray must contain a 'value' field"
1462 );
1463 }
1464
1465 #[test]
1466 fn invalid_metadata_field_type() {
1467 let fields = Fields::from(vec![
1468 Field::new("metadata", DataType::Int32, true), Field::new("value", DataType::BinaryView, true),
1470 ]);
1471 let array = StructArray::new(
1472 fields,
1473 vec![make_int32_array(), make_binary_view_array()],
1474 None,
1475 );
1476 let err = VariantArray::try_new(&array);
1477 assert_eq!(
1478 err.unwrap_err().to_string(),
1479 "Invalid argument error: VariantArray 'metadata' field must be Binary, LargeBinary, BinaryView, or a Dictionary or RunEndEncoded array of one of those types, got Int32"
1480 );
1481 }
1482
1483 #[test]
1484 fn encoded_metadata_supports_nulls_slices_and_variant_get() {
1485 let json: ArrayRef = Arc::new(StringArray::from(vec![
1486 Some(r#"{"a":0}"#),
1487 Some(r#"{"a":1}"#),
1488 None,
1489 Some(r#"{"b":3}"#),
1490 Some(r#"{"b":4}"#),
1491 ]));
1492 let baseline = json_to_variant(&json).unwrap();
1493 let metadata = baseline.metadata_column().as_binary_view();
1494 let metadata_a = metadata.value(0);
1495 let metadata_b = metadata.value(3);
1496
1497 let logical_metadata = [
1498 Some(metadata_a),
1499 Some(metadata_a),
1500 None,
1501 Some(metadata_b),
1502 Some(metadata_b),
1503 ];
1504
1505 let mut dictionary = BinaryDictionaryBuilder::<Int8Type>::new();
1506 dictionary.extend(logical_metadata);
1507 let dictionary: ArrayRef = Arc::new(dictionary.finish());
1508
1509 let mut ree = BinaryRunBuilder::<Int16Type>::new();
1510 ree.extend(logical_metadata);
1511 let run_end_encoded: ArrayRef = Arc::new(ree.finish());
1512
1513 for metadata in [dictionary, run_end_encoded] {
1514 assert_eq!(binary_array_value(metadata.as_ref(), 2), None);
1515 let fields = Fields::from(vec![
1516 Field::new("metadata", metadata.data_type().clone(), false),
1517 Field::new("value", baseline.value_column().data_type().clone(), false),
1518 ]);
1519 let input = StructArray::try_new(
1520 fields,
1521 vec![metadata, baseline.value_column().clone()],
1522 baseline.nulls().cloned(),
1523 )
1524 .unwrap()
1525 .slice(1, 3);
1526
1527 let variant = VariantArray::try_new(&input).unwrap();
1528 assert_eq!(variant.value(0), baseline.value(1));
1529 assert!(variant.is_null(1));
1530 assert_eq!(variant.value(2), baseline.value(3));
1531
1532 let input: ArrayRef = Arc::new(input);
1533 let options = GetOptions::new_with_path("b".try_into().unwrap())
1534 .with_as_type(Some(Arc::new(Field::new("b", DataType::Int8, true))));
1535 let result = variant_get(&input, options).unwrap();
1536 assert_eq!(
1537 result.as_primitive::<Int8Type>(),
1538 &Int8Array::from(vec![None, None, Some(3)])
1539 );
1540 assert_eq!(
1541 variant_to_json(&input).unwrap(),
1542 StringArray::from(vec![Some(r#"{"a":1}"#), None, Some(r#"{"b":3}"#)])
1543 );
1544 }
1545 }
1546
1547 #[test]
1548 fn invalid_value_field_type() {
1549 let fields = Fields::from(vec![
1550 Field::new("metadata", DataType::BinaryView, true),
1551 Field::new("value", DataType::Int32, true),
1552 ]);
1553 let array = StructArray::new(
1554 fields,
1555 vec![make_binary_view_array(), make_int32_array()],
1556 None,
1557 );
1558 let err = VariantArray::try_new(&array);
1559 assert_eq!(
1560 err.unwrap_err().to_string(),
1561 "Invalid argument error: VariantArray 'value' field must be Binary, LargeBinary, or BinaryView, got Int32"
1562 );
1563 }
1564
1565 fn make_binary_view_array() -> ArrayRef {
1566 Arc::new(BinaryViewArray::from(vec![b"test" as &[u8]]))
1567 }
1568
1569 fn make_int32_array() -> ArrayRef {
1570 Arc::new(Int32Array::from(vec![1]))
1571 }
1572
1573 fn make_variant_struct_with_typed_value(typed_value: ArrayRef) -> StructArray {
1574 let metadata = BinaryViewArray::from_iter_values(std::iter::repeat_n(
1575 EMPTY_VARIANT_METADATA_BYTES,
1576 typed_value.len(),
1577 ));
1578 let value = new_null_array(&DataType::BinaryView, typed_value.len());
1579 StructArrayBuilder::new()
1580 .with_field("metadata", Arc::new(metadata), false)
1581 .with_field("value", value, true)
1582 .with_field("typed_value", typed_value, true)
1583 .build()
1584 }
1585
1586 #[test]
1587 fn try_new_tags_untagged_uuid_on_read() {
1588 let typed_value = FixedSizeBinaryArray::try_from_iter(std::iter::repeat_n([0u8; 16], 2));
1591 let input = make_variant_struct_with_typed_value(Arc::new(typed_value.unwrap()));
1592
1593 let variant_array = VariantArray::try_new(&input).unwrap();
1595 let typed_value = variant_array.inner().field_by_name("typed_value").unwrap();
1596 assert_eq!(typed_value.data_type(), &DataType::FixedSizeBinary(16));
1597 assert!(typed_value.has_valid_extension_type::<UuidExtension>());
1598 }
1599
1600 #[test]
1601 fn try_new_tags_untagged_nested_uuid_on_read() {
1602 let leaf = FixedSizeBinaryArray::try_from_iter(std::iter::repeat_n([0u8; 16], 1)).unwrap();
1605 let inner = StructArrayBuilder::new()
1606 .with_field("typed_value", Arc::new(leaf), true)
1607 .build();
1608 let object = StructArrayBuilder::new()
1609 .with_field("id", Arc::new(inner), false)
1610 .build();
1611 let input = make_variant_struct_with_typed_value(Arc::new(object));
1612
1613 let variant_array = VariantArray::try_new(&input).unwrap();
1615 let object = variant_array.typed_value_column().unwrap().as_struct();
1616 let id = object.column_by_name("id").unwrap().as_struct();
1617 let uuid_leaf = id.field_by_name("typed_value").unwrap();
1618 assert!(uuid_leaf.has_valid_extension_type::<UuidExtension>());
1619 }
1620
1621 #[test]
1622 fn all_null_value_column_is_valid_and_unshredded() {
1623 let metadata = BinaryViewArray::from(vec![b"test" as &[u8]; 3]);
1626 let value = new_null_array(&DataType::BinaryView, 3);
1627
1628 let fields = Fields::from(vec![
1629 Field::new("metadata", DataType::BinaryView, false),
1630 Field::new("value", DataType::BinaryView, true),
1631 ]);
1632 let struct_array = StructArray::new(fields, vec![Arc::new(metadata), value], None);
1633
1634 let variant_array = VariantArray::try_new(&struct_array).unwrap();
1635 assert!(variant_array.typed_value_column().is_none());
1636
1637 for i in 0..variant_array.len() {
1640 assert!(variant_array.is_valid(i));
1641 assert_eq!(variant_array.value(i), Variant::Null);
1642 }
1643 }
1644
1645 #[test]
1646 fn canonicalize_and_verify_list_like_data_types() {
1647 let make_item_binary = || Arc::new(Field::new("item", DataType::Binary, true));
1651 let make_large_binary = || Arc::new(Field::new("item", DataType::LargeBinary, true));
1652 let make_item_binary_view = || Arc::new(Field::new("item", DataType::BinaryView, true));
1653
1654 let cases = vec![
1655 DataType::LargeList(make_item_binary()),
1657 DataType::ListView(make_item_binary()),
1658 DataType::LargeListView(make_item_binary()),
1659 DataType::LargeList(make_large_binary()),
1661 DataType::ListView(make_large_binary()),
1662 DataType::LargeListView(make_large_binary()),
1663 DataType::LargeList(make_item_binary_view()),
1665 DataType::ListView(make_item_binary_view()),
1666 DataType::LargeListView(make_item_binary_view()),
1667 ];
1668
1669 for input in cases {
1670 assert_eq!(
1671 canonicalize_and_verify_data_type(&input).unwrap().as_ref(),
1672 &input
1673 );
1674 }
1675 }
1676
1677 #[test]
1678 fn variant_array_try_new_supports_list_like_typed_value() {
1679 let item_field = Arc::new(Field::new("item", DataType::Int64, true));
1680 let values: ArrayRef = Arc::new(Int64Array::from(vec![Some(1), None, Some(3)]));
1681
1682 let typed_values = vec![
1683 Arc::new(ListArray::new(
1684 item_field.clone(),
1685 OffsetBuffer::new(ScalarBuffer::from(vec![0, 2, 3])),
1686 values.clone(),
1687 None,
1688 )) as ArrayRef,
1689 Arc::new(LargeListArray::new(
1690 item_field.clone(),
1691 OffsetBuffer::new(ScalarBuffer::from(vec![0_i64, 2, 3])),
1692 values.clone(),
1693 None,
1694 )) as ArrayRef,
1695 Arc::new(ListViewArray::new(
1696 item_field.clone(),
1697 ScalarBuffer::from(vec![0, 2]),
1698 ScalarBuffer::from(vec![2, 1]),
1699 values.clone(),
1700 None,
1701 )) as ArrayRef,
1702 Arc::new(LargeListViewArray::new(
1703 item_field,
1704 ScalarBuffer::from(vec![0_i64, 2]),
1705 ScalarBuffer::from(vec![2_i64, 1]),
1706 values,
1707 None,
1708 )) as ArrayRef,
1709 ];
1710
1711 for typed_value in typed_values {
1712 let input = make_variant_struct_with_typed_value(typed_value.clone());
1713 let variant_array = VariantArray::try_new(&input).unwrap();
1714 assert_eq!(
1715 variant_array.typed_value_column().unwrap().data_type(),
1716 typed_value.data_type(),
1717 );
1718 }
1719 }
1720
1721 #[test]
1722 fn test_try_value_out_of_bounds() {
1723 let mut b = VariantArrayBuilder::new(2);
1724 b.append_variant(Variant::from(1_i8));
1725 b.append_variant(Variant::Null);
1726 let v = b.build();
1727
1728 assert_eq!(v.try_value(0).unwrap(), Variant::Int8(1));
1729 assert_eq!(v.try_value(1).unwrap(), Variant::Null);
1730
1731 let err = v.try_value(2).unwrap_err();
1732 assert_eq!(
1733 err.to_string(),
1734 "Invalid argument error: Index 2 out of bounds for VariantArray of length 2"
1735 );
1736 }
1737
1738 #[test]
1739 fn test_variant_array_iterable() {
1740 let mut b = VariantArrayBuilder::new(6);
1741
1742 b.append_null();
1743 b.append_variant(Variant::from(1_i8));
1744 b.append_variant(Variant::Null);
1745 b.append_variant(Variant::from(2_i32));
1746 b.append_variant(Variant::from(3_i64));
1747 b.append_null();
1748
1749 let v = b.build();
1750
1751 let variants = v.iter().collect::<Vec<_>>();
1752
1753 assert_eq!(
1754 variants,
1755 vec![
1756 None,
1757 Some(Variant::Int8(1)),
1758 Some(Variant::Null),
1759 Some(Variant::Int32(2)),
1760 Some(Variant::Int64(3)),
1761 None,
1762 ]
1763 );
1764 }
1765
1766 #[test]
1767 fn test_variant_array_iter_double_ended() {
1768 let mut b = VariantArrayBuilder::new(5);
1769
1770 b.append_variant(Variant::from(0_i32));
1771 b.append_null();
1772 b.append_variant(Variant::from(2_i32));
1773 b.append_null();
1774 b.append_variant(Variant::from(4_i32));
1775
1776 let array = b.build();
1777 let mut iter = array.iter();
1778
1779 assert_eq!(iter.next(), Some(Some(Variant::from(0_i32))));
1780 assert_eq!(iter.next(), Some(None));
1781
1782 assert_eq!(iter.next_back(), Some(Some(Variant::from(4_i32))));
1783 assert_eq!(iter.next_back(), Some(None));
1784 assert_eq!(iter.next_back(), Some(Some(Variant::from(2_i32))));
1785
1786 assert_eq!(iter.next_back(), None);
1787 assert_eq!(iter.next(), None);
1788 }
1789
1790 #[test]
1791 fn test_variant_array_iter_reverse() {
1792 let mut b = VariantArrayBuilder::new(5);
1793
1794 b.append_variant(Variant::from("a"));
1795 b.append_null();
1796 b.append_variant(Variant::from("aaa"));
1797 b.append_null();
1798 b.append_variant(Variant::from("aaaaa"));
1799
1800 let array = b.build();
1801
1802 let result: Vec<_> = array.iter().rev().collect();
1803 assert_eq!(
1804 result,
1805 vec![
1806 Some(Variant::from("aaaaa")),
1807 None,
1808 Some(Variant::from("aaa")),
1809 None,
1810 Some(Variant::from("a")),
1811 ]
1812 );
1813 }
1814
1815 #[test]
1816 fn test_variant_array_iter_empty() {
1817 let v = VariantArrayBuilder::new(0).build();
1818 let mut i = v.iter();
1819 assert!(i.next().is_none());
1820 assert!(i.next_back().is_none());
1821 }
1822
1823 #[test]
1824 fn test_from_variant_opts_into_variant_array() {
1825 let v = vec![None, Some(Variant::Null), Some(Variant::BooleanFalse), None];
1826
1827 let variant_array = VariantArray::from_iter(v);
1828
1829 assert_eq!(variant_array.len(), 4);
1830
1831 assert!(variant_array.is_null(0));
1832
1833 assert!(!variant_array.is_null(1));
1834 assert_eq!(variant_array.value(1), Variant::Null);
1835
1836 assert!(!variant_array.is_null(2));
1837 assert_eq!(variant_array.value(2), Variant::BooleanFalse);
1838
1839 assert!(variant_array.is_null(3));
1840 }
1841
1842 #[test]
1843 fn test_from_variants_into_variant_array() {
1844 let v = vec![
1845 Variant::Null,
1846 Variant::BooleanFalse,
1847 Variant::ShortString(ShortString::try_new("norm").unwrap()),
1848 ];
1849
1850 let variant_array = VariantArray::from_iter(v);
1851
1852 assert_eq!(variant_array.len(), 3);
1853
1854 assert!(!variant_array.is_null(0));
1855 assert_eq!(variant_array.value(0), Variant::Null);
1856
1857 assert!(!variant_array.is_null(1));
1858 assert_eq!(variant_array.value(1), Variant::BooleanFalse);
1859
1860 assert!(!variant_array.is_null(2));
1861 assert_eq!(
1862 variant_array.value(2),
1863 Variant::ShortString(ShortString::try_new("norm").unwrap())
1864 );
1865 }
1866
1867 #[test]
1868 fn test_variant_equality() {
1869 let v_iter = [None, Some(Variant::BooleanFalse), Some(Variant::Null), None];
1870 let v = VariantArray::from_iter(v_iter.clone());
1871
1872 {
1873 let v_copy = v.clone();
1874 assert_eq!(v, v_copy);
1875 }
1876
1877 {
1878 let v_iter_reversed = v_iter.iter().cloned().rev();
1879 let v_reversed = VariantArray::from_iter(v_iter_reversed);
1880
1881 assert_ne!(v, v_reversed);
1882 }
1883
1884 {
1885 let v_sliced = v.slice(0, 1);
1886 assert_ne!(v, v_sliced);
1887 }
1888 }
1889
1890 #[test]
1891 fn binary_typed_value_roundtrips() {
1892 let typed_value: ArrayRef = Arc::new(BinaryArray::from(vec![b"hello" as &[u8]]));
1894 let struct_array = make_variant_struct_with_typed_value(typed_value);
1895
1896 let variant_array = VariantArray::try_new(&struct_array).unwrap();
1897 assert_eq!(variant_array.value(0), Variant::from(b"hello" as &[u8]));
1898 }
1899
1900 #[test]
1901 fn large_binary_typed_value_roundtrips() {
1902 let typed_value: ArrayRef = Arc::new(LargeBinaryArray::from(vec![b"world" as &[u8]]));
1904 let struct_array = make_variant_struct_with_typed_value(typed_value);
1905
1906 let variant_array = VariantArray::try_new(&struct_array).unwrap();
1907 assert_eq!(variant_array.value(0), Variant::from(b"world" as &[u8]));
1908 }
1909
1910 macro_rules! invalid_variant_array_test {
1911 ($fn_name: ident, $invalid_typed_value: expr, $error_msg: literal) => {
1912 #[test]
1913 fn $fn_name() {
1914 let invalid_typed_value = $invalid_typed_value;
1915
1916 let struct_array =
1917 make_variant_struct_with_typed_value(Arc::new(invalid_typed_value));
1918
1919 let array: VariantArray = VariantArray::try_new(&struct_array)
1920 .expect("should create variant array")
1921 .into();
1922
1923 let result = array.try_value(0);
1924 assert!(result.is_err());
1925 let error = result.unwrap_err();
1926 assert!(matches!(error, ArrowError::CastError(_)));
1927
1928 let expected: &str = $error_msg;
1929 assert!(
1930 error.to_string().contains($error_msg),
1931 "error `{}` did not contain `{}`",
1932 error,
1933 expected
1934 )
1935 }
1936 };
1937 }
1938
1939 invalid_variant_array_test!(
1940 test_variant_array_invalid_time,
1941 Time64MicrosecondArray::from(vec![Some(86401000000)]),
1942 "Cast error: Cast failed at index 0 (array type: Time64(µs)): Invalid microsecond from midnight: 86401000000"
1943 );
1944
1945 invalid_variant_array_test!(
1946 test_variant_array_invalid_decimal32,
1947 Decimal32Array::from(vec![Some(1234567890)]),
1948 "Cast error: Cast failed at index 0 (array type: Decimal32(9, 2)): Invalid argument error: 1234567890 is wider than max precision 9"
1949 );
1950
1951 invalid_variant_array_test!(
1952 test_variant_array_invalid_decimal64,
1953 Decimal64Array::from(vec![Some(1234567890123456789)]),
1954 "Cast error: Cast failed at index 0 (array type: Decimal64(18, 6)): Invalid argument error: 1234567890123456789 is wider than max precision 18"
1955 );
1956
1957 invalid_variant_array_test!(
1958 test_variant_array_invalid_decimal128,
1959 Decimal128Array::from(vec![Some(
1960 i128::from_str("123456789012345678901234567890123456789").unwrap()
1961 ),]),
1962 "Cast error: Cast failed at index 0 (array type: Decimal128(38, 10)): Invalid argument error: 123456789012345678901234567890123456789 is wider than max precision 38"
1963 );
1964 #[test]
1965 fn try_value_errors_on_unimplemented_typed_value_type() {
1966 use crate::{json_to_variant, shred_variant};
1967 use arrow::array::StringArray;
1968
1969 let json: ArrayRef = Arc::new(StringArray::from(vec![r#"{"qty": 3}"#]));
1970 let variant = json_to_variant(&json).unwrap();
1971 let shred_type = DataType::Struct(vec![Field::new("qty", DataType::Int64, true)].into());
1972 let shredded = shred_variant(&variant, &shred_type).unwrap();
1973 let err = shredded.try_value(0).unwrap_err();
1977 assert!(
1978 err.to_string().starts_with(
1979 "Not yet implemented: VariantArray::try_value cannot materialize typed_value"
1980 ),
1981 "unexpected error: {err}"
1982 );
1983 }
1984}