diff --git a/datafusion/expr/src/expr_schema.rs b/datafusion/expr/src/expr_schema.rs index f4e4f014f533c..400a89279c4bc 100644 --- a/datafusion/expr/src/expr_schema.rs +++ b/datafusion/expr/src/expr_schema.rs @@ -29,8 +29,8 @@ use arrow::datatypes::{DataType, Field, FieldRef}; use datafusion_common::datatype::FieldExt; use datafusion_common::metadata::FieldMetadata; use datafusion_common::{ - Column, DataFusionError, ExprSchema, Result, ScalarValue, Spans, TableReference, - not_impl_err, plan_datafusion_err, plan_err, + Column, ExprSchema, Result, ScalarValue, Spans, TableReference, not_impl_err, + plan_err, }; use datafusion_expr_common::type_coercion::binary::BinaryTypeCoercer; use datafusion_functions_window_common::field::WindowUDFFieldArgs; @@ -628,23 +628,7 @@ fn verify_function_arguments( input_fields: &[FieldRef], ) -> Result> { fields_with_udf(input_fields, function).map_err(|err| { - let data_types = input_fields - .iter() - .map(|f| f.data_type()) - .cloned() - .collect::>(); - plan_datafusion_err!( - "{} {}", - match err { - DataFusionError::Plan(msg) => msg, - err => err.to_string(), - }, - utils::generate_signature_error_message( - function.name(), - function.signature(), - &data_types - ) - ) + utils::generate_signature_error_message(function, input_fields, err) }) } diff --git a/datafusion/expr/src/type_coercion/functions.rs b/datafusion/expr/src/type_coercion/functions.rs index d839d84c6625a..f837f0a7b3be5 100644 --- a/datafusion/expr/src/type_coercion/functions.rs +++ b/datafusion/expr/src/type_coercion/functions.rs @@ -27,7 +27,7 @@ use datafusion_common::utils::{ ListCoercion, base_type, coerced_fixed_size_list_to_list, }; use datafusion_common::{ - Result, exec_err, internal_err, plan_err, types::NativeType, utils::list_ndims, + Result, internal_err, plan_err, types::NativeType, utils::list_ndims, }; use datafusion_expr_common::signature::ArrayFunctionArgument; use datafusion_expr_common::type_coercion::binary::type_union_resolution; @@ -313,16 +313,10 @@ fn get_valid_types_with_udf( func: &F, ) -> Result>> { let valid_types = match signature { - TypeSignature::UserDefined => match func.coerce_types(current_types) { - Ok(coerced_types) => vec![coerced_types], - Err(e) => { - return exec_err!( - "Function '{}' user-defined coercion failed with {:?}", - func.name(), - e.strip_backtrace() - ); - } - }, + TypeSignature::UserDefined => { + let coerced_types = func.coerce_types(current_types)?; + vec![coerced_types] + } TypeSignature::OneOf(signatures) => { let mut res = vec![]; let mut errors = vec![]; diff --git a/datafusion/expr/src/utils.rs b/datafusion/expr/src/utils.rs index b19299981cef3..abc194bfc5d85 100644 --- a/datafusion/expr/src/utils.rs +++ b/datafusion/expr/src/utils.rs @@ -23,19 +23,20 @@ use std::sync::Arc; use crate::expr::{Alias, Sort, WildcardOptions, WindowFunctionParams}; use crate::expr_rewriter::strip_outer_reference; +use crate::type_coercion::functions::UDFCoercionExt; use crate::{ BinaryExpr, Expr, ExprSchemable, Filter, GroupingSet, LogicalPlan, Operator, and, }; use datafusion_expr_common::signature::{Signature, TypeSignature}; -use arrow::datatypes::{DataType, Field, Schema}; +use arrow::datatypes::{DataType, Field, FieldRef, Schema}; use datafusion_common::tree_node::{ Transformed, TransformedResult, TreeNode, TreeNodeRecursion, }; use datafusion_common::utils::get_at_indices; use datafusion_common::{ - Column, DFSchema, DFSchemaRef, HashMap, Result, TableReference, internal_err, - plan_err, + Column, DFSchema, DFSchemaRef, DataFusionError, HashMap, Result, TableReference, + internal_err, plan_datafusion_err, plan_err, }; #[cfg(not(feature = "sql"))] @@ -971,13 +972,57 @@ pub fn generate_signature_error_msg( /// round(Float64) /// round(Float32) /// ``` -pub(crate) fn generate_signature_error_message( - func_name: &str, - func_signature: &Signature, - input_expr_types: &[DataType], -) -> String { - #[expect(deprecated)] - generate_signature_error_msg(func_name, func_signature.clone(), input_expr_types) +pub(crate) fn generate_signature_error_message( + function: &F, + input_fields: &[FieldRef], + original_error: DataFusionError, +) -> DataFusionError { + let data_types = input_fields + .iter() + .map(|f| f.data_type()) + .cloned() + .collect::>(); + let function_call_str = format!( + "{}({})", + function.name(), + TypeSignature::join_types(&data_types, ", "), + ); + + // UserDefined signatures are better served returning the original error, since + // we can't know what went wrong in the custom code + if function.signature().type_signature == TypeSignature::UserDefined { + let original_error = match original_error { + // Since we're returning a Plan error we don't want any double nesting. + // TODO: is there a better way to strip backtrace & the planning prefix? + err @ DataFusionError::Plan(_) => err + .strip_backtrace() + .strip_prefix("Error during planning: ") + .unwrap() + .to_string(), + err => err.strip_backtrace(), + }; + return plan_datafusion_err!( + "User-defined coercion of function call '{function_call_str}' failed with:\n{original_error}" + ); + } + + // For other signature types, we don't rely on what specifically went wrong; + // we will only show the valid signatures to better display what is allowed + // (instead of enumerating everything that potentially went wrong). + drop(original_error); + + let candidate_signatures = function + .signature() + .type_signature + .to_string_repr_with_names(function.signature().parameter_names.as_deref()) + .iter() + .map(|args_str| format!("\t{}({args_str})", function.name())) + .collect::>() + .join("\n"); + + plan_datafusion_err!( + "Failed to coerce function call '{function_call_str}'. You might need to add explicit type casts.\n\tCandidate functions:\n{candidate_signatures}" + ) } /// Splits a conjunctive [`Expr`] such as `A AND B AND C` => `[A, B, C]` @@ -1735,6 +1780,35 @@ mod tests { assert!(!can_hash(&list_union_type)); } + struct MockUdf(Signature); + + impl UDFCoercionExt for MockUdf { + fn name(&self) -> &str { + "mock" + } + + fn signature(&self) -> &Signature { + &self.0 + } + + fn coerce_types(&self, _arg_types: &[DataType]) -> Result> { + unimplemented!() + } + } + + #[test] + fn test_generate_signature_error_msg_user_defined() { + let error = generate_signature_error_message( + &MockUdf(Signature::user_defined(Volatility::Immutable)), + &[Field::new("name", DataType::Int32, true).into()], + DataFusionError::Plan("Expected 'mock' to fail".to_string()), + ); + + let expected = "Error during planning: User-defined coercion of function call 'mock(Int32)' failed with: +Expected 'mock' to fail"; + assert!(error.to_string().starts_with(expected)); + } + #[test] fn test_generate_signature_error_msg_with_parameter_names() { let sig = Signature::one_of( @@ -1755,18 +1829,17 @@ mod tests { ]) .expect("valid parameter names"); - // Generate error message with only 1 argument provided - let error_msg = - generate_signature_error_message("substr", &sig, &[DataType::Utf8]); - - assert!( - error_msg.contains("str: Utf8, start_pos: Int64"), - "Expected 'str: Utf8, start_pos: Int64' in error message, got: {error_msg}" - ); - assert!( - error_msg.contains("str: Utf8, start_pos: Int64, length: Int64"), - "Expected 'str: Utf8, start_pos: Int64, length: Int64' in error message, got: {error_msg}" + let error = generate_signature_error_message( + &MockUdf(sig), + &[Field::new("name", DataType::Utf8, true).into()], + DataFusionError::Plan("".to_string()), ); + + let expected = "Error during planning: Failed to coerce function call 'mock(Utf8)'. You might need to add explicit type casts. +\tCandidate functions: +\tmock(str: Utf8, start_pos: Int64) +\tmock(str: Utf8, start_pos: Int64, length: Int64)"; + assert!(error.to_string().starts_with(expected)); } #[test] @@ -1776,12 +1849,16 @@ mod tests { Volatility::Immutable, ); - let error_msg = - generate_signature_error_message("my_func", &sig, &[DataType::Int32]); - - assert!( - error_msg.contains("Any, Any"), - "Expected 'Any, Any' without parameter names, got: {error_msg}" + let error = generate_signature_error_message( + &MockUdf(sig), + &[Field::new("name", DataType::Int32, true).into()], + DataFusionError::Plan("".to_string()), ); + + let expected = "Error during planning: Failed to coerce function call 'mock(Int32)'. You might need to add explicit type casts. +\tCandidate functions: +\tmock(Any, Any) +\tmock(Any, Any, Any)"; + assert!(error.to_string().starts_with(expected)); } } diff --git a/datafusion/optimizer/src/analyzer/type_coercion.rs b/datafusion/optimizer/src/analyzer/type_coercion.rs index 8b57cc798d079..594c515538667 100644 --- a/datafusion/optimizer/src/analyzer/type_coercion.rs +++ b/datafusion/optimizer/src/analyzer/type_coercion.rs @@ -1830,7 +1830,7 @@ mod test { let err = Projection::try_new(vec![udaf], empty).err().unwrap(); assert!( - err.strip_backtrace().starts_with("Error during planning: Failed to coerce arguments to satisfy a call to 'MY_AVG' function: coercion from Utf8 to the signature Uniform(1, [Float64]) failed") + err.strip_backtrace().starts_with("Error during planning: Failed to coerce function call 'MY_AVG(Utf8)'. You might need to add explicit type casts.\n\tCandidate functions:\n\tMY_AVG(Float64)") ); Ok(()) } @@ -1891,7 +1891,7 @@ mod test { .err() .unwrap() .strip_backtrace(); - assert!(err.starts_with("Error during planning: Failed to coerce arguments to satisfy a call to 'avg' function: coercion from Utf8 to the signature Uniform(1, [Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, Float32, Float64]) failed")); + assert!(err.starts_with("Error during planning: Failed to coerce function call 'avg(Utf8)'. You might need to add explicit type casts.\n\tCandidate functions:\n\tavg(Int8/Int16/Int32/Int64/UInt8/UInt16/UInt32/UInt64/Float32/Float64)")); Ok(()) } diff --git a/datafusion/sql/tests/sql_integration.rs b/datafusion/sql/tests/sql_integration.rs index aaf0b0ae30fd0..444075be289ec 100644 --- a/datafusion/sql/tests/sql_integration.rs +++ b/datafusion/sql/tests/sql_integration.rs @@ -4744,11 +4744,11 @@ fn error_message_test(sql: &str, err_msg_starts_with: &str) { fn test_error_message_invalid_scalar_function_signature() { error_message_test( "select sqrt()", - "Error during planning: 'sqrt' does not support zero arguments", + "Error during planning: Failed to coerce function call 'sqrt()'", ); error_message_test( "select sqrt(1, 2)", - "Error during planning: Failed to coerce arguments", + "Error during planning: Failed to coerce function call 'sqrt(Int64, Int64)'", ); } @@ -4756,13 +4756,15 @@ fn test_error_message_invalid_scalar_function_signature() { 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\"", + "Error during planning: User-defined coercion of function call 'sum()' 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", + "Error during planning: User-defined coercion of function call 'max(Int64, Int64)' failed with: +Execution error: min/max was called with 2 arguments. It requires only 1.", ); } @@ -4770,7 +4772,7 @@ fn test_error_message_invalid_aggregate_function_signature() { 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", + "Error during planning: Failed to coerce function call 'rank(Int64)'", ); } @@ -4778,7 +4780,8 @@ fn test_error_message_invalid_window_function_signature() { 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\"", + "Error during planning: User-defined coercion of function call 'sum()' failed with: +Execution error: sum function requires 1 argument, got 0", ); } diff --git a/datafusion/sqllogictest/test_files/aggregate.slt b/datafusion/sqllogictest/test_files/aggregate.slt index 036bb93283cc6..70187ff9e2037 100644 --- a/datafusion/sqllogictest/test_files/aggregate.slt +++ b/datafusion/sqllogictest/test_files/aggregate.slt @@ -144,26 +144,26 @@ statement error DataFusion error: Schema error: Schema contains duplicate unqual SELECT approx_distinct(c9) count_c9, approx_distinct(cast(c9 as varchar)) count_c9_str FROM aggregate_test_100 # csv_query_approx_percentile_cont_with_weight -statement error Failed to coerce arguments to satisfy a call to 'approx_percentile_cont_with_weight' function +statement error Failed to coerce function call 'approx_percentile_cont_with_weight\(Utf8View, Int8, Float64\)' SELECT approx_percentile_cont_with_weight(c2, 0.95) WITHIN GROUP (ORDER BY c1) FROM aggregate_test_100 -statement error Failed to coerce arguments to satisfy a call to 'approx_percentile_cont_with_weight' function +statement error Failed to coerce function call 'approx_percentile_cont_with_weight\(Int16, Utf8View, Float64\)' SELECT approx_percentile_cont_with_weight(c1, 0.95) WITHIN GROUP (ORDER BY c3) FROM aggregate_test_100 -statement error Failed to coerce arguments to satisfy a call to 'approx_percentile_cont_with_weight' function +statement error Failed to coerce function call 'approx_percentile_cont_with_weight\(Int16, Int8, Utf8View\)' SELECT approx_percentile_cont_with_weight(c2, c1) WITHIN GROUP (ORDER BY c3) FROM aggregate_test_100 # csv_query_approx_percentile_cont_with_histogram_bins statement error DataFusion error: Error during planning: Tdigest max_size value for 'APPROX_PERCENTILE_CONT' must be UInt > 0 literal \(got data type Int64\)\. SELECT c1, approx_percentile_cont(0.95, -1000) WITHIN GROUP (ORDER BY c3) AS c3_p95 FROM aggregate_test_100 GROUP BY 1 ORDER BY 1 -statement error Failed to coerce arguments to satisfy a call to 'approx_percentile_cont' function +statement error Failed to coerce function call 'approx_percentile_cont\(Int16, Float64, Utf8View\)' SELECT approx_percentile_cont(0.95, c1) WITHIN GROUP (ORDER BY c3) FROM aggregate_test_100 -statement error DataFusion error: Error during planning: Failed to coerce arguments to satisfy a call to 'approx_percentile_cont' function: coercion from Int16, Float64, Float64 to the signature OneOf(.*) failed(.|\n)* +statement error Failed to coerce function call 'approx_percentile_cont\(Int16, Float64, Float64\)' SELECT approx_percentile_cont(0.95, 111.1) WITHIN GROUP (ORDER BY c3) FROM aggregate_test_100 -statement error DataFusion error: Error during planning: Failed to coerce arguments to satisfy a call to 'approx_percentile_cont' function: coercion from Float64, Float64, Float64 to the signature OneOf(.*) failed(.|\n)* +statement error Failed to coerce function call 'approx_percentile_cont\(Float64, Float64, Float64\)' SELECT approx_percentile_cont(0.95, 111.1) WITHIN GROUP (ORDER BY c12) FROM aggregate_test_100 statement error DataFusion error: Error during planning: Percentile value for 'APPROX_PERCENTILE_CONT' must be a literal diff --git a/datafusion/sqllogictest/test_files/array.slt b/datafusion/sqllogictest/test_files/array.slt index 590f6b1a9ab9f..4dc3aed783b5d 100644 --- a/datafusion/sqllogictest/test_files/array.slt +++ b/datafusion/sqllogictest/test_files/array.slt @@ -1210,7 +1210,7 @@ from arrays_values_without_nulls; ## array_element (aliases: array_extract, list_extract, list_element) # Testing with empty arguments should result in an error -query error DataFusion error: Error during planning: 'array_element' does not support zero arguments +query error Failed to coerce function call 'array_element\(\)' select array_element(); # array_element error @@ -1548,7 +1548,7 @@ select array_max(make_array()); NULL # Testing with empty arguments should result in an error -query error DataFusion error: Error during planning: 'array_max' does not support zero arguments +query error Failed to coerce function call 'array_max\(\)' select array_max(); ## array_min @@ -1638,7 +1638,7 @@ select array_min(make_array()); NULL # Testing with empty arguments should result in an error -query error DataFusion error: Error during planning: 'array_min' does not support zero arguments +query error Failed to coerce function call 'array_min\(\)' select array_min(); @@ -1993,7 +1993,7 @@ select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'), 0, # Expected output (once supported): # ---- # [1, 2, 3, 4, 5] [h, e, l, l, o] -query error Failed to coerce arguments to satisfy a call to 'array_slice' function: +query error Failed to coerce function call 'array_slice\(ListView\(Int64\), Int64, Int64\)' select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'ListView(Int64)'), 0, 6), array_slice(arrow_cast(make_array('h', 'e', 'l', 'l', 'o'), 'ListView(Utf8)'), 0, 5); @@ -2040,7 +2040,7 @@ select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeList(Int64)'), 2, # Expected output (once supported): # ---- # [2, 3, 4, 5] [l, l, o] -query error Failed to coerce arguments to satisfy a call to 'array_slice' function: +query error Failed to coerce function call 'array_slice\(LargeListView\(Int64\), Int64, Int64\)' select array_slice(arrow_cast(make_array(1, 2, 3, 4, 5), 'LargeListView(Int64)'), 2, 6), array_slice(arrow_cast(make_array('h', 'e', 'l', 'l', 'o'), 'LargeListView(Utf8)'), 3, 7); @@ -2321,10 +2321,10 @@ select array_slice(a, -1, 2, 1), array_slice(a, -1, 2), [6.0] [6.0] [] [] # Testing with empty arguments should result in an error -query error DataFusion error: Error during planning: 'array_slice' does not support zero arguments +query error Failed to coerce function call 'array_slice\(\)' select array_slice(); -query error Failed to coerce arguments +query error Failed to coerce function call 'array_slice\(Float64, Null, Null\)' select array_slice(3.5, NULL, NULL); ## array_any_value (aliases: list_any_value) @@ -3361,7 +3361,7 @@ select [1, 2, 3] List(Utf8View) # 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 User-defined coercion of function call 'array_concat\(Int64, Int64\)' failed with:\narray_concat does not support type Int64 select array_concat(1, 2); # array_concat scalar function #1 @@ -3688,10 +3688,10 @@ SELECT array_position(arrow_cast([1, 1, 100, 1, 1], 'LargeList(Int32)'), 100) ---- 3 -query error DataFusion error: Error during planning: Failed to coerce arguments to satisfy a call to 'array_position' function: coercion from +query error Failed to coerce function call 'array_position\(List\(Int64\), Utf8\)' SELECT array_position([1, 2, 3], 'foo') -query error DataFusion error: Error during planning: Failed to coerce arguments to satisfy a call to 'array_position' function: coercion from +query error Failed to coerce function call 'array_position\(List\(Int64\), Utf8, Int64\)' SELECT array_position([1, 2, 3], 'foo', 2) # list_position scalar function #5 (function alias `array_position`) @@ -4778,7 +4778,7 @@ select array_union(arrow_cast([], 'LargeList(Int64)'), arrow_cast([], 'LargeList # ---- # [[]] -query error DataFusion error: Error during planning: Failed to coerce arguments to satisfy a call to 'array_union' function: +query error Failed to coerce function call 'array_union\(LargeList\(List\(Int64\)\), LargeList\(Int64\)\)' select array_union(arrow_cast([[null]], 'LargeList(List(Int64))'), arrow_cast([], 'LargeList(Int64)')); # array_union scalar function #8 @@ -7271,17 +7271,17 @@ select generate_series(arrow_cast('2021-01-01T00:00:00', 'Timestamp(Nanosecond, [2021-01-01T00:00:00-05:00, 2021-01-01T01:29:54.500-05:00, 2021-01-01T02:59:49-05:00, 2021-01-01T04:29:43.500-05:00, 2021-01-01T05:59:38-05:00] ## mixing types for timestamps is not supported -query error DataFusion error: Error during planning: Internal error: Function 'generate_series' failed to match any signature +query error Failed to coerce function call 'generate_series\(Timestamp\(ns, "-05:00"\), Date32, Interval\(MonthDayNano\)\)' select generate_series(arrow_cast('2021-01-01T00:00:00', 'Timestamp(Nanosecond, Some("-05:00"))'), DATE '2021-01-02', INTERVAL '1' HOUR); ## mixing types not allowed even if an argument is null -query error DataFusion error: Error during planning: Internal error: Function 'generate_series' failed to match any signature +query error Failed to coerce function call 'generate_series\(Timestamp\(ns\), Date32, Null\)' select generate_series(TIMESTAMP '1992-09-01', DATE '1993-03-01', NULL); -query error DataFusion error: Error during planning: Internal error: Function 'generate_series' failed to match any signature +query error Failed to coerce function call 'generate_series\(Int64, Utf8, Utf8\)' select generate_series(1, '2024-01-01', '2025-01-02'); -query error DataFusion error: Error during planning: Internal error: Function 'generate_series' failed to match any signature +query error Failed to coerce function call 'generate_series\(Timestamp\(ns\), Utf8, Interval\(MonthDayNano\)\)' select generate_series('2024-01-01'::timestamp, '2025-01-02', interval '1 day'); ## should return NULL diff --git a/datafusion/sqllogictest/test_files/arrow_typeof.slt b/datafusion/sqllogictest/test_files/arrow_typeof.slt index 0c69e8591c3a4..7540e9d81480f 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 Failed to coerce function call 'arrow_cast\(Utf8, 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 c4a21deeff26b..12205a72e5368 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 Failed to coerce function call 'split_part\(Binary, Utf8, Int64\)' 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 fa25994ed7edc..9264abf8c6945 100644 --- a/datafusion/sqllogictest/test_files/datetime/timestamps.slt +++ b/datafusion/sqllogictest/test_files/datetime/timestamps.slt @@ -831,11 +831,11 @@ SELECT DATE_BIN(INTERVAL '23 hours 59 minutes 59 seconds', TIME '14:38:50', TIME 00:00:00 # mixed types -query error Failed to coerce arguments to satisfy a call to 'date_bin' function: +query error Failed to coerce function call 'date_bin\(Interval\(MonthDayNano\), Time64\(ns\), Timestamp\(ns\)\)' SELECT DATE_BIN(INTERVAL '23 hours', TIME '14:38:50', TIMESTAMP '2022-08-03 14:38:50.000000006Z') # mixed types -query error Failed to coerce arguments to satisfy a call to 'date_bin' function: +query error Failed to coerce function call 'date_bin\(Interval\(MonthDayNano\), Timestamp\(ns\), Time64\(ns\)\)' SELECT DATE_BIN(INTERVAL '23 hours', TIMESTAMP '2022-08-03 14:38:50.000000006Z', TIME '14:38:50') # Can coerce all string arguments @@ -3061,10 +3061,10 @@ select make_date(null, 1::bigint, 14::bigint unsigned); ---- NULL -query error DataFusion error: Error during planning: Function 'make_date' expects 3 arguments but received 1 +query error Failed to coerce function call 'make_date\(Int64\)' 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 Failed to coerce function call 'make_date\(Interval\(MonthDayNano\), Timestamp\(ns\), Timestamp\(ns\)\)' select make_date(interval '1 day', '2001-05-21'::timestamp, '2001-05-21'::timestamp); ########## @@ -3304,10 +3304,10 @@ select make_time(t.hour, t.minute, t.second) from table_strings t; statement ok drop table table_strings; -query error Function 'make_time' expects 3 arguments but received 1 +query error Failed to coerce function call 'make_time\(Int64\)' select make_time(22); -query error Function 'make_time' expects 3 arguments but received 2 +query error Failed to coerce function call 'make_time\(Int64, Int64\)' select make_time(22, 22); query error DataFusion error: Execution error: Hour value '26' is out of range @@ -3337,7 +3337,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 Failed to coerce function call 'make_time\(Float64, Int64, Utf8\)' select make_time(arrow_cast(22, 'Float64'), 1, ''); ########## @@ -3443,7 +3443,7 @@ select to_time('12:60:00'); query error Error parsing '12:30:61' as time select to_time('12:30:61'); -query error does not support zero arguments +query error Failed to coerce function call 'to_time\(\)' select to_time(); # StringView type support @@ -3952,7 +3952,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 Failed to coerce function call 'to_local_time\(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 b04d5061825b4..da5db3ff2890a 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 Failed to coerce function call 'encode\(Int64, Utf8\)' select encode(12, 'hex'); -query error DataFusion error: Error during planning: Function 'decode' requires TypeSignatureClass::Binary, but received Int64 \(DataType: Int64\) +query error Failed to coerce function call 'decode\(Int64, Utf8\)' 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 Failed to coerce function call 'to_hex\(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/errors.slt b/datafusion/sqllogictest/test_files/errors.slt index 20c1db5cb1511..aca428d31ade7 100644 --- a/datafusion/sqllogictest/test_files/errors.slt +++ b/datafusion/sqllogictest/test_files/errors.slt @@ -113,11 +113,11 @@ query error select avg(c1, c12) from aggregate_test_100; # AggregateFunction with wrong argument type -statement error DataFusion error: Error during planning: Failed to coerce arguments to satisfy a call to 'regr_slope' function: coercion from +statement error Failed to coerce function call 'regr_slope\(Int64, Utf8\)' select regr_slope(1, '2'); # WindowFunction using AggregateFunction wrong signature -statement error DataFusion error: Error during planning: Failed to coerce arguments to satisfy a call to 'regr_slope' function: coercion from +statement error Failed to coerce function call 'regr_slope\(Float32, Utf8\)' select c9, regr_slope(c11, '2') over () as min1 @@ -125,7 +125,7 @@ from aggregate_test_100 order by c9 # WindowFunction wrong signature -statement error DataFusion error: Error during planning: Internal error: Function 'nth_value' failed to match any signature +statement error Failed to coerce function call 'nth_value\(Int32, Int64, Int64\)' select c9, nth_value(c5, 2, 3) over (order by c9) as nv1 diff --git a/datafusion/sqllogictest/test_files/expr.slt b/datafusion/sqllogictest/test_files/expr.slt index 00b581632748c..7eb6951637a15 100644 --- a/datafusion/sqllogictest/test_files/expr.slt +++ b/datafusion/sqllogictest/test_files/expr.slt @@ -589,7 +589,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 Failed to coerce function call 'repeat\(Utf8, 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 6c87d618c7278..1c3a03a5bb989 100644 --- a/datafusion/sqllogictest/test_files/functions.slt +++ b/datafusion/sqllogictest/test_files/functions.slt @@ -208,10 +208,10 @@ SELECT substr('alphabet', NULL, 2) ---- NULL -statement error Function 'substr' failed to match any signature +statement error Failed to coerce function call 'substr\(Int64, Int64\)' SELECT substr(1, 3) -statement error Function 'substr' failed to match any signature +statement error Failed to coerce function call 'substr\(Int64, Int64, Int64\)' SELECT substr(1, 3, 4) query T @@ -873,7 +873,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 User-defined coercion of function call 'greatest\(\)' failed with:\ngreatest was called without any arguments. It requires at least 1. SELECT greatest() query I @@ -1071,7 +1071,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 User-defined coercion of function call 'least\(\)' failed with:\nleast was called without any arguments. It requires at least 1. SELECT least() query I diff --git a/datafusion/sqllogictest/test_files/grouping.slt b/datafusion/sqllogictest/test_files/grouping.slt index 3d38576bdbf5f..db126a3f09e06 100644 --- a/datafusion/sqllogictest/test_files/grouping.slt +++ b/datafusion/sqllogictest/test_files/grouping.slt @@ -210,7 +210,7 @@ select c1, grouping(c2) from test group by c1; statement error c2.*not in grouping columns select c1, grouping(c1, c2) from test group by CUBE(c1); -statement error zero arguments +statement error Failed to coerce function call 'grouping\(\)' select c1, grouping() from test group by CUBE(c1); # grouping_sets_with_empty_set diff --git a/datafusion/sqllogictest/test_files/math.slt b/datafusion/sqllogictest/test_files/math.slt index 71a969c751591..51702f7a3ffac 100644 --- a/datafusion/sqllogictest/test_files/math.slt +++ b/datafusion/sqllogictest/test_files/math.slt @@ -126,15 +126,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 Failed to coerce function call 'abs\(Utf8\)' 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 Failed to coerce function call 'abs\(Utf8\)' select abs('-1.2'); -query error DataFusion error: Error during planning: Function 'abs' expects NativeType::Numeric but received NativeType::String +query error Failed to coerce function call 'abs\(Utf8\)' select abs(arrow_cast('-1.2', 'Utf8')); statement ok diff --git a/datafusion/sqllogictest/test_files/named_arguments.slt b/datafusion/sqllogictest/test_files/named_arguments.slt index 07b6cc6a79a0c..e213151aee39d 100644 --- a/datafusion/sqllogictest/test_files/named_arguments.slt +++ b/datafusion/sqllogictest/test_files/named_arguments.slt @@ -86,7 +86,7 @@ SELECT substr("STR" => 'hello world', "start_pos" => 7); # Error: wrong number of arguments # This query provides only 1 argument but substr requires 2 or 3 -query error Function 'substr' failed to match any signature +query error Failed to coerce function call 'substr\(Utf8\)' SELECT substr(str => 'hello world'); ############# diff --git a/datafusion/sqllogictest/test_files/scalar.slt b/datafusion/sqllogictest/test_files/scalar.slt index 4206d4c65ed87..110a171c35d1b 100644 --- a/datafusion/sqllogictest/test_files/scalar.slt +++ b/datafusion/sqllogictest/test_files/scalar.slt @@ -2069,7 +2069,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 Failed to coerce function call 'strpos\(Int64, Int64\)' select position(1 in 1) query I diff --git a/datafusion/sqllogictest/test_files/spark/datetime/last_day.slt b/datafusion/sqllogictest/test_files/spark/datetime/last_day.slt index 6dee48de9555d..d99a0cd3110ea 100644 --- a/datafusion/sqllogictest/test_files/spark/datetime/last_day.slt +++ b/datafusion/sqllogictest/test_files/spark/datetime/last_day.slt @@ -100,19 +100,19 @@ SELECT last_day(null::DATE); NULL -statement error Failed to coerce arguments to satisfy a call to 'last_day' function +statement error Failed to coerce function call 'last_day\(Utf8\)' select last_day('foo'); -statement error Failed to coerce arguments to satisfy a call to 'last_day' function +statement error Failed to coerce function call 'last_day\(Int64\)' select last_day(123); -statement error 'last_day' does not support zero arguments +statement error Failed to coerce function call 'last_day\(\)' select last_day(); -statement error Failed to coerce arguments to satisfy a call to 'last_day' function +statement error Failed to coerce function call 'last_day\(Utf8View, Utf8\)' select last_day(last_day('2016-02-07'::string, 'foo')); -statement error Failed to coerce arguments to satisfy a call to 'last_day' function +statement error Failed to coerce function call 'last_day\(Utf8View\)' select last_day(last_day('2016-02-31'::string)); diff --git a/datafusion/sqllogictest/test_files/spark/datetime/next_day.slt b/datafusion/sqllogictest/test_files/spark/datetime/next_day.slt index 872d1f2b58eb6..470f94a09ae5c 100644 --- a/datafusion/sqllogictest/test_files/spark/datetime/next_day.slt +++ b/datafusion/sqllogictest/test_files/spark/datetime/next_day.slt @@ -36,22 +36,22 @@ SELECT next_day('2015-07-27'::DATE, 'Sat'::string); ---- 2015-08-01 -query error Failed to coerce arguments to satisfy a call to 'next_day' function +query error Failed to coerce function call 'next_day\(Date32\)' SELECT next_day('2015-07-27'::DATE); -query error Failed to coerce arguments to satisfy a call to 'next_day' function +query error Failed to coerce function call 'next_day\(Utf8View\)' SELECT next_day('Sun'::string); -query error 'next_day' does not support zero arguments +query error Failed to coerce function call 'next_day\(\)' SELECT next_day(); -query error Failed to coerce arguments to satisfy a call to 'next_day' function +query error Failed to coerce function call 'next_day\(Int32, Utf8View\)' SELECT next_day(1::int, 'Sun'::string); -query error Failed to coerce arguments to satisfy a call to 'next_day' function +query error Failed to coerce function call 'next_day\(Date32, Utf8View, Utf8View\)' SELECT next_day('2015-07-27'::DATE, 'Sat'::string, 'Sun'::string); -query error Failed to coerce arguments to satisfy a call to 'next_day' function +query error Failed to coerce function call 'next_day\(Utf8View, Utf8View\)' SELECT next_day('invalid_date'::string, 'Mon'::string); query D diff --git a/datafusion/sqllogictest/test_files/spark/datetime/unix.slt b/datafusion/sqllogictest/test_files/spark/datetime/unix.slt index d7441f487d037..48a0cfff2dbd0 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 Failed to coerce function call 'unix_date\(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 Failed to coerce function call 'unix_micros\(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 Failed to coerce function call 'unix_millis\(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 Failed to coerce function call 'unix_seconds\(Utf8View\)' SELECT unix_seconds('1970-01-01 00:00:01Z'::string); diff --git a/datafusion/sqllogictest/test_files/spark/math/factorial.slt b/datafusion/sqllogictest/test_files/spark/math/factorial.slt index f8eae5d95ab85..dd64d5bbe0f14 100644 --- a/datafusion/sqllogictest/test_files/spark/math/factorial.slt +++ b/datafusion/sqllogictest/test_files/spark/math/factorial.slt @@ -62,5 +62,5 @@ NULL NULL NULL -query error Error during planning: Failed to coerce arguments to satisfy a call to 'factorial' function +query error Failed to coerce function call 'factorial\(Int64\)' SELECT factorial(5::BIGINT); diff --git a/datafusion/sqllogictest/test_files/spark/math/hex.slt b/datafusion/sqllogictest/test_files/spark/math/hex.slt index 17e9ff432890d..08ed2e7453a35 100644 --- a/datafusion/sqllogictest/test_files/spark/math/hex.slt +++ b/datafusion/sqllogictest/test_files/spark/math/hex.slt @@ -56,7 +56,7 @@ SELECT hex(column1) FROM VALUES (arrow_cast('hello', 'LargeBinary')), (NULL), (a NULL 776F726C64 -statement error Function 'hex' expects 1 arguments but received 2 +statement error Failed to coerce function call 'hex\(Int64, Int64\)' SELECT hex(1, 2); query T diff --git a/datafusion/sqllogictest/test_files/spark/string/base64.slt b/datafusion/sqllogictest/test_files/spark/string/base64.slt index 03b488de0ee9a..aea8cfb9e8aa1 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 Failed to coerce function call 'base64\(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 Failed to coerce function call 'unbase64\(Int32\)' SELECT unbase64(12::integer); diff --git a/datafusion/sqllogictest/test_files/spark/url/parse_url.slt b/datafusion/sqllogictest/test_files/spark/url/parse_url.slt index f2dc55f75598a..fac604ba08cf3 100644 --- a/datafusion/sqllogictest/test_files/spark/url/parse_url.slt +++ b/datafusion/sqllogictest/test_files/spark/url/parse_url.slt @@ -170,7 +170,7 @@ SELECT parse_url('https://ex.com/?Tag=ok', 'query', 'tag'); ---- NULL -statement error 'parse_url' does not support zero arguments +statement error Failed to coerce function call 'parse_url\(\)' SELECT parse_url(); query error DataFusion error: Execution error: The url is invalid: inva lid://spark\.apache\.org/path\?query=1\. Use `try_parse_url` to tolerate invalid URL and return NULL instead\. SQLSTATE: 22P02 diff --git a/datafusion/sqllogictest/test_files/string/string_literal.slt b/datafusion/sqllogictest/test_files/string/string_literal.slt index 6cf02218872df..d67d3bddc2c5b 100644 --- a/datafusion/sqllogictest/test_files/string/string_literal.slt +++ b/datafusion/sqllogictest/test_files/string/string_literal.slt @@ -132,10 +132,10 @@ SELECT substr('Hello🌏世界', 5, 3) ---- o🌏世 -statement error Function 'substr' failed to match any signature +statement error Failed to coerce function call 'substr\(Int64, Int64\)' SELECT substr(1, 3) -statement error Function 'substr' failed to match any signature +statement error Failed to coerce function call 'substr\(Int64, Int64, Int64\)' SELECT substr(1, 3, 4) statement error Execution error: negative substring length not allowed diff --git a/datafusion/sqllogictest/test_files/union_function.slt b/datafusion/sqllogictest/test_files/union_function.slt index 74616490ab707..250dbd062c35c 100644 --- a/datafusion/sqllogictest/test_files/union_function.slt +++ b/datafusion/sqllogictest/test_files/union_function.slt @@ -32,13 +32,13 @@ select union_column, union_extract(union_column, 'int') from union_table; query error DataFusion error: Execution error: field bool not found on union select union_extract(union_column, 'bool') from union_table; -query error DataFusion error: Error during planning: 'union_extract' does not support zero arguments +query error Failed to coerce function call 'union_extract\(\)' select union_extract() from union_table; -query error DataFusion error: Error during planning: The function 'union_extract' expected 2 arguments but received 1 +query error Failed to coerce function call 'union_extract\(Union\(Sparse, 3: \("int": non-null Int32\), 1: \("string": non-null Utf8\)\)\)' select union_extract(union_column) from union_table; -query error DataFusion error: Error during planning: The function 'union_extract' expected 2 arguments but received 1 +query error Failed to coerce function call 'union_extract\(Utf8\)' select union_extract('a') from union_table; query error DataFusion error: Execution error: union_extract first argument must be a union, got Utf8 instead @@ -47,7 +47,7 @@ select union_extract('a', union_column) from union_table; query error DataFusion error: Execution error: union_extract second argument must be a non\-null string literal, got Int64 instead select union_extract(union_column, 1) from union_table; -query error DataFusion error: Error during planning: The function 'union_extract' expected 2 arguments but received 3 +query error Failed to coerce function call 'union_extract\(Union\(Sparse, 3: \("int": non-null Int32\), 1: \("string": non-null Utf8\)\), Utf8, Utf8\)' select union_extract(union_column, 'a', 'b') from union_table; query ?T @@ -57,10 +57,10 @@ select union_column, union_tag(union_column) from union_table; {string=bar} string {int=3} int -query error DataFusion error: Error during planning: 'union_tag' does not support zero arguments +query error Failed to coerce function call 'union_tag\(\)' select union_tag() from union_table; -query error DataFusion error: Error during planning: The function 'union_tag' expected 1 arguments but received 2 +query error Failed to coerce function call 'union_tag\(Union\(Sparse, 3: \("int": non-null Int32\), 1: \("string": non-null Utf8\)\), Utf8\)' select union_tag(union_column, 'int') from union_table; query error DataFusion error: Execution error: union_tag only support unions, got Utf8