diff --git a/optd-datafusion-bridge/src/lib.rs b/optd-datafusion-bridge/src/lib.rs index e6413653..593e8039 100644 --- a/optd-datafusion-bridge/src/lib.rs +++ b/optd-datafusion-bridge/src/lib.rs @@ -256,40 +256,45 @@ impl OptdQueryPlanner { .unwrap() .explain_to_string(if verbose { Some(&meta) } else { None }), )); - let join_order = get_join_order(optimized_rel.clone()); - explains.push(StringifiedPlan::new( - PlanType::OptimizedPhysicalPlan { - optimizer_name: "optd-join-order".to_string(), - }, - if let Some(join_order) = join_order { - join_order.to_string() - } else { - "None".to_string() - }, - )); - let bindings = optimizer - .optd_cascades_optimizer() - .get_all_group_bindings(group_id, true); - let mut join_orders = BTreeSet::new(); - let mut logical_join_orders = BTreeSet::new(); - for binding in bindings { - if let Some(join_order) = get_join_order(binding) { - logical_join_orders.insert(join_order.conv_into_logical_join_order()); - join_orders.insert(join_order); + + const ENABLE_JOIN_ORDER: bool = false; + + if ENABLE_JOIN_ORDER { + let join_order = get_join_order(optimized_rel.clone()); + explains.push(StringifiedPlan::new( + PlanType::OptimizedPhysicalPlan { + optimizer_name: "optd-join-order".to_string(), + }, + if let Some(join_order) = join_order { + join_order.to_string() + } else { + "None".to_string() + }, + )); + let bindings = optimizer + .optd_cascades_optimizer() + .get_all_group_bindings(group_id, true); + let mut join_orders = BTreeSet::new(); + let mut logical_join_orders = BTreeSet::new(); + for binding in bindings { + if let Some(join_order) = get_join_order(binding) { + logical_join_orders.insert(join_order.conv_into_logical_join_order()); + join_orders.insert(join_order); + } } + explains.push(StringifiedPlan::new( + PlanType::OptimizedPhysicalPlan { + optimizer_name: "optd-all-join-orders".to_string(), + }, + join_orders.iter().map(|x| x.to_string()).join("\n"), + )); + explains.push(StringifiedPlan::new( + PlanType::OptimizedPhysicalPlan { + optimizer_name: "optd-all-logical-join-orders".to_string(), + }, + logical_join_orders.iter().map(|x| x.to_string()).join("\n"), + )); } - explains.push(StringifiedPlan::new( - PlanType::OptimizedPhysicalPlan { - optimizer_name: "optd-all-join-orders".to_string(), - }, - join_orders.iter().map(|x| x.to_string()).join("\n"), - )); - explains.push(StringifiedPlan::new( - PlanType::OptimizedPhysicalPlan { - optimizer_name: "optd-all-logical-join-orders".to_string(), - }, - logical_join_orders.iter().map(|x| x.to_string()).join("\n"), - )); } // println!( // "{} cost={}", diff --git a/optd-datafusion-repr/src/lib.rs b/optd-datafusion-repr/src/lib.rs index 2a550826..d94bacbb 100644 --- a/optd-datafusion-repr/src/lib.rs +++ b/optd-datafusion-repr/src/lib.rs @@ -23,11 +23,11 @@ use properties::{ }; use rules::{ EliminateDuplicatedAggExprRule, EliminateDuplicatedSortExprRule, EliminateFilterRule, - EliminateJoinRule, EliminateLimitRule, FilterAggTransposeRule, FilterCrossJoinTransposeRule, - FilterInnerJoinTransposeRule, FilterMergeRule, FilterProjectTransposeRule, - FilterSortTransposeRule, HashJoinRule, JoinAssocRule, JoinCommuteRule, PhysicalConversionRule, - ProjectFilterTransposeRule, ProjectMergeRule, ProjectionPullUpJoin, SimplifyFilterRule, - SimplifyJoinCondRule, + EliminateJoinRule, EliminateLimitRule, EliminateProjectRule, FilterAggTransposeRule, + FilterCrossJoinTransposeRule, FilterInnerJoinTransposeRule, FilterMergeRule, + FilterProjectTransposeRule, FilterSortTransposeRule, HashJoinRule, JoinAssocRule, + JoinCommuteRule, PhysicalConversionRule, ProjectMergeRule, ProjectionPullUpJoin, + SimplifyFilterRule, SimplifyJoinCondRule, }; pub use optd_core::rel_node::Value; @@ -46,7 +46,7 @@ mod testing; // mod expand; pub struct DatafusionOptimizer { - hueristic_optimizer: HeuristicsOptimizer, + heuristic_optimizer: HeuristicsOptimizer, cascades_optimizer: CascadesOptimizer, pub runtime_statistics: RuntimeAdaptionStorage, enable_adaptive: bool, @@ -75,7 +75,7 @@ impl DatafusionOptimizer { } pub fn optd_hueristic_optimizer(&self) -> &HeuristicsOptimizer { - &self.hueristic_optimizer + &self.heuristic_optimizer } pub fn optd_optimizer_mut(&mut self) -> &mut CascadesOptimizer { @@ -99,6 +99,8 @@ impl DatafusionOptimizer { Arc::new(DepJoinPastAgg::new()), Arc::new(ProjectMergeRule::new()), Arc::new(FilterMergeRule::new()), + // disabled due to logical properties are not implemented in heuristics + // Arc::new(EliminateProjectRule::new()), ] } @@ -110,9 +112,10 @@ impl DatafusionOptimizer { rule_wrappers.push(RuleWrapper::new_cascades(rule)); } // project transpose rules - rule_wrappers.push(RuleWrapper::new_cascades(Arc::new( - ProjectFilterTransposeRule::new(), - ))); + // only do filter-project one way for now to reduce search space + // rule_wrappers.push(RuleWrapper::new_cascades(Arc::new( + // ProjectFilterTransposeRule::new(), + // ))); // add all filter pushdown rules as heuristic rules rule_wrappers.push(RuleWrapper::new_cascades(Arc::new( FilterProjectTransposeRule::new(), @@ -129,13 +132,19 @@ impl DatafusionOptimizer { rule_wrappers.push(RuleWrapper::new_cascades(Arc::new( FilterAggTransposeRule::new(), ))); - rule_wrappers.push(RuleWrapper::new_cascades(Arc::new(HashJoinRule::new()))); // 17 - rule_wrappers.push(RuleWrapper::new_cascades(Arc::new(JoinCommuteRule::new()))); // 18 + rule_wrappers.push(RuleWrapper::new_cascades(Arc::new(HashJoinRule::new()))); + rule_wrappers.push(RuleWrapper::new_cascades(Arc::new(JoinCommuteRule::new()))); rule_wrappers.push(RuleWrapper::new_cascades(Arc::new(JoinAssocRule::new()))); rule_wrappers.push(RuleWrapper::new_cascades(Arc::new( ProjectionPullUpJoin::new(), ))); - + rule_wrappers.push(RuleWrapper::new_cascades(Arc::new( + EliminateProjectRule::new(), + ))); + rule_wrappers.push(RuleWrapper::new_cascades(Arc::new(ProjectMergeRule::new()))); + rule_wrappers.push(RuleWrapper::new_cascades(Arc::new( + EliminateFilterRule::new(), + ))); rule_wrappers } @@ -167,7 +176,7 @@ impl DatafusionOptimizer { partial_explore_space: Some(1 << 10), }, ), - hueristic_optimizer: HeuristicsOptimizer::new_with_rules( + heuristic_optimizer: HeuristicsOptimizer::new_with_rules( heuristic_rules, ApplyOrder::TopDown, // uhh TODO reconsider property_builders.clone(), @@ -215,7 +224,7 @@ impl DatafusionOptimizer { cascades_optimizer: optimizer, enable_adaptive: true, enable_heuristic: false, - hueristic_optimizer: HeuristicsOptimizer::new_with_rules( + heuristic_optimizer: HeuristicsOptimizer::new_with_rules( vec![], ApplyOrder::BottomUp, Arc::new([]), @@ -224,7 +233,7 @@ impl DatafusionOptimizer { } pub fn heuristic_optimize(&mut self, root_rel: OptRelNodeRef) -> OptRelNodeRef { - self.hueristic_optimizer + self.heuristic_optimizer .optimize(root_rel) .expect("heuristics returns error") } diff --git a/optd-datafusion-repr/src/rules.rs b/optd-datafusion-repr/src/rules.rs index e5b1d780..c06a46e2 100644 --- a/optd-datafusion-repr/src/rules.rs +++ b/optd-datafusion-repr/src/rules.rs @@ -24,7 +24,7 @@ pub use physical::PhysicalConversionRule; pub use project_transpose::{ project_filter_transpose::{FilterProjectTransposeRule, ProjectFilterTransposeRule}, project_join_transpose::ProjectionPullUpJoin, - project_merge::ProjectMergeRule, + project_merge::{EliminateProjectRule, ProjectMergeRule}, }; pub use subquery::{ DepInitialDistinct, DepJoinEliminateAtScan, DepJoinPastAgg, DepJoinPastFilter, DepJoinPastProj, diff --git a/optd-datafusion-repr/src/rules/project_transpose/project_merge.rs b/optd-datafusion-repr/src/rules/project_transpose/project_merge.rs index 84983d53..b01641e0 100644 --- a/optd-datafusion-repr/src/rules/project_transpose/project_merge.rs +++ b/optd-datafusion-repr/src/rules/project_transpose/project_merge.rs @@ -3,7 +3,10 @@ use std::collections::HashMap; use optd_core::rules::{Rule, RuleMatcher}; use optd_core::{optimizer::Optimizer, rel_node::RelNode}; -use crate::plan_nodes::{ExprList, LogicalProjection, OptRelNode, OptRelNodeTyp, PlanNode}; +use crate::plan_nodes::{ + ColumnRefExpr, ExprList, LogicalProjection, OptRelNode, OptRelNodeTyp, PlanNode, +}; +use crate::properties::schema::SchemaPropertyBuilder; use crate::rules::macros::define_rule; use super::project_transpose_common::ProjectionMapping; @@ -41,6 +44,38 @@ fn apply_projection_merge( vec![node.into_rel_node().as_ref().clone()] } +// Proj child [identical columns] -> eliminate +define_rule!( + EliminateProjectRule, + apply_eliminate_project, + (Projection, child, [expr]) +); + +fn apply_eliminate_project( + optimizer: &impl Optimizer, + EliminateProjectRulePicks { child, expr }: EliminateProjectRulePicks, +) -> Vec> { + let exprs = ExprList::from_rel_node(expr.into()).unwrap(); + let child_columns = optimizer + .get_property::(child.clone().into(), 0) + .len(); + if child_columns != exprs.len() { + return Vec::new(); + } + for i in 0..exprs.len() { + let child_expr = exprs.child(i); + if child_expr.typ() == OptRelNodeTyp::ColumnRef { + let child_expr = ColumnRefExpr::from_rel_node(child_expr.into_rel_node()).unwrap(); + if child_expr.index() != i { + return Vec::new(); + } + } else { + return Vec::new(); + } + } + vec![child] +} + #[cfg(test)] mod tests { use std::sync::Arc; diff --git a/optd-sqlplannertest/README.md b/optd-sqlplannertest/README.md index 38668bb4..6946fe30 100644 --- a/optd-sqlplannertest/README.md +++ b/optd-sqlplannertest/README.md @@ -32,11 +32,11 @@ The `explain` and `execute` task will be run with datafusion's logical optimizer #### Flags -| Name | Description | -| -------------- | --------------------------------------- | -| use_df_logical | Enable Datafusion's logical optimizer | -| verbose | Display estimated cost in physical plan | -| logical_rules | Only enable these logical rules | +| Name | Description | +| -------------- | ------------------------------------------------------------------ | +| use_df_logical | Enable Datafusion's logical optimizer | +| verbose | Display estimated cost in physical plan | +| logical_rules | Only enable these logical rules (also disable heuristic optimizer) | Currently we have the following options for the explain task: diff --git a/optd-sqlplannertest/tests/joins/join_enumerate.planner.sql b/optd-sqlplannertest/disabled_tests/joins/join_enumerate.planner.sql similarity index 100% rename from optd-sqlplannertest/tests/joins/join_enumerate.planner.sql rename to optd-sqlplannertest/disabled_tests/joins/join_enumerate.planner.sql diff --git a/optd-sqlplannertest/tests/joins/join_enumerate.yml b/optd-sqlplannertest/disabled_tests/joins/join_enumerate.yml similarity index 100% rename from optd-sqlplannertest/tests/joins/join_enumerate.yml rename to optd-sqlplannertest/disabled_tests/joins/join_enumerate.yml diff --git a/optd-sqlplannertest/src/lib.rs b/optd-sqlplannertest/src/lib.rs index 261001fd..e2502d9c 100644 --- a/optd-sqlplannertest/src/lib.rs +++ b/optd-sqlplannertest/src/lib.rs @@ -106,6 +106,7 @@ impl DatafusionDBMS { for r in 0..rules.len() { optimizer.enable_rule(r); } + guard.as_mut().unwrap().enable_heuristic(true); } else { for (rule_id, rule) in rules.as_ref().iter().enumerate() { if rule.rule.is_impl_rule() { @@ -127,6 +128,7 @@ impl DatafusionDBMS { if !rules_to_enable.is_empty() { bail!("Unknown logical rule: {:?}", rules_to_enable); } + guard.as_mut().unwrap().enable_heuristic(false); } } let sql = unescape_input(sql)?; @@ -335,8 +337,11 @@ fn extract_flags(task: &str) -> Result { } else if flag == "use_df_logical" { options.enable_df_logical = true; } else if flag.starts_with("logical_rules") { - options.enable_logical_rules = - flag.split('+').skip(1).map(|x| x.to_string()).collect(); + if let Some((_, flag)) = flag.split_once(':') { + options.enable_logical_rules = flag.split('+').map(|x| x.to_string()).collect(); + } else { + bail!("Failed to parse logical_rules flag: {}", flag); + } } else if flag == "disable_explore_limit" { options.disable_explore_limit = true; } else { diff --git a/optd-sqlplannertest/tests/basic/basic_nodes.planner.sql b/optd-sqlplannertest/tests/basic/basic_nodes.planner.sql index 301f300e..d9d880c5 100644 --- a/optd-sqlplannertest/tests/basic/basic_nodes.planner.sql +++ b/optd-sqlplannertest/tests/basic/basic_nodes.planner.sql @@ -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 diff --git a/optd-sqlplannertest/tests/basic/cross_product.planner.sql b/optd-sqlplannertest/tests/basic/cross_product.planner.sql index fb7aecc1..0799cc5a 100644 --- a/optd-sqlplannertest/tests/basic/cross_product.planner.sql +++ b/optd-sqlplannertest/tests/basic/cross_product.planner.sql @@ -17,10 +17,9 @@ LogicalProjection { exprs: [ #0, #1 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1 ] } -└── PhysicalNestedLoopJoin { join_type: Cross, cond: true } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalNestedLoopJoin { join_type: Cross, cond: true } +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } 0 0 0 1 0 2 diff --git a/optd-sqlplannertest/tests/basic/eliminate_duplicated_expr.planner.sql b/optd-sqlplannertest/tests/basic/eliminate_duplicated_expr.planner.sql index b31e774f..db0add47 100644 --- a/optd-sqlplannertest/tests/basic/eliminate_duplicated_expr.planner.sql +++ b/optd-sqlplannertest/tests/basic/eliminate_duplicated_expr.planner.sql @@ -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 @@ -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 @@ -61,9 +59,8 @@ select * from t1 group by v1, v2, v1; LogicalProjection { exprs: [ #0, #1 ] } └── LogicalAgg { exprs: [], groups: [ #0, #1, #0 ] } └── LogicalScan { table: t1 } -PhysicalProjection { exprs: [ #0, #1 ] } -└── PhysicalAgg { aggrs: [], groups: [ #0, #1 ] } - └── PhysicalScan { table: t1 } +PhysicalAgg { aggrs: [], groups: [ #0, #1 ] } +└── PhysicalScan { table: t1 } 0 0 1 1 5 2 @@ -96,9 +93,8 @@ PhysicalSort │ │ └── #0 │ └── SortOrder { order: Asc } │ └── #1 -└── PhysicalProjection { exprs: [ #0, #1 ] } - └── PhysicalAgg { aggrs: [], groups: [ #0, #1 ] } - └── PhysicalScan { table: t1 } +└── PhysicalAgg { aggrs: [], groups: [ #0, #1 ] } + └── PhysicalScan { table: t1 } 0 0 0 2 1 1 diff --git a/optd-sqlplannertest/tests/basic/eliminate_proj.planner.sql b/optd-sqlplannertest/tests/basic/eliminate_proj.planner.sql new file mode 100644 index 00000000..5ff5e017 --- /dev/null +++ b/optd-sqlplannertest/tests/basic/eliminate_proj.planner.sql @@ -0,0 +1,88 @@ +-- (no id or description) +create table t1(v1 int, v2 int); +insert into t1 values (0, 0), (1, 1), (2, 2); +create table t2(v0 int, v1 int, v2 int, v3 int); +insert into t2 values (0, 0, 0, 0), (1, 1, 1, 1), (2, 2, 2, 2); + +/* +3 +3 +*/ + +-- Test MergeProjectRule with only the rule enabled +select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + +/* +LogicalProjection { exprs: [ #1 ] } +└── LogicalProjection { exprs: [ #1, #0 ] } + └── LogicalLimit { skip: 0(u64), fetch: 5(u64) } + └── LogicalProjection { exprs: [ #0, #1 ] } + └── LogicalScan { table: t1 } +PhysicalProjection { exprs: [ #0 ] } +└── PhysicalLimit { skip: 0(u64), fetch: 5(u64) } + └── PhysicalProjection { exprs: [ #0, #1 ] } + └── PhysicalScan { table: t1 } +*/ + +-- Test EliminateProjectRule with only the rule enabled +select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + +/* +LogicalProjection { exprs: [ #1 ] } +└── LogicalProjection { exprs: [ #1, #0 ] } + └── LogicalLimit { skip: 0(u64), fetch: 5(u64) } + └── LogicalProjection { exprs: [ #0, #1 ] } + └── LogicalScan { table: t1 } +PhysicalProjection { exprs: [ #1 ] } +└── PhysicalProjection { exprs: [ #1, #0 ] } + └── PhysicalLimit { skip: 0(u64), fetch: 5(u64) } + └── PhysicalScan { table: t1 } +*/ + +-- Test with all rules enabled +select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + +/* +LogicalProjection { exprs: [ #1 ] } +└── LogicalProjection { exprs: [ #1, #0 ] } + └── LogicalLimit { skip: 0(u64), fetch: 5(u64) } + └── LogicalProjection { exprs: [ #0, #1 ] } + └── LogicalScan { table: t1 } +PhysicalProjection { exprs: [ #0 ] } +└── PhysicalLimit { skip: 0(u64), fetch: 5(u64) } + └── PhysicalScan { table: t1 } +0 +1 +2 +*/ + +-- Test with all rules enabled +select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + +/* +LogicalProjection { exprs: [ #1 ] } +└── LogicalProjection { exprs: [ #1, #0 ] } + └── LogicalLimit { skip: 0(u64), fetch: 5(u64) } + └── LogicalProjection { exprs: [ #0, #1 ] } + └── LogicalScan { table: t1 } +PhysicalProjection { exprs: [ #0 ] } +└── PhysicalLimit { skip: 0(u64), fetch: 5(u64) } + └── PhysicalScan { table: t1 } +0 +1 +2 +*/ + +-- Test with all rules enabled +select v0, v2, v1, v3 from (select v0 as v0, v2 as v1, v1 as v2, v3 from t2); + +/* +LogicalProjection { exprs: [ #0, #2, #1, #3 ] } +└── LogicalProjection { exprs: [ #0, #2, #1, #3 ] } + └── LogicalScan { table: t2 } +PhysicalScan { table: t2 } +0 0 0 0 +1 1 1 1 +2 2 2 2 +*/ + diff --git a/optd-sqlplannertest/tests/basic/eliminate_proj.yml b/optd-sqlplannertest/tests/basic/eliminate_proj.yml new file mode 100644 index 00000000..da526b96 --- /dev/null +++ b/optd-sqlplannertest/tests/basic/eliminate_proj.yml @@ -0,0 +1,35 @@ +- sql: | + create table t1(v1 int, v2 int); + insert into t1 values (0, 0), (1, 1), (2, 2); + create table t2(v0 int, v1 int, v2 int, v3 int); + insert into t2 values (0, 0, 0, 0), (1, 1, 1, 1), (2, 2, 2, 2); + tasks: + - execute +- sql: | + select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + desc: Test MergeProjectRule with only the rule enabled + tasks: + - explain[logical_rules:project_merge_rule]:logical_optd,physical_optd +- sql: | + select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + desc: Test EliminateProjectRule with only the rule enabled + tasks: + - explain[logical_rules:eliminate_project_rule]:logical_optd,physical_optd +- sql: | + select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + desc: Test with all rules enabled + tasks: + - explain:logical_optd,physical_optd + - execute +- sql: | + select v1 from (select v2, v1 from (select v1, v2 from t1 limit 5)); + desc: Test with all rules enabled + tasks: + - explain:logical_optd,physical_optd + - execute +- sql: | + select v0, v2, v1, v3 from (select v0 as v0, v2 as v1, v1 as v2, v3 from t2); + desc: Test with all rules enabled + tasks: + - explain:logical_optd,physical_optd + - execute diff --git a/optd-sqlplannertest/tests/basic/empty_relation.planner.sql b/optd-sqlplannertest/tests/basic/empty_relation.planner.sql index 2d1c94a6..220665ec 100644 --- a/optd-sqlplannertest/tests/basic/empty_relation.planner.sql +++ b/optd-sqlplannertest/tests/basic/empty_relation.planner.sql @@ -39,7 +39,6 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } └── LogicalJoin { join_type: Inner, cond: false } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalEmptyRelation { produce_one_row: false } +PhysicalEmptyRelation { produce_one_row: false } */ diff --git a/optd-sqlplannertest/tests/basic/filter.planner.sql b/optd-sqlplannertest/tests/basic/filter.planner.sql index 8ba252fa..fc7e95b6 100644 --- a/optd-sqlplannertest/tests/basic/filter.planner.sql +++ b/optd-sqlplannertest/tests/basic/filter.planner.sql @@ -16,8 +16,7 @@ select * from t1 where false; LogicalProjection { exprs: [ #0, #1 ] } └── LogicalFilter { cond: false } └── LogicalScan { table: t1 } -PhysicalProjection { exprs: [ #0, #1 ] } -└── PhysicalEmptyRelation { produce_one_row: false } +PhysicalEmptyRelation { produce_one_row: false } */ -- Test EliminateFilterRule (replace true filter with child) @@ -27,8 +26,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 @@ -48,8 +46,7 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalEmptyRelation { produce_one_row: false } +PhysicalEmptyRelation { produce_one_row: false } */ -- Test SimplifyFilterRule (skip true filter for and) @@ -69,10 +66,9 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalHashJoin { join_type: Inner, left_keys: [ #0, #0 ], right_keys: [ #0, #1 ] } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalHashJoin { join_type: Inner, left_keys: [ #0, #0 ], right_keys: [ #0, #1 ] } +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } */ -- Test SimplifyFilterRule (skip true filter for and) @@ -93,18 +89,17 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalNestedLoopJoin - ├── join_type: Inner - ├── cond:Or - │ ├── Eq - │ │ ├── #0 - │ │ └── #2 - │ └── Eq - │ ├── #0 - │ └── #3 - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalNestedLoopJoin +├── join_type: Inner +├── cond:Or +│ ├── Eq +│ │ ├── #0 +│ │ └── #2 +│ └── Eq +│ ├── #0 +│ └── #3 +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } 0 0 0 200 1 1 1 201 2 2 2 202 @@ -127,10 +122,9 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalNestedLoopJoin { join_type: Cross, cond: true } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalNestedLoopJoin { join_type: Cross, cond: true } +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } 0 0 0 200 0 0 1 201 0 0 2 202 @@ -162,10 +156,9 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } 0 0 0 200 1 1 1 201 2 2 2 202 @@ -185,8 +178,7 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } │ └── false ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalEmptyRelation { produce_one_row: false } +PhysicalEmptyRelation { produce_one_row: false } */ -- Test SimplifyJoinCondRule (skip true filter for and) @@ -206,10 +198,9 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } │ └── true ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalHashJoin { join_type: Inner, left_keys: [ #0, #0 ], right_keys: [ #0, #1 ] } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalHashJoin { join_type: Inner, left_keys: [ #0, #0 ], right_keys: [ #0, #1 ] } +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } */ -- Test SimplifyJoinCondRule (skip true filter for and) @@ -230,18 +221,17 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } │ └── true ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalNestedLoopJoin - ├── join_type: Inner - ├── cond:Or - │ ├── Eq - │ │ ├── #0 - │ │ └── #2 - │ └── Eq - │ ├── #0 - │ └── #3 - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalNestedLoopJoin +├── join_type: Inner +├── cond:Or +│ ├── Eq +│ │ ├── #0 +│ │ └── #2 +│ └── Eq +│ ├── #0 +│ └── #3 +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } 0 0 0 200 1 1 1 201 2 2 2 202 @@ -264,10 +254,9 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } │ └── true ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalNestedLoopJoin { join_type: Cross, cond: true } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalNestedLoopJoin { join_type: Cross, cond: true } +├── PhysicalScan { table: t1 } +└── PhysicalScan { table: t2 } 0 0 0 200 0 0 1 201 0 0 2 202 @@ -299,10 +288,9 @@ LogicalProjection { exprs: [ #0, #1, #2, #3 ] } │ └── #2 ├── LogicalScan { table: t1 } └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } -└── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } +├── 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 910a1663..874ffc63 100644 --- a/optd-sqlplannertest/tests/basic/verbose.planner.sql +++ b/optd-sqlplannertest/tests/basic/verbose.planner.sql @@ -10,28 +10,25 @@ 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 select count(*) from t1; /* -PhysicalProjection { exprs: [ #0 ], cost: weighted=21.18,row_cnt=1.00,compute=20.18,io=1.00 } -└── 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 } +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 } */ diff --git a/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql b/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql index 727c1168..ef775a45 100644 --- a/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql +++ b/optd-sqlplannertest/tests/pushdowns/fliter_transpose.planner.sql @@ -15,21 +15,7 @@ SELECT t1.t1v1, t1.t1v2, t2.t2v3 WHERE t1.t1v1 = t2.t2v1; /* -LogicalProjection { exprs: [ #0, #1, #3 ] } -└── LogicalFilter - ├── cond:Eq - │ ├── #0 - │ └── #2 - └── LogicalJoin { join_type: Cross, cond: true } - ├── LogicalScan { table: t1 } - └── LogicalScan { table: t2 } -PhysicalProjection { exprs: [ #0, #1, #3 ] } -└── PhysicalFilter - ├── cond:Eq - │ ├── #0 - │ └── #2 - └── PhysicalNestedLoopJoin { join_type: Cross, cond: true } - ├── PhysicalScan { table: t1 } - └── PhysicalScan { table: t2 } +Error +Unknown logical rule: {"project_filter_transpose_rule"} */ diff --git a/optd-sqlplannertest/tests/pushdowns/fliter_transpose.yml b/optd-sqlplannertest/tests/pushdowns/fliter_transpose.yml index ebdf91ff..a1afa280 100644 --- a/optd-sqlplannertest/tests/pushdowns/fliter_transpose.yml +++ b/optd-sqlplannertest/tests/pushdowns/fliter_transpose.yml @@ -11,5 +11,4 @@ WHERE t1.t1v1 = t2.t2v1; desc: Test whether we can transpose filter and projection tasks: - # - explain[logical_rules:filter_project_transpose_rule+project_filter_transpose_rule,disable_explore_limit]:logical_optd,physical_optd - explain[logical_rules:filter_project_transpose_rule+project_filter_transpose_rule]:logical_optd,physical_optd diff --git a/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql b/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql index db8bb247..15ec3f7a 100644 --- a/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql +++ b/optd-sqlplannertest/tests/subqueries/subquery_unnesting.planner.sql @@ -54,27 +54,24 @@ LogicalProjection { exprs: [ #0, #1 ] } │ └── LogicalScan { table: t1 } └── LogicalScan { table: t2 } PhysicalProjection { exprs: [ #0, #1 ] } -└── PhysicalProjection { exprs: [ #0, #1, #3 ] } - └── PhysicalFilter - ├── cond:Gt - │ ├── #3 - │ └── 100(i64) - └── PhysicalProjection { exprs: [ #2, #3, #0, #1 ] } - └── PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } - └── PhysicalProjection { exprs: [ #2, #3, #0, #1 ] } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - ├── PhysicalScan { table: t1 } - └── 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 } +└── PhysicalFilter + ├── cond:Gt + │ ├── #3 + │ └── 100(i64) + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + ├── PhysicalScan { table: t1 } + └── PhysicalAgg + ├── aggrs:Agg(Sum) + │ └── [ Cast { cast_to: Int64, expr: #2 } ] + ├── groups: [ #1 ] + └── PhysicalProjection { exprs: [ #2, #0, #1 ] } + └── PhysicalFilter + ├── cond:Eq + │ ├── #0 + │ └── #2 + └── PhysicalNestedLoopJoin { join_type: Inner, cond: true } + ├── PhysicalScan { table: t2 } + └── PhysicalAgg { aggrs: [], groups: [ #0 ] } + └── 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 62c14a6f..61de4e1d 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-01-05.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-01-05.planner.sql @@ -161,45 +161,44 @@ PhysicalSort │ │ └── #0 │ └── SortOrder { order: Asc } │ └── #1 -└── PhysicalProjection { exprs: [ #0, #1, #2, #3, #4, #5, #6, #7, #8, #9 ] } - └── PhysicalAgg - ├── aggrs: - │ ┌── Agg(Sum) - │ │ └── [ #4 ] - │ ├── Agg(Sum) - │ │ └── [ #5 ] - │ ├── Agg(Sum) - │ │ └── Mul - │ │ ├── #5 - │ │ └── Sub - │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } - │ │ └── #6 - │ ├── Agg(Sum) - │ │ └── Mul - │ │ ├── Mul - │ │ │ ├── #5 - │ │ │ └── Sub - │ │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } - │ │ │ └── #6 - │ │ └── Add - │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } - │ │ └── #7 - │ ├── Agg(Avg) - │ │ └── [ #4 ] - │ ├── Agg(Avg) - │ │ └── [ #5 ] - │ ├── Agg(Avg) - │ │ └── [ #6 ] - │ └── Agg(Count) - │ └── [ 1(u8) ] - ├── groups: [ #8, #9 ] - └── PhysicalFilter - ├── cond:Leq - │ ├── #10 - │ └── Sub - │ ├── Cast { cast_to: Date32, expr: "1998-12-01" } - │ └── INTERVAL_MONTH_DAY_NANO (0, 90, 0) - └── PhysicalScan { table: lineitem } +└── PhysicalAgg + ├── aggrs: + │ ┌── Agg(Sum) + │ │ └── [ #4 ] + │ ├── Agg(Sum) + │ │ └── [ #5 ] + │ ├── Agg(Sum) + │ │ └── Mul + │ │ ├── #5 + │ │ └── Sub + │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } + │ │ └── #6 + │ ├── Agg(Sum) + │ │ └── Mul + │ │ ├── Mul + │ │ │ ├── #5 + │ │ │ └── Sub + │ │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } + │ │ │ └── #6 + │ │ └── Add + │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } + │ │ └── #7 + │ ├── Agg(Avg) + │ │ └── [ #4 ] + │ ├── Agg(Avg) + │ │ └── [ #5 ] + │ ├── Agg(Avg) + │ │ └── [ #6 ] + │ └── Agg(Count) + │ └── [ 1(u8) ] + ├── groups: [ #8, #9 ] + └── PhysicalFilter + ├── cond:Leq + │ ├── #10 + │ └── Sub + │ ├── Cast { cast_to: Date32, expr: "1998-12-01" } + │ └── INTERVAL_MONTH_DAY_NANO (0, 90, 0) + └── PhysicalScan { table: lineitem } */ -- TPC-H Q2 @@ -363,38 +362,29 @@ PhysicalLimit { skip: 0(u64), fetch: 100(u64) } │ │ └── #1 │ └── SortOrder { order: Asc } │ └── #3 - └── PhysicalProjection { exprs: [ #5, #2, #8, #0, #1, #3, #4, #6 ] } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0, #7 ], right_keys: [ #1, #0 ] } - ├── PhysicalProjection { exprs: [ #0, #1, #2, #3, #4, #5, #6, #7, #8 ] } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #9 ], right_keys: [ #0 ] } - │ ├── PhysicalProjection { exprs: [ #0, #1, #2, #3, #5, #6, #7, #8, #10, #11 ] } - │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #4 ], right_keys: [ #0 ] } - │ │ ├── PhysicalProjection { exprs: [ #0, #1, #5, #6, #7, #8, #9, #10, #3 ] } - │ │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #2 ], right_keys: [ #0 ] } - │ │ │ ├── PhysicalProjection { exprs: [ #0, #1, #3, #4 ] } - │ │ │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ │ │ │ ├── PhysicalProjection { exprs: [ #0, #1 ] } - │ │ │ │ │ └── PhysicalFilter - │ │ │ │ │ ├── cond:And - │ │ │ │ │ │ ├── Eq - │ │ │ │ │ │ │ ├── #3 - │ │ │ │ │ │ │ └── 4(i32) - │ │ │ │ │ │ └── Like { expr: #2, pattern: "%TIN", negated: false, case_insensitive: false } - │ │ │ │ │ └── PhysicalProjection { exprs: [ #0, #2, #4, #5 ] } - │ │ │ │ │ └── PhysicalScan { table: part } - │ │ │ │ └── PhysicalProjection { exprs: [ #0, #1, #3 ] } - │ │ │ │ └── PhysicalScan { table: partsupp } - │ │ │ └── PhysicalProjection { exprs: [ #0, #1, #2, #3, #4, #5, #6 ] } - │ │ │ └── PhysicalScan { table: supplier } - │ │ └── PhysicalProjection { exprs: [ #0, #1, #2 ] } - │ │ └── PhysicalScan { table: nation } - │ └── PhysicalProjection { exprs: [ #0 ] } - │ └── PhysicalProjection { exprs: [ #0, #1 ] } - │ └── PhysicalFilter - │ ├── cond:Eq - │ │ ├── #1 - │ │ └── "AFRICA" - │ └── PhysicalScan { table: region } + └── PhysicalProjection { exprs: [ #5, #1, #22, #7, #9, #2, #4, #6 ] } + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #7, #19 ], 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 } + │ │ └── PhysicalProjection { exprs: [ #0, #1, #2 ] } + │ │ └── PhysicalScan { table: nation } + │ └── PhysicalProjection { exprs: [ #0 ] } + │ └── PhysicalFilter + │ ├── cond:Eq + │ │ ├── #1 + │ │ └── "AFRICA" + │ └── PhysicalScan { table: region } └── PhysicalProjection { exprs: [ #1, #0 ] } └── PhysicalAgg ├── aggrs:Agg(Min) @@ -413,12 +403,11 @@ PhysicalLimit { skip: 0(u64), fetch: 100(u64) } │ └── PhysicalProjection { exprs: [ #0, #2 ] } │ └── PhysicalScan { table: nation } └── PhysicalProjection { exprs: [ #0 ] } - └── PhysicalProjection { exprs: [ #0, #1 ] } - └── PhysicalFilter - ├── cond:Eq - │ ├── #1 - │ └── "AFRICA" - └── PhysicalScan { table: region } + └── PhysicalFilter + ├── cond:Eq + │ ├── #1 + │ └── "AFRICA" + └── PhysicalScan { table: region } */ -- TPC-H Q3 @@ -510,30 +499,24 @@ PhysicalLimit { skip: 0(u64), fetch: 10(u64) } │ ├── 1(float) │ └── #4 ├── groups: [ #2, #0, #1 ] - └── PhysicalProjection { exprs: [ #1, #2, #3, #4, #5 ] } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - ├── PhysicalProjection { exprs: [ #1, #3, #4 ] } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #1 ] } - │ ├── PhysicalProjection { exprs: [ #0 ] } - │ │ └── PhysicalFilter - │ │ ├── cond:Eq - │ │ │ ├── #1 - │ │ │ └── "FURNITURE" - │ │ └── PhysicalProjection { exprs: [ #0, #6 ] } - │ │ └── PhysicalScan { table: customer } - │ └── PhysicalFilter - │ ├── cond:Lt - │ │ ├── #2 - │ │ └── 9218(i64) - │ └── PhysicalProjection { exprs: [ #0, #1, #4, #7 ] } - │ └── PhysicalScan { table: orders } - └── PhysicalProjection { exprs: [ #0, #1, #2 ] } - └── PhysicalProjection { exprs: [ #0, #5, #6, #10 ] } - └── PhysicalFilter - ├── cond:Gt - │ ├── #10 - │ └── 9218(i64) - └── PhysicalScan { table: lineitem } + └── PhysicalProjection { exprs: [ #28, #31, #8, #13, #14 ] } + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #17 ] } + ├── PhysicalFilter + │ ├── cond:Eq + │ │ ├── #6 + │ │ └── "FURNITURE" + │ └── PhysicalScan { table: customer } + └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + ├── PhysicalFilter + │ ├── cond:Gt + │ │ ├── #10 + │ │ └── 9218(i64) + │ └── PhysicalScan { table: lineitem } + └── PhysicalFilter + ├── cond:Lt + │ ├── #4 + │ └── 9218(i64) + └── PhysicalScan { table: orders } */ -- TPC-H Q5 @@ -618,37 +601,36 @@ LogicalSort PhysicalSort ├── exprs:SortOrder { order: Desc } │ └── #1 -└── PhysicalProjection { exprs: [ #0, #1 ] } - └── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── Mul - │ ├── #22 - │ └── Sub - │ ├── 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 } +└── PhysicalAgg + ├── aggrs:Agg(Sum) + │ └── Mul + │ ├── #22 + │ └── Sub + │ ├── 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 } */ diff --git a/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql b/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql index 61b55bfa..4849ebe7 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-06-10.planner.sql @@ -120,26 +120,25 @@ LogicalProjection { exprs: [ #0 ] } │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } │ └── Cast { cast_to: Decimal128(22, 2), expr: 24(i64) } └── LogicalScan { table: lineitem } -PhysicalProjection { exprs: [ #0 ] } -└── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── Mul - │ ├── #5 - │ └── #6 - ├── groups: [] - └── PhysicalFilter - ├── cond:And - │ ├── Geq - │ │ ├── #10 - │ │ └── Cast { cast_to: Date32, expr: "2023-01-01" } - │ ├── Lt - │ │ ├── #10 - │ │ └── Cast { cast_to: Date32, expr: "2024-01-01" } - │ ├── Between { expr: Cast { cast_to: Decimal128(30, 15), expr: #6 }, lower: Cast { cast_to: Decimal128(30, 15), expr: 0.05(float) }, upper: Cast { cast_to: Decimal128(30, 15), expr: 0.07(float) } } - │ └── Lt - │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } - │ └── Cast { cast_to: Decimal128(22, 2), expr: 24(i64) } - └── PhysicalScan { table: lineitem } +PhysicalAgg +├── aggrs:Agg(Sum) +│ └── Mul +│ ├── #5 +│ └── #6 +├── groups: [] +└── PhysicalFilter + ├── cond:And + │ ├── Geq + │ │ ├── #10 + │ │ └── Cast { cast_to: Date32, expr: "2023-01-01" } + │ ├── Lt + │ │ ├── #10 + │ │ └── Cast { cast_to: Date32, expr: "2024-01-01" } + │ ├── Between { expr: Cast { cast_to: Decimal128(30, 15), expr: #6 }, lower: Cast { cast_to: Decimal128(30, 15), expr: 0.05(float) }, upper: Cast { cast_to: Decimal128(30, 15), expr: 0.07(float) } } + │ └── Lt + │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } + │ └── Cast { cast_to: Decimal128(22, 2), expr: 24(i64) } + └── PhysicalScan { table: lineitem } */ -- TPC-H Q7 @@ -260,54 +259,53 @@ PhysicalSort │ │ └── #1 │ └── SortOrder { order: Asc } │ └── #2 -└── PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } - └── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── [ #3 ] - ├── groups: [ #0, #1, #2 ] - └── PhysicalProjection - ├── exprs: - │ ┌── #41 - │ ├── #45 - │ ├── Scalar(DatePart) - │ │ └── [ "YEAR", #17 ] - │ └── Mul - │ ├── #12 - │ └── Sub - │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } - │ └── #13 - └── PhysicalNestedLoopJoin - ├── join_type: Inner - ├── cond:And - │ ├── Eq - │ │ ├── #35 - │ │ └── #44 - │ └── Or - │ ├── And - │ │ ├── Eq - │ │ │ ├── #41 - │ │ │ └── "FRANCE" - │ │ └── Eq - │ │ ├── #45 - │ │ └── "GERMANY" - │ └── And - │ ├── Eq - │ │ ├── #41 - │ │ └── "GERMANY" - │ └── Eq - │ ├── #45 - │ └── "FRANCE" - ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #3 ], right_keys: [ #0 ] } - │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #7 ], right_keys: [ #0 ] } - │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #2 ] } - │ │ │ ├── PhysicalScan { table: supplier } - │ │ │ └── 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 } - │ └── PhysicalScan { table: nation } - └── PhysicalScan { table: nation } +└── PhysicalAgg + ├── aggrs:Agg(Sum) + │ └── [ #3 ] + ├── groups: [ #0, #1, #2 ] + └── PhysicalProjection + ├── exprs: + │ ┌── #41 + │ ├── #45 + │ ├── Scalar(DatePart) + │ │ └── [ "YEAR", #17 ] + │ └── Mul + │ ├── #12 + │ └── Sub + │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } + │ └── #13 + └── PhysicalNestedLoopJoin + ├── join_type: Inner + ├── cond:And + │ ├── Eq + │ │ ├── #35 + │ │ └── #44 + │ └── Or + │ ├── And + │ │ ├── Eq + │ │ │ ├── #41 + │ │ │ └── "FRANCE" + │ │ └── Eq + │ │ ├── #45 + │ │ └── "GERMANY" + │ └── And + │ ├── Eq + │ │ ├── #41 + │ │ └── "GERMANY" + │ └── Eq + │ ├── #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: [ #17 ], right_keys: [ #0 ] } + │ │ ├── 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 } + │ │ │ └── PhysicalScan { table: orders } + │ │ └── PhysicalScan { table: customer } + │ └── PhysicalScan { table: nation } + └── PhysicalScan { table: nation } */ -- TPC-H Q8 without top-most limit node @@ -470,12 +468,12 @@ PhysicalSort │ │ │ │ └── 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 } + │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #17 ], right_keys: [ #0 ] } + │ │ │ ├── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + │ │ │ │ ├── PhysicalScan { table: lineitem } + │ │ │ │ └── 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 } │ └── PhysicalScan { table: nation } └── PhysicalFilter @@ -583,37 +581,36 @@ PhysicalSort │ │ └── #0 │ └── SortOrder { order: Desc } │ └── #1 -└── PhysicalProjection { exprs: [ #0, #1, #2 ] } - └── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── [ #2 ] - ├── groups: [ #0, #1 ] - └── PhysicalProjection - ├── exprs: - │ ┌── #47 - │ ├── Scalar(DatePart) - │ │ └── [ "YEAR", #41 ] - │ └── Sub - │ ├── Mul - │ │ ├── #21 - │ │ └── Sub - │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } - │ │ └── #22 - │ └── Mul - │ ├── #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 } - └── PhysicalScan { table: nation } +└── PhysicalAgg + ├── aggrs:Agg(Sum) + │ └── [ #2 ] + ├── groups: [ #0, #1 ] + └── PhysicalProjection + ├── exprs: + │ ┌── #47 + │ ├── Scalar(DatePart) + │ │ └── [ "YEAR", #41 ] + │ └── Sub + │ ├── Mul + │ │ ├── #21 + │ │ └── Sub + │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } + │ │ └── #22 + │ └── Mul + │ ├── #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 } + └── PhysicalScan { table: nation } */ -- TPC-H Q9 @@ -714,37 +711,36 @@ PhysicalSort │ │ └── #0 │ └── SortOrder { order: Desc } │ └── #1 -└── PhysicalProjection { exprs: [ #0, #1, #2 ] } - └── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── [ #2 ] - ├── groups: [ #0, #1 ] - └── PhysicalProjection - ├── exprs: - │ ┌── #47 - │ ├── Scalar(DatePart) - │ │ └── [ "YEAR", #41 ] - │ └── Sub - │ ├── Mul - │ │ ├── #21 - │ │ └── Sub - │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } - │ │ └── #22 - │ └── Mul - │ ├── #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 } - └── PhysicalScan { table: nation } +└── PhysicalAgg + ├── aggrs:Agg(Sum) + │ └── [ #2 ] + ├── groups: [ #0, #1 ] + └── PhysicalProjection + ├── exprs: + │ ┌── #47 + │ ├── Scalar(DatePart) + │ │ └── [ "YEAR", #41 ] + │ └── Sub + │ ├── Mul + │ │ ├── #21 + │ │ └── Sub + │ │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } + │ │ └── #22 + │ └── Mul + │ ├── #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 } + └── PhysicalScan { table: nation } */ -- TPC-H Q10 diff --git a/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql b/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql index 52efaef5..7fd9e25a 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-11-15.planner.sql @@ -195,62 +195,54 @@ LogicalSort PhysicalSort ├── exprs:SortOrder { order: Desc } │ └── #1 -└── PhysicalProjection { exprs: [ #0, #1 ] } - └── PhysicalProjection { exprs: [ #0, #1 ] } - └── PhysicalNestedLoopJoin - ├── join_type: Inner - ├── cond:Gt - │ ├── Cast { cast_to: Decimal128(38, 15), expr: #1 } - │ └── #0 - ├── PhysicalProjection - │ ├── exprs:Cast - │ │ ├── cast_to: Decimal128(38, 15) - │ │ ├── expr:Mul - │ │ │ ├── Cast { cast_to: Float64, expr: #0 } - │ │ │ └── 0.0001(float) +└── PhysicalNestedLoopJoin + ├── join_type: Inner + ├── cond:Gt + │ ├── Cast { cast_to: Decimal128(38, 15), expr: #1 } + │ └── #0 + ├── PhysicalProjection + │ ├── exprs:Cast + │ │ ├── cast_to: Decimal128(38, 15) + │ │ ├── expr:Mul + │ │ │ ├── Cast { cast_to: Float64, expr: #0 } + │ │ │ └── 0.0001(float) - │ └── PhysicalAgg - │ ├── aggrs:Agg(Sum) - │ │ └── Mul - │ │ ├── #1 - │ │ └── Cast { cast_to: Decimal128(10, 0), expr: #0 } - │ ├── groups: [] - │ └── PhysicalProjection { exprs: [ #0, #1 ] } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #2 ], right_keys: [ #0 ] } - │ ├── PhysicalProjection { exprs: [ #1, #2, #4 ] } - │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ │ ├── PhysicalProjection { exprs: [ #1, #2, #3 ] } - │ │ │ └── PhysicalScan { table: partsupp } - │ │ └── PhysicalProjection { exprs: [ #0, #3 ] } - │ │ └── PhysicalScan { table: supplier } - │ └── PhysicalProjection { exprs: [ #0 ] } - │ └── PhysicalProjection { exprs: [ #0, #1 ] } - │ └── PhysicalFilter - │ ├── cond:Eq - │ │ ├── #1 - │ │ └── "CHINA" - │ └── PhysicalScan { table: nation } - └── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── Mul - │ ├── #2 - │ └── Cast { cast_to: Decimal128(10, 0), expr: #1 } - ├── groups: [ #0 ] - └── PhysicalProjection { exprs: [ #0, #1, #2 ] } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #3 ], right_keys: [ #0 ] } - ├── PhysicalProjection { exprs: [ #0, #2, #3, #5 ] } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #1 ], right_keys: [ #0 ] } - │ ├── PhysicalProjection { exprs: [ #0, #1, #2, #3 ] } - │ │ └── PhysicalScan { table: partsupp } - │ └── PhysicalProjection { exprs: [ #0, #3 ] } - │ └── PhysicalScan { table: supplier } - └── PhysicalProjection { exprs: [ #0 ] } - └── PhysicalProjection { exprs: [ #0, #1 ] } - └── PhysicalFilter - ├── cond:Eq - │ ├── #1 - │ └── "CHINA" - └── PhysicalScan { table: nation } + │ └── PhysicalAgg + │ ├── aggrs:Agg(Sum) + │ │ └── Mul + │ │ ├── #1 + │ │ └── Cast { cast_to: Decimal128(10, 0), expr: #0 } + │ ├── groups: [] + │ └── PhysicalProjection { exprs: [ #0, #1 ] } + │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #2 ], right_keys: [ #0 ] } + │ ├── PhysicalProjection { exprs: [ #1, #2, #4 ] } + │ │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } + │ │ ├── PhysicalProjection { exprs: [ #1, #2, #3 ] } + │ │ │ └── PhysicalScan { table: partsupp } + │ │ └── PhysicalProjection { exprs: [ #0, #3 ] } + │ │ └── PhysicalScan { table: supplier } + │ └── PhysicalProjection { exprs: [ #0 ] } + │ └── PhysicalFilter + │ ├── cond:Eq + │ │ ├── #1 + │ │ └── "CHINA" + │ └── PhysicalScan { table: nation } + └── PhysicalAgg + ├── aggrs:Agg(Sum) + │ └── Mul + │ ├── #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 } */ -- TPC-H Q12 @@ -333,52 +325,51 @@ LogicalSort PhysicalSort ├── exprs:SortOrder { order: Asc } │ └── #0 -└── PhysicalProjection { exprs: [ #0, #1, #2 ] } - └── PhysicalAgg - ├── aggrs: - │ ┌── Agg(Sum) - │ │ └── Case - │ │ └── - │ │ ┌── Or - │ │ │ ├── Eq - │ │ │ │ ├── #5 - │ │ │ │ └── "1-URGENT" - │ │ │ └── Eq - │ │ │ ├── #5 - │ │ │ └── "2-HIGH" - │ │ ├── 1(i64) - │ │ └── 0(i64) - │ └── Agg(Sum) - │ └── Case - │ └── - │ ┌── And - │ │ ├── Neq - │ │ │ ├── #5 - │ │ │ └── "1-URGENT" - │ │ └── Neq - │ │ ├── #5 - │ │ └── "2-HIGH" - │ ├── 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 } +└── PhysicalAgg + ├── aggrs: + │ ┌── Agg(Sum) + │ │ └── Case + │ │ └── + │ │ ┌── Or + │ │ │ ├── Eq + │ │ │ │ ├── #5 + │ │ │ │ └── "1-URGENT" + │ │ │ └── Eq + │ │ │ ├── #5 + │ │ │ └── "2-HIGH" + │ │ ├── 1(i64) + │ │ └── 0(i64) + │ └── Agg(Sum) + │ └── Case + │ └── + │ ┌── And + │ │ ├── Neq + │ │ │ ├── #5 + │ │ │ └── "1-URGENT" + │ │ └── Neq + │ │ ├── #5 + │ │ └── "2-HIGH" + │ ├── 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 } */ -- TPC-H Q14 @@ -576,56 +567,50 @@ LogicalSort PhysicalSort ├── exprs:SortOrder { order: Asc } │ └── #0 -└── PhysicalProjection { exprs: [ #0, #1, #2, #3, #4 ] } - └── PhysicalProjection { exprs: [ #0, #1, #2, #3, #5, #6 ] } - └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - ├── PhysicalProjection { exprs: [ #0, #1, #2, #4 ] } - │ └── PhysicalScan { table: supplier } - └── PhysicalProjection { exprs: [ #0, #1, #2 ] } - └── PhysicalProjection { exprs: [ #1, #2, #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: [ #0, #1, #2 ] } - │ └── PhysicalProjection { exprs: [ #2, #5, #6, #10 ] } - │ └── 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: [ #0, #1, #2 ] } - └── PhysicalProjection { exprs: [ #2, #5, #6, #10 ] } - └── 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 24067777..08459295 100644 --- a/optd-sqlplannertest/tests/tpch/tpch-16-20.planner.sql +++ b/optd-sqlplannertest/tests/tpch/tpch-16-20.planner.sql @@ -174,31 +174,27 @@ PhysicalProjection ├── aggrs:Agg(Sum) │ └── [ #0 ] ├── groups: [] - └── PhysicalProjection { exprs: [ #1 ] } + └── PhysicalProjection { exprs: [ #14 ] } └── PhysicalNestedLoopJoin ├── join_type: Inner ├── cond:And │ ├── Eq - │ │ ├── #2 - │ │ └── #4 + │ │ ├── #0 + │ │ └── #0 │ └── Lt - │ ├── Cast { cast_to: Decimal128(30, 15), expr: #0 } - │ └── #3 - ├── PhysicalProjection { exprs: [ #1, #2, #3 ] } - │ └── PhysicalHashJoin { join_type: Inner, left_keys: [ #0 ], right_keys: [ #0 ] } - │ ├── PhysicalProjection { exprs: [ #1, #4, #5 ] } - │ │ └── PhysicalScan { table: lineitem } - │ └── PhysicalProjection { exprs: [ #0 ] } - │ └── PhysicalProjection { exprs: [ #0, #3, #6 ] } - │ └── PhysicalFilter - │ ├── cond:And - │ │ ├── Eq - │ │ │ ├── #3 - │ │ │ └── "Brand#13" - │ │ └── Eq - │ │ ├── #6 - │ │ └── "JUMBO PKG" - │ └── PhysicalScan { table: part } + │ ├── 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 @@ -321,76 +317,75 @@ LogicalProjection { exprs: [ #0 ] } └── LogicalJoin { join_type: Cross, cond: true } ├── LogicalScan { table: lineitem } └── LogicalScan { table: part } -PhysicalProjection { exprs: [ #0 ] } -└── PhysicalAgg - ├── aggrs:Agg(Sum) - │ └── Mul - │ ├── #5 - │ └── Sub - │ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } - │ └── #6 - ├── groups: [] - └── PhysicalNestedLoopJoin - ├── join_type: Inner - ├── cond:Or - │ ├── And - │ │ ├── Eq - │ │ │ ├── #16 - │ │ │ └── #1 - │ │ ├── Eq - │ │ │ ├── #19 - │ │ │ └── "Brand#12" - │ │ ├── InList { expr: #22, list: [ "SM CASE", "SM BOX", "SM PACK", "SM PKG" ], negated: false } - │ │ ├── Geq - │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } - │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 1(i64) } - │ │ ├── Leq - │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } - │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 11(i64) } - │ │ ├── Between { expr: Cast { cast_to: Int64, expr: #21 }, lower: 1(i64), upper: 5(i64) } - │ │ ├── InList { expr: #14, list: [ "AIR", "AIR REG" ], negated: false } - │ │ └── Eq - │ │ ├── #13 - │ │ └── "DELIVER IN PERSON" - │ ├── And - │ │ ├── Eq - │ │ │ ├── #16 - │ │ │ └── #1 - │ │ ├── Eq - │ │ │ ├── #19 - │ │ │ └── "Brand#23" - │ │ ├── InList { expr: #22, list: [ "MED BAG", "MED BOX", "MED PKG", "MED PACK" ], negated: false } - │ │ ├── Geq - │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } - │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 10(i64) } - │ │ ├── Leq - │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } - │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 20(i64) } - │ │ ├── Between { expr: Cast { cast_to: Int64, expr: #21 }, lower: 1(i64), upper: 10(i64) } - │ │ ├── InList { expr: #14, list: [ "AIR", "AIR REG" ], negated: false } - │ │ └── Eq - │ │ ├── #13 - │ │ └── "DELIVER IN PERSON" - │ └── And - │ ├── Eq - │ │ ├── #16 - │ │ └── #1 - │ ├── Eq - │ │ ├── #19 - │ │ └── "Brand#34" - │ ├── InList { expr: #22, list: [ "LG CASE", "LG BOX", "LG PACK", "LG PKG" ], negated: false } - │ ├── Geq - │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } - │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 20(i64) } - │ ├── Leq - │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } - │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 30(i64) } - │ ├── Between { expr: Cast { cast_to: Int64, expr: #21 }, lower: 1(i64), upper: 15(i64) } - │ ├── InList { expr: #14, list: [ "AIR", "AIR REG" ], negated: false } - │ └── Eq - │ ├── #13 - │ └── "DELIVER IN PERSON" - ├── PhysicalScan { table: lineitem } - └── PhysicalScan { table: part } +PhysicalAgg +├── aggrs:Agg(Sum) +│ └── Mul +│ ├── #5 +│ └── Sub +│ ├── Cast { cast_to: Decimal128(20, 0), expr: 1(i64) } +│ └── #6 +├── groups: [] +└── PhysicalNestedLoopJoin + ├── join_type: Inner + ├── cond:Or + │ ├── And + │ │ ├── Eq + │ │ │ ├── #16 + │ │ │ └── #1 + │ │ ├── Eq + │ │ │ ├── #19 + │ │ │ └── "Brand#12" + │ │ ├── InList { expr: #22, list: [ "SM CASE", "SM BOX", "SM PACK", "SM PKG" ], negated: false } + │ │ ├── Geq + │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } + │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 1(i64) } + │ │ ├── Leq + │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } + │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 11(i64) } + │ │ ├── Between { expr: Cast { cast_to: Int64, expr: #21 }, lower: 1(i64), upper: 5(i64) } + │ │ ├── InList { expr: #14, list: [ "AIR", "AIR REG" ], negated: false } + │ │ └── Eq + │ │ ├── #13 + │ │ └── "DELIVER IN PERSON" + │ ├── And + │ │ ├── Eq + │ │ │ ├── #16 + │ │ │ └── #1 + │ │ ├── Eq + │ │ │ ├── #19 + │ │ │ └── "Brand#23" + │ │ ├── InList { expr: #22, list: [ "MED BAG", "MED BOX", "MED PKG", "MED PACK" ], negated: false } + │ │ ├── Geq + │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } + │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 10(i64) } + │ │ ├── Leq + │ │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } + │ │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 20(i64) } + │ │ ├── Between { expr: Cast { cast_to: Int64, expr: #21 }, lower: 1(i64), upper: 10(i64) } + │ │ ├── InList { expr: #14, list: [ "AIR", "AIR REG" ], negated: false } + │ │ └── Eq + │ │ ├── #13 + │ │ └── "DELIVER IN PERSON" + │ └── And + │ ├── Eq + │ │ ├── #16 + │ │ └── #1 + │ ├── Eq + │ │ ├── #19 + │ │ └── "Brand#34" + │ ├── InList { expr: #22, list: [ "LG CASE", "LG BOX", "LG PACK", "LG PKG" ], negated: false } + │ ├── Geq + │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } + │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 20(i64) } + │ ├── Leq + │ │ ├── Cast { cast_to: Decimal128(22, 2), expr: #4 } + │ │ └── Cast { cast_to: Decimal128(22, 2), expr: 30(i64) } + │ ├── Between { expr: Cast { cast_to: Int64, expr: #21 }, lower: 1(i64), upper: 15(i64) } + │ ├── InList { expr: #14, list: [ "AIR", "AIR REG" ], negated: false } + │ └── Eq + │ ├── #13 + │ └── "DELIVER IN PERSON" + ├── PhysicalScan { table: lineitem } + └── PhysicalScan { table: part } */