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 71292d09ba fix: DataFusion panics with "No candidates provided"
(#12469)
71292d09ba is described below
commit 71292d09ba1a2e26be0742a233cb1ef0e07a773d
Author: Alex Huang <[email protected]>
AuthorDate: Wed Sep 18 01:35:25 2024 +0800
fix: DataFusion panics with "No candidates provided" (#12469)
* fix: Refactor function.rs to handle empty candidates in find_closest_match
* Update datafusion/sql/src/expr/function.rs
Co-authored-by: Andrew Lamb <[email protected]>
* chore: Fix format
* test: Add test for no functions registered error
---------
Co-authored-by: Andrew Lamb <[email protected]>
---
datafusion/sql/src/expr/function.rs | 12 +++++++-----
datafusion/sql/tests/sql_integration.rs | 20 ++++++++++++++++++++
2 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/datafusion/sql/src/expr/function.rs
b/datafusion/sql/src/expr/function.rs
index 190a7e9189..1c114523d7 100644
--- a/datafusion/sql/src/expr/function.rs
+++ b/datafusion/sql/src/expr/function.rs
@@ -43,7 +43,7 @@ pub fn suggest_valid_function(
input_function_name: &str,
is_window_func: bool,
ctx: &dyn ContextProvider,
-) -> String {
+) -> Result<String> {
let valid_funcs = if is_window_func {
// All aggregate functions and builtin window functions
let mut funcs = Vec::new();
@@ -66,8 +66,8 @@ pub fn suggest_valid_function(
}
/// Find the closest matching string to the target string in the candidates
list, using edit distance(case insensitive)
-/// Input `candidates` must not be empty otherwise it will panic
-fn find_closest_match(candidates: Vec<String>, target: &str) -> String {
+/// Input `candidates` must not be empty otherwise an error is returned.
+fn find_closest_match(candidates: Vec<String>, target: &str) -> Result<String>
{
let target = target.to_lowercase();
candidates
.into_iter()
@@ -77,7 +77,9 @@ fn find_closest_match(candidates: Vec<String>, target: &str)
-> String {
&target,
)
})
- .expect("No candidates provided.") // Panic if `candidates` argument
is empty
+ .ok_or_else(|| {
+ internal_datafusion_err!("No functions registered with this
context.")
+ })
}
/// Arguments to for a function call extracted from the SQL AST
@@ -354,7 +356,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
// Could not find the relevant function, so return an error
let suggested_func_name =
- suggest_valid_function(&name, is_function_window,
self.context_provider);
+ suggest_valid_function(&name, is_function_window,
self.context_provider)?;
plan_err!("Invalid function '{name}'.\nDid you mean
'{suggested_func_name}'?")
}
diff --git a/datafusion/sql/tests/sql_integration.rs
b/datafusion/sql/tests/sql_integration.rs
index 5a203703e9..bdb84af464 100644
--- a/datafusion/sql/tests/sql_integration.rs
+++ b/datafusion/sql/tests/sql_integration.rs
@@ -4436,3 +4436,23 @@ fn init() {
// Enable RUST_LOG logging configuration for tests
let _ = env_logger::try_init();
}
+
+#[test]
+fn test_no_functions_registered() {
+ let sql = "SELECT foo()";
+
+ let options = ParserOptions::default();
+ let dialect = &GenericDialect {};
+ let state = MockSessionState::default();
+ let context = MockContextProvider { state };
+ let planner = SqlToRel::new_with_options(&context, options);
+ let result = DFParser::parse_sql_with_dialect(sql, dialect);
+ let mut ast = result.unwrap();
+
+ let err = planner.statement_to_plan(ast.pop_front().unwrap());
+
+ assert_contains!(
+ err.unwrap_err().to_string(),
+ "Internal error: No functions registered with this context."
+ );
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]