parquet_variant_compute/variant_get/output/
primitive.rs1use crate::variant_get::output::OutputBuilder;
19use crate::VariantArray;
20use arrow::error::Result;
21
22use arrow::array::{
23 Array, ArrayRef, ArrowPrimitiveType, AsArray, BinaryViewArray, NullBufferBuilder,
24 PrimitiveArray,
25};
26use arrow::compute::{cast_with_options, CastOptions};
27use arrow::datatypes::Int32Type;
28use arrow_schema::{ArrowError, FieldRef};
29use parquet_variant::{Variant, VariantPath};
30use std::marker::PhantomData;
31use std::sync::Arc;
32
33pub(super) trait ArrowPrimitiveVariant: ArrowPrimitiveType {
37 fn from_variant(variant: &Variant) -> Option<Self::Native>;
42}
43
44pub(super) struct PrimitiveOutputBuilder<'a, T: ArrowPrimitiveVariant> {
46 path: VariantPath<'a>,
48 as_type: FieldRef,
50 cast_options: CastOptions<'a>,
52 _phantom: PhantomData<T>,
54}
55
56impl<'a, T: ArrowPrimitiveVariant> PrimitiveOutputBuilder<'a, T> {
57 pub(super) fn new(
58 path: VariantPath<'a>,
59 as_type: FieldRef,
60 cast_options: CastOptions<'a>,
61 ) -> Self {
62 Self {
63 path,
64 as_type,
65 cast_options,
66 _phantom: PhantomData,
67 }
68 }
69}
70
71impl<'a, T: ArrowPrimitiveVariant> OutputBuilder for PrimitiveOutputBuilder<'a, T> {
72 fn partially_shredded(
73 &self,
74 variant_array: &VariantArray,
75 _metadata: &BinaryViewArray,
76 _value_field: &BinaryViewArray,
77 typed_value: &ArrayRef,
78 ) -> arrow::error::Result<ArrayRef> {
79 let mut nulls = NullBufferBuilder::new(variant_array.len());
81 let mut values = Vec::with_capacity(variant_array.len());
82 let typed_value =
83 cast_with_options(typed_value, self.as_type.data_type(), &self.cast_options)?;
84 let typed_value = typed_value.as_primitive::<T>();
86
87 for i in 0..variant_array.len() {
88 if variant_array.is_null(i) {
89 nulls.append_null();
90 values.push(T::default_value()); continue;
92 }
93
94 if typed_value.is_null(i) {
96 let variant = variant_array.value(i);
99 let Some(value) = T::from_variant(&variant) else {
100 if self.cast_options.safe {
101 nulls.append_null();
103 values.push(T::default_value()); continue;
105 } else {
106 return Err(ArrowError::CastError(format!(
107 "Failed to extract primitive of type {} from variant {:?} at path {:?}",
108 self.as_type.data_type(),
109 variant,
110 self.path
111 )));
112 }
113 };
114
115 nulls.append_non_null();
116 values.push(value)
117 } else {
118 nulls.append_non_null();
120 values.push(typed_value.value(i));
121 }
122 }
123
124 let nulls = nulls.finish();
125 let array = PrimitiveArray::<T>::new(values.into(), nulls)
126 .with_data_type(self.as_type.data_type().clone());
127 Ok(Arc::new(array))
128 }
129
130 fn typed(
131 &self,
132 _variant_array: &VariantArray,
133 _metadata: &BinaryViewArray,
134 typed_value: &ArrayRef,
135 ) -> arrow::error::Result<ArrayRef> {
136 if typed_value.data_type() == self.as_type.data_type() {
138 Ok(typed_value.clone())
139 } else {
140 Err(ArrowError::NotYetImplemented(format!(
143 "variant_get fully_shredded as {:?} with typed_value={:?} is not implemented yet",
144 self.as_type.data_type(),
145 typed_value.data_type()
146 )))
147 }
148 }
149
150 fn unshredded(
151 &self,
152 _variant_array: &VariantArray,
153 _metadata: &BinaryViewArray,
154 _value_field: &BinaryViewArray,
155 ) -> Result<ArrayRef> {
156 Err(ArrowError::NotYetImplemented(String::from(
157 "variant_get unshredded to primitive types is not implemented yet",
158 )))
159 }
160}
161
162impl ArrowPrimitiveVariant for Int32Type {
163 fn from_variant(variant: &Variant) -> Option<Self::Native> {
164 variant.as_int32()
165 }
166}