Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions src/binder/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,34 +110,35 @@ impl<'a, T: Transaction> Binder<'a, T> {
}),
Expr::Subquery(subquery) => {
let (sub_query, column) = self.bind_subquery(subquery)?;
self.context.sub_query(SubQueryType::SubQuery(sub_query));

if self.context.is_step(&QueryBindStep::Where) {
Ok(self.bind_temp_column(column))
let (expr, sub_query) = if !self.context.is_step(&QueryBindStep::Where) {
self.bind_temp_table(column, sub_query)?
} else {
Ok(ScalarExpression::ColumnRef(column))
}
(ScalarExpression::ColumnRef(column), sub_query)
};
self.context.sub_query(SubQueryType::SubQuery(sub_query));
Ok(expr)
}
Expr::InSubquery {
expr,
subquery,
negated,
} => {
let left_expr = Box::new(self.bind_expr(expr)?);
let (sub_query, column) = self.bind_subquery(subquery)?;
self.context
.sub_query(SubQueryType::InSubQuery(*negated, sub_query));

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

let alias_expr = self.bind_temp_column(column);
let (alias_expr, sub_query) = self.bind_temp_table(column, sub_query)?;
self.context
.sub_query(SubQueryType::InSubQuery(*negated, sub_query));

Ok(ScalarExpression::Binary {
op: expression::BinaryOperator::Eq,
left_expr: Box::new(self.bind_expr(expr)?),
left_expr,
right_expr: Box::new(alias_expr),
ty: LogicalType::Boolean,
})
Expand Down Expand Up @@ -203,16 +204,22 @@ impl<'a, T: Transaction> Binder<'a, T> {
}
}

