Skip to content

Commit

Permalink
Save
Browse files Browse the repository at this point in the history
  • Loading branch information
lewiszlw committed Aug 15, 2023
1 parent ebc37f6 commit f500150
Show file tree
Hide file tree
Showing 13 changed files with 269 additions and 15 deletions.
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
sqlparser = "0.34.0"
sqlparser = "0.34.0"
petgraph = "0.6.3"
4 changes: 2 additions & 2 deletions src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ impl Database {
// println!("{:?}", logical_plan);

// logical plan -> physical plan
let mut optimizer = Optimizer::new(Arc::new(logical_plan));
let physical_plan = optimizer.find_best();
let mut optimizer = Optimizer::new();
let physical_plan = optimizer.find_best(logical_plan);
// println!("{:?}", physical_plan);

let execution_ctx = ExecutionContext::new(&mut self.catalog);
Expand Down
20 changes: 20 additions & 0 deletions src/optimizer/heuristic/batch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use super::rule::Rule;

#[derive(Debug)]
pub struct HepBatch {
pub name: String,
pub strategy: HepBatchStrategy,
pub rules: Vec<Box<dyn Rule>>,
}

#[derive(Debug)]
pub struct HepBatchStrategy {
pub max_iteration: usize,
pub match_order: HepMatchOrder,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HepMatchOrder {
TopDown,
BottomUp,
}
16 changes: 16 additions & 0 deletions src/optimizer/heuristic/graph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use petgraph::stable_graph::{StableDiGraph, NodeIndex};

use super::opt_expr::OptExprNodeId;


pub type HepNodeId = NodeIndex<OptExprNodeId>;

pub struct HepNode {
id: HepNodeId,
// plan:
}

pub struct HepGraph {
graph: StableDiGraph<HepNode, usize, usize>,
root: HepNodeId,
}
3 changes: 3 additions & 0 deletions src/optimizer/heuristic/matcher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub struct HepMatcher {

}
26 changes: 26 additions & 0 deletions src/optimizer/heuristic/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use std::sync::Arc;

use crate::planner::logical_plan::{LogicalPlan, self};

pub mod batch;
pub mod rule;
pub mod pattern;
pub mod graph;
pub mod matcher;
pub mod opt_expr;

pub struct HepOptimizer {

}
impl HepOptimizer {
// output the optimized logical plan
pub fn find_best(&self, logical_plan: LogicalPlan) -> LogicalPlan {
// TODO
logical_plan
}
}
impl Default for HepOptimizer {
fn default() -> Self {
Self{}
}
}
15 changes: 15 additions & 0 deletions src/optimizer/heuristic/opt_expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use crate::planner::operator::LogicalOperator;

pub type OptExprNodeId = usize;

#[derive(Debug)]
pub enum OptExprNode {
OperatorRef(LogicalOperator),
OptExpr(OptExprNodeId),
}

#[derive(Debug)]
pub struct OptExpr {
pub root: OptExprNode,
pub children: Vec<OptExpr>,
}
14 changes: 14 additions & 0 deletions src/optimizer/heuristic/pattern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::planner::operator::LogicalOperator;

pub struct Pattern {
// the root node predicate, not contains the children
pub predicate: fn(&LogicalOperator) -> bool,
// the children's predicate of current node
pub children: PatternChildrenPredicate,
}

pub enum PatternChildrenPredicate {
MatchedRecursive,
Predicate(Vec<Pattern>),
None,
}
8 changes: 8 additions & 0 deletions src/optimizer/heuristic/rule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use std::fmt::Debug;

use super::{pattern::Pattern, graph::{HepGraph, HepNodeId}};

pub trait Rule: Debug {
fn pattern(&self) -> &Pattern;
fn apply(&self, node_id: HepNodeId, graph: &mut HepGraph) -> bool;
}
33 changes: 21 additions & 12 deletions src/optimizer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
use std::sync::Arc;

use crate::planner::{logical_plan::LogicalPlan, operator::LogicalOperator};
use crate::planner::{logical_plan::{LogicalPlan, self}, operator::LogicalOperator};

use self::physical_plan::PhysicalPlan;
use self::{physical_plan::PhysicalPlan, heuristic::HepOptimizer, physical_optimizer::PhysicalOptimizer};

pub mod operator;
pub mod physical_plan;
pub mod heuristic;
pub mod rule;
pub mod physical_optimizer;

pub struct Optimizer {
logical_plan: Arc<LogicalPlan>,
hep_optimizer: HepOptimizer,
physical_optimizer: PhysicalOptimizer,
}
impl Optimizer {
pub fn new(logical_plan: Arc<LogicalPlan>) -> Self {
Self { logical_plan }
pub fn new() -> Self {
Self { hep_optimizer: HepOptimizer::default(), physical_optimizer: PhysicalOptimizer {}}
}

// 生成优化后的物理计划
pub fn find_best(&self) -> PhysicalPlan {
let physical_node = Self::build_physical_node(
self.logical_plan.clone(),
self.logical_plan.children.clone(),
);
pub fn find_best(&self, logical_plan: LogicalPlan) -> PhysicalPlan {
// find best logical plan
let optimized_logical_plan = self.hep_optimizer.find_best(logical_plan);

// TODO find best physical plan
self.physical_optimizer.find_best(Arc::new(optimized_logical_plan))

// let physical_node = Self::build_physical_node(
// self.logical_plan.clone(),
// self.logical_plan.children.clone(),
// );
// TODO 递归
Self::build_physical_plan(physical_node, self.logical_plan.clone())
// Self::build_physical_plan(physical_node, self.logical_plan.clone())
}

fn build_physical_plan(
Expand Down
103 changes: 103 additions & 0 deletions src/optimizer/physical_optimizer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::sync::Arc;

use crate::planner::{logical_plan::LogicalPlan, operator::LogicalOperator};

use super::physical_plan::PhysicalPlan;

pub struct PhysicalOptimizer {}
impl PhysicalOptimizer {
pub fn find_best(&self, logical_plan: Arc<LogicalPlan>) -> PhysicalPlan {
let physical_node =
Self::build_physical_node(logical_plan.clone(), logical_plan.children.clone());
Self::build_physical_plan(physical_node, logical_plan.clone())
}

fn build_physical_plan(
mut physical_plan: PhysicalPlan,
logical_plan: Arc<LogicalPlan>,
) -> PhysicalPlan {
for logical_child in logical_plan.children.iter() {
let physical_child =
Self::build_physical_node(logical_child.clone(), logical_child.children.clone());
physical_plan
.children
.push(Arc::new(Self::build_physical_plan(
physical_child,
logical_child.clone(),
)));
}
physical_plan
}

fn build_physical_node(
logical_node: Arc<LogicalPlan>,
logical_node_children: Vec<Arc<LogicalPlan>>,
) -> PhysicalPlan {
match logical_node.operator {
LogicalOperator::Dummy => PhysicalPlan::dummy(),
LogicalOperator::CreateTable(ref logic_create_table) => {
PhysicalPlan::new_create_table_node(
&logic_create_table.table_name,
&logic_create_table.schema,
)
}
LogicalOperator::Insert(ref logic_insert) => {
PhysicalPlan::new_insert_node(&logic_insert.table_name, &logic_insert.columns)
}
LogicalOperator::Values(ref logical_values) => {
PhysicalPlan::new_values_node(&logical_values.columns, &logical_values.tuples)
}
LogicalOperator::Project(ref logical_project) => {
PhysicalPlan::new_project_node(&logical_project.expressions)
}
LogicalOperator::Filter(ref logical_filter) => {
// filter下只有一个子节点
let child_logical_node = logical_node_children[0].clone();
let child_physical_node = Self::build_physical_node(
child_logical_node.clone(),
child_logical_node.children.clone(),
);
PhysicalPlan::new_filter_node(
&logical_filter.predicate,
child_physical_node.operator.clone(),
)
}
LogicalOperator::Scan(ref logical_table_scan) => PhysicalPlan::new_table_scan_node(
&logical_table_scan.table_oid,
&logical_table_scan.columns,
),
LogicalOperator::Limit(ref logical_limit) => {
// limit下只有一个子节点
let child_logical_node = logical_node_children[0].clone();
let child_physical_node = Self::build_physical_node(
child_logical_node.clone(),
child_logical_node.children.clone(),
);
PhysicalPlan::new_limit_node(
&logical_limit.limit,
&logical_limit.offset,
child_physical_node.operator.clone(),
)
}
LogicalOperator::Join(ref logical_join) => {
let left_logical_node = logical_node_children[0].clone();
let right_logical_node = logical_node_children[1].clone();
let left_physical_node = Self::build_physical_node(
left_logical_node.clone(),
left_logical_node.children.clone(),
);
let right_physical_node = Self::build_physical_node(
right_logical_node.clone(),
right_logical_node.children.clone(),
);
PhysicalPlan::new_nested_loop_join_node(
logical_join.join_type,
logical_join.condition.clone(),
left_physical_node.operator.clone(),
right_physical_node.operator.clone(),
)
}
_ => unimplemented!(),
}
}
}
Empty file added src/optimizer/rule/mod.rs
Empty file.

0 comments on commit f500150

Please sign in to comment.