Skip to content

Commit f44ec4f

Browse files
crwenKKould
andauthored
feat: add support for nested loop join (#164)
* add support for nested loop join * fix:keep the order of tuple and schema * fix:right join not matched case * fix: expression ownership in the temp table of subquery * fix: bind error of the same fields in different tables in `in subquery` * fix: combine_operators.rs deletes the temp table alias of subquery * test: add `F041_08.slt`/`sqlite.slt`/`subquery.slt` --------- Co-authored-by: Kould <[email protected]>
1 parent b8d5416 commit f44ec4f

File tree

15 files changed

+907
-101
lines changed

15 files changed

+907
-101
lines changed

src/binder/expr.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,34 +110,35 @@ impl<'a, T: Transaction> Binder<'a, T> {
110110
}),
111111
Expr::Subquery(subquery) => {
112112
let (sub_query, column) = self.bind_subquery(subquery)?;
113-
self.context.sub_query(SubQueryType::SubQuery(sub_query));
114-
115-
if self.context.is_step(&QueryBindStep::Where) {
116-
Ok(self.bind_temp_column(column))
113+
let (expr, sub_query) = if !self.context.is_step(&QueryBindStep::Where) {
114+
self.bind_temp_table(column, sub_query)?
117115
} else {
118-
Ok(ScalarExpression::ColumnRef(column))
119-
}
116+
(ScalarExpression::ColumnRef(column), sub_query)
117+
};
118+
self.context.sub_query(SubQueryType::SubQuery(sub_query));
119+
Ok(expr)
120120
}
121121
Expr::InSubquery {
122122
expr,
123123
subquery,
124124
negated,
125125
} => {
126+
let left_expr = Box::new(self.bind_expr(expr)?);
126127
let (sub_query, column) = self.bind_subquery(subquery)?;
127-
self.context
128-
.sub_query(SubQueryType::InSubQuery(*negated, sub_query));
129128

130129
if !self.context.is_step(&QueryBindStep::Where) {
131130
return Err(DatabaseError::UnsupportedStmt(
132131
"'IN (SUBQUERY)' can only appear in `WHERE`".to_string(),
133132
));
134133
}
135134

136-
let alias_expr = self.bind_temp_column(column);
135+
let (alias_expr, sub_query) = self.bind_temp_table(column, sub_query)?;
136+
self.context
137+
.sub_query(SubQueryType::InSubQuery(*negated, sub_query));
137138

138139
Ok(ScalarExpression::Binary {
139140
op: expression::BinaryOperator::Eq,
140-
left_expr: Box::new(self.bind_expr(expr)?),
141+
left_expr,
141142
right_expr: Box::new(alias_expr),
142143
ty: LogicalType::Boolean,
143144
})
@@ -203,16 +204,22 @@ impl<'a, T: Transaction> Binder<'a, T> {
203204
}
204205
}
205206

206-
fn bind_temp_column(&mut self, column: ColumnRef) -> ScalarExpression {
207+
fn bind_temp_table(
208+
&mut self,
209+
column: ColumnRef,
210+
sub_query: LogicalPlan,
211+
) -> Result<(ScalarExpression, LogicalPlan), DatabaseError> {
207212
let mut alias_column = ColumnCatalog::clone(&column);
208213
alias_column.set_table_name(self.context.temp_table());
209214

210-
ScalarExpression::Alias {
215+
let alias_expr = ScalarExpression::Alias {
211216
expr: Box::new(ScalarExpression::ColumnRef(column)),
212217
alias: AliasType::Expr(Box::new(ScalarExpression::ColumnRef(Arc::new(
213218
alias_column,
214219
)))),
215-
}
220+
};
221+
let alias_plan = self.bind_project(sub_query, vec![alias_expr.clone()])?;
222+
Ok((alias_expr, alias_plan))
216223
}
217224

218225
fn bind_subquery(
@@ -289,7 +296,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
289296
} else {
290297
// handle col syntax
291298
let mut got_column = None;
292-
for table_catalog in self.context.bind_table.values() {
299+
for table_catalog in self.context.bind_table.values().rev() {
293300
if let Some(column_catalog) = table_catalog.get_column_by_name(&column_name) {
294301
got_column = Some(column_catalog);
295302
}

src/binder/select.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
7676
// Resolve scalar function call.
7777
// TODO support SRF(Set-Returning Function).
7878

79-
let mut select_list = self.normalize_select_item(&select.projection)?;
79+
let mut select_list = self.normalize_select_item(&select.projection, &plan)?;
8080

8181
if let Some(predicate) = &select.selection {
8282
plan = self.bind_where(plan, predicate)?;
@@ -341,6 +341,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
341341
fn normalize_select_item(
342342
&mut self,
343343
items: &[SelectItem],
344+
plan: &LogicalPlan,
344345
) -> Result<Vec<ScalarExpression>, DatabaseError> {
345346
let mut select_items = vec![];
346347

@@ -359,6 +360,9 @@ impl<'a, T: Transaction> Binder<'a, T> {
359360
});
360361
}
361362
SelectItem::Wildcard(_) => {
363+
if let Operator::Project(op) = &plan.operator {
364+
return Ok(op.exprs.clone());
365+
}
362366
for (table_name, _) in self.context.bind_table.keys() {
363367
self.bind_table_column_refs(&mut select_items, table_name.clone())?;
364368
}
@@ -510,7 +514,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
510514
Ok(FilterOperator::build(having, children, true))
511515
}
512516

513-
fn bind_project(
517+
pub(crate) fn bind_project(
514518
&mut self,
515519
children: LogicalPlan,
516520
select_list: Vec<ScalarExpression>,
@@ -791,7 +795,12 @@ impl<'a, T: Transaction> Binder<'a, T> {
791795
)?;
792796
}
793797
BinaryOperator::Or => {
794-
todo!("`NestLoopJoin` is not supported yet")
798+
accum_filter.push(ScalarExpression::Binary {
799+
left_expr,
800+
right_expr,
801+
op,
802+
ty,
803+
});
795804
}
796805
_ => {
797806
if left_expr.referenced_columns(true).iter().all(|column| {

src/execution/volcano/dql/join/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::planner::operator::join::JoinType;
22

33
pub(crate) mod hash_join;
4+
pub(crate) mod nested_loop_join;
45

56
pub fn joins_nullable(join_type: &JoinType) -> (bool, bool) {
67
match join_type {

0 commit comments

Comments
 (0)