Skip to content

Commit

Permalink
Implement user defined planner for sql_substring_to_expr (apache#11327)
Browse files Browse the repository at this point in the history
  • Loading branch information
xinlifoobar committed Jul 18, 2024
1 parent 354304b commit 7773f38
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 14 deletions.
7 changes: 7 additions & 0 deletions datafusion/expr/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ pub trait UserDefinedSQLPlanner: Send + Sync {
Ok(PlannerResult::Original(args))
}

/// Plan an substring expression, e.g., `SUBSTRING(<expr> [FROM <expr>] [FOR <expr>])`
///
/// Returns origin expression arguments if not possible
fn plan_substring(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Original(args))
}

/// Plans a struct `struct(expression1[, ..., expression_n])`
/// literal based on the given input expressions.
/// This function takes a vector of expressions and a boolean flag indicating whether
Expand Down
7 changes: 7 additions & 0 deletions datafusion/functions/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,11 @@ impl UserDefinedSQLPlanner for UserDefinedFunctionPlanner {
ScalarFunction::new_udf(crate::unicode::strpos(), args),
)))
}

#[cfg(feature = "unicode_expressions")]
fn plan_substring(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
Ok(PlannerResult::Planned(Expr::ScalarFunction(
ScalarFunction::new_udf(crate::unicode::substr(), args),
)))
}
}
8 changes: 4 additions & 4 deletions datafusion/sql/src/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,18 +670,18 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
let substr =
self.sql_expr_to_logical_expr(substr_expr, schema, planner_context)?;
let fullstr = self.sql_expr_to_logical_expr(str_expr, schema, planner_context)?;
let mut extract_args = vec![fullstr, substr];
let mut position_args = vec![fullstr, substr];
for planner in self.planners.iter() {
match planner.plan_position(extract_args)? {
match planner.plan_position(position_args)? {
PlannerResult::Planned(expr) => return Ok(expr),
PlannerResult::Original(args) => {
extract_args = args;
position_args = args;
}
}
}

not_impl_err!(
"Position not supported by UserDefinedExtensionPlanners: {extract_args:?}"
"Position not supported by UserDefinedExtensionPlanners: {position_args:?}"
)
}

Expand Down
24 changes: 14 additions & 10 deletions datafusion/sql/src/expr/substring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
// under the License.

use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
use datafusion_common::{internal_datafusion_err, plan_err};
use datafusion_common::{not_impl_err, plan_err};
use datafusion_common::{DFSchema, Result, ScalarValue};
use datafusion_expr::expr::ScalarFunction;
use datafusion_expr::planner::PlannerResult;
use datafusion_expr::Expr;
use sqlparser::ast::Expr as SQLExpr;

Expand All @@ -31,7 +31,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
schema: &DFSchema,
planner_context: &mut PlannerContext,
) -> Result<Expr> {
let args = match (substring_from, substring_for) {
let mut substring_args = match (substring_from, substring_for) {
(Some(from_expr), Some(for_expr)) => {
let arg =
self.sql_expr_to_logical_expr(*expr, schema, planner_context)?;
Expand Down Expand Up @@ -68,13 +68,17 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
}
};

let fun = self
.context_provider
.get_function_meta("substr")
.ok_or_else(|| {
internal_datafusion_err!("Unable to find expected 'substr' function")
})?;
for planner in self.planners.iter() {
match planner.plan_substring(substring_args)? {
PlannerResult::Planned(expr) => return Ok(expr),
PlannerResult::Original(args) => {
substring_args = args;
}
}
}

Ok(Expr::ScalarFunction(ScalarFunction::new_udf(fun, args)))
not_impl_err!(
"Substring not supported by UserDefinedExtensionPlanners: {substring_args:?}"
)
}
}

0 comments on commit 7773f38

Please sign in to comment.