datafusion_variant/
variant_list_insert.rs1use std::sync::Arc;
2
3use arrow::array::StructArray;
4use arrow_schema::{DataType, Field, Fields};
5use datafusion::{
6 common::exec_err,
7 error::{DataFusionError, Result},
8 logical_expr::{
9 ColumnarValue, ReturnFieldArgs, ScalarUDFImpl, Signature, TypeSignature, Volatility,
10 },
11 scalar::ScalarValue,
12};
13use parquet_variant::{Variant, VariantBuilder};
14use parquet_variant_compute::{VariantArray, VariantType};
15
16use crate::shared::{ensure, try_parse_variant_scalar};
17
18#[derive(Debug, Hash, PartialEq, Eq)]
19pub struct VariantListInsert {
20 signature: Signature,
21}
22
23impl Default for VariantListInsert {
24 fn default() -> Self {
25 Self {
26 signature: Signature::new(TypeSignature::Any(2), Volatility::Immutable),
27 }
28 }
29}
30
31impl ScalarUDFImpl for VariantListInsert {
32 fn as_any(&self) -> &dyn std::any::Any {
33 self
34 }
35
36 fn name(&self) -> &str {
37 "variant_list_insert"
38 }
39
40 fn signature(&self) -> &Signature {
41 &self.signature
42 }
43
44 fn return_type(&self, _arg_types: &[arrow_schema::DataType]) -> Result<arrow_schema::DataType> {
45 Err(DataFusionError::Internal(
46 "implemented return_field_from_args instead".into(),
47 ))
48 }
49
50 fn return_field_from_args(&self, _args: ReturnFieldArgs) -> Result<Arc<Field>> {
51 let data_type = DataType::Struct(Fields::from(vec![
52 Field::new("metadata", DataType::BinaryView, false),
53 Field::new("value", DataType::BinaryView, false),
54 ]));
55
56 Ok(Arc::new(
57 Field::new(self.name(), data_type, true).with_extension_type(VariantType),
58 ))
59 }
60
61 fn invoke_with_args(
62 &self,
63 args: datafusion::logical_expr::ScalarFunctionArgs,
64 ) -> Result<ColumnarValue> {
65 let argument_fields = args.arg_fields;
66 let argument_values = args.args;
67
68 ensure(
69 argument_fields.len() == argument_values.len(),
70 "argument fields and values must be of same length",
71 )?;
72
73 let [variant_list_to_update, element_to_append] = argument_values.as_slice() else {
74 return exec_err!("expected 2 arguments");
75 };
76
77 let all_arguments_variant_field = argument_fields
78 .iter()
79 .all(|f| matches!(f.extension_type(), VariantType));
80
81 ensure(
82 all_arguments_variant_field,
83 "expected all arguments to have the VariantType extension",
84 )?;
85
86 match (variant_list_to_update, element_to_append) {
87 (
88 ColumnarValue::Scalar(scalar_variant_list),
89 ColumnarValue::Scalar(scalar_element_to_append),
90 ) => {
91 let variant_list = try_parse_variant_scalar(scalar_variant_list)?;
92 let variant_list = variant_list.value(0);
93
94 let variant_to_insert = try_parse_variant_scalar(scalar_element_to_append)?;
95 let variant_to_insert = variant_to_insert.value(0);
96
97 let out: StructArray = {
98 let (m, v) = create_variant_list_with_new_elements(
99 variant_list,
100 [variant_to_insert].into_iter(),
101 )?;
102
103 VariantArray::from_iter([Variant::new(m.as_ref(), v.as_ref())]).into()
104 };
105
106 Ok(ColumnarValue::Scalar(ScalarValue::Struct(Arc::new(out))))
107 }
108 (
109 ColumnarValue::Array(variant_lists),
110 ColumnarValue::Scalar(scalar_element_to_append),
111 ) => {
112 let variant_array = VariantArray::try_new(&variant_lists)?;
113
114 let variant_to_insert = try_parse_variant_scalar(scalar_element_to_append)?;
115 let variant_to_insert = variant_to_insert.value(0);
116
117 let buffers = variant_array
119 .iter()
120 .map(|v| {
121 v.map(|v| {
122 create_variant_list_with_new_elements(
123 v,
124 [variant_to_insert.clone()].into_iter(),
125 )
126 })
127 .transpose()
128 })
129 .collect::<Result<Vec<_>>>()?;
130
131 let variants = buffers
132 .iter()
133 .map(|opt| {
134 opt.as_ref()
135 .map(|(m, v)| Variant::new(m.as_ref(), v.as_ref()))
136 })
137 .collect::<Vec<_>>();
138
139 let out: StructArray = VariantArray::from_iter(variants).into();
140
141 Ok(ColumnarValue::Array(Arc::new(out) as _))
142 }
143
144 (ColumnarValue::Array(variant_lists), ColumnarValue::Array(elements_to_append)) => {
145 let variant_lists = VariantArray::try_new(&variant_lists)?;
146 let elements_to_append = VariantArray::try_new(&elements_to_append)?;
147
148 ensure(
149 variant_lists.len() == elements_to_append.len(),
150 "expected arguments to have the same length",
151 )?;
152
153 let mut buffers = Vec::with_capacity(variant_lists.len());
154
155 for (variant_list_to_update, element_to_append) in
156 variant_lists.iter().zip(elements_to_append.iter())
157 {
158 match (variant_list_to_update, element_to_append) {
159 (Some(variant_list), Some(element_to_append)) => {
160 let (m, v) = create_variant_list_with_new_elements(
161 variant_list,
162 [element_to_append].into_iter(),
163 )?;
164
165 buffers.push(Some((m, v)));
166 }
167 (None, None) => buffers.push(None),
168 (Some(variant_list), None) => {
169 let mut v = VariantBuilder::new();
170 v.append_value(variant_list);
171
172 buffers.push(Some(v.finish()))
173 }
174 (None, Some(element_to_append)) => {
175 let mut v = VariantBuilder::new();
176 let mut l = v.new_list();
177
178 l.append_value(element_to_append);
179 l.finish();
180
181 buffers.push(Some(v.finish()));
182 }
183 };
184 }
185
186 let variants = buffers
187 .iter()
188 .map(|opt| {
189 opt.as_ref()
190 .map(|(m, v)| Variant::new(m.as_ref(), v.as_ref()))
191 })
192 .collect::<Vec<_>>();
193
194 let out: StructArray = VariantArray::from_iter(variants).into();
195
196 Ok(ColumnarValue::Array(Arc::new(out) as _))
197 }
198 (ColumnarValue::Scalar(_), ColumnarValue::Array(_)) => {
199 exec_err!("unsupported argument")
200 }
201 }
202 }
203}
204
205fn create_variant_list_with_new_elements<'m, 'v>(
208 variant_list: Variant,
209 elements_to_insert: impl Iterator<Item = Variant<'m, 'v>>,
210) -> Result<(Vec<u8>, Vec<u8>)> {
211 let Variant::List(variant_list) = variant_list else {
212 return exec_err!("expected variant list");
213 };
214
215 let mut v = VariantBuilder::new();
218 let mut l = v.new_list();
219
220 l.extend(variant_list.iter());
221
222 for v in elements_to_insert {
223 l.append_value(v);
224 }
225
226 l.finish();
227
228 Ok(v.finish())
229}