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

github-bot 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 3b028fe677 Improve formatting of datatypes (#20605)
3b028fe677 is described below

commit 3b028fe6774ba6391e0b12c7ca205fdbe53a6cae
Author: Emil Ernerfeldt <[email protected]>
AuthorDate: Wed Mar 4 11:35:22 2026 +0100

    Improve formatting of datatypes (#20605)
    
    ## Which issue does this PR close?
    - Part of https://github.com/apache/datafusion/issues/19004
    
    ## Rationale for this change
    Error messages should be friendly, short, and readable.
    
    ## What changes are included in this PR?
    * Implement proper `Display` for `dyn LogicalType`, `TypeSignature`,
    `TypeSignatureClass`, and `Coercion` instead of falling back to `Debug`
    * Switch error messages across the codebase from `{:?}` (`Debug`) to
    `{}` (`Display`)
    * Add `non-null` prefix for non-nullable fields in `NativeType`
    `Display`, following Arrow's convention
    
    The north star is to follow the convention set by arrow-rs
    
    
    ## Are these changes tested?
    New snapshot tests have been introduced, and existing ones updated.
    
    ## Are there any user-facing changes?
    Yes!
    
    #### Before
    > LogicalType(Native(List(LogicalField { name: "item", logical_type:
    LogicalType(Native(Int32), Int32), nullable: true })), List(LogicalField
    { name: "item", logical_type: LogicalType(Native(Int32), Int32),
    nullable: true }))
    
    
    #### After
    > List(Int32)
    
    
    #### Before
    ```
    No function matches the given name and argument types 'round(Utf8, Utf8)'.
      Candidate functions:
      round(Coercion(TypeSignatureClass::Native(LogicalType(Native(Float64), 
Float64)),
        implicit_coercion=ImplicitCoercion([Numeric], default_type=Float64)),
        Coercion(TypeSignatureClass::Native(LogicalType(Native(Int64), Int64)),
        implicit_coercion=ImplicitCoercion([Integer], default_type=Int64)))
    
    Function 'abs' expects NativeType::Numeric but received NativeType::String
    
    Failed to coerce arguments: coercion from Int32, Utf8 to the signature
      Coercible([Coercion { desired_type: Native(LogicalType(Native(Float64), 
Float64)), ... }]) failed
    ```
    
    #### After
    
    ```
    No function matches the given name and argument types 'round(Utf8, Utf8)'.
      Candidate functions:
      round(Float64, Int64)
    
    Function 'abs' expects Numeric but received String
    
    Failed to coerce arguments: coercion from Int32, Utf8 to the signature 
Coercible(Float64, Int64) failed
    ```
    
    ---------
    
    Co-authored-by: Claude Opus 4.6 <[email protected]>
    Co-authored-by: Tim Saucer <[email protected]>
---
 Cargo.lock                                         |   1 +
 datafusion/common/src/types/logical.rs             | 120 ++++++++++++-
 datafusion/common/src/types/native.rs              | 120 ++++++++++++-
 datafusion/expr-common/Cargo.toml                  |   3 +
 datafusion/expr-common/src/signature.rs            | 195 +++++++++++++++++++--
 .../expr-common/src/type_coercion/aggregates.rs    |  11 +-
 datafusion/expr-common/src/type_coercion/binary.rs |   6 +-
 datafusion/expr/src/expr_schema.rs                 |   2 +-
 datafusion/expr/src/type_coercion/functions.rs     |  18 +-
 datafusion/expr/src/udf.rs                         |   2 +-
 datafusion/expr/src/utils.rs                       | 100 +++++++++++
 .../src/aggregate/groups_accumulator/nulls.rs      |   2 +-
 datafusion/optimizer/src/analyzer/type_coercion.rs |   2 +-
 .../physical-plan/src/aggregates/topk/heap.rs      |   4 +-
 datafusion/physical-plan/src/unnest.rs             |   4 +-
 datafusion/sql/tests/sql_integration.rs            |  43 ++---
 datafusion/sqllogictest/test_files/array.slt       |   2 +-
 .../sqllogictest/test_files/arrow_typeof.slt       |   2 +-
 datafusion/sqllogictest/test_files/binary.slt      |   2 +-
 .../test_files/datetime/timestamps.slt             |   6 +-
 datafusion/sqllogictest/test_files/encoding.slt    |   6 +-
 datafusion/sqllogictest/test_files/expr.slt        |   2 +-
 datafusion/sqllogictest/test_files/functions.slt   |   4 +-
 datafusion/sqllogictest/test_files/math.slt        |   6 +-
 datafusion/sqllogictest/test_files/scalar.slt      |   2 +-
 .../test_files/spark/datetime/unix.slt             |   8 +-
 .../test_files/spark/string/base64.slt             |   4 +-
 datafusion/sqllogictest/test_files/window.slt      |   4 +-
 28 files changed, 578 insertions(+), 103 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 23670a7877..beb87f615c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2176,6 +2176,7 @@ dependencies = [
  "arrow",
  "datafusion-common",
  "indexmap 2.13.0",
+ "insta",
  "itertools 0.14.0",
  "paste",
 ]
diff --git a/datafusion/common/src/types/logical.rs 
b/datafusion/common/src/types/logical.rs
index 674b1a4120..0f886252d6 100644
--- a/datafusion/common/src/types/logical.rs
+++ b/datafusion/common/src/types/logical.rs
@@ -100,7 +100,10 @@ impl fmt::Debug for dyn LogicalType {
 
 impl std::fmt::Display for dyn LogicalType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{self:?}")
+        match self.signature() {
+            TypeSignature::Native(_) => write!(f, "{}", self.native()),
+            TypeSignature::Extension { name, .. } => write!(f, "{name}"),
+        }
     }
 }
 
@@ -132,3 +135,118 @@ impl Hash for dyn LogicalType {
         self.signature().hash(state);
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::types::{
+        LogicalField, LogicalFields, logical_boolean, logical_date, 
logical_float32,
+        logical_float64, logical_int32, logical_int64, logical_null, 
logical_string,
+    };
+    use arrow::datatypes::{DataType, Field, Fields};
+    use insta::assert_snapshot;
+
+    #[test]
+    fn test_logical_type_display_simple() {
+        assert_snapshot!(logical_null(), @"Null");
+        assert_snapshot!(logical_boolean(), @"Boolean");
+        assert_snapshot!(logical_int32(), @"Int32");
+        assert_snapshot!(logical_int64(), @"Int64");
+        assert_snapshot!(logical_float32(), @"Float32");
+        assert_snapshot!(logical_float64(), @"Float64");
+        assert_snapshot!(logical_string(), @"String");
+        assert_snapshot!(logical_date(), @"Date");
+    }
+
+    #[test]
+    fn test_logical_type_display_list() {
+        let list_type: Arc<dyn LogicalType> = 
Arc::new(NativeType::List(Arc::new(
+            LogicalField::from(&Field::new("item", DataType::Int32, true)),
+        )));
+        assert_snapshot!(list_type, @"List(Int32)");
+    }
+
+    #[test]
+    fn test_logical_type_display_struct() {
+        let struct_type: Arc<dyn LogicalType> = Arc::new(NativeType::Struct(
+            LogicalFields::from(&Fields::from(vec![
+                Field::new("x", DataType::Float64, false),
+                Field::new("y", DataType::Float64, true),
+            ])),
+        ));
+        assert_snapshot!(struct_type, @r#"Struct("x": non-null Float64, "y": 
Float64)"#);
+    }
+
+    #[test]
+    fn test_logical_type_display_fixed_size_list() {
+        let fsl_type: Arc<dyn LogicalType> = 
Arc::new(NativeType::FixedSizeList(
+            Arc::new(LogicalField::from(&Field::new(
+                "item",
+                DataType::Float32,
+                false,
+            ))),
+            3,
+        ));
+        assert_snapshot!(fsl_type, @"FixedSizeList(3 x non-null Float32)");
+    }
+
+    #[test]
+    fn test_logical_type_display_map() {
+        let map_type: Arc<dyn LogicalType> = Arc::new(NativeType::Map(Arc::new(
+            LogicalField::from(&Field::new("entries", DataType::Utf8, false)),
+        )));
+        assert_snapshot!(map_type, @"Map(non-null String)");
+    }
+
+    #[test]
+    fn test_logical_type_display_union() {
+        use arrow::datatypes::UnionFields;
+
+        let union_fields = UnionFields::try_new(
+            vec![0, 1],
+            vec![
+                Field::new("int_val", DataType::Int32, false),
+                Field::new("str_val", DataType::Utf8, true),
+            ],
+        )
+        .unwrap();
+        let union_type: Arc<dyn LogicalType> = Arc::new(NativeType::Union(
+            crate::types::LogicalUnionFields::from(&union_fields),
+        ));
+        assert_snapshot!(union_type, @r#"Union(0: ("int_val": non-null Int32), 
1: ("str_val": String))"#);
+    }
+
+    #[test]
+    fn test_logical_type_display_nullable_vs_non_nullable() {
+        let nullable_list: Arc<dyn LogicalType> = 
Arc::new(NativeType::List(Arc::new(
+            LogicalField::from(&Field::new("item", DataType::Int32, true)),
+        )));
+        let non_nullable_list: Arc<dyn LogicalType> =
+            Arc::new(NativeType::List(Arc::new(LogicalField::from(&Field::new(
+                "item",
+                DataType::Int32,
+                false,
+            )))));
+
+        assert_snapshot!(nullable_list, @"List(Int32)");
+        assert_snapshot!(non_nullable_list, @"List(non-null Int32)");
+    }
+
+    #[test]
+    fn test_logical_type_display_extension() {
+        struct JsonType;
+        impl LogicalType for JsonType {
+            fn native(&self) -> &NativeType {
+                &NativeType::String
+            }
+            fn signature(&self) -> TypeSignature<'_> {
+                TypeSignature::Extension {
+                    name: "JSON",
+                    parameters: &[],
+                }
+            }
+        }
+        let json: Arc<dyn LogicalType> = Arc::new(JsonType);
+        assert_snapshot!(json, @"JSON");
+    }
+}
diff --git a/datafusion/common/src/types/native.rs 
b/datafusion/common/src/types/native.rs
index 65b6a5a15f..a4202db986 100644
--- a/datafusion/common/src/types/native.rs
+++ b/datafusion/common/src/types/native.rs
@@ -184,6 +184,16 @@ pub enum NativeType {
     Map(LogicalFieldRef),
 }
 
