pub mod column_prune;
pub mod common_subexpression;
pub mod expr_rewrite;
pub mod filter_pushdown;
pub mod join_reorder;
pub mod limit_pushdown;
pub mod location;
pub mod scan_filter;
pub mod selection_reorder;
pub mod sort_limit_hint;
#[allow(dead_code)] pub mod redundant_groups;
use column_prune::ColumnPrune;
use common_subexpression::CommonSubExpression;
use expr_rewrite::ExpressionRewriter;
use filter_pushdown::FilterPushdown;
use glaredb_error::Result;
use join_reorder::JoinReorder;
use limit_pushdown::LimitPushdown;
use scan_filter::ScanFilterPushdown;
use selection_reorder::SelectionReorder;
use sort_limit_hint::SortLimitHint;
use tracing::debug;
use crate::catalog::profile::OptimizerProfile;
use crate::logical::binder::bind_context::BindContext;
use crate::logical::operator::LogicalOperator;
use crate::runtime::time::{RuntimeInstant, Timer};
#[derive(Debug)]
pub struct Optimizer {
pub profile_data: OptimizerProfile,
}
impl Default for Optimizer {
fn default() -> Self {
Self::new()
}
}
impl Optimizer {
pub fn new() -> Self {
Optimizer {
profile_data: OptimizerProfile::default(),
}
}
pub fn optimize<I>(
&mut self,
bind_context: &mut BindContext,
plan: LogicalOperator,
) -> Result<LogicalOperator>
where
I: RuntimeInstant,
{
let total = Timer::<I>::start();
let timer = Timer::<I>::start();
let mut rule = ExpressionRewriter;
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("expression_rewrite", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = FilterPushdown::default();
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("filter_pushdown_1", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = LimitPushdown;
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("limit_pushdown", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = ColumnPrune::default();
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("column_pruning", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = ScanFilterPushdown;
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("scan_filter_pushdown", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = CommonSubExpression;
let plan = rule.optimize(bind_context, plan)?;
self.profile_data.timings.push(("cse", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = JoinReorder::default();
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("join_reorder", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = SortLimitHint;
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("sort_limit_hint", timer.stop()));
let timer = Timer::<I>::start();
let mut rule = SelectionReorder;
let plan = rule.optimize(bind_context, plan)?;
self.profile_data
.timings
.push(("selection_reorder", timer.stop()));
self.profile_data.total = total.stop();
debug!(?self.profile_data, "optimizer timings");
Ok(plan)
}
}
pub trait OptimizeRule {
fn optimize(
&mut self,
bind_context: &mut BindContext,
plan: LogicalOperator,
) -> Result<LogicalOperator>;
}