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