+/// Format a [`LogicalField`] for display, matching 
[`arrow::datatypes::DataType`]'s
+/// Display convention of showing a `"non-null "` prefix for non-nullable 
fields.
+fn format_logical_field(
+    f: &mut std::fmt::Formatter<'_>,
+    field: &LogicalField,
+) -> std::fmt::Result {
+    let non_null = if field.nullable { "" } else { "non-null " };
+    write!(f, "{:?}: {non_null}{}", field.name, field.logical_type)
+}
+
 impl Display for NativeType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         // Match the format used by arrow::datatypes::DataType's Display impl
@@ -210,9 +220,17 @@ impl Display for NativeType {
             Self::Binary => write!(f, "Binary"),
             Self::FixedSizeBinary(size) => write!(f, 
"FixedSizeBinary({size})"),
             Self::String => write!(f, "String"),
-            Self::List(field) => write!(f, "List({})", field.logical_type),
+            Self::List(field) => {
+                let non_null = if field.nullable { "" } else { "non-null " };
+                write!(f, "List({non_null}{})", field.logical_type)
+            }
             Self::FixedSizeList(field, size) => {
-                write!(f, "FixedSizeList({size} x {})", field.logical_type)
+                let non_null = if field.nullable { "" } else { "non-null " };
+                write!(
+                    f,
+                    "FixedSizeList({size} x {non_null}{})",
+                    field.logical_type
+                )
             }
             Self::Struct(fields) => {
                 write!(f, "Struct(")?;
@@ -220,7 +238,7 @@ impl Display for NativeType {
                     if i > 0 {
                         write!(f, ", ")?;
                     }
-                    write!(f, "{:?}: {}", field.name, field.logical_type)?;
+                    format_logical_field(f, field)?;
                 }
                 write!(f, ")")
             }
@@ -230,12 +248,17 @@ impl Display for NativeType {
                     if i > 0 {
                         write!(f, ", ")?;
                     }
-                    write!(f, "{type_id}: ({:?}: {})", field.name, 
field.logical_type)?;
+                    write!(f, "{type_id}: (")?;
+                    format_logical_field(f, field)?;
+                    write!(f, ")")?;
                 }
                 write!(f, ")")
             }
             Self::Decimal(precision, scale) => write!(f, "Decimal({precision}, 
{scale})"),
-            Self::Map(field) => write!(f, "Map({})", field.logical_type),
+            Self::Map(field) => {
+                let non_null = if field.nullable { "" } else { "non-null " };
+                write!(f, "Map({non_null}{})", field.logical_type)
+            }
         }
     }
 }
@@ -537,3 +560,90 @@ impl NativeType {
         matches!(self, Self::Float16 | Self::Float32 | Self::Float64)
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::types::LogicalField;
+    use arrow::datatypes::Field;
+    use insta::assert_snapshot;
+
+    #[test]
+    fn test_native_type_display() {
+        assert_snapshot!(NativeType::Null, @"Null");
+        assert_snapshot!(NativeType::Boolean, @"Boolean");
+        assert_snapshot!(NativeType::Int8, @"Int8");
+        assert_snapshot!(NativeType::Int16, @"Int16");
+        assert_snapshot!(NativeType::Int32, @"Int32");
+        assert_snapshot!(NativeType::Int64, @"Int64");
+        assert_snapshot!(NativeType::UInt8, @"UInt8");
+        assert_snapshot!(NativeType::UInt16, @"UInt16");
+        assert_snapshot!(NativeType::UInt32, @"UInt32");
+        assert_snapshot!(NativeType::UInt64, @"UInt64");
+        assert_snapshot!(NativeType::Float16, @"Float16");
+        assert_snapshot!(NativeType::Float32, @"Float32");
+        assert_snapshot!(NativeType::Float64, @"Float64");
+        assert_snapshot!(NativeType::Date, @"Date");
+        assert_snapshot!(NativeType::Binary, @"Binary");
+        assert_snapshot!(NativeType::String, @"String");
+        assert_snapshot!(NativeType::FixedSizeBinary(16), 
@"FixedSizeBinary(16)");
+        assert_snapshot!(NativeType::Decimal(10, 2), @"Decimal(10, 2)");
+    }
+
+    #[test]
+    fn test_native_type_display_timestamp() {
+        assert_snapshot!(
+            NativeType::Timestamp(TimeUnit::Second, None),
+            @"Timestamp(s)"
+        );
+        assert_snapshot!(
+            NativeType::Timestamp(TimeUnit::Millisecond, None),
+            @"Timestamp(ms)"
+        );
+        assert_snapshot!(
+            NativeType::Timestamp(TimeUnit::Nanosecond, 
Some(Arc::from("UTC"))),
+            @r#"Timestamp(ns, "UTC")"#
+        );
+    }
+
+    #[test]
+    fn test_native_type_display_time_duration_interval() {
+        assert_snapshot!(NativeType::Time(TimeUnit::Microsecond), @"Time(µs)");
+        assert_snapshot!(NativeType::Duration(TimeUnit::Nanosecond), 
@"Duration(ns)");
+        assert_snapshot!(NativeType::Interval(IntervalUnit::YearMonth), 
@"Interval(YearMonth)");
+        assert_snapshot!(NativeType::Interval(IntervalUnit::MonthDayNano), 
@"Interval(MonthDayNano)");
+    }
+
+    #[test]
+    fn test_native_type_display_nested() {
+        let list = NativeType::List(Arc::new(LogicalField::from(&Field::new(
+            "item",
+            DataType::Int32,
+            true,
+        ))));
+        assert_snapshot!(list, @"List(Int32)");
+
+        let fixed_list = NativeType::FixedSizeList(
+            Arc::new(LogicalField::from(&Field::new(
+                "item",
+                DataType::Float64,
+                false,
+            ))),
+            3,
+        );
+        assert_snapshot!(fixed_list, @"FixedSizeList(3 x non-null Float64)");
+
+        let struct_type = 
NativeType::Struct(LogicalFields::from(&Fields::from(vec![
+            Field::new("name", DataType::Utf8, false),
+            Field::new("age", DataType::Int32, true),
+        ])));
+        assert_snapshot!(struct_type, @r#"Struct("name": non-null String, 
"age": Int32)"#);
+
+        let map = NativeType::Map(Arc::new(LogicalField::from(&Field::new(
+            "entries",
+            DataType::Utf8,
+            false,
+        ))));
+        assert_snapshot!(map, @"Map(non-null String)");
+    }
+}
diff --git a/datafusion/expr-common/Cargo.toml 
b/datafusion/expr-common/Cargo.toml
index 5ee46b454e..d66d8ee858 100644
--- a/datafusion/expr-common/Cargo.toml
+++ b/datafusion/expr-common/Cargo.toml
@@ -46,3 +46,6 @@ datafusion-common = { workspace = true }
 indexmap = { workspace = true }
 itertools = { workspace = true }
 paste = { workspace = true }
