1use crate::shred_variant::{
6 NullValue, VariantToShreddedVariantRowBuilder,
7 make_variant_to_shredded_variant_arrow_row_builder,
8};
9use crate::type_conversion::{
10 PrimitiveFromVariant, ShredDecimalVariant, TimestampFromVariant, VariantCastMode,
11 shred_variant_to_unscaled_decimal, variant_cast_with_options, variant_to_boolean,
12 variant_to_unscaled_decimal,
13};
14use crate::variant_array::ShreddedVariantFieldArray;
15use crate::{VariantArray, VariantValueArrayBuilder};
16use arrow::array::{
17 ArrayRef, ArrowNativeTypeOp, BinaryBuilder, BinaryLikeArrayBuilder, BinaryViewBuilder,
18 BooleanBuilder, FixedSizeBinaryBuilder, FixedSizeListArray, GenericListArray,
19 GenericListViewArray, LargeBinaryBuilder, LargeStringBuilder, MapArray, NullArray,
20 NullBufferBuilder, OffsetSizeTrait, PrimitiveBuilder, StringBuilder, StringLikeArrayBuilder,
21 StringViewBuilder, StructArray, UnionArray,
22};
23use arrow::buffer::{OffsetBuffer, ScalarBuffer};
24use arrow::compute::{CastOptions, DecimalCast, cast_with_options};
25use arrow::datatypes::{self, DataType, DecimalType};
26use arrow::error::{ArrowError, Result};
27use arrow_schema::{FieldRef, Fields, TimeUnit, UnionFields, UnionMode};
28use parquet_variant::{Variant, VariantPath};
29use std::sync::Arc;
30
31pub(crate) enum VariantToArrowRowBuilder<'a> {
36 Primitive(PrimitiveVariantToArrowRowBuilder<'a>),
37 Array(ArrayVariantToArrowRowBuilder<'a>),
38 Struct(StructVariantToArrowRowBuilder<'a>),
39 Union(UnionVariantToArrowRowBuilder<'a>),
40 Map(MapVariantToArrowRowBuilder<'a>),
41 Encoded(EncodedVariantToArrowRowBuilder<'a>),
42 BinaryVariant(VariantToBinaryVariantArrowRowBuilder),
43
44 WithPath(VariantPathRowBuilder<'a>),
46}
47
48impl VariantToArrowRowBuilder<'_> {
49 pub fn append_null(&mut self) -> Result<()> {
50 use VariantToArrowRowBuilder::*;
51 match self {
52 Primitive(b) => b.append_null(),
53 Array(b) => b.append_null(),
54 Struct(b) => b.append_null(),
55 Union(b) => b.append_null(),
56 Map(b) => b.append_null(),
57 Encoded(b) => b.append_null(),
58 BinaryVariant(b) => b.append_null(),
59 WithPath(path_builder) => path_builder.append_null(),
60 }
61 }
62
63 pub fn append_value(&mut self, value: Variant<'_, '_>) -> Result<bool> {
64 use VariantToArrowRowBuilder::*;
65 match self {
66 Primitive(b) => b.append_value(&value),
67 Array(b) => b.append_value(&value),
68 Struct(b) => b.append_value(&value),
69 Union(b) => b.append_value(&value),
70 Map(b) => b.append_value(&value),
71 Encoded(b) => b.append_value(value),
72 BinaryVariant(b) => b.append_value(value),
73 WithPath(path_builder) => path_builder.append_value(value),
74 }
75 }
76
77 pub fn finish(self) -> Result<ArrayRef> {
78 use VariantToArrowRowBuilder::*;
79 match self {
80 Primitive(b) => b.finish(),
81 Array(b) => b.finish(),
82 Struct(b) => b.finish(),
83 Union(b) => b.finish(),
84 Map(b) => b.finish(),
85 Encoded(b) => b.finish(),
86 BinaryVariant(b) => b.finish(),
87 WithPath(path_builder) => path_builder.finish(),
88 }
89 }
90}
91
92fn make_typed_variant_to_arrow_row_builder<'a>(
93 data_type: &'a DataType,
94 cast_options: &'a CastOptions,
95 capacity: usize,
96 cast_mode: VariantCastMode,
97) -> Result<VariantToArrowRowBuilder<'a>> {
98 use VariantToArrowRowBuilder::*;
99
100 match data_type {
101 DataType::Struct(fields) => {
102 let builder = StructVariantToArrowRowBuilder::try_new(fields, cast_options, capacity)?;
103 Ok(Struct(builder))
104 }
105 data_type @ (DataType::List(_)
106 | DataType::LargeList(_)
107 | DataType::ListView(_)
108 | DataType::LargeListView(_)
109 | DataType::FixedSizeList(..)) => {
110 let builder =
111 ArrayVariantToArrowRowBuilder::try_new(data_type, cast_options, capacity, false)?;
112 Ok(Array(builder))
113 }
114 DataType::Union(union_fields, mode) => {
115 let builder = UnionVariantToArrowRowBuilder::try_new(
116 union_fields,
117 *mode,
118 cast_options,
119 capacity,
120 )?;
121 Ok(Union(builder))
122 }
123 DataType::Map(entries_field, ordered) => {
124 let builder = MapVariantToArrowRowBuilder::try_new(
125 entries_field,
126 *ordered,
127 cast_options,
128 capacity,
129 cast_mode,
130 )?;
131 Ok(Map(builder))
132 }
133 DataType::Dictionary(_, value_type) => {
134 let builder = EncodedVariantToArrowRowBuilder::try_new(
135 data_type,
136 value_type.as_ref(),
137 cast_options,
138 capacity,
139 )?;
140 Ok(Encoded(builder))
141 }
142 DataType::RunEndEncoded(_, value_field) => {
143 let builder = EncodedVariantToArrowRowBuilder::try_new(
144 data_type,
145 value_field.data_type(),
146 cast_options,
147 capacity,
148 )?;
149 Ok(Encoded(builder))
150 }
151 data_type => {
152 let builder = make_primitive_variant_to_arrow_row_builder(
153 data_type,
154 cast_options,
155 capacity,
156 cast_mode,
157 )?;
158 Ok(Primitive(builder))
159 }
160 }
161}
162
163pub(crate) fn make_variant_to_arrow_row_builder<'a>(
164 metadata: &ArrayRef,
165 path: VariantPath<'a>,
166 data_type: Option<&'a DataType>,
167 cast_options: &'a CastOptions,
168 capacity: usize,
169) -> Result<VariantToArrowRowBuilder<'a>> {
170 use VariantToArrowRowBuilder::*;
171
172 let mut builder = match data_type {
173 None => BinaryVariant(VariantToBinaryVariantArrowRowBuilder::new(
175 metadata.clone(),
176 capacity,
177 )),
178 Some(data_type) => make_typed_variant_to_arrow_row_builder(
179 data_type,
180 cast_options,
181 capacity,
182 VariantCastMode::Get,
183 )?,
184 };
185
186 if !path.is_empty() {
188 builder = WithPath(VariantPathRowBuilder {
189 builder: Box::new(builder),
190 path,
191 })
192 }
193
194 Ok(builder)
195}
196
197pub(crate) enum PrimitiveVariantToArrowRowBuilder<'a> {
201 Null(VariantToNullArrowRowBuilder<'a>),
202 Boolean(VariantToBooleanArrowRowBuilder<'a>),
203 Int8(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Int8Type>),
204 Int16(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Int16Type>),
205 Int32(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Int32Type>),
206 Int64(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Int64Type>),
207 UInt8(VariantToPrimitiveArrowRowBuilder<'a, datatypes::UInt8Type>),
208 UInt16(VariantToPrimitiveArrowRowBuilder<'a, datatypes::UInt16Type>),
209 UInt32(VariantToPrimitiveArrowRowBuilder<'a, datatypes::UInt32Type>),
210 UInt64(VariantToPrimitiveArrowRowBuilder<'a, datatypes::UInt64Type>),
211 Float16(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Float16Type>),
212 Float32(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Float32Type>),
213 Float64(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Float64Type>),
214 Decimal32(VariantToDecimalArrowRowBuilder<'a, datatypes::Decimal32Type>),
215 Decimal64(VariantToDecimalArrowRowBuilder<'a, datatypes::Decimal64Type>),
216 Decimal128(VariantToDecimalArrowRowBuilder<'a, datatypes::Decimal128Type>),
217 Decimal256(VariantToDecimalArrowRowBuilder<'a, datatypes::Decimal256Type>),
218 TimestampSecond(VariantToTimestampArrowRowBuilder<'a, datatypes::TimestampSecondType>),
219 TimestampSecondNtz(VariantToTimestampNtzArrowRowBuilder<'a, datatypes::TimestampSecondType>),
220 TimestampMilli(VariantToTimestampArrowRowBuilder<'a, datatypes::TimestampMillisecondType>),
221 TimestampMilliNtz(
222 VariantToTimestampNtzArrowRowBuilder<'a, datatypes::TimestampMillisecondType>,
223 ),
224 TimestampMicro(VariantToTimestampArrowRowBuilder<'a, datatypes::TimestampMicrosecondType>),
225 TimestampMicroNtz(
226 VariantToTimestampNtzArrowRowBuilder<'a, datatypes::TimestampMicrosecondType>,
227 ),
228 TimestampNano(VariantToTimestampArrowRowBuilder<'a, datatypes::TimestampNanosecondType>),
229 TimestampNanoNtz(VariantToTimestampNtzArrowRowBuilder<'a, datatypes::TimestampNanosecondType>),
230 Time32Second(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Time32SecondType>),
231 Time32Milli(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Time32MillisecondType>),
232 Time64Micro(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Time64MicrosecondType>),
233 Time64Nano(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Time64NanosecondType>),
234 Date32(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Date32Type>),
235 Date64(VariantToPrimitiveArrowRowBuilder<'a, datatypes::Date64Type>),
236 Uuid(VariantToUuidArrowRowBuilder<'a>),
237 String(VariantToStringArrowBuilder<'a, StringBuilder>),
238 LargeString(VariantToStringArrowBuilder<'a, LargeStringBuilder>),
239 StringView(VariantToStringArrowBuilder<'a, StringViewBuilder>),
240 Binary(VariantToBinaryArrowRowBuilder<'a, BinaryBuilder>),
241 LargeBinary(VariantToBinaryArrowRowBuilder<'a, LargeBinaryBuilder>),
242 BinaryView(VariantToBinaryArrowRowBuilder<'a, BinaryViewBuilder>),
243}
244
245impl PrimitiveVariantToArrowRowBuilder<'_> {
246 pub fn append_null(&mut self) -> Result<()> {
247 use PrimitiveVariantToArrowRowBuilder::*;
248 match self {
249 Null(b) => b.append_null(),
250 Boolean(b) => b.append_null(),
251 Int8(b) => b.append_null(),
252 Int16(b) => b.append_null(),
253 Int32(b) => b.append_null(),
254 Int64(b) => b.append_null(),
255 UInt8(b) => b.append_null(),
256 UInt16(b) => b.append_null(),
257 UInt32(b) => b.append_null(),
258 UInt64(b) => b.append_null(),
259 Float16(b) => b.append_null(),
260 Float32(b) => b.append_null(),
261 Float64(b) => b.append_null(),
262 Decimal32(b) => b.append_null(),
263 Decimal64(b) => b.append_null(),
264 Decimal128(b) => b.append_null(),
265 Decimal256(b) => b.append_null(),
266 TimestampSecond(b) => b.append_null(),
267 TimestampSecondNtz(b) => b.append_null(),
268 TimestampMilli(b) => b.append_null(),
269 TimestampMilliNtz(b) => b.append_null(),
270 TimestampMicro(b) => b.append_null(),
271 TimestampMicroNtz(b) => b.append_null(),
272 TimestampNano(b) => b.append_null(),
273 TimestampNanoNtz(b) => b.append_null(),
274 Time32Second(b) => b.append_null(),
275 Time32Milli(b) => b.append_null(),
276 Time64Micro(b) => b.append_null(),
277 Time64Nano(b) => b.append_null(),
278 Date32(b) => b.append_null(),
279 Date64(b) => b.append_null(),
280 Uuid(b) => b.append_null(),
281 String(b) => b.append_null(),
282 LargeString(b) => b.append_null(),
283 StringView(b) => b.append_null(),
284 Binary(b) => b.append_null(),
285 LargeBinary(b) => b.append_null(),
286 BinaryView(b) => b.append_null(),
287 }
288 }
289
290 pub fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
291 use PrimitiveVariantToArrowRowBuilder::*;
292 match self {
293 Null(b) => b.append_value(value),
294 Boolean(b) => b.append_value(value),
295 Int8(b) => b.append_value(value),
296 Int16(b) => b.append_value(value),
297 Int32(b) => b.append_value(value),
298 Int64(b) => b.append_value(value),
299 UInt8(b) => b.append_value(value),
300 UInt16(b) => b.append_value(value),
301 UInt32(b) => b.append_value(value),
302 UInt64(b) => b.append_value(value),
303 Float16(b) => b.append_value(value),
304 Float32(b) => b.append_value(value),
305 Float64(b) => b.append_value(value),
306 Decimal32(b) => b.append_value(value),
307 Decimal64(b) => b.append_value(value),
308 Decimal128(b) => b.append_value(value),
309 Decimal256(b) => b.append_value(value),
310 TimestampSecond(b) => b.append_value(value),
311 TimestampSecondNtz(b) => b.append_value(value),
312 TimestampMilli(b) => b.append_value(value),
313 TimestampMilliNtz(b) => b.append_value(value),
314 TimestampMicro(b) => b.append_value(value),
315 TimestampMicroNtz(b) => b.append_value(value),
316 TimestampNano(b) => b.append_value(value),
317 TimestampNanoNtz(b) => b.append_value(value),
318 Time32Second(b) => b.append_value(value),
319 Time32Milli(b) => b.append_value(value),
320 Time64Micro(b) => b.append_value(value),
321 Time64Nano(b) => b.append_value(value),
322 Date32(b) => b.append_value(value),
323 Date64(b) => b.append_value(value),
324 Uuid(b) => b.append_value(value),
325 String(b) => b.append_value(value),
326 LargeString(b) => b.append_value(value),
327 StringView(b) => b.append_value(value),
328 Binary(b) => b.append_value(value),
329 LargeBinary(b) => b.append_value(value),
330 BinaryView(b) => b.append_value(value),
331 }
332 }
333
334 pub fn finish(self) -> Result<ArrayRef> {
335 use PrimitiveVariantToArrowRowBuilder::*;
336 match self {
337 Null(b) => b.finish(),
338 Boolean(b) => b.finish(),
339 Int8(b) => b.finish(),
340 Int16(b) => b.finish(),
341 Int32(b) => b.finish(),
342 Int64(b) => b.finish(),
343 UInt8(b) => b.finish(),
344 UInt16(b) => b.finish(),
345 UInt32(b) => b.finish(),
346 UInt64(b) => b.finish(),
347 Float16(b) => b.finish(),
348 Float32(b) => b.finish(),
349 Float64(b) => b.finish(),
350 Decimal32(b) => b.finish(),
351 Decimal64(b) => b.finish(),
352 Decimal128(b) => b.finish(),
353 Decimal256(b) => b.finish(),
354 TimestampSecond(b) => b.finish(),
355 TimestampSecondNtz(b) => b.finish(),
356 TimestampMilli(b) => b.finish(),
357 TimestampMilliNtz(b) => b.finish(),
358 TimestampMicro(b) => b.finish(),
359 TimestampMicroNtz(b) => b.finish(),
360 TimestampNano(b) => b.finish(),
361 TimestampNanoNtz(b) => b.finish(),
362 Time32Second(b) => b.finish(),
363 Time32Milli(b) => b.finish(),
364 Time64Micro(b) => b.finish(),
365 Time64Nano(b) => b.finish(),
366 Date32(b) => b.finish(),
367 Date64(b) => b.finish(),
368 Uuid(b) => b.finish(),
369 String(b) => b.finish(),
370 LargeString(b) => b.finish(),
371 StringView(b) => b.finish(),
372 Binary(b) => b.finish(),
373 LargeBinary(b) => b.finish(),
374 BinaryView(b) => b.finish(),
375 }
376 }
377}
378
379pub(crate) struct EncodedVariantToArrowRowBuilder<'a> {
380 data_type: &'a DataType,
381 cast_options: &'a CastOptions<'a>,
382 values_builder: Box<VariantToArrowRowBuilder<'a>>,
383}
384
385impl<'a> EncodedVariantToArrowRowBuilder<'a> {
386 fn try_new(
387 data_type: &'a DataType,
388 value_type: &'a DataType,
389 cast_options: &'a CastOptions,
390 capacity: usize,
391 ) -> Result<Self> {
392 let values_builder = Box::new(make_typed_variant_to_arrow_row_builder(
393 value_type,
394 cast_options,
395 capacity,
396 VariantCastMode::Get,
397 )?);
398 Ok(Self {
399 data_type,
400 cast_options,
401 values_builder,
402 })
403 }
404
405 fn append_null(&mut self) -> Result<()> {
406 self.values_builder.append_null()
407 }
408
409 fn append_value(&mut self, value: Variant<'_, '_>) -> Result<bool> {
410 self.values_builder.append_value(value)
411 }
412
413 fn finish(self) -> Result<ArrayRef> {
414 let values = self.values_builder.finish()?;
415 cast_with_options(values.as_ref(), self.data_type, self.cast_options)
416 }
417}
418
419pub(crate) fn make_primitive_variant_to_arrow_row_builder<'a>(
421 data_type: &'a DataType,
422 cast_options: &'a CastOptions,
423 capacity: usize,
424 cast_mode: VariantCastMode,
425) -> Result<PrimitiveVariantToArrowRowBuilder<'a>> {
426 use PrimitiveVariantToArrowRowBuilder::*;
427
428 let builder = match data_type {
429 DataType::Null => Null(VariantToNullArrowRowBuilder::new(cast_options, capacity)),
430 DataType::Boolean => Boolean(VariantToBooleanArrowRowBuilder::new(
431 cast_options,
432 capacity,
433 cast_mode,
434 )),
435 DataType::Int8 => Int8(VariantToPrimitiveArrowRowBuilder::new(
436 cast_options,
437 capacity,
438 cast_mode,
439 )),
440 DataType::Int16 => Int16(VariantToPrimitiveArrowRowBuilder::new(
441 cast_options,
442 capacity,
443 cast_mode,
444 )),
445 DataType::Int32 => Int32(VariantToPrimitiveArrowRowBuilder::new(
446 cast_options,
447 capacity,
448 cast_mode,
449 )),
450 DataType::Int64 => Int64(VariantToPrimitiveArrowRowBuilder::new(
451 cast_options,
452 capacity,
453 cast_mode,
454 )),
455 DataType::UInt8 => UInt8(VariantToPrimitiveArrowRowBuilder::new(
456 cast_options,
457 capacity,
458 cast_mode,
459 )),
460 DataType::UInt16 => UInt16(VariantToPrimitiveArrowRowBuilder::new(
461 cast_options,
462 capacity,
463 cast_mode,
464 )),
465 DataType::UInt32 => UInt32(VariantToPrimitiveArrowRowBuilder::new(
466 cast_options,
467 capacity,
468 cast_mode,
469 )),
470 DataType::UInt64 => UInt64(VariantToPrimitiveArrowRowBuilder::new(
471 cast_options,
472 capacity,
473 cast_mode,
474 )),
475 DataType::Float16 => Float16(VariantToPrimitiveArrowRowBuilder::new(
476 cast_options,
477 capacity,
478 cast_mode,
479 )),
480 DataType::Float32 => Float32(VariantToPrimitiveArrowRowBuilder::new(
481 cast_options,
482 capacity,
483 cast_mode,
484 )),
485 DataType::Float64 => Float64(VariantToPrimitiveArrowRowBuilder::new(
486 cast_options,
487 capacity,
488 cast_mode,
489 )),
490 DataType::Decimal32(precision, scale) => Decimal32(VariantToDecimalArrowRowBuilder::new(
491 cast_options,
492 capacity,
493 *precision,
494 *scale,
495 cast_mode,
496 )?),
497 DataType::Decimal64(precision, scale) => Decimal64(VariantToDecimalArrowRowBuilder::new(
498 cast_options,
499 capacity,
500 *precision,
501 *scale,
502 cast_mode,
503 )?),
504 DataType::Decimal128(precision, scale) => Decimal128(VariantToDecimalArrowRowBuilder::new(
505 cast_options,
506 capacity,
507 *precision,
508 *scale,
509 cast_mode,
510 )?),
511 DataType::Decimal256(precision, scale) => Decimal256(VariantToDecimalArrowRowBuilder::new(
512 cast_options,
513 capacity,
514 *precision,
515 *scale,
516 cast_mode,
517 )?),
518 DataType::Date32 => Date32(VariantToPrimitiveArrowRowBuilder::new(
519 cast_options,
520 capacity,
521 cast_mode,
522 )),
523 DataType::Date64 => Date64(VariantToPrimitiveArrowRowBuilder::new(
524 cast_options,
525 capacity,
526 cast_mode,
527 )),
528 DataType::Time32(TimeUnit::Second) => Time32Second(VariantToPrimitiveArrowRowBuilder::new(
529 cast_options,
530 capacity,
531 cast_mode,
532 )),
533 DataType::Time32(TimeUnit::Millisecond) => Time32Milli(
534 VariantToPrimitiveArrowRowBuilder::new(cast_options, capacity, cast_mode),
535 ),
536 DataType::Time32(t) => {
537 return Err(ArrowError::InvalidArgumentError(format!(
538 "The unit for Time32 must be second/millisecond, received {t:?}"
539 )));
540 }
541 DataType::Time64(TimeUnit::Microsecond) => Time64Micro(
542 VariantToPrimitiveArrowRowBuilder::new(cast_options, capacity, cast_mode),
543 ),
544 DataType::Time64(TimeUnit::Nanosecond) => Time64Nano(
545 VariantToPrimitiveArrowRowBuilder::new(cast_options, capacity, cast_mode),
546 ),
547 DataType::Time64(t) => {
548 return Err(ArrowError::InvalidArgumentError(format!(
549 "The unit for Time64 must be micro/nano seconds, received {t:?}"
550 )));
551 }
552 DataType::Timestamp(TimeUnit::Second, None) => TimestampSecondNtz(
553 VariantToTimestampNtzArrowRowBuilder::new(cast_options, capacity, cast_mode),
554 ),
555 DataType::Timestamp(TimeUnit::Second, tz) => TimestampSecond(
556 VariantToTimestampArrowRowBuilder::new(cast_options, capacity, cast_mode, tz.clone()),
557 ),
558 DataType::Timestamp(TimeUnit::Millisecond, None) => TimestampMilliNtz(
559 VariantToTimestampNtzArrowRowBuilder::new(cast_options, capacity, cast_mode),
560 ),
561 DataType::Timestamp(TimeUnit::Millisecond, tz) => TimestampMilli(
562 VariantToTimestampArrowRowBuilder::new(cast_options, capacity, cast_mode, tz.clone()),
563 ),
564 DataType::Timestamp(TimeUnit::Microsecond, None) => TimestampMicroNtz(
565 VariantToTimestampNtzArrowRowBuilder::new(cast_options, capacity, cast_mode),
566 ),
567 DataType::Timestamp(TimeUnit::Microsecond, tz) => TimestampMicro(
568 VariantToTimestampArrowRowBuilder::new(cast_options, capacity, cast_mode, tz.clone()),
569 ),
570 DataType::Timestamp(TimeUnit::Nanosecond, None) => TimestampNanoNtz(
571 VariantToTimestampNtzArrowRowBuilder::new(cast_options, capacity, cast_mode),
572 ),
573 DataType::Timestamp(TimeUnit::Nanosecond, tz) => TimestampNano(
574 VariantToTimestampArrowRowBuilder::new(cast_options, capacity, cast_mode, tz.clone()),
575 ),
576 DataType::Duration(_) | DataType::Interval(_) => {
577 return Err(ArrowError::InvalidArgumentError(
578 "Casting Variant to duration/interval types is not supported. \
579 The Variant format does not define duration/interval types."
580 .to_string(),
581 ));
582 }
583 DataType::Binary => Binary(VariantToBinaryArrowRowBuilder::new(cast_options, capacity)),
584 DataType::LargeBinary => {
585 LargeBinary(VariantToBinaryArrowRowBuilder::new(cast_options, capacity))
586 }
587 DataType::BinaryView => {
588 BinaryView(VariantToBinaryArrowRowBuilder::new(cast_options, capacity))
589 }
590 DataType::FixedSizeBinary(16) => {
591 Uuid(VariantToUuidArrowRowBuilder::new(cast_options, capacity))
592 }
593 DataType::FixedSizeBinary(_) => {
594 return Err(ArrowError::NotYetImplemented(format!(
595 "DataType {data_type:?} not yet implemented"
596 )));
597 }
598 DataType::Utf8 => String(VariantToStringArrowBuilder::new(cast_options, capacity)),
599 DataType::LargeUtf8 => {
600 LargeString(VariantToStringArrowBuilder::new(cast_options, capacity))
601 }
602 DataType::Utf8View => StringView(VariantToStringArrowBuilder::new(cast_options, capacity)),
603 DataType::List(_)
604 | DataType::LargeList(_)
605 | DataType::ListView(_)
606 | DataType::LargeListView(_)
607 | DataType::FixedSizeList(..)
608 | DataType::Struct(_)
609 | DataType::Map(..)
610 | DataType::Union(..)
611 | DataType::Dictionary(..)
612 | DataType::RunEndEncoded(..) => {
613 return Err(ArrowError::InvalidArgumentError(format!(
614 "Casting to {data_type:?} is not applicable for primitive Variant types"
615 )));
616 }
617 };
618 Ok(builder)
619}
620
621pub(crate) enum ArrayVariantToArrowRowBuilder<'a> {
622 List(VariantToListArrowRowBuilder<'a, i32, false>),
623 LargeList(VariantToListArrowRowBuilder<'a, i64, false>),
624 ListView(VariantToListArrowRowBuilder<'a, i32, true>),
625 LargeListView(VariantToListArrowRowBuilder<'a, i64, true>),
626 FixedSizeList(VariantToFixedSizeListArrowRowBuilder<'a>),
627}
628
629pub(crate) struct StructVariantToArrowRowBuilder<'a> {
630 fields: &'a Fields,
631 field_builders: Vec<VariantToArrowRowBuilder<'a>>,
632 nulls: NullBufferBuilder,
633 cast_options: &'a CastOptions<'a>,
634}
635
636impl<'a> StructVariantToArrowRowBuilder<'a> {
637 fn try_new(
638 fields: &'a Fields,
639 cast_options: &'a CastOptions<'a>,
640 capacity: usize,
641 ) -> Result<Self> {
642 let mut field_builders = Vec::with_capacity(fields.len());
643 for field in fields {
644 field_builders.push(make_typed_variant_to_arrow_row_builder(
645 field.data_type(),
646 cast_options,
647 capacity,
648 VariantCastMode::Get,
649 )?);
650 }
651 Ok(Self {
652 fields,
653 field_builders,
654 nulls: NullBufferBuilder::new(capacity),
655 cast_options,
656 })
657 }
658
659 fn append_null(&mut self) -> Result<()> {
660 for builder in &mut self.field_builders {
661 builder.append_null()?;
662 }
663 self.nulls.append_null();
664 Ok(())
665 }
666
667 fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
668 match variant_cast_with_options(value, self.cast_options, Variant::as_object) {
669 Ok(Some(obj)) => {
670 for (index, field) in self.fields.iter().enumerate() {
671 match obj.get(field.name()) {
672 Some(field_value) => {
673 self.field_builders[index].append_value(field_value)?;
674 }
675 None => {
676 self.field_builders[index].append_null()?;
677 }
678 }
679 }
680
681 self.nulls.append_non_null();
682 Ok(true)
683 }
684 Ok(None) => {
685 self.append_null()?;
686 Ok(false)
687 }
688 Err(_) => Err(ArrowError::CastError(format!(
689 "Failed to extract struct from variant {value:?}"
690 ))),
691 }
692 }
693
694 fn finish(mut self) -> Result<ArrayRef> {
695 let mut children = Vec::with_capacity(self.field_builders.len());
696 for builder in self.field_builders {
697 children.push(builder.finish()?);
698 }
699 Ok(Arc::new(StructArray::try_new(
700 self.fields.clone(),
701 children,
702 self.nulls.finish(),
703 )?))
704 }
705}
706
707pub(crate) struct UnionVariantToArrowRowBuilder<'a> {
714 fields: &'a UnionFields,
715 mode: UnionMode,
716 children: Vec<UnionChildBuilder<'a>>,
717 type_ids: Vec<i8>,
718 offsets: Vec<i32>,
720 null_child: usize,
721 cast_options: &'a CastOptions<'a>,
722}
723
724struct UnionChildBuilder<'a> {
725 type_id: i8,
726 builder: VariantToArrowRowBuilder<'a>,
727 len: i32,
728}
729
730impl<'a> UnionVariantToArrowRowBuilder<'a> {
731 fn try_new(
732 fields: &'a UnionFields,
733 mode: UnionMode,
734 cast_options: &'a CastOptions<'a>,
735 capacity: usize,
736 ) -> Result<Self> {
737 if fields.is_empty() {
739 return Err(ArrowError::InvalidArgumentError(
740 "Casting Variant to a union requires at least one union field".to_string(),
741 ));
742 }
743 let mut children = Vec::with_capacity(fields.len());
744 for (type_id, field) in fields.iter() {
745 children.push(UnionChildBuilder {
748 type_id,
749 builder: make_typed_variant_to_arrow_row_builder(
750 field.data_type(),
751 cast_options,
752 capacity,
753 VariantCastMode::Get,
754 )?,
755 len: 0,
756 });
757 }
758 let null_child = fields
759 .iter()
760 .position(|(_, field)| field.data_type() == &DataType::Null)
761 .unwrap_or(0);
762 let offsets = match mode {
763 UnionMode::Dense => Vec::with_capacity(capacity),
764 UnionMode::Sparse => Vec::new(),
765 };
766 Ok(Self {
767 fields,
768 mode,
769 children,
770 type_ids: Vec::with_capacity(capacity),
771 offsets,
772 null_child,
773 cast_options,
774 })
775 }
776
777 fn append_null(&mut self) -> Result<()> {
778 self.append_to_child(self.null_child, None)?;
779 Ok(())
780 }
781
782 fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
783 if matches!(value, Variant::Null) {
785 self.append_null()?;
786 return Ok(false);
787 }
788 match self.select_child(value) {
789 Some(index) => self.append_to_child(index, Some(value)),
790 None if self.cast_options.safe => {
791 self.append_null()?;
792 Ok(false)
793 }
794 None => Err(ArrowError::CastError(format!(
795 "Failed to cast variant {value:?} to union: no field can represent it"
796 ))),
797 }
798 }
799
800 fn select_child(&self, value: &Variant<'_, '_>) -> Option<usize> {
801 let mut best: Option<(u8, usize)> = None;
802 for (index, (_, field)) in self.fields.iter().enumerate() {
803 let Some(rank) = union_child_rank(value, field.data_type()) else {
804 continue;
805 };
806 if best.is_none_or(|(best_rank, _)| rank < best_rank) {
807 best = Some((rank, index));
808 }
809 }
810 best.map(|(_, index)| index)
811 }
812
813 fn append_to_child(&mut self, index: usize, value: Option<&Variant<'_, '_>>) -> Result<bool> {
814 self.type_ids.push(self.children[index].type_id);
815 match self.mode {
816 UnionMode::Dense => {
817 let child = &mut self.children[index];
818 self.offsets.push(child.len);
819 child.len = child.len.add_checked(1)?;
820 match value {
821 Some(value) => child.builder.append_value(value.clone()),
822 None => {
823 child.builder.append_null()?;
824 Ok(false)
825 }
826 }
827 }
828 UnionMode::Sparse => {
829 let mut appended = false;
830 for (child_index, child) in self.children.iter_mut().enumerate() {
831 match value {
832 Some(value) if child_index == index => {
833 appended = child.builder.append_value(value.clone())?;
834 }
835 _ => child.builder.append_null()?,
836 }
837 }
838 Ok(appended)
839 }
840 }
841 }
842
843 fn finish(self) -> Result<ArrayRef> {
844 let mut type_ids = Vec::with_capacity(self.children.len());
845 let mut fields = Vec::with_capacity(self.children.len());
846 let mut arrays = Vec::with_capacity(self.children.len());
847 for (child, (_, field)) in self.children.into_iter().zip(self.fields.iter()) {
848 let array = child.builder.finish()?;
849 type_ids.push(child.type_id);
850 fields.push(
851 field
852 .as_ref()
853 .clone()
854 .with_data_type(array.data_type().clone()),
855 );
856 arrays.push(array);
857 }
858 let fields = UnionFields::try_new(type_ids, fields)?;
859 let offsets = (self.mode == UnionMode::Dense).then(|| ScalarBuffer::from(self.offsets));
860 let array =
861 UnionArray::try_new(fields, ScalarBuffer::from(self.type_ids), offsets, arrays)?;
862 Ok(Arc::new(array))
863 }
864}
865
866fn union_child_rank(value: &Variant<'_, '_>, data_type: &DataType) -> Option<u8> {
871 use DataType::*;
872 let rank = match (value, data_type) {
873 (_, Dictionary(_, value_type)) => return union_child_rank(value, value_type),
874 (_, RunEndEncoded(_, value_field)) => {
875 return union_child_rank(value, value_field.data_type());
876 }
877 (Variant::BooleanTrue | Variant::BooleanFalse, Boolean) => 0,
878 (Variant::Int8(_), Int8) => 0,
879 (Variant::Int8(_), Int16) => 1,
880 (Variant::Int8(_), Int32) => 2,
881 (Variant::Int8(_), Int64) => 3,
882 (Variant::Int16(_), Int16) => 0,
883 (Variant::Int16(_), Int32) => 1,
884 (Variant::Int16(_), Int64) => 2,
885 (Variant::Int32(_), Int32) => 0,
886 (Variant::Int32(_), Int64) => 1,
887 (Variant::Int64(_), Int64) => 0,
888 (Variant::Float(_), Float32) => 0,
889 (Variant::Float(_), Float64) => 1,
890 (Variant::Double(_), Float64) => 0,
891 (Variant::Decimal4(_), Decimal32(..)) if variant_fits_decimal(value, data_type) => 0,
892 (Variant::Decimal4(_), Decimal64(..)) if variant_fits_decimal(value, data_type) => 1,
893 (Variant::Decimal4(_), Decimal128(..)) if variant_fits_decimal(value, data_type) => 2,
894 (Variant::Decimal4(_), Decimal256(..)) if variant_fits_decimal(value, data_type) => 3,
895 (Variant::Decimal8(_), Decimal64(..)) if variant_fits_decimal(value, data_type) => 0,
896 (Variant::Decimal8(_), Decimal128(..)) if variant_fits_decimal(value, data_type) => 1,
897 (Variant::Decimal8(_), Decimal256(..)) if variant_fits_decimal(value, data_type) => 2,
898 (Variant::Decimal16(_), Decimal128(..)) if variant_fits_decimal(value, data_type) => 0,
899 (Variant::Decimal16(_), Decimal256(..)) if variant_fits_decimal(value, data_type) => 1,
900 (Variant::Date(_), Date32) => 0,
901 (Variant::Date(_), Date64) => 1,
902 (Variant::TimestampMicros(_), Timestamp(TimeUnit::Microsecond, Some(_))) => 0,
903 (Variant::TimestampMicros(_), Timestamp(TimeUnit::Nanosecond, Some(_))) => 1,
904 (Variant::TimestampNanos(_), Timestamp(TimeUnit::Nanosecond, Some(_))) => 0,
905 (Variant::TimestampNtzMicros(_), Timestamp(TimeUnit::Microsecond, None)) => 0,
906 (Variant::TimestampNtzMicros(_), Timestamp(TimeUnit::Nanosecond, None)) => 1,
907 (Variant::TimestampNtzNanos(_), Timestamp(TimeUnit::Nanosecond, None)) => 0,
908 (Variant::Time(_), Time64(TimeUnit::Microsecond)) => 0,
909 (Variant::Time(_), Time64(TimeUnit::Nanosecond)) => 1,
910 (Variant::String(_) | Variant::ShortString(_), Utf8 | LargeUtf8 | Utf8View) => 0,
911 (Variant::Binary(_), Binary | LargeBinary | BinaryView) => 0,
912 (Variant::Uuid(_), FixedSizeBinary(16)) => 0,
913 (Variant::Object(_), Struct(_)) => 0,
914 (Variant::Object(_), Map(..)) => 1,
915 (Variant::List(_), List(_)) => 0,
916 (Variant::List(list), FixedSizeList(_, size)) if list.len() == *size as usize => 0,
917 (Variant::List(_), LargeList(_)) => 1,
918 (Variant::List(_), ListView(_)) => 2,
919 (Variant::List(_), LargeListView(_)) => 3,
920 _ => return None,
921 };
922 Some(rank)
923}
924
925fn variant_fits_decimal(value: &Variant<'_, '_>, data_type: &DataType) -> bool {
926 match data_type {
927 DataType::Decimal32(precision, scale) => {
928 variant_to_unscaled_decimal::<datatypes::Decimal32Type>(value, *precision, *scale)
929 .is_some()
930 }
931 DataType::Decimal64(precision, scale) => {
932 variant_to_unscaled_decimal::<datatypes::Decimal64Type>(value, *precision, *scale)
933 .is_some()
934 }
935 DataType::Decimal128(precision, scale) => {
936 variant_to_unscaled_decimal::<datatypes::Decimal128Type>(value, *precision, *scale)
937 .is_some()
938 }
939 DataType::Decimal256(precision, scale) => {
940 variant_to_unscaled_decimal::<datatypes::Decimal256Type>(value, *precision, *scale)
941 .is_some()
942 }
943 _ => false,
944 }
945}
946
947pub(crate) struct MapVariantToArrowRowBuilder<'a> {
953 entries_field: &'a FieldRef,
954 key_field: &'a FieldRef,
955 value_field: &'a FieldRef,
956 ordered: bool,
957 key_builder: Box<VariantToArrowRowBuilder<'a>>,
958 value_builder: Box<VariantToArrowRowBuilder<'a>>,
959 offsets: Vec<i32>,
960 current_offset: i32,
961 nulls: NullBufferBuilder,
962 cast_options: &'a CastOptions<'a>,
963}
964
965impl<'a> MapVariantToArrowRowBuilder<'a> {
966 fn try_new(
967 entries_field: &'a FieldRef,
968 ordered: bool,
969 cast_options: &'a CastOptions,
970 capacity: usize,
971 cast_mode: VariantCastMode,
972 ) -> Result<Self> {
973 let DataType::Struct(entry_fields) = entries_field.data_type() else {
974 return Err(ArrowError::InvalidArgumentError(format!(
975 "Map entries must be Struct, got {:?}",
976 entries_field.data_type()
977 )));
978 };
979 let (key_field, value_field) = match entry_fields.as_ref() {
980 [key_field, value_field] => (key_field, value_field),
981 fields => {
982 return Err(ArrowError::InvalidArgumentError(format!(
983 "Map entries must have exactly two fields (key, value), got {}",
984 fields.len()
985 )));
986 }
987 };
988 let key_builder = Box::new(make_typed_variant_to_arrow_row_builder(
989 key_field.data_type(),
990 cast_options,
991 capacity,
992 cast_mode,
993 )?);
994 let value_builder = Box::new(make_typed_variant_to_arrow_row_builder(
995 value_field.data_type(),
996 cast_options,
997 capacity,
998 cast_mode,
999 )?);
1000 if capacity >= isize::MAX as usize {
1001 return Err(ArrowError::ComputeError(
1002 "Capacity exceeds isize::MAX when reserving map offsets".to_string(),
1003 ));
1004 }
1005 let mut offsets = Vec::with_capacity(capacity + 1);
1006 offsets.push(0);
1007 Ok(Self {
1008 entries_field,
1009 key_field,
1010 value_field,
1011 ordered,
1012 key_builder,
1013 value_builder,
1014 offsets,
1015 current_offset: 0,
1016 nulls: NullBufferBuilder::new(capacity),
1017 cast_options,
1018 })
1019 }
1020
1021 fn append_null(&mut self) -> Result<()> {
1022 self.offsets.push(self.current_offset);
1023 self.nulls.append_null();
1024 Ok(())
1025 }
1026
1027 fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
1028 match variant_cast_with_options(value, self.cast_options, Variant::as_object) {
1029 Ok(Some(obj)) => {
1030 for (key, field_value) in obj.iter() {
1031 if !self.key_builder.append_value(Variant::from(key))? {
1034 return Err(ArrowError::CastError(format!(
1035 "Failed to cast map key {key:?} to {:?}",
1036 self.key_field.data_type()
1037 )));
1038 }
1039 self.value_builder.append_value(field_value)?;
1040 self.current_offset = self.current_offset.add_checked(1)?;
1041 }
1042 self.offsets.push(self.current_offset);
1043 self.nulls.append_non_null();
1044 Ok(true)
1045 }
1046 Ok(None) => {
1047 self.append_null()?;
1048 Ok(false)
1049 }
1050 Err(_) => Err(ArrowError::CastError(format!(
1051 "Failed to extract object from variant {value:?}"
1052 ))),
1053 }
1054 }
1055
1056 fn finish(mut self) -> Result<ArrayRef> {
1057 let keys = self.key_builder.finish()?;
1058 let values = self.value_builder.finish()?;
1059
1060 let entry_fields = Fields::from(vec![
1061 self.key_field
1062 .as_ref()
1063 .clone()
1064 .with_data_type(keys.data_type().clone()),
1065 self.value_field
1066 .as_ref()
1067 .clone()
1068 .with_data_type(values.data_type().clone()),
1069 ]);
1070 let entries = StructArray::try_new(entry_fields.clone(), vec![keys, values], None)?;
1071 let entries_field = Arc::new(
1072 self.entries_field
1073 .as_ref()
1074 .clone()
1075 .with_data_type(DataType::Struct(entry_fields)),
1076 );
1077 let map_array = MapArray::try_new(
1078 entries_field,
1079 OffsetBuffer::new(ScalarBuffer::from(self.offsets)),
1080 entries,
1081 self.nulls.finish(),
1082 self.ordered,
1083 )?;
1084 Ok(Arc::new(map_array))
1085 }
1086}
1087
1088impl<'a> ArrayVariantToArrowRowBuilder<'a> {
1089 pub(crate) fn try_new(
1096 data_type: &'a DataType,
1097 cast_options: &'a CastOptions,
1098 capacity: usize,
1099 shredded: bool,
1100 ) -> Result<Self> {
1101 use ArrayVariantToArrowRowBuilder::*;
1102
1103 macro_rules! make_list_builder {
1105 ($variant:ident, $offset:ty, $is_view:expr, $field:ident) => {
1106 $variant(VariantToListArrowRowBuilder::<$offset, $is_view>::try_new(
1107 $field.clone(),
1108 $field.data_type(),
1109 cast_options,
1110 capacity,
1111 shredded,
1112 )?)
1113 };
1114 }
1115
1116 let builder = match data_type {
1117 DataType::List(field) => make_list_builder!(List, i32, false, field),
1118 DataType::LargeList(field) => make_list_builder!(LargeList, i64, false, field),
1119 DataType::ListView(field) => make_list_builder!(ListView, i32, true, field),
1120 DataType::LargeListView(field) => make_list_builder!(LargeListView, i64, true, field),
1121 DataType::FixedSizeList(field, size) => {
1122 FixedSizeList(VariantToFixedSizeListArrowRowBuilder::try_new(
1123 field.clone(),
1124 field.data_type(),
1125 *size,
1126 cast_options,
1127 capacity,
1128 shredded,
1129 )?)
1130 }
1131 other => {
1132 return Err(ArrowError::InvalidArgumentError(format!(
1133 "Casting to {other:?} is not applicable for array Variant types"
1134 )));
1135 }
1136 };
1137 Ok(builder)
1138 }
1139
1140 pub(crate) fn append_null(&mut self) -> Result<()> {
1141 match self {
1142 Self::List(builder) => builder.append_null(),
1143 Self::LargeList(builder) => builder.append_null(),
1144 Self::ListView(builder) => builder.append_null(),
1145 Self::LargeListView(builder) => builder.append_null(),
1146 Self::FixedSizeList(builder) => builder.append_null(),
1147 }
1148 }
1149
1150 pub(crate) fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
1151 match self {
1152 Self::List(builder) => builder.append_value(value),
1153 Self::LargeList(builder) => builder.append_value(value),
1154 Self::ListView(builder) => builder.append_value(value),
1155 Self::LargeListView(builder) => builder.append_value(value),
1156 Self::FixedSizeList(builder) => builder.append_value(value),
1157 }
1158 }
1159
1160 pub(crate) fn finish(self) -> Result<ArrayRef> {
1161 match self {
1162 Self::List(builder) => builder.finish(),
1163 Self::LargeList(builder) => builder.finish(),
1164 Self::ListView(builder) => builder.finish(),
1165 Self::LargeListView(builder) => builder.finish(),
1166 Self::FixedSizeList(builder) => builder.finish(),
1167 }
1168 }
1169}
1170
1171pub(crate) struct VariantPathRowBuilder<'a> {
1174 builder: Box<VariantToArrowRowBuilder<'a>>,
1175 path: VariantPath<'a>,
1176}
1177
1178impl VariantPathRowBuilder<'_> {
1179 fn append_null(&mut self) -> Result<()> {
1180 self.builder.append_null()
1181 }
1182
1183 fn append_value(&mut self, value: Variant<'_, '_>) -> Result<bool> {
1184 if let Some(v) = value.get_path(&self.path) {
1185 self.builder.append_value(v)
1186 } else {
1187 self.builder.append_null()?;
1188 Ok(false)
1189 }
1190 }
1191
1192 fn finish(self) -> Result<ArrayRef> {
1193 self.builder.finish()
1194 }
1195}
1196
1197macro_rules! define_variant_to_primitive_builder {
1198 (struct $name:ident<$lifetime:lifetime $(, $generic:ident: $bound:path )?>
1199 |$array_param:ident $(, $field:ident: $field_type:ty)?| -> $builder_name:ident $(< $array_type:ty >)? { $init_expr: expr },
1200 |$value: ident $(, $cast_mode: ident)?| $value_transform:expr,
1201 type_name: $type_name:expr) => {
1202 pub(crate) struct $name<$lifetime $(, $generic : $bound )?>
1203 {
1204 builder: $builder_name $(<$array_type>)?,
1205 $($cast_mode: VariantCastMode,)?
1206 cast_options: &$lifetime CastOptions<$lifetime>,
1207 }
1208
1209 impl<$lifetime $(, $generic: $bound+ )?> $name<$lifetime $(, $generic )?> {
1210 fn new(
1211 cast_options: &$lifetime CastOptions<$lifetime>,
1212 $array_param: usize,
1213 $($cast_mode: VariantCastMode,)?
1214 $( $field: $field_type, )?
1216 ) -> Self {
1217 Self {
1218 builder: $init_expr,
1219 cast_options,
1220 $($cast_mode)?
1221 }
1222 }
1223
1224 fn append_null(&mut self) -> Result<()> {
1225 self.builder.append_null();
1226 Ok(())
1227 }
1228
1229 fn append_value(&mut self, $value: &Variant<'_, '_>) -> Result<bool> {
1230 $(let $cast_mode: VariantCastMode = self.cast_mode;)?
1231 match variant_cast_with_options(
1232 $value,
1233 self.cast_options,
1234 |$value| $value_transform,
1235 ) {
1236 Ok(Some(v)) => {
1237 self.builder.append_value(v);
1238 Ok(true)
1239 }
1240 Ok(None) => {
1241 self.builder.append_null();
1242 Ok(false)
1243 }
1244 Err(_) => Err(ArrowError::CastError(format!(
1245 "Failed to extract primitive of type {type_name} from variant {value:?} at path VariantPath([])",
1246 type_name = $type_name,
1247 value = $value
1248 ))),
1249 }
1250 }
1251
1252 #[expect(clippy::allow_attributes)]
1255 #[allow(unused_mut)]
1256 fn finish(mut self) -> Result<ArrayRef> {
1257 Ok(Arc::from(self.builder.finish()))
1261 }
1262 }
1263 }
1264}
1265
1266define_variant_to_primitive_builder!(
1267 struct VariantToStringArrowBuilder<'a, B: StringLikeArrayBuilder>
1268 |capacity| -> B { B::with_capacity(capacity) },
1269 |value| value.as_string(),
1270 type_name: B::type_name()
1271);
1272
1273define_variant_to_primitive_builder!(
1274 struct VariantToBooleanArrowRowBuilder<'a>
1275 |capacity| -> BooleanBuilder { BooleanBuilder::with_capacity(capacity) },
1276 |value, cast_mode| variant_to_boolean(value, cast_mode),
1277 type_name: datatypes::BooleanType::DATA_TYPE
1278);
1279
1280define_variant_to_primitive_builder!(
1281 struct VariantToPrimitiveArrowRowBuilder<'a, T:PrimitiveFromVariant>
1282 |capacity| -> PrimitiveBuilder<T> { PrimitiveBuilder::<T>::with_capacity(capacity) },
1283 |value, cast_mode| T::from_variant(value, cast_mode),
1284 type_name: T::DATA_TYPE
1285);
1286
1287define_variant_to_primitive_builder!(
1288 struct VariantToTimestampNtzArrowRowBuilder<'a, T:TimestampFromVariant<true>>
1289 |capacity| -> PrimitiveBuilder<T> { PrimitiveBuilder::<T>::with_capacity(capacity) },
1290 |value, cast_mode| T::from_variant(value, cast_mode),
1291 type_name: T::DATA_TYPE
1292);
1293
1294define_variant_to_primitive_builder!(
1295 struct VariantToTimestampArrowRowBuilder<'a, T:TimestampFromVariant<false>>
1296 |capacity, tz: Option<Arc<str>> | -> PrimitiveBuilder<T> {
1297 PrimitiveBuilder::<T>::with_capacity(capacity).with_timezone_opt(tz)
1298 },
1299 |value, cast_mode| T::from_variant(value, cast_mode),
1300 type_name: T::DATA_TYPE
1301);
1302
1303define_variant_to_primitive_builder!(
1304 struct VariantToBinaryArrowRowBuilder<'a, B: BinaryLikeArrayBuilder>
1305 |capacity| -> B { B::with_capacity(capacity) },
1306 |value| value.as_u8_slice(),
1307 type_name: B::type_name()
1308);
1309
1310pub(crate) struct VariantToDecimalArrowRowBuilder<'a, T>
1312where
1313 T: DecimalType,
1314 T::Native: DecimalCast,
1315{
1316 builder: PrimitiveBuilder<T>,
1317 cast_options: &'a CastOptions<'a>,
1318 precision: u8,
1319 scale: i8,
1320 cast_mode: VariantCastMode,
1321}
1322
1323impl<'a, T> VariantToDecimalArrowRowBuilder<'a, T>
1324where
1325 T: ShredDecimalVariant,
1326 T::Native: DecimalCast,
1327{
1328 fn new(
1329 cast_options: &'a CastOptions<'a>,
1330 capacity: usize,
1331 precision: u8,
1332 scale: i8,
1333 cast_mode: VariantCastMode,
1334 ) -> Result<Self> {
1335 let builder = PrimitiveBuilder::<T>::with_capacity(capacity)
1336 .with_precision_and_scale(precision, scale)?;
1337 Ok(Self {
1338 builder,
1339 cast_options,
1340 precision,
1341 scale,
1342 cast_mode,
1343 })
1344 }
1345
1346 fn append_null(&mut self) -> Result<()> {
1347 self.builder.append_null();
1348 Ok(())
1349 }
1350
1351 fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
1352 match variant_cast_with_options(value, self.cast_options, |value| match self.cast_mode {
1353 VariantCastMode::Shred => {
1354 shred_variant_to_unscaled_decimal::<T>(value, self.precision, self.scale)
1355 }
1356 VariantCastMode::Get => {
1357 variant_to_unscaled_decimal::<T>(value, self.precision, self.scale)
1358 }
1359 }) {
1360 Ok(Some(scaled)) => {
1361 self.builder.append_value(scaled);
1362 Ok(true)
1363 }
1364 Ok(None) => {
1365 self.builder.append_null();
1366 Ok(false)
1367 }
1368 Err(_) => Err(ArrowError::CastError(format!(
1369 "Failed to cast to {prefix}(precision={precision}, scale={scale}) from variant {value:?}",
1370 prefix = T::PREFIX,
1371 precision = self.precision,
1372 scale = self.scale
1373 ))),
1374 }
1375 }
1376
1377 fn finish(mut self) -> Result<ArrayRef> {
1378 Ok(Arc::new(self.builder.finish()))
1379 }
1380}
1381
1382pub(crate) struct VariantToUuidArrowRowBuilder<'a> {
1384 builder: FixedSizeBinaryBuilder,
1385 cast_options: &'a CastOptions<'a>,
1386}
1387
1388impl<'a> VariantToUuidArrowRowBuilder<'a> {
1389 fn new(cast_options: &'a CastOptions<'a>, capacity: usize) -> Self {
1390 Self {
1391 builder: FixedSizeBinaryBuilder::with_capacity(capacity, 16),
1392 cast_options,
1393 }
1394 }
1395
1396 fn append_null(&mut self) -> Result<()> {
1397 self.builder.append_null();
1398 Ok(())
1399 }
1400
1401 fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
1402 match variant_cast_with_options(value, self.cast_options, Variant::as_uuid) {
1403 Ok(Some(uuid)) => {
1404 self.builder
1405 .append_value(uuid.as_bytes())
1406 .map_err(|e| ArrowError::ExternalError(Box::new(e)))?;
1407 Ok(true)
1408 }
1409 Ok(None) => {
1410 self.builder.append_null();
1411 Ok(false)
1412 }
1413 Err(_) => Err(ArrowError::CastError(format!(
1414 "Failed to extract UUID from variant {value:?}"
1415 ))),
1416 }
1417 }
1418
1419 fn finish(mut self) -> Result<ArrayRef> {
1420 Ok(Arc::new(self.builder.finish()))
1421 }
1422}
1423
1424enum ListElementBuilder<'a> {
1427 Typed(Box<VariantToArrowRowBuilder<'a>>),
1429 Shredded(Box<VariantToShreddedVariantRowBuilder<'a>>),
1431}
1432
1433impl ListElementBuilder<'_> {
1434 fn append_null(&mut self) -> Result<()> {
1435 match self {
1436 Self::Typed(b) => b.append_null(),
1437 Self::Shredded(b) => b.append_null(),
1438 }
1439 }
1440
1441 fn append_value(&mut self, value: Variant<'_, '_>) -> Result<bool> {
1442 match self {
1443 Self::Typed(b) => b.append_value(value),
1444 Self::Shredded(b) => b.append_value(value),
1445 }
1446 }
1447
1448 fn finish(self) -> Result<ArrayRef> {
1449 match self {
1450 Self::Typed(b) => b.finish(),
1451 Self::Shredded(b) => {
1452 let (value, typed_value, nulls) = b.finish()?;
1453 Ok(ArrayRef::from(ShreddedVariantFieldArray::from_parts(
1454 Arc::new(value),
1455 Some(typed_value),
1456 nulls,
1457 )))
1458 }
1459 }
1460 }
1461}
1462
1463pub(crate) struct VariantToListArrowRowBuilder<'a, O, const IS_VIEW: bool>
1464where
1465 O: OffsetSizeTrait + ArrowNativeTypeOp,
1466{
1467 field: FieldRef,
1468 offsets: Vec<O>,
1469 element_builder: ListElementBuilder<'a>,
1470 nulls: NullBufferBuilder,
1471 current_offset: O,
1472 cast_options: &'a CastOptions<'a>,
1473}
1474
1475impl<'a, O, const IS_VIEW: bool> VariantToListArrowRowBuilder<'a, O, IS_VIEW>
1476where
1477 O: OffsetSizeTrait + ArrowNativeTypeOp,
1478{
1479 fn try_new(
1480 field: FieldRef,
1481 element_data_type: &'a DataType,
1482 cast_options: &'a CastOptions,
1483 capacity: usize,
1484 shredded: bool,
1485 ) -> Result<Self> {
1486 if capacity >= isize::MAX as usize {
1487 return Err(ArrowError::ComputeError(
1488 "Capacity exceeds isize::MAX when reserving list offsets".to_string(),
1489 ));
1490 }
1491 let mut offsets = Vec::with_capacity(capacity + 1);
1492 offsets.push(O::ZERO);
1493 let element_builder = if shredded {
1494 let builder = make_variant_to_shredded_variant_arrow_row_builder(
1495 element_data_type,
1496 cast_options,
1497 capacity,
1498 NullValue::ArrayElement,
1499 VariantCastMode::Shred,
1500 )?;
1501 ListElementBuilder::Shredded(Box::new(builder))
1502 } else {
1503 let builder = make_typed_variant_to_arrow_row_builder(
1504 element_data_type,
1505 cast_options,
1506 capacity,
1507 VariantCastMode::Get,
1508 )?;
1509 ListElementBuilder::Typed(Box::new(builder))
1510 };
1511
1512 Ok(Self {
1513 field,
1514 offsets,
1515 element_builder,
1516 nulls: NullBufferBuilder::new(capacity),
1517 current_offset: O::ZERO,
1518 cast_options,
1519 })
1520 }
1521
1522 fn append_null(&mut self) -> Result<()> {
1523 self.offsets.push(self.current_offset);
1524 self.nulls.append_null();
1525 Ok(())
1526 }
1527
1528 fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
1529 match variant_cast_with_options(value, self.cast_options, Variant::as_list) {
1530 Ok(Some(list)) => {
1531 for element in list.iter() {
1532 self.element_builder.append_value(element)?;
1533 self.current_offset = self.current_offset.add_checked(O::ONE)?;
1534 }
1535 self.offsets.push(self.current_offset);
1536 self.nulls.append_non_null();
1537 Ok(true)
1538 }
1539 Ok(None) => {
1540 self.append_null()?;
1541 Ok(false)
1542 }
1543 Err(_) => Err(ArrowError::CastError(format!(
1544 "Failed to extract list from variant {value:?}"
1545 ))),
1546 }
1547 }
1548
1549 fn finish(mut self) -> Result<ArrayRef> {
1550 let element_array: ArrayRef = self.element_builder.finish()?;
1551 let field = Arc::new(
1552 self.field
1553 .as_ref()
1554 .clone()
1555 .with_data_type(element_array.data_type().clone()),
1556 );
1557
1558 if IS_VIEW {
1559 let mut sizes = Vec::with_capacity(self.offsets.len() - 1);
1561 for i in 1..self.offsets.len() {
1562 sizes.push(self.offsets[i] - self.offsets[i - 1]);
1563 }
1564 self.offsets.pop();
1565 let list_view_array = GenericListViewArray::<O>::try_new(
1566 field,
1567 ScalarBuffer::from(self.offsets),
1568 ScalarBuffer::from(sizes),
1569 element_array,
1570 self.nulls.finish(),
1571 )?;
1572 Ok(Arc::new(list_view_array))
1573 } else {
1574 let list_array = GenericListArray::<O>::try_new(
1575 field,
1576 OffsetBuffer::<O>::new(ScalarBuffer::from(self.offsets)),
1577 element_array,
1578 self.nulls.finish(),
1579 )?;
1580 Ok(Arc::new(list_array))
1581 }
1582 }
1583}
1584
1585pub(crate) struct VariantToFixedSizeListArrowRowBuilder<'a> {
1586 field: FieldRef,
1587 list_size: i32,
1588 element_builder: ListElementBuilder<'a>,
1589 nulls: NullBufferBuilder,
1590 cast_options: &'a CastOptions<'a>,
1591 shredded: bool,
1592}
1593
1594impl<'a> VariantToFixedSizeListArrowRowBuilder<'a> {
1595 fn try_new(
1596 field: FieldRef,
1597 element_data_type: &'a DataType,
1598 list_size: i32,
1599 cast_options: &'a CastOptions,
1600 capacity: usize,
1601 shredded: bool,
1602 ) -> Result<Self> {
1603 let element_builder = if shredded {
1604 let builder = make_variant_to_shredded_variant_arrow_row_builder(
1605 element_data_type,
1606 cast_options,
1607 capacity,
1608 NullValue::ArrayElement,
1609 VariantCastMode::Shred,
1610 )?;
1611 ListElementBuilder::Shredded(Box::new(builder))
1612 } else {
1613 let builder = make_typed_variant_to_arrow_row_builder(
1614 element_data_type,
1615 cast_options,
1616 capacity,
1617 VariantCastMode::Get,
1618 )?;
1619 ListElementBuilder::Typed(Box::new(builder))
1620 };
1621 Ok(Self {
1622 field,
1623 list_size,
1624 element_builder,
1625 nulls: NullBufferBuilder::new(capacity),
1626 cast_options,
1627 shredded,
1628 })
1629 }
1630
1631 fn append_null(&mut self) -> Result<()> {
1632 for _ in 0..self.list_size {
1633 self.element_builder.append_null()?;
1634 }
1635 self.nulls.append_null();
1636 Ok(())
1637 }
1638
1639 fn append_value(&mut self, value: &Variant<'_, '_>) -> Result<bool> {
1640 match variant_cast_with_options(value, self.cast_options, Variant::as_list) {
1641 Ok(Some(list)) => {
1642 let len = list.len();
1643 if len != self.list_size as usize {
1644 if self.cast_options.safe && !self.shredded {
1645 self.append_null()?;
1646 return Ok(false);
1647 }
1648 return Err(ArrowError::CastError(format!(
1649 "Expected fixed size list of size {}, got size {}",
1650 self.list_size, len
1651 )));
1652 }
1653 for element in list.iter() {
1654 self.element_builder.append_value(element)?;
1655 }
1656 self.nulls.append_non_null();
1657 Ok(true)
1658 }
1659 Ok(None) => {
1660 self.append_null()?;
1661 Ok(false)
1662 }
1663 Err(_) => Err(ArrowError::CastError(format!(
1664 "Failed to extract list from variant {value:?}"
1665 ))),
1666 }
1667 }
1668
1669 fn finish(mut self) -> Result<ArrayRef> {
1670 let element_array: ArrayRef = self.element_builder.finish()?;
1671 let field = Arc::new(
1672 self.field
1673 .as_ref()
1674 .clone()
1675 .with_data_type(element_array.data_type().clone()),
1676 );
1677 let fixed_size_list_array =
1678 FixedSizeListArray::try_new(field, self.list_size, element_array, self.nulls.finish())?;
1679 Ok(Arc::new(fixed_size_list_array))
1680 }
1681}
1682
1683pub(crate) struct VariantToBinaryVariantArrowRowBuilder {
1685 metadata: ArrayRef,
1686 builder: VariantValueArrayBuilder,
1687 nulls: NullBufferBuilder,
1688}
1689
1690impl VariantToBinaryVariantArrowRowBuilder {
1691 fn new(metadata: ArrayRef, capacity: usize) -> Self {
1692 Self {
1693 metadata,
1694 builder: VariantValueArrayBuilder::new(capacity),
1695 nulls: NullBufferBuilder::new(capacity),
1696 }
1697 }
1698}
1699
1700impl VariantToBinaryVariantArrowRowBuilder {
1701 fn append_null(&mut self) -> Result<()> {
1702 self.builder.append_null();
1703 self.nulls.append_null();
1704 Ok(())
1705 }
1706
1707 fn append_value(&mut self, value: Variant<'_, '_>) -> Result<bool> {
1708 self.builder.append_value(value);
1709 self.nulls.append_non_null();
1710 Ok(true)
1711 }
1712
1713 fn finish(mut self) -> Result<ArrayRef> {
1714 let variant_array = VariantArray::from_parts_unshredded(
1717 self.metadata,
1718 Arc::new(self.builder.build()?),
1719 self.nulls.finish(),
1720 );
1721
1722 Ok(ArrayRef::from(variant_array))
1723 }
1724}
1725
1726#[derive(Default)]
1727struct FakeNullBuilder {
1728 item_count: usize,
1729}
1730
1731impl FakeNullBuilder {
1732 fn append_value(&mut self, (): ()) {
1733 self.item_count += 1;
1734 }
1735
1736 fn append_null(&mut self) {
1737 self.item_count += 1;
1738 }
1739
1740 fn finish(self) -> NullArray {
1741 NullArray::new(self.item_count)
1742 }
1743}
1744
1745define_variant_to_primitive_builder!(
1746 struct VariantToNullArrowRowBuilder<'a>
1747 |_capacity| -> FakeNullBuilder { FakeNullBuilder::default() },
1748 |value| value.as_null(),
1749 type_name: "Null"
1750);
1751
1752#[cfg(test)]
1753mod tests {
1754 use super::{
1755 make_primitive_variant_to_arrow_row_builder, make_typed_variant_to_arrow_row_builder,
1756 };
1757 use crate::type_conversion::VariantCastMode;
1758 use arrow::array::{
1759 Array, Decimal32Array, FixedSizeBinaryArray, Int32Array, ListArray, StructArray,
1760 };
1761 use arrow::compute::CastOptions;
1762 use arrow::datatypes::{DataType, Field, Fields, UnionFields, UnionMode};
1763 use arrow::error::ArrowError;
1764 use parquet_variant::{Variant, VariantDecimal4};
1765 use std::sync::Arc;
1766 use uuid::Uuid;
1767
1768 #[test]
1769 fn make_primitive_builder_rejects_non_primitive_types() {
1770 let cast_options = CastOptions::default();
1771 let item_field = Arc::new(Field::new("item", DataType::Int32, true));
1772 let struct_fields = Fields::from(vec![Field::new("child", DataType::Int32, true)]);
1773 let map_entries_field = Arc::new(Field::new(
1774 Field::MAP_ENTRIES_FIELD_DEFAULT_NAME,
1775 DataType::Struct(Fields::from(vec![
1776 Field::new(Field::MAP_KEY_FIELD_DEFAULT_NAME, DataType::Utf8, false),
1777 Field::new(Field::MAP_VALUE_FIELD_DEFAULT_NAME, DataType::Float64, true),
1778 ])),
1779 true,
1780 ));
1781 let union_fields =
1782 UnionFields::try_new(vec![1], vec![Field::new("child", DataType::Int32, true)])
1783 .unwrap();
1784 let run_ends_field = Arc::new(Field::new(
1785 Field::REE_RUN_ENDS_FIELD_DEFAULT_NAME,
1786 DataType::Int32,
1787 false,
1788 ));
1789 let ree_values_field = Arc::new(Field::new(
1790 Field::REE_VALUES_FIELD_DEFAULT_NAME,
1791 DataType::Utf8,
1792 true,
1793 ));
1794
1795 let non_primitive_types = vec![
1796 DataType::List(item_field.clone()),
1797 DataType::LargeList(item_field.clone()),
1798 DataType::ListView(item_field.clone()),
1799 DataType::LargeListView(item_field.clone()),
1800 DataType::FixedSizeList(item_field.clone(), 2),
1801 DataType::Struct(struct_fields.clone()),
1802 DataType::Map(map_entries_field.clone(), false),
1803 DataType::Union(union_fields.clone(), UnionMode::Dense),
1804 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1805 DataType::RunEndEncoded(run_ends_field.clone(), ree_values_field.clone()),
1806 ];
1807
1808 for data_type in non_primitive_types {
1809 let Err(err) = make_primitive_variant_to_arrow_row_builder(
1810 &data_type,
1811 &cast_options,
1812 1,
1813 VariantCastMode::Get,
1814 ) else {
1815 panic!("non-primitive type {data_type:?} should be rejected")
1816 };
1817
1818 match err {
1819 ArrowError::InvalidArgumentError(msg) => {
1820 assert!(msg.contains(&format!("{data_type:?}")));
1821 }
1822 other => panic!("expected InvalidArgumentError, got {other:?}"),
1823 }
1824 }
1825 }
1826
1827 #[test]
1828 fn strict_cast_allows_variant_null_for_primitive_builder() {
1829 let cast_options = CastOptions {
1830 safe: false,
1831 ..Default::default()
1832 };
1833 let mut builder = make_primitive_variant_to_arrow_row_builder(
1834 &DataType::Int32,
1835 &cast_options,
1836 2,
1837 VariantCastMode::Get,
1838 )
1839 .unwrap();
1840
1841 assert!(!builder.append_value(&Variant::Null).unwrap());
1842 assert!(builder.append_value(&Variant::Int32(42)).unwrap());
1843
1844 let array = builder.finish().unwrap();
1845 let int_array = array.as_any().downcast_ref::<Int32Array>().unwrap();
1846 assert!(int_array.is_null(0));
1847 assert_eq!(int_array.value(1), 42);
1848 }
1849
1850 #[test]
1851 fn strict_cast_allows_variant_null_for_decimal_builder() {
1852 let cast_options = CastOptions {
1853 safe: false,
1854 ..Default::default()
1855 };
1856 let mut builder = make_primitive_variant_to_arrow_row_builder(
1857 &DataType::Decimal32(9, 2),
1858 &cast_options,
1859 2,
1860 VariantCastMode::Get,
1861 )
1862 .unwrap();
1863 let decimal_variant: Variant<'_, '_> = VariantDecimal4::try_new(1234, 2).unwrap().into();
1864
1865 assert!(!builder.append_value(&Variant::Null).unwrap());
1866 assert!(builder.append_value(&decimal_variant).unwrap());
1867
1868 let array = builder.finish().unwrap();
1869 let decimal_array = array.as_any().downcast_ref::<Decimal32Array>().unwrap();
1870 assert!(decimal_array.is_null(0));
1871 assert_eq!(decimal_array.value(1), 1234);
1872 }
1873
1874 #[test]
1875 fn strict_cast_allows_variant_null_for_uuid_builder() {
1876 let cast_options = CastOptions {
1877 safe: false,
1878 ..Default::default()
1879 };
1880 let mut builder = make_primitive_variant_to_arrow_row_builder(
1881 &DataType::FixedSizeBinary(16),
1882 &cast_options,
1883 2,
1884 VariantCastMode::Get,
1885 )
1886 .unwrap();
1887 let uuid = Uuid::nil();
1888
1889 assert!(!builder.append_value(&Variant::Null).unwrap());
1890 assert!(builder.append_value(&Variant::Uuid(uuid)).unwrap());
1891
1892 let array = builder.finish().unwrap();
1893 let uuid_array = array
1894 .as_any()
1895 .downcast_ref::<FixedSizeBinaryArray>()
1896 .unwrap();
1897 assert!(uuid_array.is_null(0));
1898 assert_eq!(uuid_array.value(1), uuid.as_bytes());
1899 }
1900
1901 #[test]
1902 fn strict_cast_allows_variant_null_for_list_and_struct_builders() {
1903 let cast_options = CastOptions {
1904 safe: false,
1905 ..Default::default()
1906 };
1907
1908 let list_type = DataType::List(Arc::new(Field::new("item", DataType::Int64, true)));
1909 let mut list_builder = make_typed_variant_to_arrow_row_builder(
1910 &list_type,
1911 &cast_options,
1912 1,
1913 VariantCastMode::Get,
1914 )
1915 .unwrap();
1916 assert!(!list_builder.append_value(Variant::Null).unwrap());
1917 let list_array = list_builder.finish().unwrap();
1918 let list_array = list_array.as_any().downcast_ref::<ListArray>().unwrap();
1919 assert!(list_array.is_null(0));
1920
1921 let struct_type =
1922 DataType::Struct(Fields::from(vec![Field::new("a", DataType::Int32, true)]));
1923 let mut struct_builder = make_typed_variant_to_arrow_row_builder(
1924 &struct_type,
1925 &cast_options,
1926 1,
1927 VariantCastMode::Get,
1928 )
1929 .unwrap();
1930 assert!(!struct_builder.append_value(Variant::Null).unwrap());
1931 let struct_array = struct_builder.finish().unwrap();
1932 let struct_array = struct_array.as_any().downcast_ref::<StructArray>().unwrap();
1933 assert!(struct_array.is_null(0));
1934 }
1935}