fn bind_temp_column(&mut self, column: ColumnRef) -> ScalarExpression {
fn bind_temp_table(
&mut self,
column: ColumnRef,
sub_query: LogicalPlan,
) -> Result<(ScalarExpression, LogicalPlan), DatabaseError> {
let mut alias_column = ColumnCatalog::clone(&column);
alias_column.set_table_name(self.context.temp_table());

ScalarExpression::Alias {
let alias_expr = ScalarExpression::Alias {
expr: Box::new(ScalarExpression::ColumnRef(column)),
alias: AliasType::Expr(Box::new(ScalarExpression::ColumnRef(Arc::new(
alias_column,
)))),
}
};
let alias_plan = self.bind_project(sub_query, vec![alias_expr.clone()])?;
Ok((alias_expr, alias_plan))
}

fn bind_subquery(
Expand Down Expand Up @@ -289,7 +296,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
} else {
// handle col syntax
let mut got_column = None;
for table_catalog in self.context.bind_table.values() {
for table_catalog in self.context.bind_table.values().rev() {
if let Some(column_catalog) = table_catalog.get_column_by_name(&column_name) {
got_column = Some(column_catalog);
}
Expand Down
15 changes: 12 additions & 3 deletions src/binder/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
// Resolve scalar function call.
// TODO support SRF(Set-Returning Function).

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

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

Expand All @@ -359,6 +360,9 @@ impl<'a, T: Transaction> Binder<'a, T> {
});
}
SelectItem::Wildcard(_) => {
if let Operator::Project(op) = &plan.operator {
return Ok(op.exprs.clone());
}
for (table_name, _) in self.context.bind_table.keys() {
self.bind_table_column_refs(&mut select_items, table_name.clone())?;
}
Expand Down Expand Up @@ -510,7 +514,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
Ok(FilterOperator::build(having, children, true))
}

fn bind_project(
pub(crate) fn bind_project(
&mut self,
children: LogicalPlan,
select_list: Vec<ScalarExpression>,
Expand Down Expand Up @@ -791,7 +795,12 @@ impl<'a, T: Transaction> Binder<'a, T> {
)?;
}
BinaryOperator::Or => {
todo!("`NestLoopJoin` is not supported yet")
Copy link
Member

@KKould KKould Mar 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result is correct when Or does not exist

let _ = fnck_sql
    .run("CREATE TABLE tab64784(pk INTEGER primary key, col0 INTEGER, col1 FLOAT, col2 VARCHAR, col3 INTEGER, col4 FLOAT, col5 VARCHAR)")
    .await?;
let _ = fnck_sql
    .run("INSERT INTO tab64784 VALUES(0,212,202.62,'nshdy',212,208.79,'wsxfc'),(1,213,203.64,'xwfuo',213,209.26,'lyswz'),(2,214,204.82,'jnued',216,210.48,'qczzf'),(3,215,205.40,'jtijf',217,211.96,'dpugl'),(4,216,206.3,'dpdzk',219,212.43,'xfirg'),(5,218,207.43,'qpwyw',220,213.50,'fmgky'),(6,219,208.3,'uooxb',221,215.30,'xpmdy'),(7,220,209.54,'ndtbb',225,218.8,'ivqyw'),(8,221,210.65,'zjpts',226,219.82,'sezsm'),(9,222,211.57,'slaxq',227,220.91,'bdqyb');")
    .await?;
let (schema, tuples) = fnck_sql.run("explain SELECT pk, col0 FROM tab64784 WHERE col0 IN (SELECT col3 FROM tab64784 WHERE col3 IS NULL OR (col1 < 22.54) OR col4 > 85.74) OR ((col4 IS NULL))").await?;
println!("{}", create_table(&schema, &tuples));
let (schema, tuples) = fnck_sql.run("explain SELECT pk, col0 FROM tab64784 WHERE col0 IN (SELECT col3 FROM tab64784 WHERE col3 IS NULL OR (col1 < 22.54) OR col4 > 85.74)").await?;
println!("{}", create_table(&schema, &tuples));
+-------------------------------------------------------------------------------------------------------------------------+
| PLAN                                                                                                                    |
+=========================================================================================================================+
| Projection [tab64784.pk, tab64784.col0] [Project]                                                                       |
|   LeftSemi Join Where ((tab64784.col0 = (tab64784.col3) as (_temp_table_1_.col3)) || tab64784.col4 is null) [HashJoin]  |
|     Scan tab64784 -> [pk, col0, col3, col4] [SeqScan]                                                                   |
|     Projection [tab64784.col3] [Project]                                                                                |
|       Filter ((tab64784.col3 is null || (tab64784.col1 < 22.54)) || (tab64784.col4 > 85.74)), Is Having: false [Filter] |
|         Scan tab64784 -> [col1, col3, col4] [SeqScan]                                                                   |
+-------------------------------------------------------------------------------------------------------------------------+
+-------------------------------------------------------------------------------------------------------------------------+
| PLAN                                                                                                                    |
+=========================================================================================================================+
| Projection [tab64784.pk, tab64784.col0] [Project]                                                                       |
|   LeftSemi Join On tab64784.col0 = (tab64784.col3) as (_temp_table_1_.col3) [HashJoin]                                  |
|     Scan tab64784 -> [pk, col0, col3] [SeqScan]                                                                         |
|     Projection [tab64784.col3] [Project]                                                                                |
|       Filter ((tab64784.col3 is null || (tab64784.col1 < 22.54)) || (tab64784.col4 > 85.74)), Is Having: false [Filter] |
|         Scan tab64784 -> [col1, col3, col4] [SeqScan]                                                                   |
+-------------------------------------------------------------------------------------------------------------------------+

accum_filter.push(ScalarExpression::Binary {
left_expr,
right_expr,
op,
ty,
});
}
_ => {
if left_expr.referenced_columns(true).iter().all(|column| {
Expand Down
1 change: 1 addition & 0 deletions src/execution/volcano/dql/join/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::planner::operator::join::JoinType;

pub(crate) mod hash_join;
pub(crate) mod nested_loop_join;

pub fn joins_nullable(join_type: &JoinType) -> (bool, bool) {
match join_type {
Expand Down
Loading