| // Copyright 2022 The Blaze Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| use arrow::array::*; |
| use arrow::datatypes::DataType::Struct; |
| use arrow::datatypes::*; |
| use arrow::error::Result as ArrowResult; |
| use arrow::record_batch::RecordBatch; |
| use paste::paste; |
| use std::any::Any; |
| use std::sync::Arc; |
| |
| pub fn new_array_builders(schema: &SchemaRef, batch_size: usize) -> Vec<Box<dyn ArrayBuilder>> { |
| schema |
| .fields() |
| .iter() |
| .map(|field| new_array_builder(field.data_type(), batch_size)) |
| .collect::<Vec<_>>() |
| } |
| |
| pub fn make_batch( |
| schema: SchemaRef, |
| mut arrays: Vec<Box<dyn ArrayBuilder>>, |
| ) -> ArrowResult<RecordBatch> { |
| let columns = arrays.iter_mut().map(|array| array.finish()).collect(); |
| RecordBatch::try_new(schema, columns) |
| } |
| |
| pub fn builder_extend( |
| builder: &mut (impl ArrayBuilder + ?Sized), |
| array: &ArrayRef, |
| indices: &[usize], |
| data_type: &DataType, |
| ) { |
| macro_rules! append_simple { |
| ($arrowty:ident) => {{ |
| type B = paste::paste! {[< $arrowty Builder >]}; |
| type A = paste::paste! {[< $arrowty Array >]}; |
| let t = builder.as_any_mut().downcast_mut::<B>().unwrap(); |
| let f = array.as_any().downcast_ref::<A>().unwrap(); |
| for &i in indices { |
| if f.is_valid(i) { |
| t.append_value(f.value(i)); |
| } else { |
| t.append_null(); |
| } |
| } |
| }}; |
| } |
| |
| macro_rules! append_dict { |
| ($key_type:expr, $value_type:expr) => {{ |
| append_dict!(@match_key: $key_type, $value_type) |
| }}; |
| (@match_key: $key_type:expr, $value_type:expr) => {{ |
| match $key_type.as_ref() { |
| DataType::Int8 => append_dict!(@match_value: Int8, $value_type), |
| DataType::Int16 => append_dict!(@match_value: Int16, $value_type), |
| DataType::Int32 => append_dict!(@match_value: Int32, $value_type), |
| DataType::Int64 => append_dict!(@match_value: Int64, $value_type), |
| DataType::UInt8 => append_dict!(@match_value: UInt8, $value_type), |
| DataType::UInt16=> append_dict!(@match_value: UInt16, $value_type), |
| DataType::UInt32 => append_dict!(@match_value: UInt32, $value_type), |
| DataType::UInt64 => append_dict!(@match_value: UInt64, $value_type), |
| _ => unimplemented!("dictionary key type not supported: {:?}", $value_type), |
| } |
| }}; |
| (@match_value: $keyarrowty:ident, $value_type:expr) => {{ |
| match $value_type.as_ref() { |
| DataType::Int8 => append_dict!(@prim: $keyarrowty, Int8), |
| DataType::Int16 => append_dict!(@prim: $keyarrowty, Int16), |
| DataType::Int32 => append_dict!(@prim: $keyarrowty, Int32), |
| DataType::Int64 => append_dict!(@prim: $keyarrowty, Int64), |
| DataType::UInt8 => append_dict!(@prim: $keyarrowty, UInt8), |
| DataType::UInt16 => append_dict!(@prim: $keyarrowty, UInt16), |
| DataType::UInt32 => append_dict!(@prim: $keyarrowty, UInt32), |
| DataType::UInt64 => append_dict!(@prim: $keyarrowty, UInt64), |
| DataType::Float32 => append_dict!(@prim: $keyarrowty, Float32), |
| DataType::Float64 => append_dict!(@prim: $keyarrowty, Float64), |
| DataType::Date32 => append_dict!(@prim: $keyarrowty, Date32), |
| DataType::Date64 => append_dict!(@prim: $keyarrowty, Date64), |
| DataType::Timestamp(TimeUnit::Second, _) => { |
| append_dict!(@prim: $keyarrowty, TimestampSecond) |
| } |
| DataType::Timestamp(TimeUnit::Millisecond, _) => { |
| append_dict!(@prim: $keyarrowty, TimestampMillisecond) |
| } |
| DataType::Timestamp(TimeUnit::Microsecond, _) => { |
| append_dict!(@prim: $keyarrowty, TimestampMicrosecond) |
| } |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => { |
| append_dict!(@prim: $keyarrowty, TimestampNanosecond) |
| } |
| DataType::Utf8 => append_dict!(@str: $keyarrowty, i32), |
| DataType::LargeUtf8 => append_dict!(@str: $keyarrowty, i64), |
| _ => unimplemented!("dictionary value type not supported: {:?}", $value_type), |
| } |
| }}; |
| (@prim: $keyarrowty:ident, $valuearrowty:ident) => {{ |
| type KeyType = paste! {[< $keyarrowty Type >]}; |
| type ValueType = paste! {[< $valuearrowty Type >]}; |
| type B = PrimitiveDictionaryBuilder<KeyType, ValueType>; |
| type A = DictionaryArray<KeyType>; |
| let t = builder.as_any_mut().downcast_mut::<B>().unwrap(); |
| let f = array.as_any().downcast_ref::<A>().unwrap(); |
| let fv = f.values().as_any().downcast_ref::<paste! {[<$valuearrowty Array>]} >().unwrap(); |
| for &i in indices { |
| if f.is_valid(i) { |
| let _ = t.append(fv.value(f.key(i).unwrap())); |
| } else { |
| t.append_null(); |
| } |
| } |
| }}; |
| (@bin: $keyarrowty:ident, $strsizety:ty) => {{ |
| type KeyType = paste! {[< $keyarrowty Type >]}; |
| type B = BinaryDictionaryBuilder<KeyType>; |
| type A = DictionaryArray<KeyType>; |
| let t = builder.as_any_mut().downcast_mut::<B>().unwrap(); |
| let f = array.as_any().downcast_ref::<A>().unwrap(); |
| let fv = f.values().as_any().downcast_ref::<GenericStringArray<$strsizety>>().unwrap(); |
| for &i in indices { |
| if f.is_valid(i) { |
| t.append(fv.value(f.key(i).unwrap())); |
| } else { |
| t.append_null(); |
| } |
| } |
| }}; |
| (@str: $keyarrowty:ident, $strsizety:ty) => {{ |
| type KeyType = paste! {[< $keyarrowty Type >]}; |
| type B = StringDictionaryBuilder<KeyType>; |
| type A = DictionaryArray<KeyType>; |
| let t = builder.as_any_mut().downcast_mut::<B>().unwrap(); |
| let f = array.as_any().downcast_ref::<A>().unwrap(); |
| let fv = f.values().as_any().downcast_ref::<GenericStringArray<$strsizety>>().unwrap(); |
| for &i in indices { |
| if f.is_valid(i) { |
| let _ = t.append(fv.value(f.key(i).unwrap())); |
| } else { |
| t.append_null(); |
| } |
| } |
| }}; |
| } |
| |
| macro_rules! append_map { |
| ($key_type:expr, $value_type:expr) => {{ |
| append_map!(@match_key: $key_type, $value_type) |
| }}; |
| (@match_key: $key_type:expr, $value_type:expr) => {{ |
| match $key_type { |
| DataType::Boolean => append_map!(@match_value: Boolean, $value_type), |
| DataType::Int8 => append_map!(@match_value: Int8, $value_type), |
| DataType::Int16 => append_map!(@match_value: Int16, $value_type), |
| DataType::Int32 => append_map!(@match_value: Int32, $value_type), |
| DataType::Int64 => append_map!(@match_value: Int64, $value_type), |
| DataType::UInt8 => append_map!(@match_value: UInt8, $value_type), |
| DataType::UInt16=> append_map!(@match_value: UInt16, $value_type), |
| DataType::UInt32 => append_map!(@match_value: UInt32, $value_type), |
| DataType::UInt64 => append_map!(@match_value: UInt64, $value_type), |
| DataType::Float32 => append_map!(@match_value: Float32, $value_type), |
| DataType::Float64 => append_map!(@match_value: Float64, $value_type), |
| DataType::Date32 => append_map!(@match_value: Date32, $value_type), |
| DataType::Date64 => append_map!(@match_value: Date64, $value_type), |
| DataType::Timestamp(TimeUnit::Second, _) => |
| append_map!(@match_value: TimestampSecond, $value_type), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => |
| append_map!(@match_value: TimestampMillisecond, $value_type), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => |
| append_map!(@match_value: TimestampMicrosecond, $value_type), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => |
| append_map!(@match_value: TimestampNanosecond, $value_type), |
| DataType::Utf8 => append_map!(@match_value: String, $value_type), |
| DataType::LargeUtf8 => append_map!(@match_value: LargeString, $value_type), |
| DataType::Binary => append_map!(@match_value: Binary, $value_type), |
| DataType::LargeBinary => append_map!(@match_value: LargeBinary, $value_type), |
| _ => unimplemented!("map key type not supported: {:?}", $key_type), |
| } |
| }}; |
| (@match_value: $keyarrowty:ident, $value_type:expr) => {{ |
| match $value_type { |
| DataType::Boolean => append_map!(@prim: $keyarrowty, Boolean), |
| DataType::Int8 => append_map!(@prim: $keyarrowty, Int8), |
| DataType::Int16 => append_map!(@prim: $keyarrowty, Int16), |
| DataType::Int32 => append_map!(@prim: $keyarrowty, Int32), |
| DataType::Int64 => append_map!(@prim: $keyarrowty, Int64), |
| DataType::UInt8 => append_map!(@prim: $keyarrowty, UInt8), |
| DataType::UInt16 => append_map!(@prim: $keyarrowty, UInt16), |
| DataType::UInt32 => append_map!(@prim: $keyarrowty, UInt32), |
| DataType::UInt64 => append_map!(@prim: $keyarrowty, UInt64), |
| DataType::Float32 => append_map!(@prim: $keyarrowty, Float32), |
| DataType::Float64 => append_map!(@prim: $keyarrowty, Float64), |
| DataType::Date32 => append_map!(@prim: $keyarrowty, Date32), |
| DataType::Date64 => append_map!(@prim: $keyarrowty, Date64), |
| DataType::Timestamp(TimeUnit::Second, _) => append_map!(@prim: $keyarrowty, TimestampSecond), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => append_map!(@prim: $keyarrowty, TimestampMillisecond), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => append_map!(@prim: $keyarrowty, TimestampMicrosecond), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => append_map!(@prim: $keyarrowty, TimestampNanosecond), |
| DataType::Utf8 => append_map!(@prim: $keyarrowty, String), |
| DataType::LargeUtf8 => append_map!(@prim: $keyarrowty, LargeString), |
| DataType::Binary => append_map!(@prim: $keyarrowty, Binary), |
| DataType::LargeBinary => append_map!(@prim: $keyarrowty, LargeBinary), |
| _ => unimplemented!("map value type not supported: {:?}", $value_type), |
| } |
| }}; |
| (@prim: $keyarrowty:ident, $valuearrowty:ident) => {{ |
| type KeyType = paste! {[< $keyarrowty Builder >]}; |
| type ValueType = paste! {[< $valuearrowty Builder >]}; |
| type B = MapBuilder<KeyType, ValueType>; |
| let t = builder.as_any_mut().downcast_mut::<B>().unwrap(); |
| let f = array.as_any().downcast_ref::<MapArray>().unwrap(); |
| let fo = f.value_offsets(); |
| |
| for &i in indices { |
| if f.is_valid(i) { |
| let first_index = fo[i] as usize; |
| let last_index = fo[i + 1] as usize; |
| if(last_index - first_index > 0) { |
| builder_extend(t.keys(), f.keys(), (first_index..last_index).collect::<Vec<_>>().as_slice(), f.key_type()); |
| builder_extend(t.values(), f.values(), (first_index..last_index).collect::<Vec<_>>().as_slice(), f.value_type()); |
| } |
| t.append(true).unwrap(); |
| } else { |
| t.append(false).unwrap(); |
| } |
| } |
| }}; |
| } |
| |
| macro_rules! append_list { |
| ($data_type:expr) => {{ |
| append_list!(@match_type: $data_type) |
| }}; |
| (@match_type: $data_type:expr) => {{ |
| match $data_type { |
| DataType::Int8 => append_list!(@prim: Int8), |
| DataType::Int16 => append_list!(@prim: Int16), |
| DataType::Int32 => append_list!(@prim: Int32), |
| DataType::Int64 => append_list!(@prim: Int64), |
| DataType::UInt8 => append_list!(@prim: UInt8), |
| DataType::UInt16 => append_list!(@prim: UInt16), |
| DataType::UInt32 => append_list!(@prim: UInt32), |
| DataType::UInt64 => append_list!(@prim: UInt64), |
| DataType::Float32 => append_list!(@prim: Float32), |
| DataType::Float64 => append_list!(@prim: Float64), |
| DataType::Date32 => append_list!(@prim: Date32), |
| DataType::Date64 => append_list!(@prim: Date64), |
| DataType::Boolean => append_list!(@prim: Boolean), |
| DataType::Utf8 => append_list!(@prim: String), |
| DataType::LargeUtf8 => append_list!(@prim: LargeString), |
| DataType::Timestamp(TimeUnit::Second, _) => |
| append_list!(@prim: TimestampSecond), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => |
| append_list!(@prim: TimestampMillisecond), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => |
| append_list!(@prim: TimestampMicrosecond), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => |
| append_list!(@prim: TimestampNanosecond), |
| DataType::Time32(TimeUnit::Second) => append_list!(@prim: Time32Second), |
| DataType::Time32(TimeUnit::Millisecond) => append_list!(@prim: Time32Millisecond), |
| DataType::Time64(TimeUnit::Microsecond) => append_list!(@prim: Time64Microsecond), |
| DataType::Time64(TimeUnit::Nanosecond) => append_list!(@prim: Time64Nanosecond), |
| DataType::Binary => append_list!(@prim: Binary), |
| DataType::LargeBinary => append_list!(@prim: LargeBinary), |
| DataType::Decimal128(_, _) => append_list!(@prim: Decimal128), |
| _ => unimplemented!("list type not supported: {:?}", $data_type), |
| } |
| }}; |
| (@prim: $arrowty:ident) => {{ |
| type ElementType = paste! {[< $arrowty Builder >]}; |
| type B = ListBuilder<ElementType>; |
| type A = ListArray; |
| let t = builder.as_any_mut().downcast_mut::<B>().unwrap(); |
| let f = array.as_any().downcast_ref::<A>().unwrap(); |
| for &i in indices { |
| if f.is_valid(i) { |
| builder_extend(t.values(),&f.value(i),&(0..f.value(i).len()).collect::<Vec<_>>(), f.value(i).data_type()); |
| t.append(true); |
| } else { |
| t.append(false); |
| } |
| } |
| }}; |
| } |
| |
| macro_rules! append_struct { |
| ($fields:expr) => {{ |
| append_struct!(@make: $fields) |
| }}; |
| (@make: $fields:expr) => {{ |
| type B = StructBuilder; |
| type A = StructArray; |
| let t = builder.as_any_mut().downcast_mut::<B>().unwrap(); |
| let f = array.as_any().downcast_ref::<A>().unwrap(); |
| |
| for &i in indices { |
| if f.is_valid(i) { |
| for j in 0..$fields.len() { |
| let field_buidler: &mut dyn ArrayBuilder = match $fields[j].data_type() { |
| DataType::Int8 => t.field_builder::<Int8Builder>(j).unwrap(), |
| DataType::Int16 => t.field_builder::<Int16Builder>(j).unwrap(), |
| DataType::Int32 => t.field_builder::<Int32Builder>(j).unwrap(), |
| DataType::Int64 => t.field_builder::<Int64Builder>(j).unwrap(), |
| DataType::UInt8 => t.field_builder::<UInt8Builder>(j).unwrap(), |
| DataType::UInt16 => t.field_builder::<UInt16Builder>(j).unwrap(), |
| DataType::UInt32 => t.field_builder::<UInt32Builder>(j).unwrap(), |
| DataType::UInt64 => t.field_builder::<UInt64Builder>(j).unwrap(), |
| DataType::Float32 => t.field_builder::<Float32Builder>(j).unwrap(), |
| DataType::Float64 => t.field_builder::<Float64Builder>(j).unwrap(), |
| DataType::Date32 => t.field_builder::<Date32Builder>(j).unwrap(), |
| DataType::Date64 => t.field_builder::<Date64Builder>(j).unwrap(), |
| DataType::Boolean => t.field_builder::<BooleanBuilder>(j).unwrap(), |
| DataType::Utf8 => t.field_builder::<StringBuilder>(j).unwrap(), |
| DataType::LargeUtf8 => t.field_builder::<LargeStringBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Second, _) => t.field_builder::<TimestampSecondBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => t.field_builder::<TimestampMillisecondBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => t.field_builder::<TimestampMicrosecondBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => t.field_builder::<TimestampNanosecondBuilder>(j).unwrap(), |
| DataType::Time32(TimeUnit::Second) => t.field_builder::<Time32SecondBuilder>(j).unwrap(), |
| DataType::Time32(TimeUnit::Millisecond) => t.field_builder::<Time32MillisecondBuilder>(j).unwrap(), |
| DataType::Time64(TimeUnit::Microsecond) => t.field_builder::<Time64MicrosecondBuilder>(j).unwrap(), |
| DataType::Time64(TimeUnit::Nanosecond) => t.field_builder::<Time64NanosecondBuilder>(j).unwrap(), |
| DataType::Binary => t.field_builder::<BinaryBuilder>(j).unwrap(), |
| DataType::LargeBinary => t.field_builder::<LargeBinaryBuilder>(j).unwrap(), |
| DataType::Decimal128(_, _) => t.field_builder::<Decimal128Builder>(j).unwrap(), |
| _ => unimplemented!("struct child data_type not supported: {:?}", $fields[j].data_type()), |
| }; |
| builder_extend(field_buidler, &f.column(j), &[i], $fields[j].data_type()); |
| } |
| t.append(true); |
| } |
| else { |
| builder_append_null(t, &Struct($fields.iter().cloned().collect())); |
| } |
| |
| } |
| }}; |
| } |
| |
| match data_type { |
| DataType::Null => { |
| builder |
| .as_any_mut() |
| .downcast_mut::<NullBuilder>() |
| .unwrap() |
| .extend(indices.len()); |
| } |
| DataType::Boolean => append_simple!(Boolean), |
| DataType::Int8 => append_simple!(Int8), |
| DataType::Int16 => append_simple!(Int16), |
| DataType::Int32 => append_simple!(Int32), |
| DataType::Int64 => append_simple!(Int64), |
| DataType::UInt8 => append_simple!(UInt8), |
| DataType::UInt16 => append_simple!(UInt16), |
| DataType::UInt32 => append_simple!(UInt32), |
| DataType::UInt64 => append_simple!(UInt64), |
| DataType::Float32 => append_simple!(Float32), |
| DataType::Float64 => append_simple!(Float64), |
| DataType::Date32 => append_simple!(Date32), |
| DataType::Date64 => append_simple!(Date64), |
| DataType::Timestamp(TimeUnit::Second, _) => { |
| append_simple!(TimestampSecond) |
| } |
| DataType::Timestamp(TimeUnit::Millisecond, _) => { |
| append_simple!(TimestampMillisecond) |
| } |
| DataType::Timestamp(TimeUnit::Microsecond, _) => { |
| append_simple!(TimestampMicrosecond) |
| } |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => { |
| append_simple!(TimestampNanosecond) |
| } |
| DataType::Time32(TimeUnit::Second) => append_simple!(Time32Second), |
| DataType::Time32(TimeUnit::Millisecond) => append_simple!(Time32Millisecond), |
| DataType::Time64(TimeUnit::Microsecond) => append_simple!(Time64Microsecond), |
| DataType::Time64(TimeUnit::Nanosecond) => append_simple!(Time64Nanosecond), |
| DataType::Binary => append_simple!(Binary), |
| DataType::LargeBinary => append_simple!(LargeBinary), |
| DataType::Utf8 => append_simple!(String), |
| DataType::LargeUtf8 => append_simple!(LargeString), |
| DataType::Decimal128(_, _) => append_simple!(Decimal128), |
| DataType::Dictionary(key_type, value_type) => append_dict!(key_type, value_type), |
| DataType::List(fields) => append_list!(fields.data_type()), |
| DataType::Map(field, _) => { |
| if let DataType::Struct(fields) = field.data_type() { |
| let key_type = fields.first().unwrap().data_type(); |
| let value_type = fields.last().unwrap().data_type(); |
| append_map!(key_type, value_type) |
| } else { |
| unimplemented!("map field not support {}", field) |
| } |
| } |
| DataType::Struct(fields) => append_struct!(fields), |
| dt => unimplemented!("data type not supported in builder_extend: {:?}", dt), |
| } |
| } |
| |
| pub fn builder_append_null(to: &mut (impl ArrayBuilder + ?Sized), data_type: &DataType) { |
| macro_rules! append { |
| ($arrowty:ident) => {{ |
| type B = paste::paste! {[< $arrowty Builder >]}; |
| let t = to.as_any_mut().downcast_mut::<B>().unwrap(); |
| t.append_null(); |
| }}; |
| } |
| |
| macro_rules! append_null_for_list { |
| ($data_type:expr) => {{ |
| append_null_for_list!(@match_type: $data_type) |
| }}; |
| (@match_type: $data_type:expr) => {{ |
| match $data_type { |
| DataType::Int8 => append_null_for_list!(@prim: Int8), |
| DataType::Int16 => append_null_for_list!(@prim: Int16), |
| DataType::Int32 => append_null_for_list!(@prim: Int32), |
| DataType::Int64 => append_null_for_list!(@prim: Int64), |
| DataType::UInt8 => append_null_for_list!(@prim: UInt8), |
| DataType::UInt16 => append_null_for_list!(@prim: UInt16), |
| DataType::UInt32 => append_null_for_list!(@prim: UInt32), |
| DataType::UInt64 => append_null_for_list!(@prim: UInt64), |
| DataType::Float32 => append_null_for_list!(@prim: Float32), |
| DataType::Float64 => append_null_for_list!(@prim: Float64), |
| DataType::Date32 => append_null_for_list!(@prim: Date32), |
| DataType::Date64 => append_null_for_list!(@prim: Date64), |
| DataType::Boolean => append_null_for_list!(@prim: Boolean), |
| DataType::Utf8 => append_null_for_list!(@prim: String), |
| DataType::LargeUtf8 => append_null_for_list!(@prim: LargeString), |
| DataType::Timestamp(TimeUnit::Second, _) => { |
| append_null_for_list!(@prim: TimestampSecond) |
| } |
| DataType::Timestamp(TimeUnit::Millisecond, _) => { |
| append_null_for_list!(@prim: TimestampMillisecond) |
| } |
| DataType::Timestamp(TimeUnit::Microsecond, _) => { |
| append_null_for_list!(@prim: TimestampMicrosecond) |
| } |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => { |
| append_null_for_list!(@prim: TimestampNanosecond) |
| } |
| DataType::Time32(TimeUnit::Second) => append_null_for_list!(@prim: Time32Second), |
| DataType::Time32(TimeUnit::Millisecond) => append_null_for_list!(@prim: Time32Millisecond), |
| DataType::Time64(TimeUnit::Microsecond) => append_null_for_list!(@prim: Time64Microsecond), |
| DataType::Time64(TimeUnit::Nanosecond) => append_null_for_list!(@prim: Time64Nanosecond), |
| DataType::Binary => append_null_for_list!(@prim: Binary), |
| DataType::LargeBinary => append_null_for_list!(@prim: LargeBinary), |
| DataType::Decimal128(_, _) => append_null_for_list!(@prim: Decimal128), |
| _ => unimplemented!("list type not supported: {:?}", $data_type), |
| } |
| }}; |
| (@prim: $arrowty:ident) => {{ |
| type ElementType = paste! {[< $arrowty Builder >]}; |
| type B = ListBuilder<ElementType>; |
| let t = to.as_any_mut().downcast_mut::<B>().unwrap(); |
| t.append(false); |
| }}; |
| } |
| |
| macro_rules! append_null_for_map { |
| ($key_type:expr, $value_type:expr) => {{ |
| append_null_for_map!(@match_key: $key_type, $value_type) |
| }}; |
| (@match_key: $key_type:expr, $value_type:expr) => {{ |
| match $key_type { |
| DataType::Boolean => append_null_for_map!(@match_value: Boolean, $value_type), |
| DataType::Int8 => append_null_for_map!(@match_value: Int8, $value_type), |
| DataType::Int16 => append_null_for_map!(@match_value: Int16, $value_type), |
| DataType::Int32 => append_null_for_map!(@match_value: Int32, $value_type), |
| DataType::Int64 => append_null_for_map!(@match_value: Int64, $value_type), |
| DataType::UInt8 => append_null_for_map!(@match_value: UInt8, $value_type), |
| DataType::UInt16=> append_null_for_map!(@match_value: UInt16, $value_type), |
| DataType::UInt32 => append_null_for_map!(@match_value: UInt32, $value_type), |
| DataType::UInt64 => append_null_for_map!(@match_value: UInt64, $value_type), |
| DataType::Float32 => append_null_for_map!(@match_value: Float32, $value_type), |
| DataType::Float64 => append_null_for_map!(@match_value: Float64, $value_type), |
| DataType::Date32 => append_null_for_map!(@match_value: Date32, $value_type), |
| DataType::Date64 => append_null_for_map!(@match_value: Date64, $value_type), |
| DataType::Timestamp(TimeUnit::Second, _) => |
| append_null_for_map!(@match_value: TimestampSecond, $value_type), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => |
| append_null_for_map!(@match_value: TimestampMillisecond, $value_type), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => |
| append_null_for_map!(@match_value: TimestampMicrosecond, $value_type), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => |
| append_null_for_map!(@match_value: TimestampNanosecond, $value_type), |
| DataType::Utf8 => append_null_for_map!(@match_value: String, $value_type), |
| DataType::LargeUtf8 => append_null_for_map!(@match_value: LargeString, $value_type), |
| DataType::Binary => append_null_for_map!(@match_value: Binary, $value_type), |
| DataType::LargeBinary => append_null_for_map!(@match_value: LargeBinary, $value_type), |
| _ => unimplemented!("map key type not supported: {:?}", $key_type), |
| } |
| }}; |
| (@match_value: $keyarrowty:ident, $value_type:expr) => {{ |
| match $value_type { |
| DataType::Boolean => append_null_for_map!(@prim: $keyarrowty, Boolean), |
| DataType::Int8 => append_null_for_map!(@prim: $keyarrowty, Int8), |
| DataType::Int16 => append_null_for_map!(@prim: $keyarrowty, Int16), |
| DataType::Int32 => append_null_for_map!(@prim: $keyarrowty, Int32), |
| DataType::Int64 => append_null_for_map!(@prim: $keyarrowty, Int64), |
| DataType::UInt8 => append_null_for_map!(@prim: $keyarrowty, UInt8), |
| DataType::UInt16 => append_null_for_map!(@prim: $keyarrowty, UInt16), |
| DataType::UInt32 => append_null_for_map!(@prim: $keyarrowty, UInt32), |
| DataType::UInt64 => append_null_for_map!(@prim: $keyarrowty, UInt64), |
| DataType::Float32 => append_null_for_map!(@prim: $keyarrowty, Float32), |
| DataType::Float64 => append_null_for_map!(@prim: $keyarrowty, Float64), |
| DataType::Date32 => append_null_for_map!(@prim: $keyarrowty, Date32), |
| DataType::Date64 => append_null_for_map!(@prim: $keyarrowty, Date64), |
| DataType::Timestamp(TimeUnit::Second, _) => append_null_for_map!(@prim: $keyarrowty, TimestampSecond), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => append_null_for_map!(@prim: $keyarrowty, TimestampMillisecond), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => append_null_for_map!(@prim: $keyarrowty, TimestampMicrosecond), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => append_null_for_map!(@prim: $keyarrowty, TimestampNanosecond), |
| DataType::Utf8 => append_null_for_map!(@prim: $keyarrowty, String), |
| DataType::LargeUtf8 => append_null_for_map!(@prim: $keyarrowty, LargeString), |
| DataType::Binary => append_null_for_map!(@prim: $keyarrowty, Binary), |
| DataType::LargeBinary => append_null_for_map!(@prim: $keyarrowty, LargeBinary), |
| _ => unimplemented!("map value type not supported: {:?}", $value_type), |
| } |
| }}; |
| (@prim: $keyarrowty:ident, $valuearrowty:ident) => {{ |
| type KeyType = paste! {[< $keyarrowty Builder >]}; |
| type ValueType = paste! {[< $valuearrowty Builder >]}; |
| type B = MapBuilder<KeyType, ValueType>; |
| let t = to.as_any_mut().downcast_mut::<B>().unwrap(); |
| t.append(false).expect("map append_null() error"); |
| }}; |
| } |
| |
| macro_rules! append_null_for_struct { |
| ($fields:expr) => {{ |
| append_null_for_struct!(@make: $fields) |
| }}; |
| (@make: $fields:expr) => {{ |
| type B = StructBuilder; |
| let t = to.as_any_mut().downcast_mut::<B>().unwrap(); |
| for j in 0..$fields.len() { |
| let field_buidler: &mut dyn ArrayBuilder = match $fields[j].data_type() { |
| DataType::Int8 => t.field_builder::<Int8Builder>(j).unwrap(), |
| DataType::Int16 => t.field_builder::<Int16Builder>(j).unwrap(), |
| DataType::Int32 => t.field_builder::<Int32Builder>(j).unwrap(), |
| DataType::Int64 => t.field_builder::<Int64Builder>(j).unwrap(), |
| DataType::UInt8 => t.field_builder::<UInt8Builder>(j).unwrap(), |
| DataType::UInt16 => t.field_builder::<UInt16Builder>(j).unwrap(), |
| DataType::UInt32 => t.field_builder::<UInt32Builder>(j).unwrap(), |
| DataType::UInt64 => t.field_builder::<UInt64Builder>(j).unwrap(), |
| DataType::Float32 => t.field_builder::<Float32Builder>(j).unwrap(), |
| DataType::Float64 => t.field_builder::<Float64Builder>(j).unwrap(), |
| DataType::Date32 => t.field_builder::<Date32Builder>(j).unwrap(), |
| DataType::Date64 => t.field_builder::<Date64Builder>(j).unwrap(), |
| DataType::Boolean => t.field_builder::<BooleanBuilder>(j).unwrap(), |
| DataType::Utf8 => t.field_builder::<StringBuilder>(j).unwrap(), |
| DataType::LargeUtf8 => t.field_builder::<LargeStringBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Second, _) => t.field_builder::<TimestampSecondBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => t.field_builder::<TimestampMillisecondBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => t.field_builder::<TimestampMicrosecondBuilder>(j).unwrap(), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => t.field_builder::<TimestampNanosecondBuilder>(j).unwrap(), |
| DataType::Time32(TimeUnit::Second) => t.field_builder::<Time32SecondBuilder>(j).unwrap(), |
| DataType::Time32(TimeUnit::Millisecond) => t.field_builder::<Time32MillisecondBuilder>(j).unwrap(), |
| DataType::Time64(TimeUnit::Microsecond) => t.field_builder::<Time64MicrosecondBuilder>(j).unwrap(), |
| DataType::Time64(TimeUnit::Nanosecond) => t.field_builder::<Time64NanosecondBuilder>(j).unwrap(), |
| DataType::Binary => t.field_builder::<BinaryBuilder>(j).unwrap(), |
| DataType::LargeBinary => t.field_builder::<LargeBinaryBuilder>(j).unwrap(), |
| DataType::Decimal128(_, _) => t.field_builder::<Decimal128Builder>(j).unwrap(), |
| _ => unimplemented!("struct child data_type not supported: {:?}", $fields[j].data_type()), |
| }; |
| builder_append_null(field_buidler, $fields[j].data_type()); |
| } |
| t.append_null(); |
| }}; |
| } |
| |
| match data_type { |
| DataType::Null => { |
| to.as_any_mut() |
| .downcast_mut::<NullBuilder>() |
| .unwrap() |
| .append(); |
| } |
| DataType::Boolean => append!(Boolean), |
| DataType::Int8 => append!(Int8), |
| DataType::Int16 => append!(Int16), |
| DataType::Int32 => append!(Int32), |
| DataType::Int64 => append!(Int64), |
| DataType::UInt8 => append!(UInt8), |
| DataType::UInt16 => append!(UInt16), |
| DataType::UInt32 => append!(UInt32), |
| DataType::UInt64 => append!(UInt64), |
| DataType::Float32 => append!(Float32), |
| DataType::Float64 => append!(Float64), |
| DataType::Date32 => append!(Date32), |
| DataType::Date64 => append!(Date64), |
| DataType::Timestamp(TimeUnit::Second, _) => append!(TimestampSecond), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => append!(TimestampMillisecond), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => append!(TimestampMicrosecond), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => append!(TimestampNanosecond), |
| DataType::Time32(TimeUnit::Second) => append!(Time32Second), |
| DataType::Time32(TimeUnit::Millisecond) => append!(Time32Millisecond), |
| DataType::Time64(TimeUnit::Microsecond) => append!(Time64Microsecond), |
| DataType::Time64(TimeUnit::Nanosecond) => append!(Time64Nanosecond), |
| DataType::Binary => append!(Binary), |
| DataType::LargeBinary => append!(LargeBinary), |
| DataType::Utf8 => append!(String), |
| DataType::LargeUtf8 => append!(LargeString), |
| DataType::Decimal128(_, _) => append!(Decimal128), |
| DataType::List(field) => append_null_for_list!(field.data_type()), |
| DataType::Map(field, _) => { |
| if let DataType::Struct(fields) = field.data_type() { |
| let key_type = fields.first().unwrap().data_type(); |
| let value_type = fields.last().unwrap().data_type(); |
| append_null_for_map!(key_type, value_type) |
| } else { |
| unimplemented!("map field not support {}", field) |
| } |
| } |
| DataType::Struct(fields) => append_null_for_struct!(fields), |
| dt => unimplemented!("data type not supported in builder_append_null: {:?}", dt), |
| } |
| } |
| |
| fn new_array_builder(dt: &DataType, batch_size: usize) -> Box<dyn ArrayBuilder> { |
| macro_rules! make_dictionary_builder { |
| ($key_type:expr, $value_type:expr) => {{ |
| match $key_type.as_ref() { |
| DataType::Int8 => make_dictionary_builder!(@match_value: Int8, $value_type), |
| DataType::Int16 => make_dictionary_builder!(@match_value: Int16, $value_type), |
| DataType::Int32 => make_dictionary_builder!(@match_value: Int32, $value_type), |
| DataType::Int64 => make_dictionary_builder!(@match_value: Int64, $value_type), |
| DataType::UInt8 => make_dictionary_builder!(@match_value: UInt8, $value_type), |
| DataType::UInt16 => make_dictionary_builder!(@match_value: UInt16, $value_type), |
| DataType::UInt32 => make_dictionary_builder!(@match_value: UInt32, $value_type), |
| DataType::UInt64 => make_dictionary_builder!(@match_value: UInt64, $value_type), |
| _ => unimplemented!("unsupported dictionary key type: {:?}", $key_type), |
| } |
| }}; |
| (@match_value: $keyarrowty:ident, $value_type:expr) => {{ |
| match $value_type.as_ref() { |
| DataType::Int8 => make_dictionary_builder!(@make: $keyarrowty, Int8), |
| DataType::Int16 => make_dictionary_builder!(@make: $keyarrowty, Int16), |
| DataType::Int32 => make_dictionary_builder!(@make: $keyarrowty, Int32), |
| DataType::Int64 => make_dictionary_builder!(@make: $keyarrowty, Int64), |
| DataType::UInt8 => make_dictionary_builder!(@make: $keyarrowty, UInt8), |
| DataType::UInt16 => make_dictionary_builder!(@make: $keyarrowty, UInt16), |
| DataType::UInt32 => make_dictionary_builder!(@make: $keyarrowty, UInt32), |
| DataType::UInt64 => make_dictionary_builder!(@make: $keyarrowty, UInt64), |
| DataType::Float32 => make_dictionary_builder!(@make: $keyarrowty, Float32), |
| DataType::Float64 => make_dictionary_builder!(@make: $keyarrowty, Float64), |
| DataType::Date32 => make_dictionary_builder!(@make: $keyarrowty, Date32), |
| DataType::Date64 => make_dictionary_builder!(@make: $keyarrowty, Date64), |
| DataType::Timestamp(TimeUnit::Second, _) => { |
| make_dictionary_builder!(@make: $keyarrowty, TimestampSecond) |
| } |
| DataType::Timestamp(TimeUnit::Millisecond, _) => { |
| make_dictionary_builder!(@make: $keyarrowty, TimestampMillisecond) |
| } |
| DataType::Timestamp(TimeUnit::Microsecond, _) => { |
| make_dictionary_builder!(@make: $keyarrowty, TimestampMicrosecond) |
| } |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => { |
| make_dictionary_builder!(@make: $keyarrowty, TimestampNanosecond) |
| } |
| DataType::Utf8 | DataType::LargeUtf8 => { |
| make_dictionary_builder!(@make_str: $keyarrowty) |
| } |
| _ => unimplemented!("dictionary value type not supported: {:?}", $value_type), |
| } |
| }}; |
| (@make: $keyarrowty:ident, $valuearrowty:ident) => {{ |
| type KeyType = paste! {[< $keyarrowty Type >]}; |
| type ValueType = paste! {[< $valuearrowty Type >]}; |
| Box::new(PrimitiveDictionaryBuilder::<KeyType, ValueType>::new()) |
| }}; |
| (@make_str: $keyarrowty:ident) => {{ |
| type KeyType = paste! {[< $keyarrowty Type >]}; |
| Box::new(StringDictionaryBuilder::<KeyType>::new()) |
| }}; |
| } |
| |
| macro_rules! make_list_builder { |
| ($data_type:expr) => {{ |
| match $data_type { |
| DataType::Int8 => make_list_builder!(@make: Int8), |
| DataType::Int16 => make_list_builder!(@make: Int16), |
| DataType::Int32 => make_list_builder!(@make: Int32), |
| DataType::Int64 => make_list_builder!(@make: Int64), |
| DataType::UInt8 => make_list_builder!(@make: UInt8), |
| DataType::UInt16 => make_list_builder!(@make: UInt16), |
| DataType::UInt32 => make_list_builder!(@make: UInt32), |
| DataType::UInt64 => make_list_builder!(@make: UInt64), |
| DataType::Float32 => make_list_builder!(@make: Float32), |
| DataType::Float64 => make_list_builder!(@make: Float64), |
| DataType::Date32 => make_list_builder!(@make: Date32), |
| DataType::Date64 => make_list_builder!(@make: Date64), |
| DataType::Timestamp(TimeUnit::Second, _) => { |
| make_list_builder!(@make: TimestampSecond) |
| } |
| DataType::Timestamp(TimeUnit::Millisecond, _) => { |
| make_list_builder!(@make: TimestampMillisecond) |
| } |
| DataType::Timestamp(TimeUnit::Microsecond, _) => { |
| make_list_builder!(@make: TimestampMicrosecond) |
| } |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => { |
| make_list_builder!(@make: TimestampNanosecond) |
| } |
| DataType::Boolean => make_list_builder!(@make: Boolean), |
| DataType::Decimal128(prec, scale) => { |
| make_list_builder!(@make_decimal: Decimal128(prec, scale)) |
| } |
| DataType::Utf8 => make_list_builder!(@make: String), |
| DataType::LargeUtf8 => make_list_builder!(@make: LargeString), |
| DataType::Binary => make_list_builder!(@make: Binary), |
| DataType::LargeBinary => make_list_builder!(@make: LargeBinary), |
| _ => unimplemented!("unsupported list data type: {:?}", $data_type), |
| } |
| }}; |
| (@make: $arrowty:ident) => {{ |
| type TypeBuilder = paste! {[< $arrowty Builder >]}; |
| Box::new(ListBuilder::with_capacity( |
| TypeBuilder::new(), |
| batch_size, |
| )) |
| }}; |
| (@make_decimal: $arrowty:ident($prec:expr, $scale:expr)) => {{ |
| type TypeBuilder = paste! {[< $arrowty Builder >]}; |
| Box::new(ListBuilder::with_capacity( |
| TypeBuilder::new().with_data_type(DataType::Decimal128($prec, $scale)), |
| batch_size, |
| )) |
| }}; |
| } |
| |
| macro_rules! make_map_builder { |
| ($key_type:expr, $value_type:expr, $map_fields_name:expr) => {{ |
| match $key_type { |
| DataType::Boolean => make_map_builder!(@match_value: Boolean, $value_type, $map_fields_name), |
| DataType::Int8 => make_map_builder!(@match_value: Int8, $value_type, $map_fields_name), |
| DataType::Int16 => make_map_builder!(@match_value: Int16, $value_type, $map_fields_name), |
| DataType::Int32 => make_map_builder!(@match_value: Int32, $value_type, $map_fields_name), |
| DataType::Int64 => make_map_builder!(@match_value: Int64, $value_type, $map_fields_name), |
| DataType::UInt8 => make_map_builder!(@match_value: UInt8, $value_type, $map_fields_name), |
| DataType::UInt16 => make_map_builder!(@match_value: UInt16, $value_type, $map_fields_name), |
| DataType::UInt32 => make_map_builder!(@match_value: UInt32, $value_type, $map_fields_name), |
| DataType::UInt64 => make_map_builder!(@match_value: UInt64, $value_type, $map_fields_name), |
| DataType::Float32 => make_map_builder!(@match_value: Float32, $value_type, $map_fields_name), |
| DataType::Float64 => make_map_builder!(@match_value: Float64, $value_type, $map_fields_name), |
| DataType::Date32 => make_map_builder!(@match_value: Date32, $value_type, $map_fields_name), |
| DataType::Date64 => make_map_builder!(@match_value: Date64, $value_type, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Second, _) => make_map_builder!(@match_value: TimestampSecond, $value_type, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => make_map_builder!(@match_value: TimestampMillisecond, $value_type, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => make_map_builder!(@match_value: TimestampMicrosecond, $value_type, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => make_map_builder!(@match_value: TimestampNanosecond, $value_type, $map_fields_name), |
| DataType::Utf8 => make_map_builder!(@match_value: String, $value_type, $map_fields_name), |
| DataType::LargeUtf8 => make_map_builder!(@match_value: LargeString, $value_type, $map_fields_name), |
| DataType::Binary => make_map_builder!(@match_value: Binary, $value_type, $map_fields_name), |
| DataType::LargeBinary => make_map_builder!(@match_value: LargeBinary, $value_type, $map_fields_name), |
| _ => unimplemented!("unsupported map key type: {:?}", $key_type), |
| } |
| }}; |
| (@match_value: $keyarrowty:ident, $value_type:expr, $map_fields_name:expr) => {{ |
| match $value_type { |
| DataType::Boolean => make_map_builder!(@make: $keyarrowty, Boolean, $map_fields_name), |
| DataType::Int8 => make_map_builder!(@make: $keyarrowty, Int8, $map_fields_name), |
| DataType::Int16 => make_map_builder!(@make: $keyarrowty, Int16, $map_fields_name), |
| DataType::Int32 => make_map_builder!(@make: $keyarrowty, Int32, $map_fields_name), |
| DataType::Int64 => make_map_builder!(@make: $keyarrowty, Int64, $map_fields_name), |
| DataType::UInt8 => make_map_builder!(@make: $keyarrowty, UInt8, $map_fields_name), |
| DataType::UInt16 => make_map_builder!(@make: $keyarrowty, UInt16, $map_fields_name), |
| DataType::UInt32 => make_map_builder!(@make: $keyarrowty, UInt32, $map_fields_name), |
| DataType::UInt64 => make_map_builder!(@make: $keyarrowty, UInt64, $map_fields_name), |
| DataType::Float32 => make_map_builder!(@make: $keyarrowty, Float32, $map_fields_name), |
| DataType::Float64 => make_map_builder!(@make: $keyarrowty, Float64, $map_fields_name), |
| DataType::Date32 => make_map_builder!(@make: $keyarrowty, Date32, $map_fields_name), |
| DataType::Date64 => make_map_builder!(@make: $keyarrowty, Date64, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Second, _) => make_map_builder!(@make: $keyarrowty, TimestampSecond, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Millisecond, _) => make_map_builder!(@make: $keyarrowty, TimestampMillisecond, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Microsecond, _) => make_map_builder!(@make: $keyarrowty, TimestampMicrosecond, $map_fields_name), |
| DataType::Timestamp(TimeUnit::Nanosecond, _) => make_map_builder!(@make: $keyarrowty, TimestampNanosecond, $map_fields_name), |
| DataType::Utf8 => make_map_builder!(@make: $keyarrowty, String, $map_fields_name), |
| DataType::LargeUtf8 => make_map_builder!(@make: $keyarrowty, LargeString, $map_fields_name), |
| DataType::Binary => make_map_builder!(@make: $keyarrowty, Binary, $map_fields_name), |
| DataType::LargeBinary => make_map_builder!(@make: $keyarrowty, LargeBinary, $map_fields_name), |
| _ => unimplemented!("map value type not supported: {:?}", $value_type), |
| } |
| }}; |
| (@make: $keyarrowty:ident, $valuearrowty:ident, $map_fields_name:expr) => {{ |
| type KeyBuilder = paste! {[< $keyarrowty Builder >]}; |
| type ValueBuilder = paste! {[< $valuearrowty Builder >]}; |
| Box::new(MapBuilder::with_capacity( |
| $map_fields_name, |
| KeyBuilder::new(), |
| ValueBuilder::new(), |
| batch_size, |
| )) |
| }}; |
| |
| } |
| |
| match dt { |
| DataType::Null => Box::new(NullBuilder::new()), |
| DataType::Dictionary(key_type, value_type) => { |
| make_dictionary_builder!(key_type, value_type) |
| } |
| DataType::List(fields) => { |
| make_list_builder!(fields.data_type().clone()) |
| } |
| DataType::Map(field, _) => { |
| if let Struct(fields) = field.data_type() { |
| let map_fields_name = Some(MapFieldNames { |
| entry: "entries".to_string(), |
| key: "key".to_string(), |
| value: "value".to_string(), |
| }); |
| let key_type = fields.first().unwrap().data_type().clone(); |
| let value_type = fields.last().unwrap().data_type().clone(); |
| make_map_builder!(key_type, value_type, map_fields_name) |
| } else { |
| unimplemented!("map field not support {}", field); |
| } |
| } |
| dt => make_builder(dt, batch_size), |
| } |
| } |
| |
| pub struct NullBuilder { |
| len: usize, |
| } |
| impl Default for NullBuilder { |
| fn default() -> Self { |
| Self::new() |
| } |
| } |
| |
| impl NullBuilder { |
| pub fn new() -> Self { |
| Self { len: 0 } |
| } |
| |
| pub fn append(&mut self) { |
| self.len += 1; |
| } |
| |
| pub fn extend(&mut self, len: usize) { |
| self.len += len; |
| } |
| } |
| |
| impl ArrayBuilder for NullBuilder { |
| fn len(&self) -> usize { |
| self.len |
| } |
| |
| fn is_empty(&self) -> bool { |
| self.len == 0 |
| } |
| |
| fn finish(&mut self) -> ArrayRef { |
| self.finish_cloned() |
| } |
| |
| fn finish_cloned(&self) -> ArrayRef { |
| Arc::new(NullArray::new(self.len)) |
| } |
| |
| fn as_any(&self) -> &dyn Any { |
| self |
| } |
| |
| fn as_any_mut(&mut self) -> &mut dyn Any { |
| self |
| } |
| |
| fn into_box_any(self: Box<Self>) -> Box<dyn Any> { |
| self |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use arrow::array::{ArrayRef, Int32Array, StringArray, StructArray}; |
| use arrow::record_batch::RecordBatch; |
| use datafusion::assert_batches_eq; |
| use std::sync::Arc; |
| |
| #[test] |
| fn test_struct_array_from_vec() { |
| let strings: ArrayRef = Arc::new(StringArray::from(vec![ |
| Some("joe"), |
| None, |
| None, |
| Some("mark"), |
| ])); |
| let ints: ArrayRef = Arc::new(Int32Array::from(vec![Some(1), Some(2), None, Some(4)])); |
| let arr = |
| StructArray::try_from(vec![("f1", strings.clone()), ("f2", ints.clone())]).unwrap(); |
| |
| let arr_into_batch = RecordBatch::try_from(arr).unwrap(); |
| let expected = vec![ |
| "+------+----+", |
| "| f1 | f2 |", |
| "+------+----+", |
| "| joe | 1 |", |
| "| | 2 |", |
| "| | |", |
| "| mark | 4 |", |
| "+------+----+", |
| ]; |
| assert_batches_eq!(expected, &[arr_into_batch]); |
| } |
| } |