diff --git a/optd-core/src/expression.rs b/optd-core/src/expression.rs index bdd89c0..808cd7c 100644 --- a/optd-core/src/expression.rs +++ b/optd-core/src/expression.rs @@ -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; +/// References children using [`GroupId`]s for expression sharing and memoization. +pub type LogicalExpression = LogicalOperator; /// A physical expression in the memo table. /// -/// Like [`LogicalExpression`] but with specific implementation -/// strategies. -pub type PhysicalExpression = PhysicalOperator; +/// Like [`LogicalExpression`] but with specific implementation strategies. +pub type PhysicalExpression = PhysicalOperator; diff --git a/optd-core/src/lib.rs b/optd-core/src/lib.rs index cdfd561..9ab7f2c 100644 --- a/optd-core/src/lib.rs +++ b/optd-core/src/lib.rs @@ -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; diff --git a/optd-core/src/operator/relational/physical/filter/filter.rs b/optd-core/src/operator/relational/physical/filter/filter.rs index 8061ef6..9af1df6 100644 --- a/optd-core/src/operator/relational/physical/filter/filter.rs +++ b/optd-core/src/operator/relational/physical/filter/filter.rs @@ -4,7 +4,7 @@ /// (`Scalar`) that evaluates to true/false. Only rows where predicate is true /// are emitted. #[derive(Clone)] -pub struct Filter { +pub struct PhysicalFilter { pub child: Relation, pub predicate: Scalar, } diff --git a/optd-core/src/operator/relational/physical/mod.rs b/optd-core/src/operator/relational/physical/mod.rs index 5f6e582..44fbb4a 100644 --- a/optd-core/src/operator/relational/physical/mod.rs +++ b/optd-core/src/operator/relational/physical/mod.rs @@ -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; @@ -25,7 +25,7 @@ use scan::table_scan::TableScan; #[derive(Clone)] pub enum PhysicalOperator { TableScan(TableScan), - Filter(Filter), + Filter(PhysicalFilter), Project(Project), HashJoin(HashJoin), NestedLoopJoin(NestedLoopJoin), diff --git a/optd-core/src/operator/scalar/mod.rs b/optd-core/src/operator/scalar/mod.rs index 4d8ca58..169b824 100644 --- a/optd-core/src/operator/scalar/mod.rs +++ b/optd-core/src/operator/scalar/mod.rs @@ -20,7 +20,7 @@ use constants::Constant; /// [`PartialLogicalPlan`]: crate::plan::partial_logical_plan::PartialLogicalPlan #[derive(Clone)] pub enum ScalarOperator { - Add(Add), - ColumnRef(ColumnRef), Constant(Constant), + ColumnRef(ColumnRef), + Add(Add), } diff --git a/optd-core/src/rules/implementation/hash_join.rs b/optd-core/src/rules/implementation/hash_join.rs index fb747fc..9738be4 100644 --- a/optd-core/src/rules/implementation/hash_join.rs +++ b/optd-core/src/rules/implementation/hash_join.rs @@ -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 { - 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, + })) } } diff --git a/optd-core/src/rules/implementation/mod.rs b/optd-core/src/rules/implementation/mod.rs index 08da6f0..22ee6ef 100644 --- a/optd-core/src/rules/implementation/mod.rs +++ b/optd-core/src/rules/implementation/mod.rs @@ -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 { diff --git a/optd-core/src/rules/implementation/physical_filter.rs b/optd-core/src/rules/implementation/physical_filter.rs index 8c06072..019e243 100644 --- a/optd-core/src/rules/implementation/physical_filter.rs +++ b/optd-core/src/rules/implementation/physical_filter.rs @@ -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 { - 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 })) } } diff --git a/optd-core/src/rules/implementation/table_scan.rs b/optd-core/src/rules/implementation/table_scan.rs index 375d9ae..22382c2 100644 --- a/optd-core/src/rules/implementation/table_scan.rs +++ b/optd-core/src/rules/implementation/table_scan.rs @@ -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 { - 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, + })) } } diff --git a/optd-core/src/rules/mod.rs b/optd-core/src/rules/mod.rs index edc3d0b..b7e1002 100644 --- a/optd-core/src/rules/mod.rs +++ b/optd-core/src/rules/mod.rs @@ -1,2 +1,5 @@ +//! This module contains all rules that the optimizer has available, including both transformation +//! and implementation rules. + mod implementation; mod transformation; diff --git a/optd-core/src/rules/transformation/join_associativity.rs b/optd-core/src/rules/transformation/join_associativity.rs index 7c42c89..3e6bf36 100644 --- a/optd-core/src/rules/transformation/join_associativity.rs +++ b/optd-core/src/rules/transformation/join_associativity.rs @@ -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 { diff --git a/optd-core/src/rules/transformation/join_commutativity.rs b/optd-core/src/rules/transformation/join_commutativity.rs index 0ef1e63..2f78a18 100644 --- a/optd-core/src/rules/transformation/join_commutativity.rs +++ b/optd-core/src/rules/transformation/join_commutativity.rs @@ -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 { diff --git a/optd-core/src/rules/transformation/mod.rs b/optd-core/src/rules/transformation/mod.rs index 2b32ab7..fee2d9f 100644 --- a/optd-core/src/rules/transformation/mod.rs +++ b/optd-core/src/rules/transformation/mod.rs @@ -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 { @@ -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; }