diff --git a/datafusion/functions-nested/src/concat.rs b/datafusion/functions-nested/src/concat.rs index 5dc437b3c20b5..daedbe429e943 100644 --- a/datafusion/functions-nested/src/concat.rs +++ b/datafusion/functions-nested/src/concat.rs @@ -33,7 +33,7 @@ use datafusion_common::utils::{ }; use datafusion_common::{ cast::as_generic_list_array, - exec_err, plan_err, + exec_err, internal_err, plan_err, utils::{list_ndims, take_function_args}, }; use datafusion_expr::binary::type_union_resolution; @@ -439,10 +439,21 @@ fn concat_internal(args: &[ArrayRef]) -> Result { } let data_type = list_arrays[0].value_type(); + // Preserve the input list's inner field (name, nullability, metadata) instead + // of creating a new default field, matching the promised return type. + let field = match list_arrays[0].data_type() { + DataType::List(field) | DataType::LargeList(field) => Arc::clone(field), + other => { + return internal_err!( + "array_concat got unexpected data type: {}", + other + ); + } + }; let data = mutable.freeze(); Ok(Arc::new(GenericListArray::::try_new( - Arc::new(Field::new_list_field(data_type, true)), + field, OffsetBuffer::new(offsets.into()), arrow::array::make_array(data), valid, @@ -564,8 +575,20 @@ where let data = mutable.freeze(); + // Preserve the input list's inner field (name, nullability, metadata) instead + // of creating a new default field, matching the promised return type. + let field = match list_array.data_type() { + DataType::List(field) | DataType::LargeList(field) => Arc::clone(field), + other => { + return internal_err!( + "array_append/array_prepend got unexpected data type: {}", + other + ); + } + }; + Ok(Arc::new(GenericListArray::::try_new( - Arc::new(Field::new_list_field(data_type.to_owned(), true)), + field, OffsetBuffer::new(offsets.into()), arrow::array::make_array(data), None, diff --git a/datafusion/functions-nested/src/replace.rs b/datafusion/functions-nested/src/replace.rs index 71d6f578158f4..a9ab0760ea9cc 100644 --- a/datafusion/functions-nested/src/replace.rs +++ b/datafusion/functions-nested/src/replace.rs @@ -25,7 +25,7 @@ use arrow::buffer::OffsetBuffer; use arrow::datatypes::{DataType, Field}; use datafusion_common::cast::as_int64_array; use datafusion_common::utils::ListCoercion; -use datafusion_common::{Result, ScalarValue, exec_err, utils::take_function_args}; +use datafusion_common::{Result, ScalarValue, exec_err, internal_err, utils::take_function_args}; use datafusion_expr::{ ArrayFunctionArgument, ArrayFunctionSignature, ColumnarValue, Documentation, ScalarFunctionArgs, ScalarUDFImpl, Signature, TypeSignature, Volatility, @@ -501,8 +501,20 @@ fn general_replace( let data = mutable.freeze(); + // Preserve the input list's inner field (name, nullability, metadata) instead + // of creating a new default field, matching the promised return type. + let field = match list_array.data_type() { + DataType::List(field) | DataType::LargeList(field) => Arc::clone(field), + other => { + return internal_err!( + "array_replace got unexpected data type: {}", + other + ); + } + }; + Ok(Arc::new(GenericListArray::::try_new( - Arc::new(Field::new_list_field(list_array.value_type(), true)), + field, OffsetBuffer::::new(offsets.into()), arrow::array::make_array(data), valid.finish(), @@ -597,8 +609,20 @@ fn general_replace_with_scalar( let data = mutable.freeze(); + // Preserve the input list's inner field (name, nullability, metadata) instead + // of creating a new default field, matching the promised return type. + let field = match list_array.data_type() { + DataType::List(field) | DataType::LargeList(field) => Arc::clone(field), + other => { + return internal_err!( + "array_replace got unexpected data type: {}", + other + ); + } + }; + Ok(Arc::new(GenericListArray::::try_new( - Arc::new(Field::new_list_field(list_array.value_type(), true)), + field, OffsetBuffer::new(offsets.into()), arrow::array::make_array(data), list_array.nulls().cloned(),