Describe the bug
When a table function is called with a tuple argument, the SQL parser preserves the argument, but DataFusion drops it during planning and ContextProvider::get_table_function_source receives an empty args vector.
For example:
SELECT * FROM my_func(('a', 'b', 'c'));
... will lead to a call equivalent to get_table_function_source("my_func", vec![])
To Reproduce
With datafusion-sql 53.0.0:
use std::sync::Arc;
use datafusion_common::{arrow::datatypes::DataType, config::ConfigOptions, DataFusionError};
use datafusion_expr::{AggregateUDF, Expr, ScalarUDF, TableSource, WindowUDF};
use datafusion_sql::{
planner::{ContextProvider, SqlToRel},
sqlparser::{dialect::GenericDialect, parser::Parser},
TableReference,
};
struct Dummy;
impl ContextProvider for Dummy {
fn get_table_source(
&self,
_name: TableReference,
) -> Result<Arc<dyn TableSource>, DataFusionError> {
unimplemented!()
}
fn get_table_function_source(
&self,
name: &str,
args: Vec<Expr>,
) -> Result<Arc<dyn TableSource>, DataFusionError> {
println!("table function name={name:?} args={args:#?}");
unimplemented!()
}
fn get_function_meta(&self, _name: &str) -> Option<Arc<ScalarUDF>> { None }
fn get_aggregate_meta(&self, _name: &str) -> Option<Arc<AggregateUDF>> { None }
fn get_window_meta(&self, _name: &str) -> Option<Arc<WindowUDF>> { None }
fn get_variable_type(&self, _variable_names: &[String]) -> Option<DataType> { None }
fn options(&self) -> &ConfigOptions {
static OPTIONS: std::sync::OnceLock<ConfigOptions> = std::sync::OnceLock::new();
OPTIONS.get_or_init(ConfigOptions::default)
}
fn udf_names(&self) -> Vec<String> { vec![] }
fn udaf_names(&self) -> Vec<String> { vec![] }
fn udwf_names(&self) -> Vec<String> { vec![] }
}
fn main() {
let sql = "select * from my_func(('a', 'b', 'c'))";
let dialect = GenericDialect {};
let ast = Parser::parse_sql(&dialect, sql).unwrap();
println!("ast = {:#?}", ast[0]);
let provider = Dummy;
let sql_to_rel = SqlToRel::new(&provider);
let _ = sql_to_rel.sql_statement_to_plan(ast[0].clone());
}
Cargo.toml:
[dependencies]
datafusion-common = "53.0.0"
datafusion-expr = "53.0.0"
datafusion-sql = "53.0.0"
This prints: table function name="my_func" args=[]
Expected behavior
I would expect get_table_function_source to either get a non-empty argument list, or for planning to return an error.
Additional context
It looks like the issue might be here:
The flat_map will happily turn the error result into a iterable, ignoring the error.
Describe the bug
When a table function is called with a tuple argument, the SQL parser preserves the argument, but DataFusion drops it during planning and
ContextProvider::get_table_function_sourcereceives an emptyargsvector.For example:
... will lead to a call equivalent to
get_table_function_source("my_func", vec![])To Reproduce
With
datafusion-sql53.0.0:Cargo.toml:This prints:
table function name="my_func" args=[]Expected behavior
I would expect
get_table_function_sourceto either get a non-empty argument list, or for planning to return an error.Additional context
It looks like the issue might be here:
datafusion/datafusion/sql/src/relation/mod.rs
Line 154 in 2b986c8
The
flat_mapwill happily turn the error result into a iterable, ignoring the error.