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]