diff --git a/datafusion/expr/src/planner.rs b/datafusion/expr/src/planner.rs index a456db87ab9a..a969ff6dc5f4 100644 --- a/datafusion/expr/src/planner.rs +++ b/datafusion/expr/src/planner.rs @@ -111,9 +111,12 @@ pub trait UserDefinedSQLPlanner: Send + Sync { Ok(PlannerResult::Original(exprs)) } - // Plan the POSITION expression, e.g., POSITION( in ) - // returns origin expression arguments if not possible - fn plan_position(&self, args: Vec) -> Result>> { + // Plan the user defined function, returns origin expression arguments if not possible + fn plan_udf( + &self, + _sql: &sqlparser::ast::Expr, + args: Vec, + ) -> Result>> { Ok(PlannerResult::Original(args)) } } diff --git a/datafusion/functions/src/unicode/planner.rs b/datafusion/functions/src/unicode/planner.rs index d3f9db324beb..d618913658c3 100644 --- a/datafusion/functions/src/unicode/planner.rs +++ b/datafusion/functions/src/unicode/planner.rs @@ -21,14 +21,22 @@ use datafusion_common::Result; use datafusion_expr::{ expr::ScalarFunction, planner::{PlannerResult, UserDefinedSQLPlanner}, - Expr, + sqlparser, Expr, }; #[derive(Default)] pub struct PositionPlanner {} impl UserDefinedSQLPlanner for PositionPlanner { - fn plan_position(&self, args: Vec) -> Result>> { + fn plan_udf( + &self, + sql: &sqlparser::ast::Expr, + args: Vec, + ) -> Result>> { + let sqlparser::ast::Expr::Position { .. } = sql else { + return Ok(PlannerResult::Original(args)); + }; + Ok(PlannerResult::Planned(Expr::ScalarFunction( ScalarFunction::new_udf(crate::unicode::strpos(), args), ))) diff --git a/datafusion/sql/src/expr/mod.rs b/datafusion/sql/src/expr/mod.rs index 55af96c3bb27..65e0513745d1 100644 --- a/datafusion/sql/src/expr/mod.rs +++ b/datafusion/sql/src/expr/mod.rs @@ -170,6 +170,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { schema: &DFSchema, planner_context: &mut PlannerContext, ) -> Result { + let sql_not_moved = sql.clone(); match sql { SQLExpr::Value(value) => { self.parse_value(value, planner_context.prepare_param_data_types()) @@ -601,18 +602,18 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { self.sql_expr_to_logical_expr(*expr, schema, planner_context)?; let fullstr = self.sql_expr_to_logical_expr(*r#in, schema, planner_context)?; - let mut extract_args = vec![fullstr, substr]; + let mut extracted_args = vec![fullstr, substr]; for planner in self.planners.iter() { - match planner.plan_position(extract_args)? { + match planner.plan_udf(&sql_not_moved, extracted_args)? { PlannerResult::Planned(expr) => return Ok(expr), PlannerResult::Original(args) => { - extract_args = args; + extracted_args = args; } } } - not_impl_err!("Position not supported by UserDefinedExtensionPlanners: {extract_args:?}") + not_impl_err!("Position not supported by UserDefinedExtensionPlanners: {extracted_args:?}") } SQLExpr::AtTimeZone { timestamp,