This is an automated email from the ASF dual-hosted git repository.

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new edbdefe0fd Support `array_concat` for `Utf8View` (#14378)
edbdefe0fd is described below

commit edbdefe0fd20285aeac4a5dee1e8c3e87aa62706
Author: Andrew Lamb <[email protected]>
AuthorDate: Mon Feb 3 09:50:52 2025 -0500

    Support `array_concat` for `Utf8View` (#14378)
    
    * Add tests for concatenating differnet string types
    
    * clean up code
    
    * fmt
---
 datafusion/expr-common/src/type_coercion/binary.rs | 52 +---------------------
 datafusion/functions-nested/src/concat.rs          | 46 ++++++++++---------
 datafusion/sqllogictest/test_files/array.slt       | 41 +++++++++++++++++
 3 files changed, 69 insertions(+), 70 deletions(-)

diff --git a/datafusion/expr-common/src/type_coercion/binary.rs 
b/datafusion/expr-common/src/type_coercion/binary.rs
index 3195218ea2..de0608426e 100644
--- a/datafusion/expr-common/src/type_coercion/binary.rs
+++ b/datafusion/expr-common/src/type_coercion/binary.rs
@@ -30,8 +30,8 @@ use arrow::datatypes::{
 };
 use datafusion_common::types::NativeType;
 use datafusion_common::{
-    exec_datafusion_err, exec_err, internal_err, plan_datafusion_err, plan_err,
-    Diagnostic, Result, Span, Spans,
+    exec_err, internal_err, plan_datafusion_err, plan_err, Diagnostic, Result, 
Span,
+    Spans,
 };
 use itertools::Itertools;
 
@@ -928,54 +928,6 @@ fn get_wider_decimal_type(
     }
 }
 
-/// Returns the wider type among arguments `lhs` and `rhs`.
-/// The wider type is the type that can safely represent values from both types
-/// without information loss. Returns an Error if types are incompatible.
-pub fn get_wider_type(lhs: &DataType, rhs: &DataType) -> Result<DataType> {
-    use arrow::datatypes::DataType::*;
-    Ok(match (lhs, rhs) {
-        (lhs, rhs) if lhs == rhs => lhs.clone(),
-        // Right UInt is larger than left UInt.
-        (UInt8, UInt16 | UInt32 | UInt64) | (UInt16, UInt32 | UInt64) | 
(UInt32, UInt64) |
-        // Right Int is larger than left Int.
-        (Int8, Int16 | Int32 | Int64) | (Int16, Int32 | Int64) | (Int32, 
Int64) |
-        // Right Float is larger than left Float.
-        (Float16, Float32 | Float64) | (Float32, Float64) |
-        // Right String is larger than left String.
-        (Utf8, LargeUtf8) |
-        // Any right type is wider than a left hand side Null.
-        (Null, _) => rhs.clone(),
-        // Left UInt is larger than right UInt.
-        (UInt16 | UInt32 | UInt64, UInt8) | (UInt32 | UInt64, UInt16) | 
(UInt64, UInt32) |
-        // Left Int is larger than right Int.
-        (Int16 | Int32 | Int64, Int8) | (Int32 | Int64, Int16) | (Int64, 
Int32) |
-        // Left Float is larger than right Float.
-        (Float32 | Float64, Float16) | (Float64, Float32) |
-        // Left String is larger than right String.
-        (LargeUtf8, Utf8) |
-        // Any left type is wider than a right hand side Null.
-        (_, Null) => lhs.clone(),
-        (List(lhs_field), List(rhs_field)) => {
-            let field_type =
-                get_wider_type(lhs_field.data_type(), rhs_field.data_type())?;
-            if lhs_field.name() != rhs_field.name() {
-                return Err(exec_datafusion_err!(
-                    "There is no wider type that can represent both {lhs} and 
{rhs}."
-                ));
-            }
-            assert_eq!(lhs_field.name(), rhs_field.name());
-            let field_name = lhs_field.name();
-            let nullable = lhs_field.is_nullable() | rhs_field.is_nullable();
-            List(Arc::new(Field::new(field_name, field_type, nullable)))
-        }
-        (_, _) => {
-            return Err(exec_datafusion_err!(
-                "There is no wider type that can represent both {lhs} and 
{rhs}."
-            ));
-        }
-    })
-}
-
 /// Convert the numeric data type to the decimal data type.
 /// We support signed and unsigned integer types and floating-point type.
 fn coerce_numeric_type_to_decimal(numeric_type: &DataType) -> Option<DataType> 
{
diff --git a/datafusion/functions-nested/src/concat.rs 
b/datafusion/functions-nested/src/concat.rs
index a6557e36da..93305faad5 100644
--- a/datafusion/functions-nested/src/concat.rs
+++ b/datafusion/functions-nested/src/concat.rs
@@ -29,8 +29,7 @@ use datafusion_common::{
     cast::as_generic_list_array, exec_err, not_impl_err, plan_err, 
utils::list_ndims,
 };
 use datafusion_expr::{
-    type_coercion::binary::get_wider_type, ColumnarValue, Documentation, 
ScalarUDFImpl,
-    Signature, Volatility,
+    ColumnarValue, Documentation, ScalarUDFImpl, Signature, Volatility,
 };
 use datafusion_macros::user_doc;
 
@@ -276,25 +275,32 @@ impl ScalarUDFImpl for ArrayConcat {
         let mut expr_type = DataType::Null;
         let mut max_dims = 0;
         for arg_type in arg_types {
-            match arg_type {
-                DataType::List(field) => {
-                    if !field.data_type().equals_datatype(&DataType::Null) {
-                        let dims = list_ndims(arg_type);
-                        expr_type = match max_dims.cmp(&dims) {
-                            Ordering::Greater => expr_type,
-                            Ordering::Equal => get_wider_type(&expr_type, 
arg_type)?,
-                            Ordering::Less => {
-                                max_dims = dims;
-                                arg_type.clone()
-                            }
-                        };
+            let DataType::List(field) = arg_type else {
+                return plan_err!(
+                    "The array_concat function can only accept list as the 
args."
+                );
+            };
+            if !field.data_type().equals_datatype(&DataType::Null) {
+                let dims = list_ndims(arg_type);
+                expr_type = match max_dims.cmp(&dims) {
+                    Ordering::Greater => expr_type,
+                    Ordering::Equal => {
+                        if expr_type == DataType::Null {
+                            arg_type.clone()
+                        } else if !expr_type.equals_datatype(arg_type) {
+                            return plan_err!(
+                            "It is not possible to concatenate arrays of 
different types. Expected: {}, got: {}", expr_type, arg_type
+                                );
+                        } else {
+                            expr_type
+                        }
                     }
-                }
-                _ => {
-                    return plan_err!(
-                        "The array_concat function can only accept list as the 
args."
-                    )
-                }
+
+                    Ordering::Less => {
+                        max_dims = dims;
+                        arg_type.clone()
+                    }
+                };
             }
         }
 
diff --git a/datafusion/sqllogictest/test_files/array.slt 
b/datafusion/sqllogictest/test_files/array.slt
index ce66acd670..ff701b5540 100644
--- a/datafusion/sqllogictest/test_files/array.slt
+++ b/datafusion/sqllogictest/test_files/array.slt
@@ -2870,6 +2870,47 @@ select array_concat([]);
 ----
 []
 
+# Concatenating strings arrays
+query ?
+select array_concat(
+  ['1', '2'],
+  ['3']
+);
+----
+[1, 2, 3]
+
+# Concatenating string arrays
+query ?
+select array_concat(
+  [arrow_cast('1', 'LargeUtf8'), arrow_cast('2', 'LargeUtf8')],
+  [arrow_cast('3', 'LargeUtf8')]
+);
+----
+[1, 2, 3]
+
+# Concatenating stringview
+query ?
+select array_concat(
+  [arrow_cast('1', 'Utf8View'), arrow_cast('2', 'Utf8View')],
+  [arrow_cast('3', 'Utf8View')]
+);
+----
+[1, 2, 3]
+
+# Concatenating Mixed types (doesn't work)
+query error DataFusion error: Error during planning: It is not possible to 
concatenate arrays of different types\. Expected: List\(Field \{ name: "item", 
data_type: Utf8, nullable: true, dict_id: 0, dict_is_ordered: false, metadata: 
\{\} \}\), got: List\(Field \{ name: "item", data_type: LargeUtf8, nullable: 
true, dict_id: 0, dict_is_ordered: false, metadata: \{\} \}\)
+select array_concat(
+  [arrow_cast('1', 'Utf8'), arrow_cast('2', 'Utf8')],
+  [arrow_cast('3', 'LargeUtf8')]
+);
+
+# Concatenating Mixed types (doesn't work)
+query error DataFusion error: Error during planning: It is not possible to 
concatenate arrays of different types\. Expected: List\(Field \{ name: "item", 
data_type: Utf8, nullable: true, dict_id: 0, dict_is_ordered: false, metadata: 
\{\} \}\), got: List\(Field \{ name: "item", data_type: Utf8View, nullable: 
true, dict_id: 0, dict_is_ordered: false, metadata: \{\} \}\)
+select array_concat(
+  [arrow_cast('1', 'Utf8'), arrow_cast('2', 'Utf8')],
+  [arrow_cast('3', 'Utf8View')]
+);
+
 # array_concat error
 query error DataFusion error: Error during planning: The array_concat function 
can only accept list as the args\.
 select array_concat(1, 2);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to