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]

Reply via email to