Skip to content

Commit 5ebdfbe

Browse files
authored
refactor(query): refactor bind set returning functions (#16316)
* refactor(query): refactor bind set returning functions * fix tests
1 parent 04a4929 commit 5ebdfbe

File tree

11 files changed

+204
-283
lines changed

11 files changed

+204
-283
lines changed

src/query/ast/src/ast/common.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -174,27 +174,6 @@ impl Display for TableRef {
174174
}
175175
}
176176

177-
#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
178-
pub struct DictionaryRef {
179-
pub catalog: Option<Identifier>,
180-
pub database: Option<Identifier>,
181-
pub dictionary_name: Identifier,
182-
}
183-
184-
impl Display for DictionaryRef {
185-
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
186-
assert!(self.catalog.is_none() || (self.catalog.is_some() && self.database.is_some()));
187-
if let Some(catalog) = &self.catalog {
188-
write!(f, "{}.", catalog)?;
189-
}
190-
if let Some(database) = &self.database {
191-
write!(f, "{}.", database)?;
192-
}
193-
write!(f, "{}", self.dictionary_name)?;
194-
Ok(())
195-
}
196-
}
197-
198177
#[derive(Debug, Clone, PartialEq, Eq, Drive, DriveMut)]
199178
pub struct ColumnRef {
200179
pub database: Option<Identifier>,

src/query/ast/src/ast/visitors/walk.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,6 @@ pub fn walk_table_ref<'a, V: Visitor<'a>>(visitor: &mut V, table: &'a TableRef)
167167
visitor.visit_identifier(&table.table);
168168
}
169169

170-
pub fn walk_dictionary_ref<'a, V: Visitor<'a>>(visitor: &mut V, dictionary: &'a DictionaryRef) {
171-
if let Some(catalog) = &dictionary.catalog {
172-
visitor.visit_identifier(catalog);
173-
}
174-
if let Some(database) = &dictionary.database {
175-
visitor.visit_identifier(database);
176-
}
177-
visitor.visit_identifier(&dictionary.dictionary_name);
178-
}
179-
180170
pub fn walk_query<'a, V: Visitor<'a>>(visitor: &mut V, query: &'a Query) {
181171
let Query {
182172
with,

src/query/sql/src/planner/binder/bind_context.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use crate::binder::ColumnBindingBuilder;
4545
use crate::normalize_identifier;
4646
use crate::optimizer::SExpr;
4747
use crate::plans::ScalarExpr;
48+
use crate::plans::ScalarItem;
4849
use crate::ColumnSet;
4950
use crate::IndexType;
5051
use crate::MetadataRef;
@@ -135,8 +136,7 @@ pub struct BindContext {
135136
pub view_info: Option<(String, String)>,
136137

137138
/// Set-returning functions in current context.
138-
/// The key is the `Expr::to_string` of the function.
139-
pub srfs: DashMap<String, ScalarExpr>,
139+
pub srfs: Vec<ScalarItem>,
140140

141141
pub inverted_index_map: Box<IndexMap<IndexType, InvertedIndexInfo>>,
142142

@@ -177,7 +177,7 @@ impl BindContext {
177177
cte_map_ref: Box::default(),
178178
in_grouping: false,
179179
view_info: None,
180-
srfs: DashMap::new(),
180+
srfs: Vec::new(),
181181
inverted_index_map: Box::default(),
182182
expr_context: ExprContext::default(),
183183
planning_agg_index: false,
@@ -197,7 +197,7 @@ impl BindContext {
197197
cte_map_ref: parent.cte_map_ref.clone(),
198198
in_grouping: false,
199199
view_info: None,
200-
srfs: DashMap::new(),
200+
srfs: Vec::new(),
201201
inverted_index_map: Box::default(),
202202
expr_context: ExprContext::default(),
203203
planning_agg_index: false,

src/query/sql/src/planner/binder/bind_query/bind_select.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ use derive_visitor::Drive;
3838
use derive_visitor::Visitor;
3939
use log::warn;
4040

41-
use crate::binder::project_set::SrfCollector;
4241
use crate::optimizer::SExpr;
4342
use crate::planner::binder::BindContext;
4443
use crate::planner::binder::Binder;
@@ -102,27 +101,16 @@ impl Binder {
102101
let new_stmt = rewriter.rewrite(stmt)?;
103102
let stmt = new_stmt.as_ref().unwrap_or(stmt);
104103

105-
// Collect set returning functions
106-
let set_returning_functions = {
107-
let mut collector = SrfCollector::new();
108-
stmt.select_list.iter().for_each(|item| {
109-
if let SelectTarget::AliasedExpr { expr, .. } = item {
110-
collector.visit(expr);
111-
}
112-
});
113-
collector.into_srfs()
114-
};
115-
116-
// Bind set returning functions
117-
s_expr = self.bind_project_set(&mut from_context, &set_returning_functions, s_expr)?;
118-
119104
// Try put window definitions into bind context.
120105
// This operation should be before `normalize_select_list` because window functions can be used in select list.
121106
self.analyze_window_definition(&mut from_context, &stmt.window_list)?;
122107

123108
// Generate a analyzed select list with from context
124109
let mut select_list = self.normalize_select_list(&mut from_context, &stmt.select_list)?;
125110

111+
// analyze set returning functions
112+
self.analyze_project_set_select(&mut from_context, &mut select_list)?;
113+
126114
// This will potentially add some alias group items to `from_context` if find some.
127115
if let Some(group_by) = stmt.group_by.as_ref() {
128116
self.analyze_group_items(&mut from_context, &select_list, group_by)?;
@@ -140,6 +128,12 @@ impl Binder {
140128
.map(|item| (item.alias.clone(), item.scalar.clone()))
141129
.collect::<Vec<_>>();
142130

131+
let have_srfs = !from_context.srfs.is_empty();
132+
if have_srfs {
133+
// Bind set returning functions first.
134+
s_expr = self.bind_project_set(&mut from_context, s_expr)?;
135+
}
136+
143137
// To support using aliased column in `WHERE` clause,
144138
// we should bind where after `select_list` is rewritten.
145139
let where_scalar = if let Some(expr) = &stmt.selection {
@@ -179,7 +173,7 @@ impl Binder {
179173
)?;
180174

181175
// After all analysis is done.
182-
if set_returning_functions.is_empty() {
176+
if !have_srfs {
183177
// Ignore SRFs.
184178
self.analyze_lazy_materialization(
185179
&from_context,

src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,19 @@ impl Binder {
348348
lambda: None,
349349
},
350350
};
351-
let srfs = vec![srf.clone()];
352-
let srf_expr = self.bind_project_set(&mut bind_context, &srfs, child)?;
353-
354-
if let Some((_, srf_result)) = bind_context.srfs.remove(&srf.to_string()) {
351+
let select_list = vec![SelectTarget::AliasedExpr {
352+
expr: Box::new(srf.clone()),
353+
alias: None,
354+
}];
355+
let mut select_list =
356+
self.normalize_select_list(&mut bind_context, &select_list)?;
357+
// analyze set returning functions
358+
self.analyze_project_set_select(&mut bind_context, &mut select_list)?;
359+
// bind set returning functions
360+
let srf_expr = self.bind_project_set(&mut bind_context, child)?;
361+
362+
if let Some(item) = select_list.items.pop() {
363+
let srf_result = item.scalar;
355364
let column_binding =
356365
if let ScalarExpr::BoundColumnRef(column_ref) = &srf_result {
357366
column_ref.column.clone()
@@ -408,7 +417,7 @@ impl Binder {
408417
"The function '{}' is not supported for lateral joins. Lateral joins currently support only Set Returning Functions (SRFs).",
409418
func_name
410419
))
411-
.set_span(*span))
420+
.set_span(*span))
412421
}
413422
}
414423
_ => unreachable!(),

0 commit comments

Comments
 (0)