Skip to content

Commit

Permalink
Plan from table
Browse files Browse the repository at this point in the history
  • Loading branch information
lewiszlw committed Feb 1, 2024
1 parent 93b7628 commit afcc2ed
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 7 deletions.
9 changes: 9 additions & 0 deletions bustubx/src/planner/logical_plan_v2/empty_relation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use crate::catalog::SchemaRef;

#[derive(Debug, Clone)]
pub struct EmptyRelation {
/// Whether to produce a placeholder row
pub produce_one_row: bool,
/// The schema description of the output
pub schema: SchemaRef,
}
3 changes: 3 additions & 0 deletions bustubx/src/planner/logical_plan_v2/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod create_index;
mod create_table;
mod empty_relation;
mod filter;
mod insert;
mod join;
Expand All @@ -11,6 +12,7 @@ mod values;

pub use create_index::CreateIndex;
pub use create_table::CreateTable;
pub use empty_relation::EmptyRelation;
pub use filter::Filter;
pub use insert::Insert;
pub use join::Join;
Expand All @@ -32,4 +34,5 @@ pub enum LogicalPlanV2 {
TableScan(TableScan),
Sort(Sort),
Values(Values),
EmptyRelation(EmptyRelation),
}
4 changes: 1 addition & 3 deletions bustubx/src/planner/logical_plan_v2/table_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use crate::expression::Expr;