+
+[dev-dependencies]
+insta = { workspace = true }
diff --git a/datafusion/expr-common/src/signature.rs 
b/datafusion/expr-common/src/signature.rs
index 857e9dc5d4..82759be9f7 100644
--- a/datafusion/expr-common/src/signature.rs
+++ b/datafusion/expr-common/src/signature.rs
@@ -322,6 +322,43 @@ impl TypeSignature {
     }
 }
 
+impl Display for TypeSignature {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            TypeSignature::Variadic(types) => {
+                write!(f, "Variadic({})", types.iter().join(", "))
+            }
+            TypeSignature::UserDefined => write!(f, "UserDefined"),
+            TypeSignature::VariadicAny => write!(f, "VariadicAny"),
+            TypeSignature::Uniform(count, types) => {
+                write!(f, "Uniform({count}, [{}])", types.iter().join(", "))
+            }
+            TypeSignature::Exact(types) => {
+                write!(f, "Exact({})", types.iter().join(", "))
+            }
+            TypeSignature::Coercible(coercions) => {
+                write!(f, "Coercible({})", coercions.iter().join(", "))
+            }
+            TypeSignature::Comparable(count) => write!(f, 
"Comparable({count})"),
+            TypeSignature::Any(count) => write!(f, "Any({count})"),
+            TypeSignature::OneOf(sigs) => {
+                write!(f, "OneOf(")?;
+                for (i, sig) in sigs.iter().enumerate() {
+                    if i > 0 {
+                        write!(f, ", ")?;
+                    }
+                    write!(f, "{sig}")?;
+                }
+                write!(f, ")")
+            }
+            TypeSignature::ArraySignature(sig) => write!(f, 
"ArraySignature({sig})"),
+            TypeSignature::Numeric(count) => write!(f, "Numeric({count})"),
+            TypeSignature::String(count) => write!(f, "String({count})"),
+            TypeSignature::Nullary => write!(f, "Nullary"),
+        }
+    }
+}
+
 /// Represents the class of types that can be used in a function signature.
 ///
 /// This is used to specify what types are valid for function arguments in a 
more flexible way than
@@ -358,7 +395,19 @@ pub enum TypeSignatureClass {
 
 impl Display for TypeSignatureClass {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "TypeSignatureClass::{self:?}")
+        match self {
+            Self::Any => write!(f, "Any"),
+            Self::Timestamp => write!(f, "Timestamp"),
+            Self::Time => write!(f, "Time"),
+            Self::Interval => write!(f, "Interval"),
+            Self::Duration => write!(f, "Duration"),
+            Self::Native(logical_type) => write!(f, "{logical_type}"),
+            Self::Integer => write!(f, "Integer"),
+            Self::Float => write!(f, "Float"),
+            Self::Decimal => write!(f, "Decimal"),
+            Self::Numeric => write!(f, "Numeric"),
+            Self::Binary => write!(f, "Binary"),
+        }
     }
 }
 
@@ -1062,12 +1111,7 @@ impl Coercion {
 
 impl Display for Coercion {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "Coercion({}", self.desired_type())?;
-        if let Some(implicit_coercion) = self.implicit_coercion() {
-            write!(f, ", implicit_coercion={implicit_coercion}",)
-        } else {
-            write!(f, ")")
-        }
+        write!(f, "{}", self.desired_type())
     }
 }
 
@@ -1119,11 +1163,14 @@ pub struct ImplicitCoercion {
 
 impl Display for ImplicitCoercion {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(
-            f,
-            "ImplicitCoercion({:?}, default_type={:?})",
-            self.allowed_source_types, self.default_casted_type
-        )
+        write!(f, "ImplicitCoercion(")?;
+        for (i, source_type) in self.allowed_source_types.iter().enumerate() {
+            if i > 0 {
+                write!(f, ", ")?;
+            }
+            write!(f, "{source_type}")?;
+        }
+        write!(f, "; default={}", self.default_casted_type)
     }
 }
 
