diff --git a/optd-datafusion-repr/src/cost/adaptive_cost.rs b/optd-datafusion-repr/src/cost/adaptive_cost.rs index 00dc2bc2..77c0cd4d 100644 --- a/optd-datafusion-repr/src/cost/adaptive_cost.rs +++ b/optd-datafusion-repr/src/cost/adaptive_cost.rs @@ -10,6 +10,8 @@ use optd_core::{ rel_node::{RelNode, Value}, }; +use super::base_cost::DEFAULT_TABLE_ROW_CNT; + pub type RuntimeAdaptionStorage = Arc>; #[derive(Default, Debug)] @@ -52,10 +54,10 @@ impl CostModel for AdaptiveCostModel { let runtime_row_cnt = (*runtime_row_cnt).max(1) as f64; return OptCostModel::cost(runtime_row_cnt, 0.0, runtime_row_cnt); } else { - return OptCostModel::cost(1.0, 0.0, 1.0); + return OptCostModel::cost(DEFAULT_TABLE_ROW_CNT as f64, 0.0, 1.0); } } else { - return OptCostModel::cost(1.0, 0.0, 1.0); + return OptCostModel::cost(DEFAULT_TABLE_ROW_CNT as f64, 0.0, 1.0); } } let (mut row_cnt, compute_cost, io_cost) = OptCostModel::cost_tuple( diff --git a/optd-datafusion-repr/src/cost/base_cost.rs b/optd-datafusion-repr/src/cost/base_cost.rs index 3e86b56a..608f0508 100644 --- a/optd-datafusion-repr/src/cost/base_cost.rs +++ b/optd-datafusion-repr/src/cost/base_cost.rs @@ -31,6 +31,8 @@ pub const ROW_COUNT: usize = 1; pub const COMPUTE_COST: usize = 2; pub const IO_COST: usize = 3; +pub(crate) const DEFAULT_TABLE_ROW_CNT: usize = 1000; + impl OptCostModel { pub fn row_cnt(Cost(cost): &Cost) -> f64 { cost[ROW_COUNT] @@ -104,7 +106,7 @@ impl CostModel for OptCostModel { .table_stat .get(table_name.as_ref()) .copied() - .unwrap_or(1) as f64; + .unwrap_or(DEFAULT_TABLE_ROW_CNT) as f64; Self::cost(row_cnt, 0.0, row_cnt) } OptRelNodeTyp::PhysicalLimit => { diff --git a/optd-datafusion-repr/src/rules/filter.rs b/optd-datafusion-repr/src/rules/filter.rs index 81936204..f7f897cb 100644 --- a/optd-datafusion-repr/src/rules/filter.rs +++ b/optd-datafusion-repr/src/rules/filter.rs @@ -22,7 +22,7 @@ define_rule!( // - Replaces the Or operator with True if any operand is True // - Replaces the And operator with False if any operand is False // - Removes Duplicates -fn simplify_log_expr(log_expr: OptRelNodeRef, changed: &mut bool) -> OptRelNodeRef { +pub(crate) fn simplify_log_expr(log_expr: OptRelNodeRef, changed: &mut bool) -> OptRelNodeRef { let log_expr = LogOpExpr::from_rel_node(log_expr).unwrap(); let op = log_expr.op_type(); // we need a new children vec to output deterministic order diff --git a/optd-datafusion-repr/src/rules/filter_join.rs b/optd-datafusion-repr/src/rules/filter_join.rs deleted file mode 100644 index 3d5d43cb..00000000 --- a/optd-datafusion-repr/src/rules/filter_join.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::collections::HashMap; - -use optd_core::rel_node::RelNode; -use optd_core::rules::{Rule, RuleMatcher}; - -use crate::plan_nodes::{JoinType, OptRelNodeTyp}; - -pub struct FilterJoinPullUpRule { - matcher: RuleMatcher, -} - -const LEFT_CHILD: usize = 0; -const RIGHT_CHILD: usize = 1; -const JOIN_COND: usize = 2; -const FILTER_COND: usize = 3; - -impl FilterJoinPullUpRule { - pub fn new() -> Self { - Self { - matcher: RuleMatcher::MatchNode { - typ: OptRelNodeTyp::Join(JoinType::Inner), - children: vec![ - RuleMatcher::MatchNode { - typ: OptRelNodeTyp::Filter, - children: vec![ - RuleMatcher::PickOne { - pick_to: LEFT_CHILD, - expand: false, - }, - RuleMatcher::PickOne { - pick_to: FILTER_COND, - expand: true, - }, - ], - }, - RuleMatcher::PickOne { - pick_to: RIGHT_CHILD, - expand: false, - }, - RuleMatcher::PickOne { - pick_to: JOIN_COND, - expand: true, - }, - ], - }, - } - } -} - -impl Rule for FilterJoinPullUpRule { - fn matcher(&self) -> &RuleMatcher { - &self.matcher - } - - fn apply( - &self, - mut input: HashMap>, - ) -> Vec> { - let left_child = input.remove(&LEFT_CHILD).unwrap(); - let right_child = input.remove(&RIGHT_CHILD).unwrap(); - let join_cond = input.remove(&JOIN_COND).unwrap(); - let filter_cond = input.remove(&FILTER_COND).unwrap(); - let join_node = RelNode { - typ: OptRelNodeTyp::Join(JoinType::Inner), - children: vec![left_child.into(), right_child.into(), join_cond.into()], - data: None, - }; - let filter_node = RelNode { - typ: OptRelNodeTyp::Filter, - children: vec![join_node.into(), filter_cond.into()], - data: None, - }; - vec![filter_node] - } - - fn name(&self) -> &'static str { - "filter_join" - } -} diff --git a/optd-datafusion-repr/src/rules/filter_pushdown.rs b/optd-datafusion-repr/src/rules/filter_pushdown.rs index 2be62b82..121af011 100644 --- a/optd-datafusion-repr/src/rules/filter_pushdown.rs +++ b/optd-datafusion-repr/src/rules/filter_pushdown.rs @@ -21,6 +21,7 @@ use crate::plan_nodes::{ }; use crate::properties::schema::SchemaPropertyBuilder; +use super::filter::simplify_log_expr; use super::macros::define_rule; /// Emits a LogOpExpr AND if the list has more than one element @@ -36,7 +37,11 @@ fn and_expr_list_to_expr(exprs: Vec) -> Expr { fn merge_conds(first: Expr, second: Expr) -> Expr { let new_expr_list = ExprList::new(vec![first, second]); // Flatten nested logical expressions if possible - LogOpExpr::new_flattened_nested_logical(LogOpType::And, new_expr_list).into_expr() + let flattened = + LogOpExpr::new_flattened_nested_logical(LogOpType::And, new_expr_list).into_expr(); + let mut changed = false; + // TODO: such simplifications should be invoked from optd-core, instead of ad-hoc + Expr::from_rel_node(simplify_log_expr(flattened.into_rel_node(), &mut changed)).unwrap() } #[derive(Debug, Clone, Copy)] diff --git a/optd-sqlplannertest/tests/basic/filter.planner.sql b/optd-sqlplannertest/tests/basic/filter.planner.sql index fc7e95b6..f3ad2f1c 100644 --- a/optd-sqlplannertest/tests/basic/filter.planner.sql +++ b/optd-sqlplannertest/tests/basic/filter.planner.sql @@ -89,8 +89,7 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalNestedLoopJoin -├── join_type: Inner +PhysicalFilter ├── cond:Or │ ├── Eq │ │ ├── #0 @@ -98,8 +97,9 @@ PhysicalNestedLoopJoin │ └── Eq │ ├── #0 │ └── #3 -├── PhysicalScan { table: t1 } -└── PhysicalScan { table: t2 } +└── PhysicalNestedLoopJoin { join_type: Cross, cond: true } + ├── PhysicalScan { table: t1 } + └── PhysicalScan { table: t2 } 0 0 0 200 1 1 1 201 2 2 2 202 diff --git a/optd-sqlplannertest/tests/basic/verbose.planner.sql b/optd-sqlplannertest/tests/basic/verbose.planner.sql index 874ffc63..00b4169c 100644 --- a/optd-sqlplannertest/tests/basic/verbose.planner.sql +++ b/optd-sqlplannertest/tests/basic/verbose.planner.sql @@ -17,7 +17,7 @@ PhysicalScan { table: t1 } select * from t1; /* -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=1000.00,compute=0.00,io=1.00 } */ -- Test verbose explain with aggregation @@ -28,7 +28,7 @@ PhysicalAgg ├── aggrs:Agg(Count) │ └── [ 1(u8) ] ├── groups: [] -├── cost: weighted=21.12,row_cnt=1.00,compute=20.12,io=1.00 -└── PhysicalScan { table: t1, cost: weighted=1.00,row_cnt=1.00,compute=0.00,io=1.00 } +├── cost: weighted=10071.06,row_cnt=1000.00,compute=10070.06,io=1.00 +└── PhysicalScan { table: t1, cost: weighted=1.00,row_cnt=1000.00,compute=0.00,io=1.00 } */ diff --git a/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql b/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql index 079634f3..4277bd5e 100644 --- a/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql +++ b/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql @@ -47,11 +47,11 @@ LogicalProjection { exprs: [ #0, #1, #3 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalFilter -├── cond:Eq -│ ├── #0 -│ └── #2 -└── PhysicalProjection { exprs: [ #0, #1, #3 ] } +PhysicalProjection { exprs: [ #0, #1, #3 ] } +└── PhysicalFilter + ├── cond:Eq + │ ├── #0 + │ └── #3 └── PhysicalNestedLoopJoin { join_type: Cross, cond: true } ├── PhysicalScan { table: t1 } └── PhysicalScan { table: t2 } @@ -72,11 +72,11 @@ LogicalProjection { exprs: [ #0, #1, #2 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalFilter -├── cond:Eq -│ ├── #0 -│ └── #2 -└── PhysicalProjection { exprs: [ #0, #1, #3 ] } +PhysicalProjection { exprs: [ #0, #1, #3 ] } +└── PhysicalFilter + ├── cond:Eq + │ ├── #0 + │ └── #3 └── PhysicalNestedLoopJoin { join_type: Cross, cond: true } ├── PhysicalScan { table: t1 } └── PhysicalScan { table: t2 } diff --git a/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql b/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql index 05693c9c..ce52ee3e 100644 --- a/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql +++ b/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql @@ -53,24 +53,21 @@ LogicalProjection { exprs: [ #0, #1 ] } ├── LogicalAgg { exprs: [], groups: [ #0 ] } │ └── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1 ] } +PhysicalProjection { exprs: [ #2, #3 ] } └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - ├── PhysicalScan { table: t1 } - └── PhysicalFilter - ├── cond:Gt - │ ├── #1 - │ └── 100(i64) - └── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── [ Cast { cast_to: Int64, expr: #2 } ] - ├── groups: [ #1 ] - └── PhysicalFilter - ├── cond:Eq - │ ├── #1 - │ └── #0 - └── PhysicalNestedLoopJoin { join_type: Inner, cond: true } - ├── PhysicalAgg { aggrs: [], groups: [ #0 ] } - │ └── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } + ├── PhysicalAgg + │ ├── aggrs:Agg(Sum) + │ │ └── [ Cast { cast_to: Int64, expr: #2 } ] + │ ├── groups: [ #1 ] + │ └── PhysicalProjection { exprs: [ #2, #0, #1 ] } + │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + │ ├── PhysicalFilter + │ │ ├── cond:Gt + │ │ │ ├── #0 + │ │ │ └── 100(i64) + │ │ └── PhysicalScan { table: t2 } + │ └── PhysicalAgg { aggrs: [], groups: [ #0 ] } + │ └── PhysicalScan { table: t1 } + └── PhysicalScan { table: t1 } */ diff --git a/optd-sqlplannertest/tests/tpch/tpch-01-05.planner.sql b/optd-sqlplannertest/tests/tpch/tpch-01-05.planner.sql index 61de4e1d..b6e1ab35 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-01-05.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-01-05.planner.sql @@ -362,21 +362,21 @@ PhysicalLimit { skip: 0(u64), fetch: 100(u64) } │ │ └── #1 │ └── SortOrder { order: Asc } │ └── #3 - └── PhysicalProjection { exprs: [ #5, #1, #22, #7, #9, #2, #4, #6 ] } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #7, #19 ], right_keys: [ #1, #0 ] } + └── PhysicalProjection { exprs: [ #19, #15, #22, #0, #2, #16, #18, #20 ] } + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0, #12 ], right_keys: [ #1, #0 ] } ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #23 ], right_keys: [ #0 ] } - │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #3 ], right_keys: [ #0 ] } - │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #10 ] } - │ │ │ ├── PhysicalScan { table: supplier } - │ │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ │ │ ├── PhysicalFilter - │ │ │ │ ├── cond:And - │ │ │ │ │ ├── Eq - │ │ │ │ │ │ ├── #5 - │ │ │ │ │ │ └── 4(i32) - │ │ │ │ │ └── Like { expr: #4, pattern: "%TIN", negated: false, case_insensitive: false } - │ │ │ │ └── PhysicalScan { table: part } - │ │ │ └── PhysicalScan { table: partsupp } + │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #17 ], right_keys: [ #0 ] } + │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #10 ], right_keys: [ #0 ] } + │ │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + │ │ │ │ ├── PhysicalFilter + │ │ │ │ │ ├── cond:And + │ │ │ │ │ │ ├── Eq + │ │ │ │ │ │ │ ├── #5 + │ │ │ │ │ │ │ └── 4(i32) + │ │ │ │ │ │ └── Like { expr: #4, pattern: "%TIN", negated: false, case_insensitive: false } + │ │ │ │ │ └── PhysicalScan { table: part } + │ │ │ │ └── PhysicalScan { table: partsupp } + │ │ │ └── PhysicalScan { table: supplier } │ │ └── PhysicalProjection { exprs: [ #0, #1, #2 ] } │ │ └── PhysicalScan { table: nation } │ └── PhysicalProjection { exprs: [ #0 ] } @@ -609,28 +609,29 @@ PhysicalSort │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } │ └── #23 ├── groups: [ #41 ] - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #19, #3 ], right_keys: [ #0, #3 ] } - ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } - │ ├── PhysicalScan { table: customer } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ ├── PhysicalFilter - │ │ ├── cond:And - │ │ │ ├── Geq - │ │ │ │ ├── #4 - │ │ │ │ └── Cast { cast_to: Date32, expr: "2023-01-01" } - │ │ │ └── Lt - │ │ │ ├── #4 - │ │ │ └── Cast { cast_to: Date32, expr: "2024-01-01" } - │ │ └── PhysicalScan { table: orders } - │ └── PhysicalScan { table: lineitem } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #9 ], right_keys: [ #0 ] } - ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #3 ], right_keys: [ #0 ] } - │ ├── PhysicalScan { table: supplier } - │ └── PhysicalScan { table: nation } - └── PhysicalFilter - ├── cond:Eq - │ ├── #1 - │ └── "Asia" - └── PhysicalScan { table: region } + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #42 ], right_keys: [ #0 ] } + ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #36 ], right_keys: [ #0 ] } + │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #19, #3 ], right_keys: [ #0, #3 ] } + │ │ ├── PhysicalProjection { exprs: [ #25, #26, #27, #28, #29, #30, #31, #32, #0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24 ] } + │ │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #1 ], right_keys: [ #0 ] } + │ │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + │ │ │ │ ├── PhysicalFilter + │ │ │ │ │ ├── cond:And + │ │ │ │ │ │ ├── Geq + │ │ │ │ │ │ │ ├── #4 + │ │ │ │ │ │ │ └── Cast { cast_to: Date32, expr: "2023-01-01" } + │ │ │ │ │ │ └── Lt + │ │ │ │ │ │ ├── #4 + │ │ │ │ │ │ └── Cast { cast_to: Date32, expr: "2024-01-01" } + │ │ │ │ │ └── PhysicalScan { table: orders } + │ │ │ │ └── PhysicalScan { table: lineitem } + │ │ │ └── PhysicalScan { table: customer } + │ │ └── PhysicalScan { table: supplier } + │ └── PhysicalScan { table: nation } + └── PhysicalFilter + ├── cond:Eq + │ ├── #1 + │ └── "Asia" + └── PhysicalScan { table: region } */ diff --git a/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql b/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql index f74ba072..6c4bcf59 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql @@ -296,14 +296,15 @@ PhysicalSort │ ├── #45 │ └── "FRANCE" ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #3 ], right_keys: [ #0 ] } - │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #2 ] } - │ │ ├── PhysicalScan { table: supplier } - │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ │ ├── PhysicalFilter { cond: Between { expr: #10, lower: Cast { cast_to: Date32, expr: "1995-01-01" }, upper: Cast { cast_to: Date32, expr: "1996-12-31" } } } - │ │ │ └── PhysicalScan { table: lineitem } - │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #1 ], right_keys: [ #0 ] } - │ │ ├── PhysicalScan { table: orders } - │ │ └── PhysicalScan { table: customer } + │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #24 ], right_keys: [ #0 ] } + │ │ ├── PhysicalProjection { exprs: [ #16, #17, #18, #19, #20, #21, #22, #0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #23, #24, #25, #26, #27, #28, #29, #30, #31 ] } + │ │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + │ │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #2 ], right_keys: [ #0 ] } + │ │ │ │ ├── PhysicalFilter { cond: Between { expr: #10, lower: Cast { cast_to: Date32, expr: "1995-01-01" }, upper: Cast { cast_to: Date32, expr: "1996-12-31" } } } + │ │ │ │ │ └── PhysicalScan { table: lineitem } + │ │ │ │ └── PhysicalScan { table: supplier } + │ │ │ └── PhysicalScan { table: orders } + │ │ └── PhysicalScan { table: customer } │ └── PhysicalScan { table: nation } └── PhysicalScan { table: nation } */ @@ -459,22 +460,23 @@ PhysicalSort │ └── #54 └── PhysicalHashJoin { join_type: Inner, left_keys: [ #51 ], right_keys: [ #0 ] } ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #12 ], right_keys: [ #0 ] } - │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0, #9 ], right_keys: [ #1, #2 ] } - │ │ ├── PhysicalNestedLoopJoin { join_type: Cross, cond: true } - │ │ │ ├── PhysicalFilter - │ │ │ │ ├── cond:Eq - │ │ │ │ │ ├── #4 - │ │ │ │ │ └── "ECONOMY ANODIZED STEEL" - │ │ │ │ └── PhysicalScan { table: part } - │ │ │ └── PhysicalScan { table: supplier } - │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #28 ], right_keys: [ #0 ] } - │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ │ │ ├── PhysicalScan { table: lineitem } - │ │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #1 ], right_keys: [ #0 ] } - │ │ │ ├── PhysicalFilter { cond: Between { expr: #4, lower: Cast { cast_to: Date32, expr: "1995-01-01" }, upper: Cast { cast_to: Date32, expr: "1996-12-31" } } } - │ │ │ │ └── PhysicalScan { table: orders } - │ │ │ └── PhysicalScan { table: customer } - │ │ └── PhysicalScan { table: nation } + │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #44 ], right_keys: [ #0 ] } + │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #33 ], right_keys: [ #0 ] } + │ │ │ ├── PhysicalProjection { exprs: [ #25, #26, #27, #28, #29, #30, #31, #32, #33, #34, #35, #36, #37, #38, #39, #40, #9, #10, #11, #12, #13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24, #0, #1, #2, #3, #4, #5, #6, #7, #8 ] } + │ │ │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #10, #11 ], right_keys: [ #0, #9 ] } + │ │ │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + │ │ │ │ │ ├── PhysicalFilter { cond: Between { expr: #4, lower: Cast { cast_to: Date32, expr: "1995-01-01" }, upper: Cast { cast_to: Date32, expr: "1996-12-31" } } } + │ │ │ │ │ │ └── PhysicalScan { table: orders } + │ │ │ │ │ └── PhysicalScan { table: lineitem } + │ │ │ │ └── PhysicalNestedLoopJoin { join_type: Cross, cond: true } + │ │ │ │ ├── PhysicalFilter + │ │ │ │ │ ├── cond:Eq + │ │ │ │ │ │ ├── #4 + │ │ │ │ │ │ └── "ECONOMY ANODIZED STEEL" + │ │ │ │ │ └── PhysicalScan { table: part } + │ │ │ │ └── PhysicalScan { table: supplier } + │ │ │ └── PhysicalScan { table: customer } + │ │ └── PhysicalScan { table: nation } │ └── PhysicalScan { table: nation } └── PhysicalFilter ├── cond:Eq @@ -600,16 +602,16 @@ PhysicalSort │ ├── #35 │ └── #20 └── PhysicalHashJoin { join_type: Inner, left_keys: [ #12 ], right_keys: [ #0 ] } - ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #9, #0 ], right_keys: [ #2, #1 ] } - │ ├── PhysicalNestedLoopJoin { join_type: Cross, cond: true } - │ │ ├── PhysicalFilter { cond: Like { expr: #1, pattern: "%green%", negated: false, case_insensitive: false } } - │ │ │ └── PhysicalScan { table: part } - │ │ └── PhysicalScan { table: supplier } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #2, #1 ], right_keys: [ #1, #0 ] } - │ │ ├── PhysicalScan { table: lineitem } - │ │ └── PhysicalScan { table: partsupp } - │ └── PhysicalScan { table: orders } + ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #16 ], right_keys: [ #0 ] } + │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #18, #17 ], right_keys: [ #1, #0 ] } + │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #9, #0 ], right_keys: [ #2, #1 ] } + │ │ │ ├── PhysicalNestedLoopJoin { join_type: Cross, cond: true } + │ │ │ │ ├── PhysicalFilter { cond: Like { expr: #1, pattern: "%green%", negated: false, case_insensitive: false } } + │ │ │ │ │ └── PhysicalScan { table: part } + │ │ │ │ └── PhysicalScan { table: supplier } + │ │ │ └── PhysicalScan { table: lineitem } + │ │ └── PhysicalScan { table: partsupp } + │ └── PhysicalScan { table: orders } └── PhysicalScan { table: nation } */ @@ -730,16 +732,16 @@ PhysicalSort │ ├── #35 │ └── #20 └── PhysicalHashJoin { join_type: Inner, left_keys: [ #12 ], right_keys: [ #0 ] } - ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #9, #0 ], right_keys: [ #2, #1 ] } - │ ├── PhysicalNestedLoopJoin { join_type: Cross, cond: true } - │ │ ├── PhysicalFilter { cond: Like { expr: #1, pattern: "%green%", negated: false, case_insensitive: false } } - │ │ │ └── PhysicalScan { table: part } - │ │ └── PhysicalScan { table: supplier } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #2, #1 ], right_keys: [ #1, #0 ] } - │ │ ├── PhysicalScan { table: lineitem } - │ │ └── PhysicalScan { table: partsupp } - │ └── PhysicalScan { table: orders } + ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #16 ], right_keys: [ #0 ] } + │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #18, #17 ], right_keys: [ #1, #0 ] } + │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #9, #0 ], right_keys: [ #2, #1 ] } + │ │ │ ├── PhysicalNestedLoopJoin { join_type: Cross, cond: true } + │ │ │ │ ├── PhysicalFilter { cond: Like { expr: #1, pattern: "%green%", negated: false, case_insensitive: false } } + │ │ │ │ │ └── PhysicalScan { table: part } + │ │ │ │ └── PhysicalScan { table: supplier } + │ │ │ └── PhysicalScan { table: lineitem } + │ │ └── PhysicalScan { table: partsupp } + │ └── PhysicalScan { table: orders } └── PhysicalScan { table: nation } */ @@ -834,25 +836,26 @@ PhysicalLimit { skip: 0(u64), fetch: 20(u64) } │ └── #23 ├── groups: [ #0, #1, #5, #4, #34, #2, #7 ] └── PhysicalHashJoin { join_type: Inner, left_keys: [ #3 ], right_keys: [ #0 ] } - ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } - │ ├── PhysicalScan { table: customer } + ├── PhysicalProjection { exprs: [ #25, #26, #27, #28, #29, #30, #31, #32, #16, #17, #18, #19, #20, #21, #22, #23, #24, #0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15 ] } │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } │ ├── PhysicalFilter - │ │ ├── cond:And - │ │ │ ├── Geq - │ │ │ │ ├── #4 - │ │ │ │ └── Cast { cast_to: Date32, expr: "1993-07-01" } - │ │ │ └── Lt - │ │ │ ├── #4 - │ │ │ └── Add - │ │ │ ├── Cast { cast_to: Date32, expr: "1993-07-01" } - │ │ │ └── INTERVAL_MONTH_DAY_NANO (3, 0, 0) - │ │ └── PhysicalScan { table: orders } - │ └── PhysicalFilter - │ ├── cond:Eq - │ │ ├── #8 - │ │ └── "R" - │ └── PhysicalScan { table: lineitem } + │ │ ├── cond:Eq + │ │ │ ├── #8 + │ │ │ └── "R" + │ │ └── PhysicalScan { table: lineitem } + │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #1 ], right_keys: [ #0 ] } + │ ├── PhysicalFilter + │ │ ├── cond:And + │ │ │ ├── Geq + │ │ │ │ ├── #4 + │ │ │ │ └── Cast { cast_to: Date32, expr: "1993-07-01" } + │ │ │ └── Lt + │ │ │ ├── #4 + │ │ │ └── Add + │ │ │ ├── Cast { cast_to: Date32, expr: "1993-07-01" } + │ │ │ └── INTERVAL_MONTH_DAY_NANO (3, 0, 0) + │ │ └── PhysicalScan { table: orders } + │ └── PhysicalScan { table: customer } └── PhysicalScan { table: nation } */ diff --git a/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql b/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql index d448b5fa..81157d57 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql @@ -206,16 +206,16 @@ PhysicalSort │ │ ├── #2 │ │ └── Cast { cast_to: Decimal128(10, 0), expr: #1 } │ ├── groups: [ #0 ] - │ └── PhysicalProjection { exprs: [ #0, #2, #3 ] } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #1 ], right_keys: [ #4 ] } - │ ├── PhysicalScan { table: partsupp } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #3 ] } - │ ├── PhysicalFilter - │ │ ├── cond:Eq - │ │ │ ├── #1 - │ │ │ └── "CHINA" - │ │ └── PhysicalScan { table: nation } - │ └── PhysicalScan { table: supplier } + │ └── PhysicalProjection { exprs: [ #11, #13, #14 ] } + │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #4 ], right_keys: [ #1 ] } + │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #3 ] } + │ │ ├── PhysicalFilter + │ │ │ ├── cond:Eq + │ │ │ │ ├── #1 + │ │ │ │ └── "CHINA" + │ │ │ └── PhysicalScan { table: nation } + │ │ └── PhysicalScan { table: supplier } + │ └── PhysicalScan { table: partsupp } └── PhysicalProjection ├── exprs:Cast │ ├── cast_to: Decimal128(38, 15) @@ -352,24 +352,25 @@ PhysicalSort │ ├── 1(i64) │ └── 0(i64) ├── groups: [ #23 ] - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - ├── PhysicalScan { table: orders } - └── PhysicalFilter - ├── cond:And - │ ├── InList { expr: #14, list: [ "MAIL", "SHIP" ], negated: false } - │ ├── Lt - │ │ ├── #11 - │ │ └── #12 - │ ├── Lt - │ │ ├── #10 - │ │ └── #11 - │ ├── Geq - │ │ ├── #12 - │ │ └── Cast { cast_to: Date32, expr: "1994-01-01" } - │ └── Lt - │ ├── #12 - │ └── Cast { cast_to: Date32, expr: "1995-01-01" } - └── PhysicalScan { table: lineitem } + └── PhysicalProjection { exprs: [ #16, #17, #18, #19, #20, #21, #22, #23, #24, #0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15 ] } + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + ├── PhysicalFilter + │ ├── cond:And + │ │ ├── InList { expr: #14, list: [ "MAIL", "SHIP" ], negated: false } + │ │ ├── Lt + │ │ │ ├── #11 + │ │ │ └── #12 + │ │ ├── Lt + │ │ │ ├── #10 + │ │ │ └── #11 + │ │ ├── Geq + │ │ │ ├── #12 + │ │ │ └── Cast { cast_to: Date32, expr: "1994-01-01" } + │ │ └── Lt + │ │ ├── #12 + │ │ └── Cast { cast_to: Date32, expr: "1995-01-01" } + │ └── PhysicalScan { table: lineitem } + └── PhysicalScan { table: orders } */ -- TPC-H Q14 @@ -567,50 +568,50 @@ LogicalSort PhysicalSort ├── exprs:SortOrder { order: Asc } │ └── #0 -└── PhysicalProjection { exprs: [ #0, #1, #2, #4, #9 ] } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } - ├── PhysicalScan { table: supplier } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } - ├── PhysicalAgg - │ ├── aggrs:Agg(Max) - │ │ └── [ #0 ] - │ ├── groups: [] - │ └── PhysicalProjection { exprs: [ #1 ] } - │ └── PhysicalAgg - │ ├── aggrs:Agg(Sum) - │ │ └── Mul - │ │ ├── #1 - │ │ └── Sub - │ │ ├── 1(float) - │ │ └── #2 - │ ├── groups: [ #0 ] - │ └── PhysicalProjection { exprs: [ #2, #5, #6 ] } - │ └── PhysicalFilter - │ ├── cond:And - │ │ ├── Geq - │ │ │ ├── #10 - │ │ │ └── 8401(i64) - │ │ └── Lt - │ │ ├── #10 - │ │ └── 8491(i64) - │ └── PhysicalScan { table: lineitem } - └── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── Mul - │ ├── #1 - │ └── Sub - │ ├── 1(float) - │ └── #2 - ├── groups: [ #0 ] - └── PhysicalProjection { exprs: [ #2, #5, #6 ] } - └── PhysicalFilter - ├── cond:And - │ ├── Geq - │ │ ├── #10 - │ │ └── 8401(i64) - │ └── Lt - │ ├── #10 - │ └── 8491(i64) - └── PhysicalScan { table: lineitem } +└── PhysicalProjection { exprs: [ #3, #4, #5, #7, #2 ] } + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #1 ], right_keys: [ #0 ] } + ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } + │ ├── PhysicalAgg + │ │ ├── aggrs:Agg(Max) + │ │ │ └── [ #0 ] + │ │ ├── groups: [] + │ │ └── PhysicalProjection { exprs: [ #1 ] } + │ │ └── PhysicalAgg + │ │ ├── aggrs:Agg(Sum) + │ │ │ └── Mul + │ │ │ ├── #1 + │ │ │ └── Sub + │ │ │ ├── 1(float) + │ │ │ └── #2 + │ │ ├── groups: [ #0 ] + │ │ └── PhysicalProjection { exprs: [ #2, #5, #6 ] } + │ │ └── PhysicalFilter + │ │ ├── cond:And + │ │ │ ├── Geq + │ │ │ │ ├── #10 + │ │ │ │ └── 8401(i64) + │ │ │ └── Lt + │ │ │ ├── #10 + │ │ │ └── 8491(i64) + │ │ └── PhysicalScan { table: lineitem } + │ └── PhysicalAgg + │ ├── aggrs:Agg(Sum) + │ │ └── Mul + │ │ ├── #1 + │ │ └── Sub + │ │ ├── 1(float) + │ │ └── #2 + │ ├── groups: [ #0 ] + │ └── PhysicalProjection { exprs: [ #2, #5, #6 ] } + │ └── PhysicalFilter + │ ├── cond:And + │ │ ├── Geq + │ │ │ ├── #10 + │ │ │ └── 8401(i64) + │ │ └── Lt + │ │ ├── #10 + │ │ └── 8491(i64) + │ └── PhysicalScan { table: lineitem } + └── PhysicalScan { table: supplier } */ diff --git a/optd-sqlplannertest/tests/tpch/tpch-16-20.planner.sql b/optd-sqlplannertest/tests/tpch/tpch-16-20.planner.sql index ae726b44..307e0729 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-16-20.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-16-20.planner.sql @@ -174,42 +174,42 @@ PhysicalProjection ├── aggrs:Agg(Sum) │ └── [ #0 ] ├── groups: [] - └── PhysicalProjection { exprs: [ #15 ] } + └── PhysicalProjection { exprs: [ #14 ] } └── PhysicalNestedLoopJoin ├── join_type: Inner ├── cond:And │ ├── Eq - │ │ ├── #1 - │ │ └── #11 + │ │ ├── #0 + │ │ └── #10 │ └── Lt - │ ├── Cast { cast_to: Decimal128(30, 15), expr: #14 } - │ └── #0 - ├── PhysicalProjection - │ ├── exprs: - │ │ ┌── Cast - │ │ │ ├── cast_to: Decimal128(30, 15) - │ │ │ ├── expr:Mul - │ │ │ │ ├── 0.2(float) - │ │ │ │ └── Cast { cast_to: Float64, expr: #1 } + │ ├── Cast { cast_to: Decimal128(30, 15), expr: #13 } + │ └── #25 + ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } + │ ├── PhysicalFilter + │ │ ├── cond:And + │ │ │ ├── Eq + │ │ │ │ ├── #3 + │ │ │ │ └── "Brand#13" + │ │ │ └── Eq + │ │ │ ├── #6 + │ │ │ └── "JUMBO PKG" + │ │ └── PhysicalScan { table: part } + │ └── PhysicalScan { table: lineitem } + └── PhysicalProjection + ├── exprs: + │ ┌── Cast + │ │ ├── cast_to: Decimal128(30, 15) + │ │ ├── expr:Mul + │ │ │ ├── 0.2(float) + │ │ │ └── Cast { cast_to: Float64, expr: #1 } - │ │ └── #0 - │ └── PhysicalAgg - │ ├── aggrs:Agg(Avg) - │ │ └── [ #1 ] - │ ├── groups: [ #0 ] - │ └── PhysicalProjection { exprs: [ #1, #4 ] } - │ └── PhysicalScan { table: lineitem } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } - ├── PhysicalFilter - │ ├── cond:And - │ │ ├── Eq - │ │ │ ├── #3 - │ │ │ └── "Brand#13" - │ │ └── Eq - │ │ ├── #6 - │ │ └── "JUMBO PKG" - │ └── PhysicalScan { table: part } - └── PhysicalScan { table: lineitem } + │ └── #0 + └── PhysicalAgg + ├── aggrs:Agg(Avg) + │ └── [ #1 ] + ├── groups: [ #0 ] + └── PhysicalProjection { exprs: [ #1, #4 ] } + └── PhysicalScan { table: lineitem } */ -- TPC-H Q19 @@ -325,8 +325,7 @@ PhysicalAgg │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } │ └── #6 ├── groups: [] -└── PhysicalNestedLoopJoin - ├── join_type: Inner +└── PhysicalFilter ├── cond:Or │ ├── And │ │ ├── Eq @@ -385,7 +384,8 @@ PhysicalAgg │ └── Eq │ ├── #13 │ └── "DELIVER IN PERSON" - ├── PhysicalScan { table: lineitem } - └── PhysicalScan { table: part } + └── PhysicalNestedLoopJoin { join_type: Cross, cond: true } + ├── PhysicalScan { table: lineitem } + └── PhysicalScan { table: part } */