Skip to content

Commit

Permalink
clean up expression and rules modules
Browse files Browse the repository at this point in the history
  • Loading branch information
connortsui20 committed Jan 30, 2025
1 parent c41cf41 commit f96f771
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 43 deletions.
12 changes: 5 additions & 7 deletions optd-core/src/expression.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
//! Types for logical and physical expressions in the optimizer.
use crate::memo::GroupId;
use crate::memo::{GroupId, ScalarGroupId};
use crate::operator::relational::logical::LogicalOperator;
use crate::operator::relational::physical::PhysicalOperator;

/// A logical expression in the memo table.
///
/// References children using [`GroupId`]s for expression sharing
/// and memoization.
pub type LogicalExpression = LogicalOperator<GroupId, GroupId>;
/// References children using [`GroupId`]s for expression sharing and memoization.
pub type LogicalExpression = LogicalOperator<GroupId, ScalarGroupId>;

/// A physical expression in the memo table.
///
/// Like [`LogicalExpression`] but with specific implementation
/// strategies.
pub type PhysicalExpression = PhysicalOperator<GroupId, GroupId>;
/// Like [`LogicalExpression`] but with specific implementation strategies.
pub type PhysicalExpression = PhysicalOperator<GroupId, ScalarGroupId>;
8 changes: 8 additions & 0 deletions optd-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
//! TODO Add docs. We will likely want to add a `#![doc = include_str!("../README.md")]` here.
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::missing_panics_doc)]
#![warn(clippy::missing_safety_doc)]

