1use std::sync::Arc;
19
20use arrow_array::{
21 Array, ArrayRef, BinaryArray, BinaryViewArray, BooleanArray, Date32Array, Decimal128Array,
22 FixedSizeBinaryArray, FixedSizeListArray, Float32Array, Float64Array, Int32Array, Int64Array,
23 LargeBinaryArray, LargeListArray, LargeStringArray, ListArray, MapArray, StringArray,
24 StructArray, Time64MicrosecondArray, TimestampMicrosecondArray, TimestampNanosecondArray,
25 new_null_array,
26};
27use arrow_buffer::BooleanBuffer;
28use arrow_schema::{DataType, FieldRef, TimeUnit};
29use uuid::Uuid;
30
31use super::get_field_id_from_metadata;
32use crate::error::invalid_data;
33use crate::spec::{
34 ListType, Literal, Map, MapType, NestedField, PartnerAccessor, PrimitiveLiteral, PrimitiveType,
35 SchemaWithPartnerVisitor, Struct, StructType, Type, VariantType, visit_struct_with_partner,
36 visit_type_with_partner,
37};
38use crate::{Error, ErrorKind, Result};
39
40struct ArrowArrayToIcebergStructConverter;
41
42impl SchemaWithPartnerVisitor<ArrayRef> for ArrowArrayToIcebergStructConverter {
43 type T = Vec<Option<Literal>>;
44
45 fn schema(
46 &mut self,
47 _schema: &crate::spec::Schema,
48 _partner: &ArrayRef,
49 value: Vec<Option<Literal>>,
50 ) -> Result<Vec<Option<Literal>>> {
51 Ok(value)
52 }
53
54 fn field(
55 &mut self,
56 field: &crate::spec::NestedFieldRef,
57 _partner: &ArrayRef,
58 value: Vec<Option<Literal>>,
59 ) -> Result<Vec<Option<Literal>>> {
60 if field.required && value.iter().any(Option::is_none) {
62 return Err(invalid_data!("The field is required but has null value")
63 .with_context("field_id", field.id.to_string())
64 .with_context("field_name", &field.name));
65 }
66 Ok(value)
67 }
68
69 fn r#struct(
70 &mut self,
71 _struct: &StructType,
72 array: &ArrayRef,
73 results: Vec<Vec<Option<Literal>>>,
74 ) -> Result<Vec<Option<Literal>>> {
75 let row_len = results.first().map(|column| column.len()).unwrap_or(0);
76 if let Some(col) = results.iter().find(|col| col.len() != row_len) {
77 return Err(
78 invalid_data!("The struct columns have different row length")
79 .with_context("first col length", row_len.to_string())
80 .with_context("actual col length", col.len().to_string()),
81 );
82 }
83
84 let mut struct_literals = Vec::with_capacity(row_len);
85 let mut columns_iters = results
86 .into_iter()
87 .map(|column| column.into_iter())
88 .collect::<Vec<_>>();
89
90 for i in 0..row_len {
91 let mut literals = Vec::with_capacity(columns_iters.len());
92 for column_iter in columns_iters.iter_mut() {
93 literals.push(column_iter.next().unwrap());
94 }
95 if array.is_null(i) {
96 struct_literals.push(None);
97 } else {
98 struct_literals.push(Some(Literal::Struct(Struct::from_iter(literals))));
99 }
100 }
101
102 Ok(struct_literals)
103 }
104
105 fn list(
106 &mut self,
107 list: &ListType,
108 array: &ArrayRef,
109 elements: Vec<Option<Literal>>,
110 ) -> Result<Vec<Option<Literal>>> {
111 if list.element_field.required && elements.iter().any(Option::is_none) {
112 return Err(invalid_data!("The list should not have null value"));
113 }
114 match array.data_type() {
115 DataType::List(_) => {
116 let offset = array
117 .as_any()
118 .downcast_ref::<ListArray>()
119 .ok_or_else(|| invalid_data!("The partner is not a list array"))?
120 .offsets();
121 let mut result = Vec::with_capacity(offset.len() - 1);
123 for i in 0..offset.len() - 1 {
124 let start = offset[i] as usize;
125 let end = offset[i + 1] as usize;
126 result.push(Some(Literal::List(elements[start..end].to_vec())));
127 }
128 Ok(result)
129 }
130 DataType::LargeList(_) => {
131 let offset = array
132 .as_any()
133 .downcast_ref::<LargeListArray>()
134 .ok_or_else(|| invalid_data!("The partner is not a large list array"))?
135 .offsets();
136 let mut result = Vec::with_capacity(offset.len() - 1);
138 for i in 0..offset.len() - 1 {
139 let start = offset[i] as usize;
140 let end = offset[i + 1] as usize;
141 result.push(Some(Literal::List(elements[start..end].to_vec())));
142 }
143 Ok(result)
144 }
145 DataType::FixedSizeList(_, len) => {
146 let mut result = Vec::with_capacity(elements.len() / *len as usize);
147 for i in 0..elements.len() / *len as usize {
148 let start = i * *len as usize;
149 let end = (i + 1) * *len as usize;
150 result.push(Some(Literal::List(elements[start..end].to_vec())));
151 }
152 Ok(result)
153 }
154 _ => Err(invalid_data!("The partner is not a list type")),
155 }
156 }
157
158 fn map(
159 &mut self,
160 _map: &MapType,
161 partner: &ArrayRef,
162 key_values: Vec<Option<Literal>>,
163 values: Vec<Option<Literal>>,
164 ) -> Result<Vec<Option<Literal>>> {
165 if key_values.len() != values.len() {
167 return Err(invalid_data!(
168 "The key value and value of map should have the same row length"
169 ));
170 }
171
172 let offsets = partner
173 .as_any()
174 .downcast_ref::<MapArray>()
175 .ok_or_else(|| invalid_data!("The partner is not a map array"))?
176 .offsets();
177 let mut result = Vec::with_capacity(offsets.len() - 1);
179 for i in 0..offsets.len() - 1 {
180 let start = offsets[i] as usize;
181 let end = offsets[i + 1] as usize;
182 let mut map = Map::new();
183 for (key, value) in key_values[start..end].iter().zip(values[start..end].iter()) {
184 map.insert(key.clone().unwrap(), value.clone());
185 }
186 result.push(Some(Literal::Map(map)));
187 }
188 Ok(result)
189 }
190
191 fn primitive(&mut self, p: &PrimitiveType, partner: &ArrayRef) -> Result<Vec<Option<Literal>>> {
192 match p {
193 PrimitiveType::Unknown => Ok(vec![None; partner.len()]),
194 PrimitiveType::Boolean => {
195 let array = partner
196 .as_any()
197 .downcast_ref::<BooleanArray>()
198 .ok_or_else(|| invalid_data!("The partner is not a boolean array"))?;
199 Ok(array.iter().map(|v| v.map(Literal::bool)).collect())
200 }
201 PrimitiveType::Int => {
202 let array = partner
203 .as_any()
204 .downcast_ref::<Int32Array>()
205 .ok_or_else(|| invalid_data!("The partner is not a int32 array"))?;
206 Ok(array.iter().map(|v| v.map(Literal::int)).collect())
207 }
208 PrimitiveType::Long => {
209 let array = partner
210 .as_any()
211 .downcast_ref::<Int64Array>()
212 .ok_or_else(|| invalid_data!("The partner is not a int64 array"))?;
213 Ok(array.iter().map(|v| v.map(Literal::long)).collect())
214 }
215 PrimitiveType::Float => {
216 let array = partner
217 .as_any()
218 .downcast_ref::<Float32Array>()
219 .ok_or_else(|| invalid_data!("The partner is not a float32 array"))?;
220 Ok(array.iter().map(|v| v.map(Literal::float)).collect())
221 }
222 PrimitiveType::Double => {
223 let array = partner
224 .as_any()
225 .downcast_ref::<Float64Array>()
226 .ok_or_else(|| invalid_data!("The partner is not a float64 array"))?;
227 Ok(array.iter().map(|v| v.map(Literal::double)).collect())
228 }
229 PrimitiveType::Decimal { precision, scale } => {
230 let array = partner
231 .as_any()
232 .downcast_ref::<Decimal128Array>()
233 .ok_or_else(|| invalid_data!("The partner is not a decimal128 array"))?;
234 if let DataType::Decimal128(arrow_precision, arrow_scale) = array.data_type()
235 && (*arrow_precision as u32 != *precision || *arrow_scale as u32 != *scale)
236 {
237 return Err(invalid_data!(
238 "The precision or scale ({arrow_precision},{arrow_scale}) of arrow decimal128 array is not compatible with iceberg decimal type ({precision},{scale})"
239 ));
240 }
241 Ok(array.iter().map(|v| v.map(Literal::decimal)).collect())
242 }
243 PrimitiveType::Date => {
244 let array = partner
245 .as_any()
246 .downcast_ref::<Date32Array>()
247 .ok_or_else(|| invalid_data!("The partner is not a date32 array"))?;
248 Ok(array.iter().map(|v| v.map(Literal::date)).collect())
249 }
250 PrimitiveType::Time => {
251 let array = partner
252 .as_any()
253 .downcast_ref::<Time64MicrosecondArray>()
254 .ok_or_else(|| invalid_data!("The partner is not a time64 array"))?;
255 Ok(array.iter().map(|v| v.map(Literal::time)).collect())
256 }
257 PrimitiveType::Timestamp => {
258 let array = partner
259 .as_any()
260 .downcast_ref::<TimestampMicrosecondArray>()
261 .ok_or_else(|| invalid_data!("The partner is not a timestamp array"))?;
262 Ok(array.iter().map(|v| v.map(Literal::timestamp)).collect())
263 }
264 PrimitiveType::Timestamptz => {
265 let array = partner
266 .as_any()
267 .downcast_ref::<TimestampMicrosecondArray>()
268 .ok_or_else(|| invalid_data!("The partner is not a timestamptz array"))?;
269 Ok(array.iter().map(|v| v.map(Literal::timestamptz)).collect())
270 }
271 PrimitiveType::TimestampNs => {
272 let array = partner
273 .as_any()
274 .downcast_ref::<TimestampNanosecondArray>()
275 .ok_or_else(|| invalid_data!("The partner is not a timestamp_ns array"))?;
276 Ok(array
277 .iter()
278 .map(|v| v.map(Literal::timestamp_nano))
279 .collect())
280 }
281 PrimitiveType::TimestamptzNs => {
282 let array = partner
283 .as_any()
284 .downcast_ref::<TimestampNanosecondArray>()
285 .ok_or_else(|| invalid_data!("The partner is not a timestamptz_ns array"))?;
286 Ok(array
287 .iter()
288 .map(|v| v.map(Literal::timestamptz_nano))
289 .collect())
290 }
291 PrimitiveType::String => {
292 if let Some(array) = partner.as_any().downcast_ref::<LargeStringArray>() {
293 Ok(array.iter().map(|v| v.map(Literal::string)).collect())
294 } else if let Some(array) = partner.as_any().downcast_ref::<StringArray>() {
295 Ok(array.iter().map(|v| v.map(Literal::string)).collect())
296 } else {
297 Err(invalid_data!("The partner is not a string array"))
298 }
299 }
300 PrimitiveType::Uuid => {
301 if let Some(array) = partner.as_any().downcast_ref::<FixedSizeBinaryArray>() {
302 if array.value_length() != 16 {
303 return Err(invalid_data!("The partner is not a uuid array"));
304 }
305 Ok(array
306 .iter()
307 .map(|v| {
308 v.map(|v| {
309 Ok(Literal::uuid(Uuid::from_bytes(v.try_into().map_err(
310 |_| invalid_data!("Failed to convert binary to uuid"),
311 )?)))
312 })
313 .transpose()
314 })
315 .collect::<Result<Vec<_>>>()?)
316 } else {
317 Err(invalid_data!("The partner is not a uuid array"))
318 }
319 }
320 PrimitiveType::Fixed(len) => {
321 let array = partner
322 .as_any()
323 .downcast_ref::<FixedSizeBinaryArray>()
324 .ok_or_else(|| invalid_data!("The partner is not a fixed array"))?;
325 if array.value_length() != *len as i32 {
326 return Err(invalid_data!(
327 "The length of fixed size binary array is not compatible with iceberg fixed type"
328 ));
329 }
330 Ok(array
331 .iter()
332 .map(|v| v.map(|v| Literal::fixed(v.iter().cloned())))
333 .collect())
334 }
335 PrimitiveType::Binary | PrimitiveType::Geometry(_) | PrimitiveType::Geography(_) => {
336 if let Some(array) = partner.as_any().downcast_ref::<LargeBinaryArray>() {
337 Ok(array
338 .iter()
339 .map(|v| v.map(|v| Literal::binary(v.to_vec())))
340 .collect())
341 } else if let Some(array) = partner.as_any().downcast_ref::<BinaryArray>() {
342 Ok(array
343 .iter()
344 .map(|v| v.map(|v| Literal::binary(v.to_vec())))
345 .collect())
346 } else if let Some(array) = partner.as_any().downcast_ref::<BinaryViewArray>() {
347 Ok(array
348 .iter()
349 .map(|v| v.map(|v| Literal::binary(v.to_vec())))
350 .collect())
351 } else {
352 Err(invalid_data!("The partner is not a binary array"))
353 }
354 }
355 }
356 }
357
358 fn variant(&mut self, _v: &VariantType, _partner: &ArrayRef) -> Result<Vec<Option<Literal>>> {
359 Err(Error::new(
360 ErrorKind::FeatureUnsupported,
361 "Converting variant Arrow array to Iceberg literal is not supported yet",
362 ))
363 }
364}
365
366#[derive(Clone, Copy, Debug)]
377pub enum FieldMatchMode {
378 Id,
380 Name,
382}
383
384impl FieldMatchMode {
385 pub fn match_field(&self, arrow_field: &FieldRef, iceberg_field: &NestedField) -> bool {
387 match self {
388 FieldMatchMode::Id => get_field_id_from_metadata(arrow_field)
389 .map(|id| id == iceberg_field.id)
390 .unwrap_or(false),
391 FieldMatchMode::Name => arrow_field.name() == &iceberg_field.name,
392 }
393 }
394}
395
396pub struct ArrowArrayAccessor {
398 match_mode: FieldMatchMode,
399}
400
401impl ArrowArrayAccessor {
402 pub fn new() -> Self {
404 Self {
405 match_mode: FieldMatchMode::Id,
406 }
407 }
408
409 pub fn new_with_match_mode(match_mode: FieldMatchMode) -> Self {
411 Self { match_mode }
412 }
413}
414
415impl Default for ArrowArrayAccessor {
416 fn default() -> Self {
417 Self::new()
418 }
419}
420
421impl PartnerAccessor<ArrayRef> for ArrowArrayAccessor {
422 fn struct_partner<'a>(&self, schema_partner: &'a ArrayRef) -> Result<&'a ArrayRef> {
423 if !matches!(schema_partner.data_type(), DataType::Struct(_)) {
424 return Err(invalid_data!("The schema partner is not a struct type"));
425 }
426
427 Ok(schema_partner)
428 }
429
430 fn field_partner<'a>(
431 &self,
432 struct_partner: &'a ArrayRef,
433 field: &NestedField,
434 ) -> Result<&'a ArrayRef> {
435 let struct_array = struct_partner
436 .as_any()
437 .downcast_ref::<StructArray>()
438 .ok_or_else(|| {
439 invalid_data!(
440 "The struct partner is not a struct array, partner: {struct_partner:?}"
441 )
442 })?;
443
444 let field_pos = struct_array
445 .fields()
446 .iter()
447 .position(|arrow_field| self.match_mode.match_field(arrow_field, field))
448 .ok_or_else(|| invalid_data!("Field id {} not found in struct array", field.id))?;
449
450 Ok(struct_array.column(field_pos))
451 }
452
453 fn list_element_partner<'a>(&self, list_partner: &'a ArrayRef) -> Result<&'a ArrayRef> {
454 match list_partner.data_type() {
455 DataType::List(_) => {
456 let list_array = list_partner
457 .as_any()
458 .downcast_ref::<ListArray>()
459 .ok_or_else(|| invalid_data!("The list partner is not a list array"))?;
460 Ok(list_array.values())
461 }
462 DataType::LargeList(_) => {
463 let list_array = list_partner
464 .as_any()
465 .downcast_ref::<LargeListArray>()
466 .ok_or_else(|| invalid_data!("The list partner is not a large list array"))?;
467 Ok(list_array.values())
468 }
469 DataType::FixedSizeList(_, _) => {
470 let list_array = list_partner
471 .as_any()
472 .downcast_ref::<FixedSizeListArray>()
473 .ok_or_else(|| {
474 invalid_data!("The list partner is not a fixed size list array")
475 })?;
476 Ok(list_array.values())
477 }
478 _ => Err(invalid_data!("The list partner is not a list type")),
479 }
480 }
481
482 fn map_key_partner<'a>(&self, map_partner: &'a ArrayRef) -> Result<&'a ArrayRef> {
483 let map_array = map_partner
484 .as_any()
485 .downcast_ref::<MapArray>()
486 .ok_or_else(|| invalid_data!("The map partner is not a map array"))?;
487 Ok(map_array.keys())
488 }
489
490 fn map_value_partner<'a>(&self, map_partner: &'a ArrayRef) -> Result<&'a ArrayRef> {
491 let map_array = map_partner
492 .as_any()
493 .downcast_ref::<MapArray>()
494 .ok_or_else(|| invalid_data!("The map partner is not a map array"))?;
495 Ok(map_array.values())
496 }
497}
498
499pub fn arrow_struct_to_literal(
502 struct_array: &ArrayRef,
503 ty: &StructType,
504) -> Result<Vec<Option<Literal>>> {
505 visit_struct_with_partner(
506 ty,
507 struct_array,
508 &mut ArrowArrayToIcebergStructConverter,
509 &ArrowArrayAccessor::new(),
510 )
511}
512
513pub fn arrow_primitive_to_literal(
516 primitive_array: &ArrayRef,
517 ty: &Type,
518) -> Result<Vec<Option<Literal>>> {
519 visit_type_with_partner(
520 ty,
521 primitive_array,
522 &mut ArrowArrayToIcebergStructConverter,
523 &ArrowArrayAccessor::new(),
524 )
525}
526
527pub(crate) fn create_primitive_array_single_element(
532 data_type: &DataType,
533 prim_lit: Option<&PrimitiveLiteral>,
534) -> Result<ArrayRef> {
535 if prim_lit.is_none() {
537 return Ok(new_null_array(data_type, 1));
538 }
539 match (data_type, prim_lit) {
540 (DataType::Boolean, Some(PrimitiveLiteral::Boolean(v))) => {
541 Ok(Arc::new(BooleanArray::from(vec![*v])))
542 }
543 (DataType::Int32, Some(PrimitiveLiteral::Int(v))) => {
544 Ok(Arc::new(Int32Array::from(vec![*v])))
545 }
546 (DataType::Date32, Some(PrimitiveLiteral::Int(v))) => {
547 Ok(Arc::new(Date32Array::from(vec![*v])))
548 }
549 (DataType::Int64, Some(PrimitiveLiteral::Long(v))) => {
550 Ok(Arc::new(Int64Array::from(vec![*v])))
551 }
552 (DataType::Timestamp(TimeUnit::Microsecond, timezone), Some(PrimitiveLiteral::Long(v))) => {
553 let array = TimestampMicrosecondArray::from(vec![*v]);
554 if let Some(timezone) = timezone {
555 Ok(Arc::new(array.with_timezone(timezone.clone())))
556 } else {
557 Ok(Arc::new(array))
558 }
559 }
560 (DataType::Timestamp(TimeUnit::Nanosecond, timezone), Some(PrimitiveLiteral::Long(v))) => {
561 let array = TimestampNanosecondArray::from(vec![*v]);
562 if let Some(timezone) = timezone {
563 Ok(Arc::new(array.with_timezone(timezone.clone())))
564 } else {
565 Ok(Arc::new(array))
566 }
567 }
568 (DataType::Float32, Some(PrimitiveLiteral::Float(v))) => {
569 Ok(Arc::new(Float32Array::from(vec![v.0])))
570 }
571 (DataType::Float64, Some(PrimitiveLiteral::Double(v))) => {
572 Ok(Arc::new(Float64Array::from(vec![v.0])))
573 }
574 (DataType::Utf8, Some(PrimitiveLiteral::String(v))) => {
575 Ok(Arc::new(StringArray::from(vec![v.as_str()])))
576 }
577 (DataType::Binary, Some(PrimitiveLiteral::Binary(v))) => {
578 Ok(Arc::new(BinaryArray::from_vec(vec![v.as_slice()])))
579 }
580 (DataType::LargeBinary, Some(PrimitiveLiteral::Binary(v))) => {
581 Ok(Arc::new(LargeBinaryArray::from_vec(vec![v.as_slice()])))
582 }
583 (DataType::Decimal128(precision, scale), Some(PrimitiveLiteral::Int128(v))) => {
584 let array = Decimal128Array::from(vec![{ *v }])
585 .with_precision_and_scale(*precision, *scale)
586 .map_err(|e| {
587 invalid_data!(
588 "Failed to create Decimal128Array with precision {precision} and scale {scale}: {e}"
589 )
590 })?;
591 Ok(Arc::new(array))
592 }
593 (DataType::Decimal128(precision, scale), Some(PrimitiveLiteral::UInt128(v))) => {
594 let array = Decimal128Array::from(vec![*v as i128])
595 .with_precision_and_scale(*precision, *scale)
596 .map_err(|e| {
597 invalid_data!(
598 "Failed to create Decimal128Array with precision {precision} and scale {scale}: {e}"
599 )
600 })?;
601 Ok(Arc::new(array))
602 }
603 _ => Err(Error::new(
604 ErrorKind::Unexpected,
605 format!("Unsupported constant type combination: {data_type:?} with {prim_lit:?}"),
606 )),
607 }
608}
609
610pub(crate) fn create_primitive_array_repeated(
615 data_type: &DataType,
616 prim_lit: Option<&PrimitiveLiteral>,
617 num_rows: usize,
618) -> Result<ArrayRef> {
619 if prim_lit.is_none() {
621 return Ok(new_null_array(data_type, num_rows));
622 }
623 Ok(match (data_type, prim_lit) {
624 (DataType::Boolean, Some(PrimitiveLiteral::Boolean(value))) => {
626 let buffer = if *value {
627 BooleanBuffer::new_set(num_rows)
628 } else {
629 BooleanBuffer::new_unset(num_rows)
630 };
631 Arc::new(BooleanArray::new(buffer, None))
632 }
633 (DataType::Int32, Some(PrimitiveLiteral::Int(value))) => {
634 Arc::new(Int32Array::from(vec![*value; num_rows]))
635 }
636 (DataType::Date32, Some(PrimitiveLiteral::Int(value))) => {
637 Arc::new(Date32Array::from(vec![*value; num_rows]))
638 }
639 (DataType::Int64, Some(PrimitiveLiteral::Int(value))) => {
640 Arc::new(Int64Array::from(vec![i64::from(*value); num_rows]))
641 }
642 (DataType::Int64, Some(PrimitiveLiteral::Long(value))) => {
643 Arc::new(Int64Array::from(vec![*value; num_rows]))
644 }
645 (
646 DataType::Timestamp(TimeUnit::Microsecond, timezone),
647 Some(PrimitiveLiteral::Long(value)),
648 ) => {
649 let array = TimestampMicrosecondArray::from(vec![*value; num_rows]);
650 if let Some(timezone) = timezone {
651 Arc::new(array.with_timezone(timezone.clone()))
652 } else {
653 Arc::new(array)
654 }
655 }
656 (
657 DataType::Timestamp(TimeUnit::Nanosecond, timezone),
658 Some(PrimitiveLiteral::Long(value)),
659 ) => {
660 let array = TimestampNanosecondArray::from(vec![*value; num_rows]);
661 if let Some(timezone) = timezone {
662 Arc::new(array.with_timezone(timezone.clone()))
663 } else {
664 Arc::new(array)
665 }
666 }
667 (DataType::Float32, Some(PrimitiveLiteral::Float(value))) => {
668 Arc::new(Float32Array::from(vec![value.0; num_rows]))
669 }
670 (DataType::Float64, Some(PrimitiveLiteral::Double(value))) => {
671 Arc::new(Float64Array::from(vec![value.0; num_rows]))
672 }
673 (DataType::Utf8, Some(PrimitiveLiteral::String(value))) => Arc::new(
674 StringArray::from_iter_values(std::iter::repeat_n(value.as_str(), num_rows)),
675 ),
676 (DataType::Binary, Some(PrimitiveLiteral::Binary(value))) => Arc::new(
677 BinaryArray::from_iter_values(std::iter::repeat_n(value.as_slice(), num_rows)),
678 ),
679 (DataType::LargeBinary, Some(PrimitiveLiteral::Binary(value))) => Arc::new(
680 LargeBinaryArray::from_iter_values(std::iter::repeat_n(value.as_slice(), num_rows)),
681 ),
682 (DataType::FixedSizeBinary(len), Some(PrimitiveLiteral::Binary(value))) => {
683 if value.len() != *len as usize {
687 return Err(invalid_data!(
688 "FixedSizeBinary literal length {} does not match declared width {len}",
689 value.len()
690 ));
691 }
692
693 Arc::new(
694 FixedSizeBinaryArray::try_from_iter(std::iter::repeat_n(value.as_slice(), num_rows))
695 .map_err(|e| {
696 invalid_data!("Failed to create FixedSizeBinary({len}) array: {e}")
697 })?,
698 )
699 }
700 (DataType::Time64(TimeUnit::Microsecond), Some(PrimitiveLiteral::Long(value))) => {
701 Arc::new(Time64MicrosecondArray::from(vec![*value; num_rows]))
702 }
703 (DataType::Decimal128(precision, scale), Some(PrimitiveLiteral::Int128(value))) => {
704 Arc::new(
705 Decimal128Array::from(vec![*value; num_rows])
706 .with_precision_and_scale(*precision, *scale)
707 .map_err(|e| {
708 invalid_data!(
709 "Failed to create Decimal128Array with precision {precision} and scale {scale}: {e}"
710 )
711 })?,
712 )
713 }
714 (DataType::Decimal128(precision, scale), Some(PrimitiveLiteral::UInt128(value))) => {
715 Arc::new(
716 Decimal128Array::from(vec![*value as i128; num_rows])
717 .with_precision_and_scale(*precision, *scale)
718 .map_err(|e| {
719 invalid_data!(
720 "Failed to create Decimal128Array with precision {precision} and scale {scale}: {e}"
721 )
722 })?,
723 )
724 }
725
726 (dt, _) => {
727 return Err(Error::new(
728 ErrorKind::Unexpected,
729 format!("unexpected target column type {dt}, prim_lit {prim_lit:?}"),
730 ));
731 }
732 })
733}
734
735#[cfg(test)]
736mod test {
737 use std::collections::HashMap;
738 use std::sync::Arc;
739
740 use arrow_array::builder::{Int32Builder, ListBuilder, MapBuilder, StructBuilder};
741 use arrow_array::{
742 ArrayRef, BinaryArray, BooleanArray, Date32Array, Decimal128Array, Float32Array,
743 Float64Array, Int32Array, Int64Array, StringArray, StructArray, Time64MicrosecondArray,
744 TimestampMicrosecondArray, TimestampNanosecondArray,
745 };
746 use arrow_schema::{DataType, Field, Fields, TimeUnit};
747 use parquet::arrow::PARQUET_FIELD_ID_META_KEY;
748
749 use super::*;
750 use crate::spec::{ListType, Literal, MapType, NestedField, PrimitiveType, StructType, Type};
751
752 #[test]
753 fn test_arrow_struct_to_iceberg_struct() {
754 let bool_array = BooleanArray::from(vec![Some(true), Some(false), None]);
755 let int32_array = Int32Array::from(vec![Some(3), Some(4), None]);
756 let int64_array = Int64Array::from(vec![Some(5), Some(6), None]);
757 let float32_array = Float32Array::from(vec![Some(1.1), Some(2.2), None]);
758 let float64_array = Float64Array::from(vec![Some(3.3), Some(4.4), None]);
759 let decimal_array = Decimal128Array::from(vec![Some(1000), Some(2000), None])
760 .with_precision_and_scale(10, 2)
761 .unwrap();
762 let date_array = Date32Array::from(vec![Some(18628), Some(18629), None]);
763 let time_array = Time64MicrosecondArray::from(vec![Some(123456789), Some(987654321), None]);
764 let timestamp_micro_array = TimestampMicrosecondArray::from(vec![
765 Some(1622548800000000),
766 Some(1622635200000000),
767 None,
768 ]);
769 let timestamp_nano_array = TimestampNanosecondArray::from(vec![
770 Some(1622548800000000000),
771 Some(1622635200000000000),
772 None,
773 ]);
774 let string_array = StringArray::from(vec![Some("a"), Some("b"), None]);
775 let binary_array =
776 BinaryArray::from(vec![Some(b"abc".as_ref()), Some(b"def".as_ref()), None]);
777
778 let struct_array = Arc::new(StructArray::from(vec![
779 (
780 Arc::new(
781 Field::new("bool_field", DataType::Boolean, true).with_metadata(HashMap::from(
782 [(PARQUET_FIELD_ID_META_KEY.to_string(), "0".to_string())],
783 )),
784 ),
785 Arc::new(bool_array) as ArrayRef,
786 ),
787 (
788 Arc::new(
789 Field::new("int32_field", DataType::Int32, true).with_metadata(HashMap::from(
790 [(PARQUET_FIELD_ID_META_KEY.to_string(), "2".to_string())],
791 )),
792 ),
793 Arc::new(int32_array) as ArrayRef,
794 ),
795 (
796 Arc::new(
797 Field::new("int64_field", DataType::Int64, true).with_metadata(HashMap::from(
798 [(PARQUET_FIELD_ID_META_KEY.to_string(), "3".to_string())],
799 )),
800 ),
801 Arc::new(int64_array) as ArrayRef,
802 ),
803 (
804 Arc::new(
805 Field::new("float32_field", DataType::Float32, true).with_metadata(
806 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "4".to_string())]),
807 ),
808 ),
809 Arc::new(float32_array) as ArrayRef,
810 ),
811 (
812 Arc::new(
813 Field::new("float64_field", DataType::Float64, true).with_metadata(
814 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "5".to_string())]),
815 ),
816 ),
817 Arc::new(float64_array) as ArrayRef,
818 ),
819 (
820 Arc::new(
821 Field::new("decimal_field", DataType::Decimal128(10, 2), true).with_metadata(
822 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "6".to_string())]),
823 ),
824 ),
825 Arc::new(decimal_array) as ArrayRef,
826 ),
827 (
828 Arc::new(
829 Field::new("date_field", DataType::Date32, true).with_metadata(HashMap::from(
830 [(PARQUET_FIELD_ID_META_KEY.to_string(), "7".to_string())],
831 )),
832 ),
833 Arc::new(date_array) as ArrayRef,
834 ),
835 (
836 Arc::new(
837 Field::new("time_field", DataType::Time64(TimeUnit::Microsecond), true)
838 .with_metadata(HashMap::from([(
839 PARQUET_FIELD_ID_META_KEY.to_string(),
840 "8".to_string(),
841 )])),
842 ),
843 Arc::new(time_array) as ArrayRef,
844 ),
845 (
846 Arc::new(
847 Field::new(
848 "timestamp_micro_field",
849 DataType::Timestamp(TimeUnit::Microsecond, None),
850 true,
851 )
852 .with_metadata(HashMap::from([(
853 PARQUET_FIELD_ID_META_KEY.to_string(),
854 "9".to_string(),
855 )])),
856 ),
857 Arc::new(timestamp_micro_array) as ArrayRef,
858 ),
859 (
860 Arc::new(
861 Field::new(
862 "timestamp_nano_field",
863 DataType::Timestamp(TimeUnit::Nanosecond, None),
864 true,
865 )
866 .with_metadata(HashMap::from([(
867 PARQUET_FIELD_ID_META_KEY.to_string(),
868 "10".to_string(),
869 )])),
870 ),
871 Arc::new(timestamp_nano_array) as ArrayRef,
872 ),
873 (
874 Arc::new(
875 Field::new("string_field", DataType::Utf8, true).with_metadata(HashMap::from(
876 [(PARQUET_FIELD_ID_META_KEY.to_string(), "11".to_string())],
877 )),
878 ),
879 Arc::new(string_array) as ArrayRef,
880 ),
881 (
882 Arc::new(
883 Field::new("binary_field", DataType::Binary, true).with_metadata(
884 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "12".to_string())]),
885 ),
886 ),
887 Arc::new(binary_array) as ArrayRef,
888 ),
889 ])) as ArrayRef;
890
891 let iceberg_struct_type = StructType::new(vec![
892 Arc::new(NestedField::optional(
893 0,
894 "bool_field",
895 Type::Primitive(PrimitiveType::Boolean),
896 )),
897 Arc::new(NestedField::optional(
898 2,
899 "int32_field",
900 Type::Primitive(PrimitiveType::Int),
901 )),
902 Arc::new(NestedField::optional(
903 3,
904 "int64_field",
905 Type::Primitive(PrimitiveType::Long),
906 )),
907 Arc::new(NestedField::optional(
908 4,
909 "float32_field",
910 Type::Primitive(PrimitiveType::Float),
911 )),
912 Arc::new(NestedField::optional(
913 5,
914 "float64_field",
915 Type::Primitive(PrimitiveType::Double),
916 )),
917 Arc::new(NestedField::optional(
918 6,
919 "decimal_field",
920 Type::Primitive(PrimitiveType::Decimal {
921 precision: 10,
922 scale: 2,
923 }),
924 )),
925 Arc::new(NestedField::optional(
926 7,
927 "date_field",
928 Type::Primitive(PrimitiveType::Date),
929 )),
930 Arc::new(NestedField::optional(
931 8,
932 "time_field",
933 Type::Primitive(PrimitiveType::Time),
934 )),
935 Arc::new(NestedField::optional(
936 9,
937 "timestamp_micro_field",
938 Type::Primitive(PrimitiveType::Timestamp),
939 )),
940 Arc::new(NestedField::optional(
941 10,
942 "timestamp_nao_field",
943 Type::Primitive(PrimitiveType::TimestampNs),
944 )),
945 Arc::new(NestedField::optional(
946 11,
947 "string_field",
948 Type::Primitive(PrimitiveType::String),
949 )),
950 Arc::new(NestedField::optional(
951 12,
952 "binary_field",
953 Type::Primitive(PrimitiveType::Binary),
954 )),
955 ]);
956
957 let result = arrow_struct_to_literal(&struct_array, &iceberg_struct_type).unwrap();
958
959 assert_eq!(result, vec![
960 Some(Literal::Struct(Struct::from_iter(vec![
961 Some(Literal::bool(true)),
962 Some(Literal::int(3)),
963 Some(Literal::long(5)),
964 Some(Literal::float(1.1_f32)),
965 Some(Literal::double(3.3)),
966 Some(Literal::decimal(1000)),
967 Some(Literal::date(18628)),
968 Some(Literal::time(123456789)),
969 Some(Literal::timestamp(1622548800000000)),
970 Some(Literal::timestamp_nano(1622548800000000000)),
971 Some(Literal::string("a".to_string())),
972 Some(Literal::binary(b"abc".to_vec())),
973 ]))),
974 Some(Literal::Struct(Struct::from_iter(vec![
975 Some(Literal::bool(false)),
976 Some(Literal::int(4)),
977 Some(Literal::long(6)),
978 Some(Literal::float(2.2_f32)),
979 Some(Literal::double(4.4)),
980 Some(Literal::decimal(2000)),
981 Some(Literal::date(18629)),
982 Some(Literal::time(987654321)),
983 Some(Literal::timestamp(1622635200000000)),
984 Some(Literal::timestamp_nano(1622635200000000000)),
985 Some(Literal::string("b".to_string())),
986 Some(Literal::binary(b"def".to_vec())),
987 ]))),
988 Some(Literal::Struct(Struct::from_iter(vec![
989 None, None, None, None, None, None, None, None, None, None, None, None,
990 ]))),
991 ]);
992 }
993
994 #[test]
995 fn test_nullable_struct() {
996 let struct_array = {
1003 let mut builder = StructBuilder::from_fields(
1004 Fields::from(vec![
1005 Field::new("a", DataType::Int32, true).with_metadata(HashMap::from([(
1006 PARQUET_FIELD_ID_META_KEY.to_string(),
1007 "0".to_string(),
1008 )])),
1009 Field::new("b", DataType::Int32, true).with_metadata(HashMap::from([(
1010 PARQUET_FIELD_ID_META_KEY.to_string(),
1011 "1".to_string(),
1012 )])),
1013 ]),
1014 3,
1015 );
1016 builder
1017 .field_builder::<Int32Builder>(0)
1018 .unwrap()
1019 .append_null();
1020 builder
1021 .field_builder::<Int32Builder>(1)
1022 .unwrap()
1023 .append_null();
1024 builder.append(true);
1025
1026 builder
1027 .field_builder::<Int32Builder>(0)
1028 .unwrap()
1029 .append_value(1);
1030 builder
1031 .field_builder::<Int32Builder>(1)
1032 .unwrap()
1033 .append_null();
1034 builder.append(true);
1035
1036 builder
1037 .field_builder::<Int32Builder>(0)
1038 .unwrap()
1039 .append_value(1);
1040 builder
1041 .field_builder::<Int32Builder>(1)
1042 .unwrap()
1043 .append_value(1);
1044 builder.append_null();
1045
1046 Arc::new(builder.finish()) as ArrayRef
1047 };
1048
1049 let iceberg_struct_type = StructType::new(vec![
1050 Arc::new(NestedField::optional(
1051 0,
1052 "a",
1053 Type::Primitive(PrimitiveType::Int),
1054 )),
1055 Arc::new(NestedField::optional(
1056 1,
1057 "b",
1058 Type::Primitive(PrimitiveType::Int),
1059 )),
1060 ]);
1061
1062 let result = arrow_struct_to_literal(&struct_array, &iceberg_struct_type).unwrap();
1063 assert_eq!(result, vec![
1064 Some(Literal::Struct(Struct::from_iter(vec![None, None,]))),
1065 Some(Literal::Struct(Struct::from_iter(vec![
1066 Some(Literal::int(1)),
1067 None,
1068 ]))),
1069 None,
1070 ]);
1071 }
1072
1073 #[test]
1074 fn test_empty_struct() {
1075 let struct_array = Arc::new(StructArray::new_null(Fields::empty(), 3)) as ArrayRef;
1076 let iceberg_struct_type = StructType::new(vec![]);
1077 let result = arrow_struct_to_literal(&struct_array, &iceberg_struct_type).unwrap();
1078 assert_eq!(result, vec![None; 0]);
1079 }
1080
1081 #[test]
1082 fn test_arrow_variant_to_literal_is_unsupported() {
1083 let variant_child = Arc::new(StructArray::from(vec![
1086 (
1087 Arc::new(Field::new("metadata", DataType::Binary, false)),
1088 Arc::new(BinaryArray::from(vec![Some(b"m".as_ref())])) as ArrayRef,
1089 ),
1090 (
1091 Arc::new(Field::new("value", DataType::Binary, false)),
1092 Arc::new(BinaryArray::from(vec![Some(b"v".as_ref())])) as ArrayRef,
1093 ),
1094 ])) as ArrayRef;
1095
1096 let struct_array = Arc::new(StructArray::from(vec![(
1097 Arc::new(
1098 Field::new("v", variant_child.data_type().clone(), false).with_metadata(
1099 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "1".to_string())]),
1100 ),
1101 ),
1102 variant_child,
1103 )])) as ArrayRef;
1104
1105 let ty = StructType::new(vec![
1106 NestedField::required(1, "v", Type::Variant(VariantType)).into(),
1107 ]);
1108
1109 let err = arrow_struct_to_literal(&struct_array, &ty).unwrap_err();
1110 assert_eq!(err.kind(), ErrorKind::FeatureUnsupported);
1111 assert!(
1112 err.to_string()
1113 .contains("Converting variant Arrow array to Iceberg literal is not supported yet"),
1114 "{err}"
1115 );
1116 }
1117
1118 #[test]
1119 fn test_arrow_geospatial_to_literal() {
1120 let values = Arc::new(LargeBinaryArray::from(vec![
1121 Some(b"wkb-1".as_slice()),
1122 None,
1123 Some(b"wkb-2".as_slice()),
1124 ])) as ArrayRef;
1125 let mut converter = ArrowArrayToIcebergStructConverter;
1126
1127 let result = converter
1128 .primitive(&PrimitiveType::Geometry(Default::default()), &values)
1129 .unwrap();
1130
1131 assert_eq!(result, vec![
1132 Some(Literal::binary(b"wkb-1".to_vec())),
1133 None,
1134 Some(Literal::binary(b"wkb-2".to_vec())),
1135 ]);
1136 }
1137
1138 #[test]
1139 fn test_arrow_geospatial_binary_view_to_literal() {
1140 let wkb = parquet_geospatial::testing::wkb_point_xy(1.0, 2.0);
1141 let values = Arc::new(BinaryViewArray::from(vec![Some(wkb.as_slice()), None])) as ArrayRef;
1142 let ty = Type::Primitive(PrimitiveType::Geography(Default::default()));
1143
1144 let result = arrow_primitive_to_literal(&values, &ty).unwrap();
1145
1146 assert_eq!(result, vec![Some(Literal::binary(wkb)), None]);
1147 }
1148
1149 #[test]
1150 fn test_find_field_by_id() {
1151 let field_a_array = Int32Array::from(vec![Some(42), Some(43), None]);
1153 let field_b_array = StringArray::from(vec![Some("value1"), Some("value2"), None]);
1154
1155 let nested_struct_array =
1157 Arc::new(StructArray::from(vec![
1158 (
1159 Arc::new(Field::new("field_a", DataType::Int32, true).with_metadata(
1160 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "1".to_string())]),
1161 )),
1162 Arc::new(field_a_array) as ArrayRef,
1163 ),
1164 (
1165 Arc::new(Field::new("field_b", DataType::Utf8, true).with_metadata(
1166 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "2".to_string())]),
1167 )),
1168 Arc::new(field_b_array) as ArrayRef,
1169 ),
1170 ])) as ArrayRef;
1171
1172 let field_c_array = Int32Array::from(vec![Some(100), Some(200), None]);
1173
1174 let struct_array = Arc::new(StructArray::from(vec![
1176 (
1177 Arc::new(
1178 Field::new(
1179 "nested_struct",
1180 DataType::Struct(Fields::from(vec![
1181 Field::new("field_a", DataType::Int32, true).with_metadata(
1182 HashMap::from([(
1183 PARQUET_FIELD_ID_META_KEY.to_string(),
1184 "1".to_string(),
1185 )]),
1186 ),
1187 Field::new("field_b", DataType::Utf8, true).with_metadata(
1188 HashMap::from([(
1189 PARQUET_FIELD_ID_META_KEY.to_string(),
1190 "2".to_string(),
1191 )]),
1192 ),
1193 ])),
1194 true,
1195 )
1196 .with_metadata(HashMap::from([(
1197 PARQUET_FIELD_ID_META_KEY.to_string(),
1198 "3".to_string(),
1199 )])),
1200 ),
1201 nested_struct_array,
1202 ),
1203 (
1204 Arc::new(Field::new("field_c", DataType::Int32, true).with_metadata(
1205 HashMap::from([(PARQUET_FIELD_ID_META_KEY.to_string(), "4".to_string())]),
1206 )),
1207 Arc::new(field_c_array) as ArrayRef,
1208 ),
1209 ])) as ArrayRef;
1210
1211 let accessor = ArrowArrayAccessor::new_with_match_mode(FieldMatchMode::Id);
1213
1214 let nested_field = NestedField::optional(
1216 3,
1217 "nested_struct",
1218 Type::Struct(StructType::new(vec![
1219 Arc::new(NestedField::optional(
1220 1,
1221 "field_a",
1222 Type::Primitive(PrimitiveType::Int),
1223 )),
1224 Arc::new(NestedField::optional(
1225 2,
1226 "field_b",
1227 Type::Primitive(PrimitiveType::String),
1228 )),
1229 ])),
1230 );
1231 let nested_partner = accessor
1232 .field_partner(&struct_array, &nested_field)
1233 .unwrap();
1234
1235 let field_a = NestedField::optional(1, "field_a", Type::Primitive(PrimitiveType::Int));
1237 let field_a_partner = accessor.field_partner(nested_partner, &field_a).unwrap();
1238
1239 let int_array = field_a_partner
1241 .as_any()
1242 .downcast_ref::<Int32Array>()
1243 .unwrap();
1244 assert_eq!(int_array.value(0), 42);
1245 assert_eq!(int_array.value(1), 43);
1246 assert!(int_array.is_null(2));
1247 }
1248
1249 #[test]
1250 fn test_find_field_by_name() {
1251 let field_a_array = Int32Array::from(vec![Some(42), Some(43), None]);
1253 let field_b_array = StringArray::from(vec![Some("value1"), Some("value2"), None]);
1254
1255 let nested_struct_array = Arc::new(StructArray::from(vec![
1257 (
1258 Arc::new(Field::new("field_a", DataType::Int32, true)),
1259 Arc::new(field_a_array) as ArrayRef,
1260 ),
1261 (
1262 Arc::new(Field::new("field_b", DataType::Utf8, true)),
1263 Arc::new(field_b_array) as ArrayRef,
1264 ),
1265 ])) as ArrayRef;
1266
1267 let field_c_array = Int32Array::from(vec![Some(100), Some(200), None]);
1268
1269 let struct_array = Arc::new(StructArray::from(vec![
1271 (
1272 Arc::new(Field::new(
1273 "nested_struct",
1274 DataType::Struct(Fields::from(vec![
1275 Field::new("field_a", DataType::Int32, true),
1276 Field::new("field_b", DataType::Utf8, true),
1277 ])),
1278 true,
1279 )),
1280 nested_struct_array,
1281 ),
1282 (
1283 Arc::new(Field::new("field_c", DataType::Int32, true)),
1284 Arc::new(field_c_array) as ArrayRef,
1285 ),
1286 ])) as ArrayRef;
1287
1288 let accessor = ArrowArrayAccessor::new_with_match_mode(FieldMatchMode::Name);
1290
1291 let nested_field = NestedField::optional(
1293 3,
1294 "nested_struct",
1295 Type::Struct(StructType::new(vec![
1296 Arc::new(NestedField::optional(
1297 1,
1298 "field_a",
1299 Type::Primitive(PrimitiveType::Int),
1300 )),
1301 Arc::new(NestedField::optional(
1302 2,
1303 "field_b",
1304 Type::Primitive(PrimitiveType::String),
1305 )),
1306 ])),
1307 );
1308 let nested_partner = accessor
1309 .field_partner(&struct_array, &nested_field)
1310 .unwrap();
1311
1312 let field_a = NestedField::optional(1, "field_a", Type::Primitive(PrimitiveType::Int));
1314 let field_a_partner = accessor.field_partner(nested_partner, &field_a).unwrap();
1315
1316 let int_array = field_a_partner
1318 .as_any()
1319 .downcast_ref::<Int32Array>()
1320 .unwrap();
1321 assert_eq!(int_array.value(0), 42);
1322 assert_eq!(int_array.value(1), 43);
1323 assert!(int_array.is_null(2));
1324 }
1325
1326 #[test]
1327 fn test_complex_nested() {
1328 let struct_type = StructType::new(vec![
1335 Arc::new(NestedField::required(
1336 0,
1337 "A",
1338 Type::List(ListType::new(Arc::new(NestedField::required(
1339 1,
1340 "item",
1341 Type::Struct(StructType::new(vec![
1342 Arc::new(NestedField::required(
1343 2,
1344 "a1",
1345 Type::Primitive(PrimitiveType::Int),
1346 )),
1347 Arc::new(NestedField::required(
1348 3,
1349 "a2",
1350 Type::Primitive(PrimitiveType::Int),
1351 )),
1352 ])),
1353 )))),
1354 )),
1355 Arc::new(NestedField::required(
1356 4,
1357 "B",
1358 Type::List(ListType::new(Arc::new(NestedField::required(
1359 5,
1360 "item",
1361 Type::Map(MapType::new(
1362 NestedField::optional(6, "keys", Type::Primitive(PrimitiveType::Int))
1363 .into(),
1364 NestedField::optional(7, "values", Type::Primitive(PrimitiveType::Int))
1365 .into(),
1366 )),
1367 )))),
1368 )),
1369 Arc::new(NestedField::required(
1370 8,
1371 "C",
1372 Type::List(ListType::new(Arc::new(NestedField::required(
1373 9,
1374 "item",
1375 Type::List(ListType::new(Arc::new(NestedField::optional(
1376 10,
1377 "item",
1378 Type::Primitive(PrimitiveType::Int),
1379 )))),
1380 )))),
1381 )),
1382 ]);
1383
1384 let struct_array =
1390 {
1391 let a_struct_a1_builder = Int32Builder::new();
1392 let a_struct_a2_builder = Int32Builder::new();
1393 let a_struct_builder =
1394 StructBuilder::new(
1395 vec![
1396 Field::new("a1", DataType::Int32, false).with_metadata(HashMap::from(
1397 [(PARQUET_FIELD_ID_META_KEY.to_string(), "2".to_string())],
1398 )),
1399 Field::new("a2", DataType::Int32, false).with_metadata(HashMap::from(
1400 [(PARQUET_FIELD_ID_META_KEY.to_string(), "3".to_string())],
1401 )),
1402 ],
1403 vec![Box::new(a_struct_a1_builder), Box::new(a_struct_a2_builder)],
1404 );
1405 let a_builder = ListBuilder::new(a_struct_builder);
1406
1407 let map_key_builder = Int32Builder::new();
1408 let map_value_builder = Int32Builder::new();
1409 let map_builder = MapBuilder::new(None, map_key_builder, map_value_builder);
1410 let b_builder = ListBuilder::new(map_builder);
1411
1412 let inner_list_item_builder = Int32Builder::new();
1413 let inner_list_builder = ListBuilder::new(inner_list_item_builder);
1414 let c_builder = ListBuilder::new(inner_list_builder);
1415
1416 let mut top_struct_builder = {
1417 let a_struct_type =
1418 DataType::Struct(Fields::from(vec![
1419 Field::new("a1", DataType::Int32, false).with_metadata(HashMap::from(
1420 [(PARQUET_FIELD_ID_META_KEY.to_string(), "2".to_string())],
1421 )),
1422 Field::new("a2", DataType::Int32, false).with_metadata(HashMap::from(
1423 [(PARQUET_FIELD_ID_META_KEY.to_string(), "3".to_string())],
1424 )),
1425 ]));
1426 let a_type =
1427 DataType::List(Arc::new(Field::new("item", a_struct_type.clone(), true)));
1428
1429 let b_map_entry_struct = Field::new(
1430 "entries",
1431 DataType::Struct(Fields::from(vec![
1432 Field::new("keys", DataType::Int32, false),
1433 Field::new("values", DataType::Int32, true),
1434 ])),
1435 false,
1436 );
1437 let b_map_type =
1438 DataType::Map(Arc::new(b_map_entry_struct), false);
1439 let b_type =
1440 DataType::List(Arc::new(Field::new("item", b_map_type.clone(), true)));
1441
1442 let c_inner_list_type =
1443 DataType::List(Arc::new(Field::new("item", DataType::Int32, true)));
1444 let c_type = DataType::List(Arc::new(Field::new(
1445 "item",
1446 c_inner_list_type.clone(),
1447 true,
1448 )));
1449 StructBuilder::new(
1450 Fields::from(vec![
1451 Field::new("A", a_type.clone(), false).with_metadata(HashMap::from([
1452 (PARQUET_FIELD_ID_META_KEY.to_string(), "0".to_string()),
1453 ])),
1454 Field::new("B", b_type.clone(), false).with_metadata(HashMap::from([
1455 (PARQUET_FIELD_ID_META_KEY.to_string(), "4".to_string()),
1456 ])),
1457 Field::new("C", c_type.clone(), false).with_metadata(HashMap::from([
1458 (PARQUET_FIELD_ID_META_KEY.to_string(), "8".to_string()),
1459 ])),
1460 ]),
1461 vec![
1462 Box::new(a_builder),
1463 Box::new(b_builder),
1464 Box::new(c_builder),
1465 ],
1466 )
1467 };
1468
1469 {
1472 let a_builder = top_struct_builder
1473 .field_builder::<ListBuilder<StructBuilder>>(0)
1474 .unwrap();
1475 let struct_builder = a_builder.values();
1476 struct_builder
1477 .field_builder::<Int32Builder>(0)
1478 .unwrap()
1479 .append_value(10);
1480 struct_builder
1481 .field_builder::<Int32Builder>(1)
1482 .unwrap()
1483 .append_value(20);
1484 struct_builder.append(true);
1485 let struct_builder = a_builder.values();
1486 struct_builder
1487 .field_builder::<Int32Builder>(0)
1488 .unwrap()
1489 .append_value(11);
1490 struct_builder
1491 .field_builder::<Int32Builder>(1)
1492 .unwrap()
1493 .append_value(21);
1494 struct_builder.append(true);
1495 a_builder.append(true);
1496 }
1497 {
1498 let b_builder = top_struct_builder
1499 .field_builder::<ListBuilder<MapBuilder<Int32Builder, Int32Builder>>>(1)
1500 .unwrap();
1501 let map_builder = b_builder.values();
1502 map_builder.keys().append_value(1);
1503 map_builder.values().append_value(100);
1504 map_builder.keys().append_value(3);
1505 map_builder.values().append_value(300);
1506 map_builder.append(true).unwrap();
1507
1508 map_builder.keys().append_value(2);
1509 map_builder.values().append_value(200);
1510 map_builder.append(true).unwrap();
1511
1512 b_builder.append(true);
1513 }
1514 {
1515 let c_builder = top_struct_builder
1516 .field_builder::<ListBuilder<ListBuilder<Int32Builder>>>(2)
1517 .unwrap();
1518 let inner_list_builder = c_builder.values();
1519 inner_list_builder.values().append_value(100);
1520 inner_list_builder.values().append_value(101);
1521 inner_list_builder.values().append_value(102);
1522 inner_list_builder.append(true);
1523 let inner_list_builder = c_builder.values();
1524 inner_list_builder.values().append_value(200);
1525 inner_list_builder.values().append_value(201);
1526 inner_list_builder.append(true);
1527 c_builder.append(true);
1528 }
1529 top_struct_builder.append(true);
1530
1531 {
1534 let a_builder = top_struct_builder
1535 .field_builder::<ListBuilder<StructBuilder>>(0)
1536 .unwrap();
1537 let struct_builder = a_builder.values();
1538 struct_builder
1539 .field_builder::<Int32Builder>(0)
1540 .unwrap()
1541 .append_value(12);
1542 struct_builder
1543 .field_builder::<Int32Builder>(1)
1544 .unwrap()
1545 .append_value(22);
1546 struct_builder.append(true);
1547 let struct_builder = a_builder.values();
1548 struct_builder
1549 .field_builder::<Int32Builder>(0)
1550 .unwrap()
1551 .append_value(13);
1552 struct_builder
1553 .field_builder::<Int32Builder>(1)
1554 .unwrap()
1555 .append_value(23);
1556 struct_builder.append(true);
1557 a_builder.append(true);
1558 }
1559 {
1560 let b_builder = top_struct_builder
1561 .field_builder::<ListBuilder<MapBuilder<Int32Builder, Int32Builder>>>(1)
1562 .unwrap();
1563 let map_builder = b_builder.values();
1564 map_builder.keys().append_value(3);
1565 map_builder.values().append_value(300);
1566 map_builder.append(true).unwrap();
1567
1568 b_builder.append(true);
1569 }
1570 {
1571 let c_builder = top_struct_builder
1572 .field_builder::<ListBuilder<ListBuilder<Int32Builder>>>(2)
1573 .unwrap();
1574 let inner_list_builder = c_builder.values();
1575 inner_list_builder.values().append_value(300);
1576 inner_list_builder.values().append_value(301);
1577 inner_list_builder.values().append_value(302);
1578 inner_list_builder.append(true);
1579 let inner_list_builder = c_builder.values();
1580 inner_list_builder.values().append_value(400);
1581 inner_list_builder.values().append_value(401);
1582 inner_list_builder.append(true);
1583 c_builder.append(true);
1584 }
1585 top_struct_builder.append(true);
1586
1587 Arc::new(top_struct_builder.finish()) as ArrayRef
1588 };
1589
1590 let result = arrow_struct_to_literal(&struct_array, &struct_type).unwrap();
1591 assert_eq!(result, vec![
1592 Some(Literal::Struct(Struct::from_iter(vec![
1593 Some(Literal::List(vec![
1594 Some(Literal::Struct(Struct::from_iter(vec![
1595 Some(Literal::int(10)),
1596 Some(Literal::int(20)),
1597 ]))),
1598 Some(Literal::Struct(Struct::from_iter(vec![
1599 Some(Literal::int(11)),
1600 Some(Literal::int(21)),
1601 ]))),
1602 ])),
1603 Some(Literal::List(vec![
1604 Some(Literal::Map(Map::from_iter(vec![
1605 (Literal::int(1), Some(Literal::int(100))),
1606 (Literal::int(3), Some(Literal::int(300))),
1607 ]))),
1608 Some(Literal::Map(Map::from_iter(vec![(
1609 Literal::int(2),
1610 Some(Literal::int(200))
1611 ),]))),
1612 ])),
1613 Some(Literal::List(vec![
1614 Some(Literal::List(vec![
1615 Some(Literal::int(100)),
1616 Some(Literal::int(101)),
1617 Some(Literal::int(102)),
1618 ])),
1619 Some(Literal::List(vec![
1620 Some(Literal::int(200)),
1621 Some(Literal::int(201)),
1622 ])),
1623 ])),
1624 ]))),
1625 Some(Literal::Struct(Struct::from_iter(vec![
1626 Some(Literal::List(vec![
1627 Some(Literal::Struct(Struct::from_iter(vec![
1628 Some(Literal::int(12)),
1629 Some(Literal::int(22)),
1630 ]))),
1631 Some(Literal::Struct(Struct::from_iter(vec![
1632 Some(Literal::int(13)),
1633 Some(Literal::int(23)),
1634 ]))),
1635 ])),
1636 Some(Literal::List(vec![Some(Literal::Map(Map::from_iter(
1637 vec![(Literal::int(3), Some(Literal::int(300))),]
1638 ))),])),
1639 Some(Literal::List(vec![
1640 Some(Literal::List(vec![
1641 Some(Literal::int(300)),
1642 Some(Literal::int(301)),
1643 Some(Literal::int(302)),
1644 ])),
1645 Some(Literal::List(vec![
1646 Some(Literal::int(400)),
1647 Some(Literal::int(401)),
1648 ])),
1649 ])),
1650 ]))),
1651 ]);
1652 }
1653
1654 #[test]
1655 fn test_create_decimal_array_respects_precision() {
1656 let target_precision = 18u8;
1659 let target_scale = 10i8;
1660 let target_type = DataType::Decimal128(target_precision, target_scale);
1661 let value = PrimitiveLiteral::Int128(10000000000);
1662
1663 let array = create_primitive_array_single_element(&target_type, Some(&value))
1664 .expect("Failed to create decimal array");
1665
1666 match array.data_type() {
1667 DataType::Decimal128(precision, scale) => {
1668 assert_eq!(*precision, target_precision);
1669 assert_eq!(*scale, target_scale);
1670 }
1671 other => panic!("Expected Decimal128, got {other:?}"),
1672 }
1673 }
1674
1675 #[test]
1676 fn test_create_null_arrays_preserve_type_and_length() {
1677 let data_types = [
1678 DataType::Decimal128(10, 2),
1679 DataType::Timestamp(TimeUnit::Microsecond, Some("+00:00".into())),
1680 DataType::Struct(
1681 vec![
1682 Field::new("a", DataType::Utf8, true),
1683 Field::new(
1684 "ys",
1685 DataType::List(Arc::new(Field::new("element", DataType::Int64, true))),
1686 true,
1687 ),
1688 ]
1689 .into(),
1690 ),
1691 DataType::Null,
1692 ];
1693
1694 for data_type in data_types {
1696 let single = create_primitive_array_single_element(&data_type, None)
1697 .unwrap_or_else(|err| panic!("single, type={data_type:?}: {err}"));
1698 assert_eq!(single.data_type(), &data_type, "single, type={data_type:?}");
1699 assert_eq!(single.len(), 1, "single, type={data_type:?}");
1700 if data_type != DataType::Null {
1701 assert_eq!(single.null_count(), 1, "single, type={data_type:?}");
1702 }
1703 assert_eq!(single.logical_null_count(), 1, "single, type={data_type:?}");
1704
1705 for num_rows in [0, 1, 3] {
1706 let repeated = create_primitive_array_repeated(&data_type, None, num_rows)
1707 .unwrap_or_else(|err| {
1708 panic!("repeated, type={data_type:?}, rows={num_rows}: {err}")
1709 });
1710 assert_eq!(
1711 repeated.data_type(),
1712 &data_type,
1713 "repeated, type={data_type:?}, rows={num_rows}"
1714 );
1715 assert_eq!(
1716 repeated.len(),
1717 num_rows,
1718 "repeated, type={data_type:?}, rows={num_rows}"
1719 );
1720 if data_type != DataType::Null {
1721 assert_eq!(
1722 repeated.null_count(),
1723 num_rows,
1724 "repeated, type={data_type:?}, rows={num_rows}"
1725 );
1726 }
1727 assert_eq!(
1728 repeated.logical_null_count(),
1729 num_rows,
1730 "repeated, type={data_type:?}, rows={num_rows}"
1731 );
1732 }
1733 }
1734 }
1735
1736 #[test]
1737 fn test_create_null_array_rejects_non_null_literal() {
1738 let literal = Some(PrimitiveLiteral::Int(1));
1739
1740 assert!(create_primitive_array_single_element(&DataType::Null, literal.as_ref()).is_err());
1741 assert!(create_primitive_array_repeated(&DataType::Null, literal.as_ref(), 2).is_err());
1742 assert_eq!(
1743 create_primitive_array_single_element(&DataType::Null, None)
1744 .unwrap()
1745 .len(),
1746 1
1747 );
1748 assert_eq!(
1749 create_primitive_array_repeated(&DataType::Null, None, 2)
1750 .unwrap()
1751 .len(),
1752 2
1753 );
1754 }
1755
1756 #[test]
1757 fn test_create_decimal_array_repeated_respects_precision() {
1758 let target_precision = 18u8;
1760 let target_scale = 10i8;
1761 let target_type = DataType::Decimal128(target_precision, target_scale);
1762 let value = PrimitiveLiteral::Int128(10000000000);
1763 let num_rows = 5;
1764
1765 let array = create_primitive_array_repeated(&target_type, Some(&value), num_rows)
1766 .expect("Failed to create repeated decimal array");
1767
1768 match array.data_type() {
1769 DataType::Decimal128(precision, scale) => {
1770 assert_eq!(*precision, target_precision);
1771 assert_eq!(*scale, target_scale);
1772 }
1773 other => panic!("Expected Decimal128, got {other:?}"),
1774 }
1775
1776 assert_eq!(array.len(), num_rows);
1777 }
1778
1779 #[test]
1780 fn test_create_timestamp_microsecond_array_repeated() {
1781 let target_type = DataType::Timestamp(TimeUnit::Microsecond, None);
1782 let value = PrimitiveLiteral::Long(1_740_600_000_000_000);
1783 let num_rows = 3;
1784
1785 let array = create_primitive_array_repeated(&target_type, Some(&value), num_rows)
1786 .expect("Failed to create repeated timestamp microsecond array");
1787
1788 assert_eq!(array.data_type(), &target_type);
1789 assert_eq!(array.len(), num_rows);
1790 }
1791
1792 #[test]
1793 fn test_create_timestamp_microsecond_with_timezone_array_repeated() {
1794 let target_type = DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into()));
1795 let value = PrimitiveLiteral::Long(1_740_600_000_000_000);
1796 let num_rows = 2;
1797
1798 let array = create_primitive_array_repeated(&target_type, Some(&value), num_rows)
1799 .expect("Failed to create repeated timestamp microsecond array with timezone");
1800
1801 assert_eq!(array.data_type(), &target_type);
1802 assert_eq!(array.len(), num_rows);
1803 }
1804
1805 #[test]
1806 fn test_create_string_and_binary_arrays_repeated() {
1807 let text = "partition-value-2026";
1808 let bytes: Vec<u8> = vec![0xDE, 0xAD, 0xBE, 0xEF];
1809 let num_rows = 4;
1810
1811 let utf8 = create_primitive_array_repeated(
1812 &DataType::Utf8,
1813 Some(&PrimitiveLiteral::String(text.to_string())),
1814 num_rows,
1815 )
1816 .unwrap();
1817 let utf8 = utf8.as_any().downcast_ref::<StringArray>().unwrap();
1818 assert_eq!(utf8.len(), num_rows);
1819 assert!((0..num_rows).all(|i| utf8.value(i) == text));
1820
1821 let binary = create_primitive_array_repeated(
1822 &DataType::Binary,
1823 Some(&PrimitiveLiteral::Binary(bytes.clone())),
1824 num_rows,
1825 )
1826 .unwrap();
1827 let binary = binary.as_any().downcast_ref::<BinaryArray>().unwrap();
1828 assert_eq!(binary.len(), num_rows);
1829 assert!((0..num_rows).all(|i| binary.value(i) == bytes.as_slice()));
1830
1831 let large = create_primitive_array_repeated(
1832 &DataType::LargeBinary,
1833 Some(&PrimitiveLiteral::Binary(bytes.clone())),
1834 num_rows,
1835 )
1836 .unwrap();
1837 let large = large.as_any().downcast_ref::<LargeBinaryArray>().unwrap();
1838 assert_eq!(large.len(), num_rows);
1839 assert!((0..num_rows).all(|i| large.value(i) == bytes.as_slice()));
1840
1841 let fixed = create_primitive_array_repeated(
1842 &DataType::FixedSizeBinary(bytes.len() as i32),
1843 Some(&PrimitiveLiteral::Binary(bytes.clone())),
1844 num_rows,
1845 )
1846 .unwrap();
1847 let fixed = fixed
1848 .as_any()
1849 .downcast_ref::<FixedSizeBinaryArray>()
1850 .unwrap();
1851 assert_eq!(fixed.len(), num_rows);
1852 assert!((0..num_rows).all(|i| fixed.value(i) == bytes.as_slice()));
1853 }
1854
1855 #[test]
1856 fn test_create_boolean_array_repeated() {
1857 let num_rows = 4;
1858
1859 for value in [true, false] {
1860 let array = create_primitive_array_repeated(
1861 &DataType::Boolean,
1862 Some(&PrimitiveLiteral::Boolean(value)),
1863 num_rows,
1864 )
1865 .unwrap();
1866 let array = array.as_any().downcast_ref::<BooleanArray>().unwrap();
1867 assert_eq!(array.len(), num_rows);
1868 assert_eq!(array.null_count(), 0);
1869 assert!((0..num_rows).all(|i| array.value(i) == value));
1870 }
1871
1872 let empty = create_primitive_array_repeated(
1874 &DataType::Boolean,
1875 Some(&PrimitiveLiteral::Boolean(true)),
1876 0,
1877 )
1878 .unwrap();
1879 assert_eq!(empty.len(), 0);
1880 assert_eq!(empty.null_count(), 0);
1881 }
1882
1883 #[test]
1884 fn test_create_string_array_repeated_empty() {
1885 let array = create_primitive_array_repeated(
1887 &DataType::Utf8,
1888 Some(&PrimitiveLiteral::String("x".to_string())),
1889 0,
1890 )
1891 .unwrap();
1892 assert_eq!(array.len(), 0);
1893 }
1894
1895 #[test]
1896 fn test_create_fixed_size_binary_repeated_wrong_width_errors() {
1897 let err = create_primitive_array_repeated(
1900 &DataType::FixedSizeBinary(4),
1901 Some(&PrimitiveLiteral::Binary(vec![0x01, 0x02, 0x03])),
1902 2,
1903 )
1904 .unwrap_err();
1905 assert!(err.to_string().contains("does not match declared width"));
1906 }
1907
1908 #[test]
1909 fn test_create_fixed_size_binary_repeated_empty_errors() {
1910 let result = create_primitive_array_repeated(
1914 &DataType::FixedSizeBinary(4),
1915 Some(&PrimitiveLiteral::Binary(vec![0xDE, 0xAD, 0xBE, 0xEF])),
1916 0,
1917 );
1918 assert!(result.is_err());
1919 }
1920}