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