From b8ca86a8e36ad34e58e1151b9c1cc1d1d094b1d2 Mon Sep 17 00:00:00 2001 From: Liang-Chi Hsieh Date: Fri, 15 Dec 2023 09:48:34 -0800 Subject: [PATCH] Support MapBuilder in make_builder (#5210) --- arrow-array/src/builder/map_builder.rs | 45 ++++++++++++++++++++++- arrow-array/src/builder/struct_builder.rs | 34 ++++++++++++----- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/arrow-array/src/builder/map_builder.rs b/arrow-array/src/builder/map_builder.rs index 3a5244ed81a0..5785bb5fafb5 100644 --- a/arrow-array/src/builder/map_builder.rs +++ b/arrow-array/src/builder/map_builder.rs @@ -234,7 +234,8 @@ impl ArrayBuilder for MapBuilder { #[cfg(test)] mod tests { - use crate::builder::{Int32Builder, StringBuilder}; + use crate::builder::{make_builder, Int32Builder, StringBuilder}; + use crate::{Int32Array, StringArray}; use super::*; @@ -248,4 +249,46 @@ mod tests { builder.finish(); } + + #[test] + fn test_boxed_map_builder() { + let keys_builder = make_builder(&DataType::Utf8, 5); + let values_builder = make_builder(&DataType::Int32, 5); + + let mut builder = MapBuilder::new(None, keys_builder, values_builder); + builder + .keys() + .as_any_mut() + .downcast_mut::() + .expect("should be an StringBuilder") + .append_value("1"); + builder + .values() + .as_any_mut() + .downcast_mut::() + .expect("should be an Int32Builder") + .append_value(42); + builder.append(true).unwrap(); + + let map_array = builder.finish(); + + assert_eq!( + map_array + .keys() + .as_any() + .downcast_ref::() + .expect("should be an StringArray") + .value(0), + "1" + ); + assert_eq!( + map_array + .values() + .as_any() + .downcast_ref::() + .expect("should be an Int32Array") + .value(0), + 42 + ); + } } diff --git a/arrow-array/src/builder/struct_builder.rs b/arrow-array/src/builder/struct_builder.rs index 960949a2f09f..196ae8092b85 100644 --- a/arrow-array/src/builder/struct_builder.rs +++ b/arrow-array/src/builder/struct_builder.rs @@ -177,6 +177,24 @@ pub fn make_builder(datatype: &DataType, capacity: usize) -> Box match field.data_type() { + DataType::Struct(fields) => { + let map_field_names = MapFieldNames { + key: fields[0].name().clone(), + value: fields[1].name().clone(), + entry: field.name().clone(), + }; + let key_builder = make_builder(fields[0].data_type(), capacity); + let value_builder = make_builder(fields[1].data_type(), capacity); + Box::new(MapBuilder::with_capacity( + Some(map_field_names), + key_builder, + value_builder, + capacity, + )) + } + t => panic!("The field of Map data type {t:?} should has a child Struct field"), + }, DataType::Struct(fields) => Box::new(StructBuilder::from_fields(fields.clone(), capacity)), t => panic!("Data type {t:?} is not currently supported"), } @@ -514,19 +532,15 @@ mod tests { } #[test] - #[should_panic( - expected = "Data type Map(Field { name: \"entries\", data_type: Struct([Field { name: \"keys\", data_type: Int32, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, Field { name: \"values\", data_type: UInt32, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }]), nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} }, false) is not currently supported" - )] + #[should_panic(expected = "Data type Dictionary(Int32, Utf8) is not currently supported")] fn test_struct_array_builder_from_schema_unsupported_type() { - let keys = Arc::new(Field::new("keys", DataType::Int32, false)); - let values = Arc::new(Field::new("values", DataType::UInt32, false)); - let struct_type = DataType::Struct(Fields::from(vec![keys, values])); - let map_data_type = - DataType::Map(Arc::new(Field::new("entries", struct_type, false)), false); - let fields = vec![ Field::new("f1", DataType::Int16, false), - Field::new("f2", map_data_type, false), + Field::new( + "f2", + DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)), + false, + ), ]; let _ = StructBuilder::from_fields(fields, 5);