#[derive(derive_new::new, Debug, Clone)]
pub struct TableScan {
pub table_name: TableReference,
pub columns: Vec<ColumnRef>,
// TODO project push down
pub table_ref: TableReference,
pub filters: Vec<Expr>,
pub limit: Option<usize>,
}
2 changes: 1 addition & 1 deletion bustubx/src/planner/logical_planner/logical_planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl<'a> LogicalPlanner<'a> {
columns,
..
} => self.plan_create_index(name, table_name, columns),
Statement::Query(query) => self.plan_select(query),
Statement::Query(query) => self.plan_query(query),
Statement::Insert {
table_name,
columns,
Expand Down
2 changes: 1 addition & 1 deletion bustubx/src/planner/logical_planner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod plan_create_index;
mod plan_create_table;
mod plan_expr;
mod plan_insert;
mod plan_select;
mod plan_query;
mod plan_set_expr;

pub use logical_planner::{LogicalPlanner, PlannerContext};
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::planner::order_by::BoundOrderBy;
use super::LogicalPlanner;

impl<'a> LogicalPlanner<'a> {
pub fn plan_select(&mut self, query: &Query) -> LogicalPlan {
pub fn plan_query(&mut self, query: &Query) -> LogicalPlan {
let select = match query.body.as_ref() {
SetExpr::Select(select) => &**select,
_ => unimplemented!(),
Expand Down
158 changes: 157 additions & 1 deletion bustubx/src/planner/logical_planner/plan_set_expr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::catalog::{Column, Schema};
use crate::expression::ExprTrait;
use crate::planner::logical_plan_v2::{LogicalPlanV2, Values};
use crate::planner::logical_plan_v2::{
EmptyRelation, Filter, Join, LogicalPlanV2, TableScan, Values,
};
use crate::planner::table_ref::join::JoinType;
use crate::planner::LogicalPlanner;
use crate::{BustubxError, BustubxResult};
use std::sync::Arc;
Expand All @@ -21,6 +24,159 @@ impl LogicalPlanner<'_> {
}
}

pub fn plan_select(&self, select: &sqlparser::ast::Select) -> BustubxResult<LogicalPlanV2> {
let table_scan = self.plan_from_tables(&select.from)?;
let selection = self.plan_selection(table_scan, &select.selection)?;

todo!()
}

pub fn plan_selection(
&self,
input: LogicalPlanV2,
selection: &Option<sqlparser::ast::Expr>,
) -> BustubxResult<LogicalPlanV2> {
match selection {
None => Ok(input),
Some(predicate) => {
let predicate = self.plan_expr(predicate)?;
Ok(LogicalPlanV2::Filter(Filter {
input: Arc::new(input),
predicate,
}))
}
}
}

pub fn plan_from_tables(
&self,
from: &Vec<sqlparser::ast::TableWithJoins>,
) -> BustubxResult<LogicalPlanV2> {
match from.len() {
0 => Ok(LogicalPlanV2::EmptyRelation(EmptyRelation {
produce_one_row: true,
schema: Arc::new(Schema::empty()),
})),
1 => self.plan_table_with_joins(&from[0]),
_ => {
let mut left = self.plan_table_with_joins(&from[0])?;
for t in from.iter().skip(1) {
let right = self.plan_table_with_joins(t)?;
left = self.plan_cross_join(left, right)?;
}
Ok(left)
}
}
}

pub fn plan_table_with_joins(
&self,
t: &sqlparser::ast::TableWithJoins,
) -> BustubxResult<LogicalPlanV2> {
let mut left = self.plan_relation(&t.relation)?;
match t.joins.len() {
0 => Ok(left),
_ => {
for join in t.joins.iter() {
left = self.plan_relation_join(left, join)?;
}
Ok(left)
}
}
}

pub fn plan_relation_join(
&self,
left: LogicalPlanV2,
join: &sqlparser::ast::Join,
) -> BustubxResult<LogicalPlanV2> {
let right = self.plan_relation(&join.relation)?;
match &join.join_operator {
sqlparser::ast::JoinOperator::Inner(constraint) => {
self.plan_join(left, right, constraint, JoinType::Inner)
}
sqlparser::ast::JoinOperator::LeftOuter(constraint) => {
self.plan_join(left, right, constraint, JoinType::Inner)
}
sqlparser::ast::JoinOperator::RightOuter(constraint) => {
self.plan_join(left, right, constraint, JoinType::Inner)
}
sqlparser::ast::JoinOperator::FullOuter(constraint) => {
self.plan_join(left, right, constraint, JoinType::Inner)
}
sqlparser::ast::JoinOperator::CrossJoin => self.plan_cross_join(left, right),
_ => Err(BustubxError::Plan(format!(
"sqlparser join operator {:?} not supported",
join.join_operator
))),
}
}

pub fn plan_join(
&self,
left: LogicalPlanV2,
right: LogicalPlanV2,
constraint: &sqlparser::ast::JoinConstraint,
join_type: JoinType,
) -> BustubxResult<LogicalPlanV2> {
match constraint {
sqlparser::ast::JoinConstraint::On(expr) => {
let expr = self.plan_expr(expr)?;
Ok(LogicalPlanV2::Join(Join {
left: Arc::new((left)),
right: Arc::new((right)),
join_type,
condition: Some(expr),
}))
}
_ => Err(BustubxError::Plan(format!(
"Only support join on constraint, {:?}",
constraint
))),
}
}

pub fn plan_cross_join(
&self,
left: LogicalPlanV2,
right: LogicalPlanV2,
) -> BustubxResult<LogicalPlanV2> {
Ok(LogicalPlanV2::Join(Join {
left: Arc::new(left),
right: Arc::new(right),
join_type: JoinType::CrossJoin,
condition: None,
}))
}

pub fn plan_relation(
&self,
relation: &sqlparser::ast::TableFactor,
) -> BustubxResult<LogicalPlanV2> {
match relation {
sqlparser::ast::TableFactor::Table { name, alias, .. } => {
// TODO handle alias
let table_ref = self.plan_table_name(name)?;
Ok(LogicalPlanV2::TableScan(TableScan {
table_ref,
filters: vec![],
limit: None,
}))
}
sqlparser::ast::TableFactor::NestedJoin {
table_with_joins,
alias,
} => {
// TODO handle alias
self.plan_table_with_joins(table_with_joins)
}
_ => Err(BustubxError::Plan(format!(
"sqlparser relation {} not supported",
relation
))),
}
}

pub fn plan_values(&self, values: &sqlparser::ast::Values) -> BustubxResult<LogicalPlanV2> {
let mut result = vec![];
for row in values.rows.iter() {
Expand Down

0 comments on commit afcc2ed

Please sign in to comment.