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
42 changes: 41 additions & 1 deletion src/binder/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ pub use agg_func::*;
use arrow::datatypes::DataType;
pub use binary_op::*;
use itertools::Itertools;
use paste::paste;
use sqlparser::ast::{Expr, Ident};

use super::{BindError, Binder};
use super::{BindError, Binder, BoundSubqueryExpr};
use crate::catalog::{ColumnCatalog, ColumnId, TableId};
use crate::optimizer::ExprVisitor;
use crate::types::ScalarValue;

#[derive(Clone, PartialEq, Eq, Hash)]
Expand All @@ -21,6 +23,7 @@ pub enum BoundExpr {
TypeCast(BoundTypeCast),
AggFunc(BoundAggFunc),
Alias(BoundAlias),
Subquery(BoundSubqueryExpr),
}

impl BoundExpr {
Expand All @@ -33,6 +36,7 @@ impl BoundExpr {
BoundExpr::TypeCast(e) => e.expr.nullable(),
BoundExpr::AggFunc(e) => e.exprs[0].nullable(),
BoundExpr::Alias(e) => e.expr.nullable(),
BoundExpr::Subquery(e) => e.query_ref.query.select_list[0].nullable(),
}
}

Expand All @@ -47,6 +51,7 @@ impl BoundExpr {
BoundExpr::TypeCast(tc) => Some(tc.cast_type.clone()),
BoundExpr::AggFunc(agg) => Some(agg.return_type.clone()),
BoundExpr::Alias(alias) => alias.expr.return_type(),
BoundExpr::Subquery(e) => e.query_ref.query.select_list[0].return_type(),
}
}

Expand All @@ -68,6 +73,7 @@ impl BoundExpr {
.flat_map(|arg| arg.get_referenced_column_catalog())
.collect::<Vec<_>>(),
BoundExpr::Alias(alias) => alias.expr.get_referenced_column_catalog(),
BoundExpr::Subquery(_) => unreachable!(),
}
}

Expand Down Expand Up @@ -110,6 +116,7 @@ impl BoundExpr {
let data_type = e.expr.return_type().unwrap();
(table_id, column_id, data_type)
}
BoundExpr::Subquery(_) => unreachable!(),
};
ColumnCatalog::new(table_id, column_id, self.nullable(), data_type)
}
Expand Down Expand Up @@ -154,6 +161,7 @@ impl Binder {
Expr::Value(v) => Ok(BoundExpr::Constant(v.into())),
Expr::Function(func) => self.bind_agg_func(func),
Expr::Nested(expr) => self.bind_expr(expr),
Expr::Subquery(query) => self.bind_scalar_subquery(query),
_ => todo!("unsupported expr {:?}", expr),
}
}
Expand Down Expand Up @@ -239,6 +247,9 @@ impl fmt::Debug for BoundExpr {
alias.expr, alias.table_id, alias.column_id
)
}
BoundExpr::Subquery(subquery) => {
write!(f, "ScalarSubquery {{{:?}}}", subquery.query_ref)
}
}
}
}
Expand All @@ -260,3 +271,32 @@ impl fmt::Debug for BoundTypeCast {
write!(f, "Cast({:?} as {})", self.expr, self.cast_type)
}
}

macro_rules! impl_contains_variant {
( $($variant:ty),* ) => {
paste! {
impl BoundExpr {
$(
pub fn [<contains_$variant:snake>](&self) -> bool {
struct Contains(bool);

impl ExprVisitor for Contains {
fn pre_visit(&mut self, expr: &BoundExpr) {
if let BoundExpr::$variant(_) = expr {
self.0 = true;
}
}

}

let mut visitor = Contains(false);
visitor.visit_expr(self);
visitor.0
}
)*
}
}
};
}

impl_contains_variant! {Subquery}
12 changes: 7 additions & 5 deletions src/binder/statement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub enum BoundStatement {
Select(BoundSelect),
}

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BoundSelect {
pub select_list: Vec<BoundExpr>,
pub from_table: Option<BoundTableRef>,
Expand All @@ -22,7 +22,7 @@ pub struct BoundSelect {
pub select_distinct: bool,
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BoundOrderBy {
pub expr: BoundExpr,
pub asc: bool,
Expand All @@ -36,7 +36,7 @@ impl Binder {
};

// currently, only support select one table
let from_table = if select.from.is_empty() {
let mut from_table = if select.from.is_empty() {
None
} else if select.from.len() > 1 {
// merge select from multiple tables into one cross join
Expand Down Expand Up @@ -67,11 +67,13 @@ impl Binder {
for item in &select.projection {
match item {
SelectItem::UnnamedExpr(expr) => {
let expr = self.bind_expr(expr)?;
let mut expr = self.bind_expr(expr)?;
self.rewrite_scalar_subquery(&mut expr, &mut from_table);
select_list.push(expr);
}
SelectItem::ExprWithAlias { expr, alias } => {
let expr = self.bind_expr(expr)?;
let mut expr = self.bind_expr(expr)?;
self.rewrite_scalar_subquery(&mut expr, &mut from_table);
self.context.aliases.insert(alias.to_string(), expr.clone());
select_list.push(BoundExpr::Alias(BoundAlias {
expr: Box::new(expr),
Expand Down
6 changes: 3 additions & 3 deletions src/binder/table/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ use sqlparser::ast::{BinaryOperator, Expr, JoinConstraint, JoinOperator};
use super::*;
use crate::binder::{BoundBinaryOp, BoundExpr};

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Join {
pub left: Box<BoundTableRef>,
pub right: Box<BoundTableRef>,
pub join_type: JoinType,
pub join_condition: JoinCondition,
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum JoinType {
Inner,
Left,
Expand All @@ -36,7 +36,7 @@ impl fmt::Display for JoinType {
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum JoinCondition {
On {
/// Equijoin clause expressed as pairs of (left, right) join columns
Expand Down
8 changes: 4 additions & 4 deletions src/binder/table/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ pub static DEFAULT_DATABASE_NAME: &str = "postgres";
pub static DEFAULT_SCHEMA_NAME: &str = "postgres";
pub static EMPTY_DATABASE_ID: &str = "empty-database-id";

#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum BoundTableRef {
Table(BoundSimpleTable),
Join(Join),
Subquery(BoundSubquery),
Subquery(BoundSubqueryRef),
}

#[derive(Clone, PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct BoundSimpleTable {
pub catalog: TableCatalog,
pub alias: Option<TableId>,
Expand Down Expand Up @@ -199,7 +199,7 @@ impl Binder {
.clone()
.map(|a| a.to_string().to_lowercase())
.ok_or(BindError::SubqueryMustHaveAlias)?;
let mut subquery = BoundSubquery::new(Box::new(query), alias.clone());
let mut subquery = BoundSubqueryRef::new(Box::new(query), alias.clone());

// add subquery output columns into context
let subquery_catalog = subquery.gen_table_catalog_for_outside_reference();
Expand Down
Loading