Skip to content

Commit a665a9d

Browse files
xinlifoobaralamb
authored andcommitted
Implement user defined planner for extract (apache#11215)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
1 parent 286ae6a commit a665a9d

5 files changed

Lines changed: 64 additions & 16 deletions

File tree

datafusion/core/src/execution/session_state.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -967,14 +967,19 @@ impl SessionState {
967967
let field_access_planner =
968968
Arc::new(functions_array::planner::FieldAccessPlanner) as _;
969969

970-
query
970+
query = query
971971
.with_user_defined_planner(array_planner)
972-
.with_user_defined_planner(field_access_planner)
972+
.with_user_defined_planner(field_access_planner);
973973
}
974-
#[cfg(not(feature = "array_expressions"))]
974+
#[cfg(feature = "datetime_expressions")]
975975
{
976-
query
976+
let extract_planner =
977+
Arc::new(functions::datetime::planner::ExtractPlanner::default()) as _;
978+
979+
query = query.with_user_defined_planner(extract_planner);
977980
}
981+
982+
query
978983
}
979984
}
980985

datafusion/expr/src/planner.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ pub trait UserDefinedSQLPlanner: Send + Sync {
110110
) -> Result<PlannerResult<Vec<Expr>>> {
111111
Ok(PlannerResult::Original(exprs))
112112
}
113+
114+
// Plan the Extract expression, e.g., EXTRACT(month FROM foo)
115+
// returns origin expression arguments if not possible
116+
fn plan_extract(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
117+
Ok(PlannerResult::Original(args))
118+
}
113119
}
114120

115121
/// An operator with two arguments to plan

datafusion/functions/src/datetime/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub mod date_trunc;
3030
pub mod from_unixtime;
3131
pub mod make_date;
3232
pub mod now;
33+
pub mod planner;
3334
pub mod to_char;
3435
pub mod to_date;
3536
pub mod to_timestamp;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//! SQL planning extensions like [`ExtractPlanner`]
19+
20+
use datafusion_common::Result;
21+
use datafusion_expr::{
22+
expr::ScalarFunction,
23+
planner::{PlannerResult, UserDefinedSQLPlanner},
24+
Expr,
25+
};
26+
27+
#[derive(Default)]
28+
pub struct ExtractPlanner {}
29+
30+
impl UserDefinedSQLPlanner for ExtractPlanner {
31+
fn plan_extract(&self, args: Vec<Expr>) -> Result<PlannerResult<Vec<Expr>>> {
32+
Ok(PlannerResult::Planned(Expr::ScalarFunction(
33+
ScalarFunction::new_udf(crate::datetime::date_part(), args),
34+
)))
35+
}
36+
}

datafusion/sql/src/expr/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -175,21 +175,21 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
175175
self.parse_value(value, planner_context.prepare_param_data_types())
176176
}
177177
SQLExpr::Extract { field, expr } => {
178-
let date_part = self
179-
.context_provider
180-
.get_function_meta("date_part")
181-
.ok_or_else(|| {
182-
internal_datafusion_err!(
183-
"Unable to find expected 'date_part' function"
184-
)
185-
})?;
186-
let args = vec![
178+
let mut extract_args = vec![
187179
Expr::Literal(ScalarValue::from(format!("{field}"))),
188180
self.sql_expr_to_logical_expr(*expr, schema, planner_context)?,
189181
];
190-
Ok(Expr::ScalarFunction(ScalarFunction::new_udf(
191-
date_part, args,
192-
)))
182+
183+
for planner in self.planners.iter() {
184+
match planner.plan_extract(extract_args)? {
185+
PlannerResult::Planned(expr) => return Ok(expr),
186+
PlannerResult::Original(args) => {
187+
extract_args = args;
188+
}
189+
}
190+
}
191+
192+
not_impl_err!("Extract not supported by UserDefinedExtensionPlanners: {extract_args:?}")
193193
}
194194

195195
SQLExpr::Array(arr) => self.sql_array_literal(arr.elem, schema),

0 commit comments

Comments
 (0)