diff --git a/arrow-json/src/reader/list_array.rs b/arrow-json/src/reader/list_array.rs index 81fe4e3ffab..d363b6be978 100644 --- a/arrow-json/src/reader/list_array.rs +++ b/arrow-json/src/reader/list_array.rs @@ -34,18 +34,18 @@ pub struct ListArrayDecoder { impl ListArrayDecoder { pub fn new( ctx: &DecoderContext, - data_type: DataType, + data_type: &DataType, is_nullable: bool, ) -> Result { - let field = match &data_type { + let field = match data_type { DataType::List(f) if !O::IS_LARGE => f, DataType::LargeList(f) if O::IS_LARGE => f, _ => unreachable!(), }; - let decoder = ctx.make_decoder(field.data_type().clone(), field.is_nullable())?; + let decoder = ctx.make_decoder(field.data_type(), field.is_nullable())?; Ok(Self { - data_type, + data_type: data_type.clone(), decoder, phantom: Default::default(), is_nullable, diff --git a/arrow-json/src/reader/map_array.rs b/arrow-json/src/reader/map_array.rs index 3c19cb3eb50..ff22b588c51 100644 --- a/arrow-json/src/reader/map_array.rs +++ b/arrow-json/src/reader/map_array.rs @@ -33,10 +33,10 @@ pub struct MapArrayDecoder { impl MapArrayDecoder { pub fn new( ctx: &DecoderContext, - data_type: DataType, + data_type: &DataType, is_nullable: bool, ) -> Result { - let fields = match &data_type { + let fields = match data_type { DataType::Map(_, true) => { return Err(ArrowError::NotYetImplemented( "Decoding MapArray with sorted fields".to_string(), @@ -53,11 +53,11 @@ impl MapArrayDecoder { _ => unreachable!(), }; - let keys = ctx.make_decoder(fields[0].data_type().clone(), fields[0].is_nullable())?; - let values = ctx.make_decoder(fields[1].data_type().clone(), fields[1].is_nullable())?; + let keys = ctx.make_decoder(fields[0].data_type(), fields[0].is_nullable())?; + let values = ctx.make_decoder(fields[1].data_type(), fields[1].is_nullable())?; Ok(Self { - data_type, + data_type: data_type.clone(), keys, values, is_nullable, diff --git a/arrow-json/src/reader/mod.rs b/arrow-json/src/reader/mod.rs index 6b3ab0097fe..1a63ea75653 100644 --- a/arrow-json/src/reader/mod.rs +++ b/arrow-json/src/reader/mod.rs @@ -137,6 +137,7 @@ use crate::StructMode; use crate::reader::binary_array::{ BinaryArrayDecoder, BinaryViewDecoder, FixedSizeBinaryArrayDecoder, }; +use std::borrow::Cow; use std::io::BufRead; use std::sync::Arc; @@ -295,12 +296,13 @@ impl ReaderBuilder { /// Create a [`Decoder`] pub fn build_decoder(self) -> Result { - let (data_type, nullable) = match self.is_field { - false => (DataType::Struct(self.schema.fields.clone()), false), - true => { - let field = &self.schema.fields[0]; - (field.data_type().clone(), field.is_nullable()) - } + let (data_type, nullable) = if self.is_field { + let field = &self.schema.fields[0]; + let data_type = Cow::Borrowed(field.data_type()); + (data_type, field.is_nullable()) + } else { + let data_type = Cow::Owned(DataType::Struct(self.schema.fields.clone())); + (data_type, false) }; let ctx = DecoderContext { @@ -308,7 +310,7 @@ impl ReaderBuilder { strict_mode: self.strict_mode, struct_mode: self.struct_mode, }; - let decoder = ctx.make_decoder(data_type, nullable)?; + let decoder = ctx.make_decoder(data_type.as_ref(), nullable)?; let num_fields = self.schema.flattened_fields().len(); @@ -713,7 +715,7 @@ impl DecoderContext { /// implementation. fn make_decoder( &self, - data_type: DataType, + data_type: &DataType, is_nullable: bool, ) -> Result, ArrowError> { make_decoder(self, data_type, is_nullable) @@ -728,12 +730,12 @@ macro_rules! primitive_decoder { fn make_decoder( ctx: &DecoderContext, - data_type: DataType, + data_type: &DataType, is_nullable: bool, ) -> Result, ArrowError> { let coerce_primitive = ctx.coerce_primitive(); downcast_integer! { - data_type => (primitive_decoder, data_type), + *data_type => (primitive_decoder, data_type), DataType::Null => Ok(Box::::default()), DataType::Float16 => primitive_decoder!(Float16Type, data_type), DataType::Float32 => primitive_decoder!(Float32Type, data_type), @@ -792,7 +794,7 @@ fn make_decoder( DataType::FixedSizeBinary(len) => Ok(Box::new(FixedSizeBinaryArrayDecoder::new(len))), DataType::BinaryView => Ok(Box::new(BinaryViewDecoder::default())), DataType::Map(_, _) => Ok(Box::new(MapArrayDecoder::new(ctx, data_type, is_nullable)?)), - d => Err(ArrowError::NotYetImplemented(format!("Support for {d} in JSON reader"))) + _ => Err(ArrowError::NotYetImplemented(format!("Support for {data_type} in JSON reader"))) } } diff --git a/arrow-json/src/reader/primitive_array.rs b/arrow-json/src/reader/primitive_array.rs index fa8464aa325..b2bffe45e43 100644 --- a/arrow-json/src/reader/primitive_array.rs +++ b/arrow-json/src/reader/primitive_array.rs @@ -80,9 +80,9 @@ pub struct PrimitiveArrayDecoder { } impl PrimitiveArrayDecoder

{ - pub fn new(data_type: DataType) -> Self { + pub fn new(data_type: &DataType) -> Self { Self { - data_type, + data_type: data_type.clone(), phantom: Default::default(), } } diff --git a/arrow-json/src/reader/struct_array.rs b/arrow-json/src/reader/struct_array.rs index 915c0607fdf..9191afb8e63 100644 --- a/arrow-json/src/reader/struct_array.rs +++ b/arrow-json/src/reader/struct_array.rs @@ -81,20 +81,22 @@ pub struct StructArrayDecoder { impl StructArrayDecoder { pub fn new( ctx: &DecoderContext, - data_type: DataType, + data_type: &DataType, is_nullable: bool, ) -> Result { - let struct_mode = ctx.struct_mode(); - let fields = struct_fields(&data_type); - - // If this struct nullable, need to permit nullability in child array - // StructArrayDecoder::decode verifies that if the child is not nullable - // it doesn't contain any nulls not masked by its parent + let fields = struct_fields(data_type); let decoders = fields .iter() - .map(|f| ctx.make_decoder(f.data_type().clone(), f.is_nullable() || is_nullable)) + .map(|f| { + // If this struct nullable, need to permit nullability in child array + // StructArrayDecoder::decode verifies that if the child is not nullable + // it doesn't contain any nulls not masked by its parent + let nullable = f.is_nullable() || is_nullable; + ctx.make_decoder(f.data_type(), nullable) + }) .collect::, ArrowError>>()?; + let struct_mode = ctx.struct_mode(); let field_name_to_index = if struct_mode == StructMode::ObjectOnly { build_field_index(fields) } else { @@ -102,7 +104,7 @@ impl StructArrayDecoder { }; Ok(Self { - data_type, + data_type: data_type.clone(), decoders, strict_mode: ctx.strict_mode(), is_nullable, diff --git a/arrow-json/src/reader/timestamp_array.rs b/arrow-json/src/reader/timestamp_array.rs index 79f2b04eeba..ff24d5391f9 100644 --- a/arrow-json/src/reader/timestamp_array.rs +++ b/arrow-json/src/reader/timestamp_array.rs @@ -37,9 +37,9 @@ pub struct TimestampArrayDecoder { } impl TimestampArrayDecoder { - pub fn new(data_type: DataType, timezone: Tz) -> Self { + pub fn new(data_type: &DataType, timezone: Tz) -> Self { Self { - data_type, + data_type: data_type.clone(), timezone, phantom: Default::default(), }