@@ -1438,7 +1485,9 @@ impl Signature {
 
 #[cfg(test)]
 mod tests {
-    use datafusion_common::types::{logical_int32, logical_int64, 
logical_string};
+    use datafusion_common::types::{
+        NativeType, logical_float64, logical_int32, logical_int64, 
logical_string,
+    };
 
     use super::*;
     use crate::signature::{
@@ -2034,4 +2083,124 @@ mod tests {
         let sig = TypeSignature::UserDefined;
         assert_eq!(sig.arity(), Arity::Variable);
     }
+
+    #[test]
+    fn test_type_signature_display() {
+        use insta::assert_snapshot;
+
+        assert_snapshot!(TypeSignature::Nullary, @"Nullary");
+        assert_snapshot!(TypeSignature::Any(2), @"Any(2)");
+        assert_snapshot!(TypeSignature::Numeric(3), @"Numeric(3)");
+        assert_snapshot!(TypeSignature::String(1), @"String(1)");
+        assert_snapshot!(TypeSignature::Comparable(2), @"Comparable(2)");
+        assert_snapshot!(TypeSignature::VariadicAny, @"VariadicAny");
+        assert_snapshot!(TypeSignature::UserDefined, @"UserDefined");
+
+        assert_snapshot!(
+            TypeSignature::Exact(vec![DataType::Int32, DataType::Utf8]),
+            @"Exact(Int32, Utf8)"
+        );
+        assert_snapshot!(
+            TypeSignature::Variadic(vec![DataType::Utf8, DataType::LargeUtf8]),
+            @"Variadic(Utf8, LargeUtf8)"
+        );
+        assert_snapshot!(
+            TypeSignature::Uniform(2, vec![DataType::Float32, 
DataType::Float64]),
+            @"Uniform(2, [Float32, Float64])"
+        );
+
+        assert_snapshot!(
+            TypeSignature::Coercible(vec![
+                
Coercion::new_exact(TypeSignatureClass::Native(logical_float64())),
+                
Coercion::new_exact(TypeSignatureClass::Native(logical_int32())),
+            ]),
+            @"Coercible(Float64, Int32)"
+        );
+
+        assert_snapshot!(
+            TypeSignature::OneOf(vec![
+                TypeSignature::Nullary,
+                TypeSignature::VariadicAny,
+            ]),
+            @"OneOf(Nullary, VariadicAny)"
+        );
+    }
+
+    #[test]
+    fn test_type_signature_class_display() {
+        use insta::assert_snapshot;
+
+        assert_snapshot!(TypeSignatureClass::Any, @"Any");
+        assert_snapshot!(TypeSignatureClass::Numeric, @"Numeric");
+        assert_snapshot!(TypeSignatureClass::Integer, @"Integer");
+        assert_snapshot!(TypeSignatureClass::Float, @"Float");
+        assert_snapshot!(TypeSignatureClass::Decimal, @"Decimal");
+        assert_snapshot!(TypeSignatureClass::Timestamp, @"Timestamp");
+        assert_snapshot!(TypeSignatureClass::Time, @"Time");
+        assert_snapshot!(TypeSignatureClass::Interval, @"Interval");
+        assert_snapshot!(TypeSignatureClass::Duration, @"Duration");
+        assert_snapshot!(TypeSignatureClass::Binary, @"Binary");
+        assert_snapshot!(TypeSignatureClass::Native(logical_int32()), 
@"Int32");
+        assert_snapshot!(TypeSignatureClass::Native(logical_string()), 
@"String");
+    }
+
+    #[test]
+    fn test_coercion_display() {
+        use insta::assert_snapshot;
+
+        let exact_int = 
Coercion::new_exact(TypeSignatureClass::Native(logical_int32()));
+        assert_snapshot!(exact_int, @"Int32");
+
+        let exact_numeric = Coercion::new_exact(TypeSignatureClass::Numeric);
+        assert_snapshot!(exact_numeric, @"Numeric");
+
+        let implicit = Coercion::new_implicit(
+            TypeSignatureClass::Native(logical_float64()),
+            vec![TypeSignatureClass::Numeric],
+            NativeType::Float64,
+        );
+        assert_snapshot!(implicit, @"Float64");
+
+        let implicit_with_multiple_sources = Coercion::new_implicit(
+            TypeSignatureClass::Native(logical_int64()),
+            vec![TypeSignatureClass::Integer, TypeSignatureClass::Numeric],
+            NativeType::Int64,
+        );
+        assert_snapshot!(implicit_with_multiple_sources, @"Int64");
+    }
+
+    #[test]
+    fn test_to_string_repr_coercible() {
+        use insta::assert_snapshot;
+
+        // Simulates a function like round(Float64, Int64) with coercion
+        let sig = TypeSignature::Coercible(vec![
+            Coercion::new_implicit(
+                TypeSignatureClass::Native(logical_float64()),
+                vec![TypeSignatureClass::Numeric],
+                NativeType::Float64,
+            ),
+            Coercion::new_implicit(
+                TypeSignatureClass::Native(logical_int64()),
+                vec![TypeSignatureClass::Integer],
+                NativeType::Int64,
+            ),
+        ]);
+        let repr = sig.to_string_repr();
+        assert_eq!(repr.len(), 1);
+        assert_snapshot!(repr[0], @"Float64, Int64");
+    }
+
+    #[test]
+    fn test_to_string_repr_coercible_exact() {
+        use insta::assert_snapshot;
+
+        let sig = TypeSignature::Coercible(vec![
+            Coercion::new_exact(TypeSignatureClass::Native(logical_string())),
+            Coercion::new_exact(TypeSignatureClass::Native(logical_int64())),
+        ]);
+        let repr = sig.to_string_repr();
+        assert_eq!(repr.len(), 1);
+        assert_snapshot!(repr[0], @"String, Int64");
+    }
 }
diff --git a/datafusion/expr-common/src/type_coercion/aggregates.rs 
b/datafusion/expr-common/src/type_coercion/aggregates.rs
index ab4d086e4c..df86ff582d 100644
--- a/datafusion/expr-common/src/type_coercion/aggregates.rs
+++ b/datafusion/expr-common/src/type_coercion/aggregates.rs
@@ -61,8 +61,7 @@ pub fn check_arg_count(
         TypeSignature::Uniform(agg_count, _) | TypeSignature::Any(agg_count) 
=> {
             if input_fields.len() != *agg_count {
                 return plan_err!(
-                    "The function {func_name} expects {:?} arguments, but {:?} 
were provided",
-                    agg_count,
+                    "The function {func_name} expects {agg_count} arguments, 
but {} were provided",
                     input_fields.len()
                 );
             }
@@ -70,7 +69,7 @@ pub fn check_arg_count(
         TypeSignature::Exact(types) => {
             if types.len() != input_fields.len() {
                 return plan_err!(
-                    "The function {func_name} expects {:?} arguments, but {:?} 
were provided",
+                    "The function {func_name} expects {} arguments, but {} 
were provided",
                     types.len(),
                     input_fields.len()
                 );
@@ -82,7 +81,7 @@ pub fn check_arg_count(
                 .any(|v| check_arg_count(func_name, input_fields, v).is_ok());
             if !ok {
                 return plan_err!(
-                    "The function {func_name} does not accept {:?} function 
arguments.",
+                    "The function {func_name} does not accept {} function 
arguments.",
                     input_fields.len()
                 );
             }
@@ -101,9 +100,7 @@ pub fn check_arg_count(
             // Numeric and Coercible signature is validated in 
`get_valid_types`
         }
         _ => {
-            return internal_err!(
-                "Aggregate functions do not support this {signature:?}"
-            );
+            return internal_err!("Aggregate functions do not support this 
{signature}");
         }
     }
     Ok(())
diff --git a/datafusion/expr-common/src/type_coercion/binary.rs 
b/datafusion/expr-common/src/type_coercion/binary.rs
index c6ac86cd39..dd3db8e40b 100644
--- a/datafusion/expr-common/src/type_coercion/binary.rs
+++ b/datafusion/expr-common/src/type_coercion/binary.rs
@@ -753,15 +753,15 @@ fn type_union_resolution_coercion(
 
 /// Handle type union resolution including struct type and others.
 pub fn try_type_union_resolution(data_types: &[DataType]) -> 
Result<Vec<DataType>> {
-    let err = match try_type_union_resolution_with_struct(data_types) {
+    let struct_err = match try_type_union_resolution_with_struct(data_types) {
         Ok(struct_types) => return Ok(struct_types),
-        Err(e) => Some(e),
+        Err(e) => e,
     };
 
     if let Some(new_type) = type_union_resolution(data_types) {
         Ok(vec![new_type; data_types.len()])
     } else {
-        exec_err!("Fail to find the coerced type, errors: {:?}", err)
+        exec_err!("Fail to find the coerced type, errors: {struct_err}")
     }
 }
 
diff --git a/datafusion/expr/src/expr_schema.rs 
b/datafusion/expr/src/expr_schema.rs
index f2ac777af3..4168310002 100644
--- a/datafusion/expr/src/expr_schema.rs
+++ b/datafusion/expr/src/expr_schema.rs
@@ -649,7 +649,7 @@ fn verify_function_arguments<F: UDFCoercionExt>(
             .cloned()
             .collect::<Vec<_>>();
         plan_datafusion_err!(
-            "{} {}",
+            "{}. {}",
             match err {
                 DataFusionError::Plan(msg) => msg,
                 err => err.to_string(),
diff --git a/datafusion/expr/src/type_coercion/functions.rs 
b/datafusion/expr/src/type_coercion/functions.rs
index fe259fb8c9..a79f2c6683 100644
--- a/datafusion/expr/src/type_coercion/functions.rs
+++ b/datafusion/expr/src/type_coercion/functions.rs
@@ -221,12 +221,12 @@ pub fn data_types(
         } else if type_signature.used_to_support_zero_arguments() {
             // Special error to help during upgrade: 
https://github.com/apache/datafusion/issues/13763
             return plan_err!(
-                "function '{}' has signature {type_signature:?} which does not 
support zero arguments. Use TypeSignature::Nullary for zero arguments",
+                "function '{}' has signature {type_signature} which does not 
support zero arguments. Use TypeSignature::Nullary for zero arguments",
                 function_name.as_ref()
             );
         } else {
             return plan_err!(
-                "Function '{}' has signature {type_signature:?} which does not 
support zero arguments",
+                "Function '{}' has signature {type_signature} which does not 
support zero arguments",
                 function_name.as_ref()
             );
         }
@@ -302,7 +302,7 @@ fn try_coerce_types(
 
     // none possible -> Error
     plan_err!(
-        "Failed to coerce arguments to satisfy a call to '{function_name}' 
function: coercion from {} to the signature {type_signature:?} failed",
+        "Failed to coerce arguments to satisfy a call to '{function_name}' 
function: coercion from {} to the signature {type_signature} failed",
         current_types.iter().join(", ")
     )
 }
@@ -317,7 +317,7 @@ fn get_valid_types_with_udf<F: UDFCoercionExt>(
             Ok(coerced_types) => vec![coerced_types],
             Err(e) => {
                 return exec_err!(
-                    "Function '{}' user-defined coercion failed with {:?}",
+                    "Function '{}' user-defined coercion failed with: {}",
                     func.name(),
                     e.strip_backtrace()
                 );
@@ -502,7 +502,7 @@ fn get_valid_types(
                     new_types.push(DataType::Utf8);
                 } else {
                     return plan_err!(
-                        "Function '{function_name}' expects NativeType::String 
but NativeType::received NativeType::{logical_data_type}"
+                        "Function '{function_name}' expects String but 
received {logical_data_type}"
                     );
                 }
             }
@@ -562,7 +562,7 @@ fn get_valid_types(
 
                 if !logical_data_type.is_numeric() {
                     return plan_err!(
-                        "Function '{function_name}' expects 
NativeType::Numeric but received NativeType::{logical_data_type}"
+                        "Function '{function_name}' expects Numeric but 
received {logical_data_type}"
                     );
                 }
 
@@ -583,7 +583,7 @@ fn get_valid_types(
                 valid_type = DataType::Float64;
             } else if !logical_data_type.is_numeric() {
                 return plan_err!(
-                    "Function '{function_name}' expects NativeType::Numeric 
but received NativeType::{logical_data_type}"
+                    "Function '{function_name}' expects Numeric but received 
{logical_data_type}"
                 );
             }
 
@@ -1056,7 +1056,7 @@ mod tests {
         .unwrap_err();
         assert_contains!(
             got.to_string(),
-            "Function 'test' expects NativeType::Numeric but received 
NativeType::String"
+            "Function 'test' expects Numeric but received String"
         );
 
         // Fallbacks to float64 if the arg is of type null.
@@ -1076,7 +1076,7 @@ mod tests {
         .unwrap_err();
         assert_contains!(
             got.to_string(),
-            "Function 'test' expects NativeType::Numeric but received 
NativeType::Timestamp(s)"
+            "Function 'test' expects Numeric but received Timestamp(s)"
         );
 
         Ok(())
diff --git a/datafusion/expr/src/udf.rs b/datafusion/expr/src/udf.rs
index 405fb25680..9705006e41 100644
--- a/datafusion/expr/src/udf.rs
+++ b/datafusion/expr/src/udf.rs
@@ -261,7 +261,7 @@ impl ScalarUDF {
             let expected_type = return_field.data_type();
             assert_or_internal_err!(
                 result_data_type == *expected_type,
-                "Function '{}' returned value of type '{:?}' while the 
following type was promised at planning time and expected: '{:?}'",
+                "Function '{}' returned value of type '{}' while the following 
type was promised at planning time and expected: '{}'",
                 self.name(),
                 result_data_type,
                 expected_type
diff --git a/datafusion/expr/src/utils.rs b/datafusion/expr/src/utils.rs
index b19299981c..81a6fd393a 100644
--- a/datafusion/expr/src/utils.rs
+++ b/datafusion/expr/src/utils.rs
@@ -1784,4 +1784,104 @@ mod tests {
             "Expected 'Any, Any' without parameter names, got: {error_msg}"
         );
     }
+
+    #[test]
+    fn test_signature_error_msg_exact() {
+        use insta::assert_snapshot;
+
+        let sig = Signature::one_of(
+            vec![
+                TypeSignature::Exact(vec![DataType::Float64, DataType::Int64]),
+                TypeSignature::Exact(vec![DataType::Float32, DataType::Int64]),
+                TypeSignature::Exact(vec![DataType::Float64]),
+                TypeSignature::Exact(vec![DataType::Float32]),
+            ],
+            Volatility::Immutable,
+        );
+        let msg = generate_signature_error_message(
+            "round",
+            &sig,
+            &[DataType::Float64, DataType::Float64],
+        );
+        assert_snapshot!(msg, @r"
+        No function matches the given name and argument types 'round(Float64, 
Float64)'. You might need to add explicit type casts.
+               Candidate functions:
+               round(Float64, Int64)
+               round(Float32, Int64)
+               round(Float64)
+               round(Float32)
+        ");
+    }
+
+    #[test]
+    fn test_signature_error_msg_coercible() {
+        use datafusion_common::types::NativeType;
+        use datafusion_expr_common::signature::{Coercion, TypeSignatureClass};
+        use insta::assert_snapshot;
+
+        let sig = Signature::coercible(
+            vec![
+                Coercion::new_implicit(
+                    TypeSignatureClass::Native(
+                        datafusion_common::types::logical_float64(),
+                    ),
+                    vec![TypeSignatureClass::Numeric],
+                    NativeType::Float64,
+                ),
+                Coercion::new_implicit(
+                    
TypeSignatureClass::Native(datafusion_common::types::logical_int64()),
+                    vec![TypeSignatureClass::Integer],
+                    NativeType::Int64,
+                ),
+            ],
+            Volatility::Immutable,
+        );
+        let msg = generate_signature_error_message(
+            "round",
+            &sig,
+            &[DataType::Utf8, DataType::Utf8],
+        );
+        assert_snapshot!(msg, @r"
+        No function matches the given name and argument types 'round(Utf8, 
Utf8)'. You might need to add explicit type casts.
+               Candidate functions:
+               round(Float64, Int64)
+        ");
+    }
+
+    #[test]
+    fn test_signature_error_msg_with_names_coercible() {
+        use datafusion_common::types::NativeType;
+        use datafusion_expr_common::signature::{Coercion, TypeSignatureClass};
+        use insta::assert_snapshot;
+
+        let sig = Signature::coercible(
+            vec![
+                Coercion::new_exact(TypeSignatureClass::Native(
+                    datafusion_common::types::logical_string(),
+                )),
+                Coercion::new_exact(TypeSignatureClass::Native(
+                    datafusion_common::types::logical_int64(),
+                )),
+                Coercion::new_implicit(
+                    
TypeSignatureClass::Native(datafusion_common::types::logical_int64()),
+                    vec![TypeSignatureClass::Integer],
+                    NativeType::Int64,
+                ),
+            ],
+            Volatility::Immutable,
+        )
+        .with_parameter_names(vec![
+            "string".to_string(),
+            "start_pos".to_string(),
+            "length".to_string(),
+        ])
+        .expect("valid parameter names");
+
+        let msg = generate_signature_error_message("substr", &sig, 
&[DataType::Int32]);
+        assert_snapshot!(msg, @r"
+        No function matches the given name and argument types 'substr(Int32)'. 
You might need to add explicit type casts.
+               Candidate functions:
+               substr(string: String, start_pos: Int64, length: Int64)
+        ");
+    }
 }
diff --git 
a/datafusion/functions-aggregate-common/src/aggregate/groups_accumulator/nulls.rs
 
b/datafusion/functions-aggregate-common/src/aggregate/groups_accumulator/nulls.rs
index 435560721c..5b56b77e11 100644
--- 
a/datafusion/functions-aggregate-common/src/aggregate/groups_accumulator/nulls.rs
+++ 
b/datafusion/functions-aggregate-common/src/aggregate/groups_accumulator/nulls.rs
@@ -206,7 +206,7 @@ pub fn set_nulls_dyn(input: &dyn Array, nulls: 
Option<NullBuffer>) -> Result<Arr
             }
         }
         _ => {
-            return not_impl_err!("Applying nulls {:?}", input.data_type());
+            return not_impl_err!("Applying nulls {}", input.data_type());
         }
     };
     assert_eq!(input.len(), output.len());
diff --git a/datafusion/optimizer/src/analyzer/type_coercion.rs 
b/datafusion/optimizer/src/analyzer/type_coercion.rs
index ed04aa4285..efc9984acb 100644
--- a/datafusion/optimizer/src/analyzer/type_coercion.rs
+++ b/datafusion/optimizer/src/analyzer/type_coercion.rs
@@ -849,7 +849,7 @@ fn coerce_scalar_range_aware(
         // If type coercion fails, check if the largest type in family works:
         if let Some(largest_type) = get_widest_type_in_family(target_type) {
             coerce_scalar(largest_type, value).map_or_else(
-                |_| exec_err!("Cannot cast {value:?} to {target_type}"),
+                |_| exec_err!("Cannot cast {value} to {target_type}"),
                 |_| ScalarValue::try_from(target_type),
             )
         } else {
diff --git a/datafusion/physical-plan/src/aggregates/topk/heap.rs 
b/datafusion/physical-plan/src/aggregates/topk/heap.rs
index 9f0b697cca..889fe04bf8 100644
--- a/datafusion/physical-plan/src/aggregates/topk/heap.rs
+++ b/datafusion/physical-plan/src/aggregates/topk/heap.rs
@@ -216,7 +216,7 @@ fn extract_string_value<'a>(
         DataType::Utf8 => batch.as_string::<i32>().value(idx),
         DataType::LargeUtf8 => batch.as_string::<i64>().value(idx),
         DataType::Utf8View => batch.as_string_view().value(idx),
-        _ => unreachable!("Unsupported string type: {:?}", data_type),
+        _ => unreachable!("Unsupported string type: {data_type}"),
     }
 }
 
@@ -316,7 +316,7 @@ impl ArrowHeap for StringHeap {
             DataType::Utf8 => build_string_array!(StringBuilder),
             DataType::LargeUtf8 => build_string_array!(LargeStringBuilder),
             DataType::Utf8View => build_string_array!(StringViewBuilder),
-            _ => unreachable!("Unsupported string type: {:?}", self.data_type),
+            _ => unreachable!("Unsupported string type: {}", self.data_type),
         };
         (arr, map_idxs)
     }
diff --git a/datafusion/physical-plan/src/unnest.rs 
b/datafusion/physical-plan/src/unnest.rs
index 72faeb83c5..48de79b741 100644
--- a/datafusion/physical-plan/src/unnest.rs
+++ b/datafusion/physical-plan/src/unnest.rs
@@ -426,9 +426,7 @@ fn flatten_struct_cols(
                     Ok(struct_arr.columns().to_vec())
                 }
                 data_type => internal_err!(
-                    "expecting column {} from input plan to be a struct, got 
{:?}",
-                    idx,
-                    data_type
+                    "expecting column {idx} from input plan to be a struct, 
got {data_type}"
                 ),
             },
             None => Ok(vec![Arc::clone(column_data)]),
diff --git a/datafusion/sql/tests/sql_integration.rs 
b/datafusion/sql/tests/sql_integration.rs
index 444bdae73a..9570336e99 100644
--- a/datafusion/sql/tests/sql_integration.rs
+++ b/datafusion/sql/tests/sql_integration.rs
@@ -4730,56 +4730,35 @@ fn test_custom_type_plan() -> Result<()> {
     Ok(())
 }
 
-fn error_message_test(sql: &str, err_msg_starts_with: &str) {
+fn error_message(sql: &str) -> String {
     let err = logical_plan(sql).expect_err("query should have failed");
-    assert!(
-        err.strip_backtrace().starts_with(err_msg_starts_with),
-        "Expected error to start with '{}', but got: '{}'",
-        err_msg_starts_with,
-        err.strip_backtrace(),
-    );
+    err.strip_backtrace()
 }
 
 #[test]
 fn test_error_message_invalid_scalar_function_signature() {
-    error_message_test(
-        "select sqrt()",
-        "Error during planning: 'sqrt' does not support zero arguments",
-    );
-    error_message_test(
-        "select sqrt(1, 2)",
-        "Error during planning: Failed to coerce arguments",
+    assert!(
+        error_message("select sqrt()").starts_with(
+            r"Error during planning: 'sqrt' does not support zero arguments"
+        )
     );
+    assert!(error_message("select sqrt(1, 2)").starts_with(r"Error during 
planning: Failed to coerce arguments to satisfy a call to 'sqrt' function: 
coercion from Int64, Int64 to the signature Exact(Int64) failed"));
 }
 
 #[test]
 fn test_error_message_invalid_aggregate_function_signature() {
-    error_message_test(
-        "select sum()",
-        "Error during planning: Execution error: Function 'sum' user-defined 
coercion failed with \"Execution error: sum function requires 1 argument, got 
0\"",
-    );
-    // We keep two different prefixes because they clarify each other.
-    // It might be incorrect, and we should consider keeping only one.
-    error_message_test(
-        "select max(9, 3)",
-        "Error during planning: Execution error: Function 'max' user-defined 
coercion failed",
-    );
+    assert!(error_message("select sum()").starts_with(r"Error during planning: 
Execution error: Function 'sum' user-defined coercion failed with: Execution 
error: sum function requires 1 argument, got 0"));
+    assert!(error_message("select max(9, 3)").starts_with(r"Error during 
planning: Execution error: Function 'max' user-defined coercion failed with: 
Execution error: min/max was called with 2 arguments. It requires only 1"));
 }
 
 #[test]
 fn test_error_message_invalid_window_function_signature() {
-    error_message_test(
-        "select rank(1) over()",
-        "Error during planning: The function 'rank' expected zero argument but 
received 1",
-    );
+    assert!(error_message("select rank(1) over()").starts_with(r"Error during 
planning: The function 'rank' expected zero argument but received 1"));
 }
 
 #[test]
 fn test_error_message_invalid_window_aggregate_function_signature() {
-    error_message_test(
-        "select sum() over()",
-        "Error during planning: Execution error: Function 'sum' user-defined 
coercion failed with \"Execution error: sum function requires 1 argument, got 
0\"",
-    );
+    assert!(error_message("select sum() over()").starts_with(r"Error during 
planning: Execution error: Function 'sum' user-defined coercion failed with: 
Execution error: sum function requires 1 argument, got 0"));
 }
 
 // Test issue: https://github.com/apache/datafusion/issues/14058
diff --git a/datafusion/sqllogictest/test_files/array.slt 
b/datafusion/sqllogictest/test_files/array.slt
index 00d28d38d6..112351c5ef 100644
--- a/datafusion/sqllogictest/test_files/array.slt
+++ b/datafusion/sqllogictest/test_files/array.slt
@@ -3470,7 +3470,7 @@ select array_concat([NULL, NULL], [NULL, NULL]);
 [NULL, NULL, NULL, NULL]
 
 # array_concat error
-query error DataFusion error: Error during planning: Execution error: Function 
'array_concat' user-defined coercion failed with "Error during planning: 
array_concat does not support type Int64"
+query error DataFusion error: Error during planning: Execution error: Function 
'array_concat' user-defined coercion failed with: Error during planning: 
array_concat does not support type Int64
 select array_concat(1, 2);
 
 # array_concat scalar function #1
diff --git a/datafusion/sqllogictest/test_files/arrow_typeof.slt 
b/datafusion/sqllogictest/test_files/arrow_typeof.slt
index 0c69e8591c..e00909ad5f 100644
--- a/datafusion/sqllogictest/test_files/arrow_typeof.slt
+++ b/datafusion/sqllogictest/test_files/arrow_typeof.slt
@@ -95,7 +95,7 @@ SELECT arrow_cast('1', 'Int16')
 query error
 SELECT arrow_cast('1')
 
-query error DataFusion error: Error during planning: Function 'arrow_cast' 
requires TypeSignatureClass::Native\(LogicalType\(Native\(String\), String\)\), 
but received Int64 \(DataType: Int64\)
+query error DataFusion error: Error during planning: Function 'arrow_cast' 
requires String, but received Int64 \(DataType: Int64\)
 SELECT arrow_cast('1', 43)
 
 query error DataFusion error: Execution error: arrow_cast requires its second 
argument to be a non\-empty constant string
diff --git a/datafusion/sqllogictest/test_files/binary.slt 
b/datafusion/sqllogictest/test_files/binary.slt
index c4a21deeff..54ac51d9e7 100644
--- a/datafusion/sqllogictest/test_files/binary.slt
+++ b/datafusion/sqllogictest/test_files/binary.slt
@@ -313,7 +313,7 @@ Bar Bar Bar Bar
 FooBar fooBar FooBar fooBar
 
 # show helpful error msg when Binary type is used with string functions
-query error DataFusion error: Error during planning: Function 'split_part' 
requires TypeSignatureClass::Native\(LogicalType\(Native\(String\), String\)\), 
but received Binary \(DataType: Binary\)\.\n\nHint: Binary types are not 
automatically coerced to String\. Use CAST\(column AS VARCHAR\) to convert 
Binary data to String\.
+query error DataFusion error: Error during planning: Function 'split_part' 
requires String, but received Binary \(DataType: Binary\)\.\n\nHint: Binary 
types are not automatically coerced to String\. Use CAST\(column AS VARCHAR\) 
to convert Binary data to String\.
 SELECT split_part(binary, '~', 2) FROM t WHERE binary IS NOT NULL LIMIT 1;
 
 # ensure the suggested CAST workaround works
diff --git a/datafusion/sqllogictest/test_files/datetime/timestamps.slt 
b/datafusion/sqllogictest/test_files/datetime/timestamps.slt
index 9526ccebfd..78889230fd 100644
--- a/datafusion/sqllogictest/test_files/datetime/timestamps.slt
+++ b/datafusion/sqllogictest/test_files/datetime/timestamps.slt
@@ -3076,7 +3076,7 @@ NULL
 query error DataFusion error: Error during planning: Function 'make_date' 
expects 3 arguments but received 1
 select make_date(1);
 
-query error DataFusion error: Error during planning: Function 'make_date' 
requires TypeSignatureClass::Native\(LogicalType\(Native\(Int32\), Int32\)\), 
but received Interval\(MonthDayNano\) \(DataType: Interval\(MonthDayNano\)\)
+query error DataFusion error: Error during planning: Function 'make_date' 
requires Int32, but received Interval\(MonthDayNano\) \(DataType: 
Interval\(MonthDayNano\)\).
 select make_date(interval '1 day', '2001-05-21'::timestamp, 
'2001-05-21'::timestamp);
 
 ##########
@@ -3349,7 +3349,7 @@ select make_time(22, '', 27);
 query error Cannot cast string '' to value of Int32 type
 select make_time(22, 1, '');
 
-query error DataFusion error: Error during planning: Function 'make_time' 
requires TypeSignatureClass::Native\(LogicalType\(Native\(Int32\), Int32\)\), 
but received Float64 \(DataType: Float64\)
+query error DataFusion error: Error during planning: Function 'make_time' 
requires Int32, but received Float64 \(DataType: Float64\)
 select make_time(arrow_cast(22, 'Float64'), 1, '');
 
 ##########
@@ -3964,7 +3964,7 @@ statement error
 select to_local_time('2024-04-01T00:00:20Z'::timestamp, 'some string');
 
 # invalid argument data type
-statement error DataFusion error: Error during planning: Function 
'to_local_time' requires TypeSignatureClass::Timestamp, but received String 
\(DataType: Utf8\)
+statement error DataFusion error: Error during planning: Function 
'to_local_time' requires Timestamp, but received String \(DataType: Utf8\)
 select to_local_time('2024-04-01T00:00:20Z');
 
 # invalid timezone
diff --git a/datafusion/sqllogictest/test_files/encoding.slt 
b/datafusion/sqllogictest/test_files/encoding.slt
index b04d506182..c68d59819e 100644
--- a/datafusion/sqllogictest/test_files/encoding.slt
+++ b/datafusion/sqllogictest/test_files/encoding.slt
@@ -75,10 +75,10 @@ CREATE TABLE test(
 ;
 
 # errors
-query error DataFusion error: Error during planning: Function 'encode' 
requires TypeSignatureClass::Binary, but received Int64 \(DataType: Int64\)
+query error DataFusion error: Error during planning: Function 'encode' 
requires Binary, but received Int64 \(DataType: Int64\)
 select encode(12, 'hex');
 
-query error DataFusion error: Error during planning: Function 'decode' 
requires TypeSignatureClass::Binary, but received Int64 \(DataType: Int64\)
+query error DataFusion error: Error during planning: Function 'decode' 
requires Binary, but received Int64 \(DataType: Int64\)
 select decode(12, 'hex');
 
 query error DataFusion error: Error during planning: There is no built\-in 
encoding named 'non_encoding', currently supported encodings are: base64, 
base64pad, hex
@@ -93,7 +93,7 @@ select decode('', null) from test;
 query error DataFusion error: This feature is not implemented: Encoding must 
be a scalar; array specified encoding is not yet supported
 select decode('', hex_field) from test;
 
-query error DataFusion error: Error during planning: Function 'to_hex' 
requires TypeSignatureClass::Integer, but received String \(DataType: Utf8View\)
+query error DataFusion error: Error during planning: Function 'to_hex' 
requires Integer, but received String \(DataType: Utf8View\)
 select to_hex(hex_field) from test;
 
 query error DataFusion error: Execution error: Failed to decode value using 
base64
diff --git a/datafusion/sqllogictest/test_files/expr.slt 
b/datafusion/sqllogictest/test_files/expr.slt
index 6d19d1436e..a6341bc686 100644
--- a/datafusion/sqllogictest/test_files/expr.slt
+++ b/datafusion/sqllogictest/test_files/expr.slt
@@ -618,7 +618,7 @@ select repeat('-1.2', arrow_cast(3, 'Int32'));
 ----
 -1.2-1.2-1.2
 
-query error DataFusion error: Error during planning: Function 'repeat' 
requires TypeSignatureClass::Native\(LogicalType\(Native\(Int64\), Int64\)\), 
but received Float64 \(DataType: Float64\)
+query error DataFusion error: Error during planning: Function 'repeat' 
requires Int64, but received Float64 \(DataType: Float64\)
 select repeat('-1.2', 3.2);
 
 query T
diff --git a/datafusion/sqllogictest/test_files/functions.slt 
b/datafusion/sqllogictest/test_files/functions.slt
index 5a43d18e23..fa852e98ac 100644
--- a/datafusion/sqllogictest/test_files/functions.slt
+++ b/datafusion/sqllogictest/test_files/functions.slt
@@ -887,7 +887,7 @@ SELECT greatest(-1, 1, 2.3, 123456789, 3 + 5, -(-4), 
abs(-9.0))
 123456789
 
 
-query error Function 'greatest' user-defined coercion failed with "Error 
during planning: greatest was called without any arguments. It requires at 
least 1."
+query error Function 'greatest' user-defined coercion failed with: Error 
during planning: greatest was called without any arguments. It requires at 
least 1.
 SELECT greatest()
 
 query I
@@ -1085,7 +1085,7 @@ SELECT least(-1, 1, 2.3, 123456789, 3 + 5, -(-4), 
abs(-9.0))
 -1
 
 
-query error Function 'least' user-defined coercion failed with "Error during 
planning: least was called without any arguments. It requires at least 1."
+query error Function 'least' user-defined coercion failed with: Error during 
planning: least was called without any arguments. It requires at least 1.
 SELECT least()
 
 query I
diff --git a/datafusion/sqllogictest/test_files/math.slt 
b/datafusion/sqllogictest/test_files/math.slt
index 2227466fdf..d571fcd947 100644
--- a/datafusion/sqllogictest/test_files/math.slt
+++ b/datafusion/sqllogictest/test_files/math.slt
@@ -158,15 +158,15 @@ statement error
 SELECT abs(1, 2);
 
 # abs: unsupported argument type
-query error DataFusion error: Error during planning: Function 'abs' expects 
NativeType::Numeric but received NativeType::String
+query error DataFusion error: Error during planning: Function 'abs' expects 
Numeric but received String
 SELECT abs('foo');
 
 # abs: numeric string
 # TODO: In Postgres, '-1.2' is unknown type and interpreted to float8 so they 
don't fail on this query
-query error DataFusion error: Error during planning: Function 'abs' expects 
NativeType::Numeric but received NativeType::String
+query error DataFusion error: Error during planning: Function 'abs' expects 
Numeric but received String
 select abs('-1.2');
 
-query error DataFusion error: Error during planning: Function 'abs' expects 
NativeType::Numeric but received NativeType::String
+query error DataFusion error: Error during planning: Function 'abs' expects 
Numeric but received String
 select abs(arrow_cast('-1.2', 'Utf8'));
 
 statement ok
diff --git a/datafusion/sqllogictest/test_files/scalar.slt 
b/datafusion/sqllogictest/test_files/scalar.slt
index 681540a29d..e91ec1cb84 100644
--- a/datafusion/sqllogictest/test_files/scalar.slt
+++ b/datafusion/sqllogictest/test_files/scalar.slt
@@ -2137,7 +2137,7 @@ select position('' in '')
 ----
 1
 
-query error DataFusion error: Error during planning: Function 'strpos' 
requires TypeSignatureClass::Native\(LogicalType\(Native\(String\), String\)\), 
but received Int64 \(DataType: Int64\)
+query error DataFusion error: Error during planning: Function 'strpos' 
requires String, but received Int64 \(DataType: Int64\).
 select position(1 in 1)
 
 query I
diff --git a/datafusion/sqllogictest/test_files/spark/datetime/unix.slt 
b/datafusion/sqllogictest/test_files/spark/datetime/unix.slt
index d7441f487d..9dd39acd7f 100644
--- a/datafusion/sqllogictest/test_files/spark/datetime/unix.slt
+++ b/datafusion/sqllogictest/test_files/spark/datetime/unix.slt
@@ -38,7 +38,7 @@ SELECT unix_date(NULL::date);
 ----
 NULL
 
-query error Function 'unix_date' requires 
TypeSignatureClass::Native\(LogicalType\(Native\(Date\), Date\)\), but received 
String \(DataType: Utf8View\)
+query error Function 'unix_date' requires Date, but received String 
\(DataType: Utf8View\)
 SELECT unix_date('1970-01-02'::string);
 
 # Unix Micro Tests
@@ -68,7 +68,7 @@ SELECT unix_micros(NULL::timestamp);
 ----
 NULL
 
-query error Function 'unix_micros' requires TypeSignatureClass::Timestamp, but 
received String \(DataType: Utf8View\)
+query error Function 'unix_micros' requires Timestamp, but received String 
\(DataType: Utf8View\)
 SELECT unix_micros('1970-01-01 00:00:01Z'::string);
 
 
@@ -99,7 +99,7 @@ SELECT unix_millis(NULL::timestamp);
 ----
 NULL
 
-query error Function 'unix_millis' requires TypeSignatureClass::Timestamp, but 
received String \(DataType: Utf8View\)
+query error Function 'unix_millis' requires Timestamp, but received String 
\(DataType: Utf8View\)
 SELECT unix_millis('1970-01-01 00:00:01Z'::string);
 
 
@@ -130,5 +130,5 @@ SELECT unix_seconds(NULL::timestamp);
 ----
 NULL
 
-query error Function 'unix_seconds' requires TypeSignatureClass::Timestamp, 
but received String \(DataType: Utf8View\)
+query error Function 'unix_seconds' requires Timestamp, but received String 
\(DataType: Utf8View\)
 SELECT unix_seconds('1970-01-01 00:00:01Z'::string);
diff --git a/datafusion/sqllogictest/test_files/spark/string/base64.slt 
b/datafusion/sqllogictest/test_files/spark/string/base64.slt
index 03b488de0e..dbd266f65a 100644
--- a/datafusion/sqllogictest/test_files/spark/string/base64.slt
+++ b/datafusion/sqllogictest/test_files/spark/string/base64.slt
@@ -58,7 +58,7 @@ U3BhcmsgU1E=
 U3BhcmsgUw==
 NULL
 
-query error Function 'base64' requires TypeSignatureClass::Binary, but 
received Int32 \(DataType: Int32\)
+query error Error during planning: Function 'base64' requires Binary, but 
received Int32 \(DataType: Int32\)
 SELECT base64(12::integer);
 
 
@@ -111,5 +111,5 @@ SELECT unbase64('123'::string);
 query error Failed to decode value using base64
 SELECT unbase64('123'::bytea);
 
-query error Function 'unbase64' requires TypeSignatureClass::Binary, but 
received Int32 \(DataType: Int32\)
+query error Error during planning: Function 'unbase64' requires Binary, but 
received Int32 \(DataType: Int32\)
 SELECT unbase64(12::integer);
diff --git a/datafusion/sqllogictest/test_files/window.slt 
b/datafusion/sqllogictest/test_files/window.slt
index c3e6f39adb..62296c5d87 100644
--- a/datafusion/sqllogictest/test_files/window.slt
+++ b/datafusion/sqllogictest/test_files/window.slt
@@ -2580,7 +2580,7 @@ statement ok
 set datafusion.optimizer.skip_failed_rules = true
 
 # Error is returned from the physical plan.
-query error Cannot cast Utf8\("1 DAY"\) to Int8
+query error Cannot cast 1 DAY to Int8
 SELECT
   COUNT(c1) OVER (ORDER BY c2 RANGE BETWEEN '1 DAY' PRECEDING AND '2 DAY' 
FOLLOWING)
   FROM aggregate_test_100;
@@ -2589,7 +2589,7 @@ statement ok
 set datafusion.optimizer.skip_failed_rules = false
 
 # Error is returned from the logical plan.
-query error Cannot cast Utf8\("1 DAY"\) to Int8
+query error Cannot cast 1 DAY to Int8
 SELECT
   COUNT(c1) OVER (ORDER BY c2 RANGE BETWEEN '1 DAY' PRECEDING AND '2 DAY' 
FOLLOWING)
   FROM aggregate_test_100;


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

Reply via email to