pub mod expression;
pub mod memo;
pub mod operator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/// (`Scalar`) that evaluates to true/false. Only rows where predicate is true
/// are emitted.
#[derive(Clone)]
pub struct Filter<Relation, Scalar> {
pub struct PhysicalFilter<Relation, Scalar> {
pub child: Relation,
pub predicate: Scalar,
}
4 changes: 2 additions & 2 deletions optd-core/src/operator/relational/physical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod join;
pub mod project;
pub mod scan;

use filter::filter::Filter;
use filter::filter::PhysicalFilter;
use join::{hash_join::HashJoin, merge_join::MergeJoin, nested_loop_join::NestedLoopJoin};
use project::project::Project;
use scan::table_scan::TableScan;
Expand All @@ -25,7 +25,7 @@ use scan::table_scan::TableScan;
#[derive(Clone)]
pub enum PhysicalOperator<Relation, Scalar> {
TableScan(TableScan<Scalar>),
Filter(Filter<Relation, Scalar>),
Filter(PhysicalFilter<Relation, Scalar>),
Project(Project<Relation, Scalar>),
HashJoin(HashJoin<Relation, Scalar>),
NestedLoopJoin(NestedLoopJoin<Relation, Scalar>),
Expand Down
4 changes: 2 additions & 2 deletions optd-core/src/operator/scalar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use constants::Constant;
/// [`PartialLogicalPlan`]: crate::plan::partial_logical_plan::PartialLogicalPlan
#[derive(Clone)]
pub enum ScalarOperator<Scalar> {
Add(Add<Scalar>),
ColumnRef(ColumnRef),
Constant(Constant),
ColumnRef(ColumnRef),
Add(Add<Scalar>),
}
35 changes: 24 additions & 11 deletions optd-core/src/rules/implementation/hash_join.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
//! The rule for implementing `Join` as a `HashJoin`.
//!
//! See [`HashJoinRule`] for more information.
use super::*;
use crate::operator::relational::{
logical::LogicalOperator,
logical::{join::Join, LogicalOperator},
physical::{join::hash_join::HashJoin, PhysicalOperator},
};

/// Implementation rule that converts a logical join into a hash join physical operator
/// A unit / marker struct for implementing `HashJoin`.
///
/// This implementation rule converts a logical `Join` into a physical `HashJoin` operator.
pub struct HashJoinRule;

// TODO: rule may fail, need to check join condition
// https://github.com/cmu-db/optd/issues/15
impl ImplementationRule for HashJoinRule {
fn check_and_apply(&self, expr: LogicalExpression) -> Option<PhysicalExpression> {
if let LogicalOperator::Join(join) = expr {
return Some(PhysicalOperator::HashJoin(HashJoin {
join_type: join.join_type,
probe_side: join.left,
build_side: join.right,
condition: join.condition,
}));
}
None
let LogicalOperator::Join(Join {
join_type,
left,
right,
condition,
}) = expr
else {
return None;
};

Some(PhysicalOperator::HashJoin(HashJoin {
join_type,
probe_side: left,
build_side: right,
condition,
}))
}
}
2 changes: 2 additions & 0 deletions optd-core/src/rules/implementation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use crate::expression::{LogicalExpression, PhysicalExpression};

/// The interface for implementation rules, which help convert logical plans into physical
/// (executable) query plans.
#[trait_variant::make(Send)]
#[allow(dead_code)]
pub trait ImplementationRule {
Expand Down
23 changes: 13 additions & 10 deletions optd-core/src/rules/implementation/physical_filter.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
//! The rule for implementing a logical `Filter` as a physical `Filter`.
//!
//! See [`PhysicalFilterRule`] for more information.
use super::*;
use crate::operator::relational::{
logical::LogicalOperator,
physical::{filter::filter::Filter, PhysicalOperator},
logical::{filter::Filter as LogicalFilter, LogicalOperator},
physical::{filter::filter::PhysicalFilter, PhysicalOperator},
};

/// Implementation rule that converts a logical filter into a filter physical operator.
/// A unit / marker struct for implementing `PhysicalFilterRule`.
///
/// This mplementation rule converts a logical `Filter` into a physical `Filter` operator.
pub struct PhysicalFilterRule;

impl ImplementationRule for PhysicalFilterRule {
fn check_and_apply(&self, expr: LogicalExpression) -> Option<PhysicalExpression> {
if let LogicalOperator::Filter(filter) = expr {
return Some(PhysicalOperator::Filter(Filter {
child: filter.child,
predicate: filter.predicate,
}));
}
let LogicalOperator::Filter(LogicalFilter { child, predicate }) = expr else {
return None;
};

None
Some(PhysicalOperator::Filter(PhysicalFilter { child, predicate }))
}
}
28 changes: 19 additions & 9 deletions optd-core/src/rules/implementation/table_scan.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
//! The rule for implementing `Scan` as a `TableScan`.
//!
//! See [`TableScanRule`] for more information.
use crate::operator::relational::{
logical::LogicalOperator,
logical::{scan::Scan, LogicalOperator},
physical::{scan::table_scan::TableScan, PhysicalOperator},
};

use super::*;

// Implementation rule that converts a logical scan into a table scan physical operator.
/// A unit / marker struct for implementing `TableScan`.
///
/// This implementation rule converts a logical `Scan` into a physical `TableScan` operator.
pub struct TableScanRule;

impl ImplementationRule for TableScanRule {
fn check_and_apply(&self, expr: LogicalExpression) -> Option<PhysicalExpression> {
if let LogicalOperator::Scan(scan) = expr {
return Some(PhysicalOperator::TableScan(TableScan {
table_name: scan.table_name,
predicate: scan.predicate,
}));
}
let LogicalOperator::Scan(Scan {
table_name,
predicate,
}) = expr
else {
return None;
};

None
Some(PhysicalOperator::TableScan(TableScan {
table_name,
predicate,
}))
}
}
3 changes: 3 additions & 0 deletions optd-core/src/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
//! This module contains all rules that the optimizer has available, including both transformation
//! and implementation rules.
mod implementation;
mod transformation;
8 changes: 8 additions & 0 deletions optd-core/src/rules/transformation/join_associativity.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
//! The rule for join associativity.
//!
//! See [`JoinAssociativityRule`] for more information.
use super::*;

/// A unit / marker struct for join associativity.
///
/// Since joining is an associative operation, we can convert a `Join(Join(A, B), C)` into a
/// `Join(A, Join(B, C))`.
pub struct JoinAssociativityRule;

impl TransformationRule for JoinAssociativityRule {
Expand Down
7 changes: 7 additions & 0 deletions optd-core/src/rules/transformation/join_commutativity.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
//! The rule for join commutativity.
//!
//! See [`JoinCommutativityRule`] for more information.
use super::*;

/// A unit / marker struct for join commutativity.
///
/// Since joining is an commutative operation, we can convert a `Join(A, B)` into a `Join(B, C)`.
pub struct JoinCommutativityRule;

impl TransformationRule for JoinCommutativityRule {
Expand Down
6 changes: 5 additions & 1 deletion optd-core/src/rules/transformation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
//! This module contains the transformation rule trait / API, as well as the rules that implement
//! said trait.
//!
//! TODO(connor) Add more docs.
//! TODO(everyone) Add more docs.
use crate::{
expression::LogicalExpression, memo::Memo, plan::partial_logical_plan::PartialLogicalPlan,
};

/// The interface for transformation rules, which help enumerate logically equivalent plans during
/// the optimization search.
#[trait_variant::make(Send)]
#[allow(dead_code)]
pub trait TransformationRule {
Expand All @@ -31,6 +33,8 @@ pub trait TransformationRule {
///
/// These changes can create new logical or scalar expressions. However, note that
/// transformation rules will _not_ create new physical expressions.
///
/// TODO(everyone) Figure out what the return type should really be.
fn apply(&self, expr: PartialLogicalPlan) -> PartialLogicalPlan;
}

Expand Down

0 comments on commit f96f771

Please sign in to comment.