kip-sql 0.0.1-alpha.8

build the SQL layer of KipDB database
Documentation
use crate::optimizer::core::pattern::PatternMatcher;
use crate::optimizer::core::rule::Rule;
use crate::optimizer::heuristic::batch::{HepBatch, HepBatchStrategy};
use crate::optimizer::heuristic::graph::{HepGraph, HepNodeId};
use crate::optimizer::heuristic::matcher::HepMatcher;
use crate::optimizer::rule::RuleImpl;
use crate::optimizer::OptimizerError;
use crate::planner::LogicalPlan;

pub struct HepOptimizer {
    batches: Vec<HepBatch>,
    pub graph: HepGraph,
}

impl HepOptimizer {
    pub fn new(root: LogicalPlan) -> Self {
        Self {
            batches: vec![],
            graph: HepGraph::new(root),
        }
    }

    pub fn batch(mut self, name: String, strategy: HepBatchStrategy, rules: Vec<RuleImpl>) -> Self {
        self.batches.push(HepBatch::new(name, strategy, rules));
        self
    }

    pub fn find_best(&mut self) -> Result<LogicalPlan, OptimizerError> {
        let batches = self.batches.clone();

        for batch in batches {
            let mut batch_over = false;
            let mut iteration = 1usize;

            while iteration <= batch.strategy.max_iteration && !batch_over {
                if self.apply_batch(&batch)? {
                    iteration += 1;
                } else {
                    batch_over = true
                }
            }
        }

        Ok(self.graph.to_plan())
    }

    fn apply_batch(
        &mut self,
        HepBatch {
            rules, strategy, ..
        }: &HepBatch,
    ) -> Result<bool, OptimizerError> {
        let start_ver = self.graph.version;

        for rule in rules {
            for node_id in self.graph.nodes_iter(strategy.match_order, None) {
                if self.apply_rule(rule, node_id)? {
                    break;
                }
            }
        }

        Ok(start_ver != self.graph.version)
    }

    fn apply_rule(&mut self, rule: &RuleImpl, node_id: HepNodeId) -> Result<bool, OptimizerError> {
        let after_version = self.graph.version;

        if HepMatcher::new(rule.pattern(), node_id, &self.graph).match_opt_expr() {
            rule.apply(node_id, &mut self.graph)?;
        }

        Ok(after_version != self.graph.version)
    }
}