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 13af5f342e chore: Attach Diagnostic to "incompatible type in unary 
expression" error (#15209)
13af5f342e is described below

commit 13af5f342ed15c629f382f78649117d398fb14f0
Author: Andy Yen <[email protected]>
AuthorDate: Wed Mar 19 01:44:56 2025 +0800

    chore: Attach Diagnostic to "incompatible type in unary expression" error 
(#15209)
    
    * chore: attach diagnostic to unary_op PLUS
    
    * remove condition and update test case
---
 datafusion/sql/src/expr/unary_op.rs      | 13 +++++++++--
 datafusion/sql/tests/cases/diagnostic.rs | 38 ++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/datafusion/sql/src/expr/unary_op.rs 
b/datafusion/sql/src/expr/unary_op.rs
index a4096ec235..a4a973a74a 100644
--- a/datafusion/sql/src/expr/unary_op.rs
+++ b/datafusion/sql/src/expr/unary_op.rs
@@ -16,7 +16,7 @@
 // under the License.
 
 use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
-use datafusion_common::{not_impl_err, plan_err, DFSchema, Result};
+use datafusion_common::{not_impl_err, plan_err, DFSchema, Diagnostic, Result};
 use datafusion_expr::{
     type_coercion::{is_interval, is_timestamp},
     Expr, ExprSchemable,
@@ -45,7 +45,16 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
                 {
                     Ok(operand)
                 } else {
-                    plan_err!("Unary operator '+' only supports numeric, 
interval and timestamp types")
+                    plan_err!("Unary operator '+' only supports numeric, 
interval and timestamp types").map_err(|e| {
+                        let span = operand.spans().and_then(|s| s.first());
+                        let mut diagnostic = Diagnostic::new_error(
+                            format!("+ cannot be used with {data_type}"), 
+                            span
+                        );
+                        diagnostic.add_note("+ can only be used with numbers, 
intervals, and timestamps", None);
+                        diagnostic.add_help(format!("perhaps you need to cast 
{operand}"), None);
+                        e.with_diagnostic(diagnostic)
+                    })
                 }
             }
             UnaryOperator::Minus => {
diff --git a/datafusion/sql/tests/cases/diagnostic.rs 
b/datafusion/sql/tests/cases/diagnostic.rs
index 5481f046e7..db3aad1467 100644
--- a/datafusion/sql/tests/cases/diagnostic.rs
+++ b/datafusion/sql/tests/cases/diagnostic.rs
@@ -351,6 +351,44 @@ fn test_in_subquery_multiple_columns() -> Result<(), 
Box<dyn std::error::Error>>
             .collect::<Vec<_>>(),
         vec!["Select only one column in the subquery"]
     );
+    Ok(())
+}
 
+#[test]
+fn test_unary_op_plus_with_column() -> Result<()> {
+    // Test with a direct query that references a column with an incompatible 
type
+    let query = "SELECT +/*whole*/first_name/*whole*/ FROM person";
+    let spans = get_spans(query);
+    let diag = do_query(query);
+    assert_eq!(diag.message, "+ cannot be used with Utf8");
+    assert_eq!(diag.span, Some(spans["whole"]));
+    assert_eq!(
+        diag.notes[0].message,
+        "+ can only be used with numbers, intervals, and timestamps"
+    );
+    assert_eq!(
+        diag.helps[0].message,
+        "perhaps you need to cast person.first_name"
+    );
+    Ok(())
+}
+
+#[test]
+fn test_unary_op_plus_with_non_column() -> Result<()> {
+    // create a table with a column of type varchar
+    let query = "SELECT +'a'";
+    let diag = do_query(query);
+    assert_eq!(diag.message, "+ cannot be used with Utf8");
+    assert_eq!(
+        diag.notes[0].message,
+        "+ can only be used with numbers, intervals, and timestamps"
+    );
+    assert_eq!(diag.notes[0].span, None);
+    assert_eq!(
+        diag.helps[0].message,
+        "perhaps you need to cast Utf8(\"a\")"
+    );
+    assert_eq!(diag.helps[0].span, None);
+    assert_eq!(diag.span, None);
     Ok(())
 }


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

Reply via email to