Skip to content

Commit

Permalink
proj remove implmented (hueristic pass ONLY)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sweetsuro committed May 1, 2024
1 parent a965f4b commit c970648
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 16 deletions.
3 changes: 2 additions & 1 deletion optd-datafusion-repr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use properties::{
schema::{Catalog, SchemaPropertyBuilder},
};
use rules::{
EliminateDuplicatedAggExprRule, EliminateDuplicatedSortExprRule, EliminateFilterRule, EliminateJoinRule, EliminateLimitRule, FilterAggTransposeRule, FilterCrossJoinTransposeRule, FilterInnerJoinTransposeRule, FilterMergeRule, FilterProjectTransposeRule, FilterSortTransposeRule, HashJoinRule, JoinAssocRule, JoinCommuteRule, PhysicalConversionRule, ProjectFilterTransposeRule, ProjectMergeRule, ProjectionPullUpJoin, ProjectionPushDownJoin, SimplifyFilterRule, SimplifyJoinCondRule
EliminateDuplicatedAggExprRule, EliminateDuplicatedSortExprRule, EliminateFilterRule, EliminateJoinRule, EliminateLimitRule, FilterAggTransposeRule, FilterCrossJoinTransposeRule, FilterInnerJoinTransposeRule, FilterMergeRule, FilterProjectTransposeRule, FilterSortTransposeRule, HashJoinRule, JoinAssocRule, JoinCommuteRule, PhysicalConversionRule, ProjectFilterTransposeRule, ProjectMergeRule, ProjectRemoveRule, ProjectionPullUpJoin, ProjectionPushDownJoin, SimplifyFilterRule, SimplifyJoinCondRule
};

pub use optd_core::rel_node::Value;
Expand Down Expand Up @@ -85,6 +85,7 @@ impl DatafusionOptimizer {
Arc::new(EliminateDuplicatedAggExprRule::new()),
Arc::new(ProjectMergeRule::new()),
Arc::new(FilterMergeRule::new()),
Arc::new(ProjectRemoveRule::new()),
]
}

Expand Down
1 change: 1 addition & 0 deletions optd-datafusion-repr/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ pub use project_transpose::{
project_filter_transpose::{FilterProjectTransposeRule, ProjectFilterTransposeRule},
project_join_transpose::{ProjectionPullUpJoin, ProjectionPushDownJoin},
project_merge::ProjectMergeRule,
project_remove::ProjectRemoveRule,
};
1 change: 1 addition & 0 deletions optd-datafusion-repr/src/rules/project_transpose.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod project_filter_transpose;
pub mod project_join_transpose;
pub mod project_merge;
pub mod project_remove;
pub mod project_transpose_common;
Original file line number Diff line number Diff line change
@@ -1,2 +1,83 @@
// intended to remove a projection that outputs the same num of cols
// that are in scan node
// that are in scan node
use std::collections::HashMap;

use optd_core::rules::{Rule, RuleMatcher};
use optd_core::{optimizer::Optimizer, rel_node::RelNode};

use crate::plan_nodes::{ColumnRefExpr, ExprList, OptRelNode, OptRelNodeTyp, PlanNode};
use crate::properties::schema::SchemaPropertyBuilder;
use crate::rules::macros::define_rule;

// Proj (Scan A) -> Scan A
// removes projections
// TODO: need to somehow match on just scan node instead
// only works in hueristic optimizer (which may be ok)
// ideally include a pass after for physical proj -> physical scan
define_rule!(
ProjectRemoveRule,
apply_projection_remove,
(Projection, child, [exprs])
);

fn apply_projection_remove(
optimizer: &impl Optimizer<OptRelNodeTyp>,
ProjectRemoveRulePicks {
child,
exprs
}: ProjectRemoveRulePicks,
) -> Vec<RelNode<OptRelNodeTyp>> {
let child_schema = optimizer.get_property::<SchemaPropertyBuilder>(child.clone().into(), 0);
let child = PlanNode::from_group(child.into());
if child.typ() != OptRelNodeTyp::Scan {
return vec![];
}
let exprs = ExprList::from_rel_node(exprs.into()).unwrap().to_vec();
if exprs.len() != child_schema.len() {
return vec![];
}
let mut exp_col_idx: usize = 0;
for expr in exprs {
let col_ref = ColumnRefExpr::from_rel_node(expr.into_rel_node()).unwrap();
let col_idx = col_ref.index();
if exp_col_idx != col_idx {
return vec![];
}
exp_col_idx += 1;
}
vec![child.into_rel_node().as_ref().clone()]
}

