diff --git a/datafusion/expr-common/src/type_coercion/binary.rs b/datafusion/expr-common/src/type_coercion/binary.rs index 861e57ba7383..510b70a0be73 100644 --- a/datafusion/expr-common/src/type_coercion/binary.rs +++ b/datafusion/expr-common/src/type_coercion/binary.rs @@ -595,7 +595,7 @@ fn type_union_resolution_coercion( /// Handle type union resolution including struct type and others. pub fn try_type_union_resolution(data_types: &[DataType]) -> Result> { - let err = match try_type_union_resolution_with_struct(data_types) { + let err = match try_type_union_resolution_with_struct(data_types, false) { Ok(struct_types) => return Ok(struct_types), Err(e) => Some(e), }; @@ -611,6 +611,7 @@ pub fn try_type_union_resolution(data_types: &[DataType]) -> Result Result> { let mut keys_string: Option = None; for data_type in data_types { @@ -632,6 +633,12 @@ pub fn try_type_union_resolution_with_struct( } } + let first_fields = if let DataType::Struct(fields) = &data_types[0] { + fields.clone() + } else { + return internal_err!("Struct type is checked is the previous function, so this should be unreachable"); + }; + let mut struct_types_map: HashMap = if let DataType::Struct( fields, ) = &data_types[0] @@ -650,7 +657,7 @@ pub fn try_type_union_resolution_with_struct( let field_name = field.name(); if let Some(existing_type) = struct_types_map.get_mut(field_name) { if let Some(coerced_type) = - type_union_resolution_coercion(&field.data_type(), existing_type) + type_union_resolution_coercion(field.data_type(), existing_type) { *existing_type = coerced_type; } else { @@ -669,6 +676,20 @@ pub fn try_type_union_resolution_with_struct( } } + if is_unique { + let new_fields = + first_fields + .iter() + .map(|f| { + Arc::new(Arc::unwrap_or_clone(Arc::clone(f)).with_data_type( + struct_types_map.get(f.name()).unwrap().to_owned(), + )) + }) + .collect(); + let unified_struct = DataType::Struct(new_fields); + return Ok(vec![unified_struct; data_types.len()]); + } + let mut final_struct_types = vec![]; for s in data_types { let mut new_fields = vec![]; diff --git a/datafusion/functions-nested/src/make_array.rs b/datafusion/functions-nested/src/make_array.rs index 6bc1f6f2c2d1..e5337504b6d5 100644 --- a/datafusion/functions-nested/src/make_array.rs +++ b/datafusion/functions-nested/src/make_array.rs @@ -128,7 +128,7 @@ impl ScalarUDFImpl for MakeArray { fn coerce_types(&self, arg_types: &[DataType]) -> Result> { let mut errors = vec![]; - match try_type_union_resolution_with_struct(arg_types) { + match try_type_union_resolution_with_struct(arg_types, true) { Ok(r) => return Ok(r), Err(e) => { errors.push(e);