#[cfg(test)]
mod tests {
use std::sync::Arc;

use optd_core::optimizer::Optimizer;

use crate::{
plan_nodes::{
ColumnRefExpr, ExprList, LogicalProjection, LogicalScan, OptRelNode, OptRelNodeTyp,
},
rules::ProjectRemoveRule,
testing::new_test_optimizer,
};

#[test]
fn proj_scan_basic() {
// convert proj -> scan to scan
let mut test_optimizer = new_test_optimizer(Arc::new(ProjectRemoveRule::new()));

let scan = LogicalScan::new("region".into());

let proj_exprs = ExprList::new(vec![
ColumnRefExpr::new(0).into_expr(),
ColumnRefExpr::new(1).into_expr(),
ColumnRefExpr::new(2).into_expr(),
]);

let proj_node: LogicalProjection = LogicalProjection::new(scan.into_plan_node(), proj_exprs);
let plan = test_optimizer.optimize(proj_node.into_rel_node()).unwrap();

assert_eq!(plan.typ, OptRelNodeTyp::Scan);
}
}
3 changes: 1 addition & 2 deletions optd-sqlplannertest/tests/basic_nodes.planner.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ LogicalLimit { skip: 0(u64), fetch: 1(u64) }
└── LogicalProjection { exprs: [ #0, #1 ] }
└── LogicalScan { table: t1 }
PhysicalLimit { skip: 0(u64), fetch: 1(u64) }
└── PhysicalProjection { exprs: [ #0, #1 ] }
└── PhysicalScan { table: t1 }
└── PhysicalScan { table: t1 }
0 0
0 0
1 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ select * from t1;
/*
LogicalProjection { exprs: [ #0, #1 ] }
└── LogicalScan { table: t1 }
PhysicalProjection { exprs: [ #0, #1 ] }
└── PhysicalScan { table: t1 }
PhysicalScan { table: t1 }
0 0
1 1
5 2
Expand Down Expand Up @@ -45,8 +44,7 @@ PhysicalSort
│ │ └── #0
│ └── SortOrder { order: Asc }
│ └── #1
└── PhysicalProjection { exprs: [ #0, #1 ] }
└── PhysicalScan { table: t1 }
└── PhysicalScan { table: t1 }
0 0
0 2
1 1
Expand Down
3 changes: 1 addition & 2 deletions optd-sqlplannertest/tests/filter.planner.sql
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ select * from t1 where true;
LogicalProjection { exprs: [ #0, #1 ] }
└── LogicalFilter { cond: true }
└── LogicalScan { table: t1 }
PhysicalProjection { exprs: [ #0, #1 ] }
└── PhysicalScan { table: t1 }
PhysicalScan { table: t1 }
0 0
1 1
2 2
Expand Down
3 changes: 1 addition & 2 deletions optd-sqlplannertest/tests/tpch.planner.sql
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,7 @@ PhysicalLimit { skip: 0(u64), fetch: 100(u64) }
│ │ │ │ │ └── PhysicalScan { table: part }
│ │ │ │ └── PhysicalProjection { exprs: [ #0, #1, #3 ] }
│ │ │ │ └── PhysicalScan { table: partsupp }
│ │ │ └── PhysicalProjection { exprs: [ #0, #1, #2, #3, #4, #5, #6 ] }
│ │ │ └── PhysicalScan { table: supplier }
│ │ │ └── PhysicalScan { table: supplier }
│ │ └── PhysicalProjection { exprs: [ #0, #1, #2 ] }
│ │ └── PhysicalScan { table: nation }
│ └── PhysicalProjection { exprs: [ #0 ] }
Expand Down
6 changes: 2 additions & 4 deletions optd-sqlplannertest/tests/verbose.planner.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@ insert into t1 values (0), (1), (2), (3);
select * from t1;

/*
PhysicalProjection { exprs: [ #0 ] }
└── PhysicalScan { table: t1 }
PhysicalScan { table: t1 }
*/

-- Test verbose explain
select * from t1;

/*
PhysicalProjection { exprs: [ #0 ], cost: weighted=1.06,row_cnt=1.00,compute=0.06,io=1.00 }
└── PhysicalScan { table: t1, cost: weighted=1.00,row_cnt=1.00,compute=0.00,io=1.00 }
PhysicalScan { table: t1, cost: weighted=1.00,row_cnt=1.00,compute=0.00,io=1.00 }
*/

-- Test verbose explain with aggregation
Expand Down

0 comments on commit c970648

Please sign in to comment.