From b2d595a7cb3c30a1b7bcf33309d28ec483e245ad Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Tue, 1 Jul 2025 03:56:37 +0000 Subject: [PATCH 01/14] fix(query): add compatibility check for decimal64 --- .../src/converts/meta/index_scalar.rs | 41 +++++++++++++++++-- src/query/expression/src/values.rs | 2 + .../compat-logictest/base/fuse_compat_write | 10 ++++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/query/expression/src/converts/meta/index_scalar.rs b/src/query/expression/src/converts/meta/index_scalar.rs index 19bd95546f6bd..8524b07e94b9d 100644 --- a/src/query/expression/src/converts/meta/index_scalar.rs +++ b/src/query/expression/src/converts/meta/index_scalar.rs @@ -23,14 +23,26 @@ use serde::Deserialize; use serde::Serialize; use crate::types::decimal::DecimalScalar; +use crate::types::i256; use crate::types::number::NumberScalar; +use crate::types::DecimalSize; use crate::Scalar; +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, EnumAsInner)] +pub enum IndexDecimalScalar { + // For compatibility reason + // The old version only support Decimal128 and Decimal256 + // We don't store decimal64 in index scalar, this is only used for compatibility reading + Decimal64(i64, DecimalSize), + Decimal128(i128, DecimalSize), + Decimal256(i256, DecimalSize), +} + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, EnumAsInner)] pub enum IndexScalar { Null, Number(NumberScalar), - Decimal(DecimalScalar), + Decimal(IndexDecimalScalar), Timestamp(i64), Date(i32), Interval(months_days_micros), @@ -50,7 +62,21 @@ impl TryFrom for Scalar { Ok(match value { IndexScalar::Null => Scalar::Null, IndexScalar::Number(num_scalar) => Scalar::Number(num_scalar), - IndexScalar::Decimal(dec_scalar) => Scalar::Decimal(dec_scalar), + IndexScalar::Decimal(dec_scalar) => match dec_scalar { + IndexDecimalScalar::Decimal128(v, size) => { + if size.can_carried_by_64() { + Scalar::Decimal(DecimalScalar::Decimal64(v as i64, size)) + } else { + Scalar::Decimal(DecimalScalar::Decimal128(v, size)) + } + } + IndexDecimalScalar::Decimal256(v, size) => { + Scalar::Decimal(DecimalScalar::Decimal256(v, size)) + } + IndexDecimalScalar::Decimal64(v, size) => { + Scalar::Decimal(DecimalScalar::Decimal64(v, size)) + } + }, IndexScalar::Timestamp(ts) => Scalar::Timestamp(ts), IndexScalar::Date(date) => Scalar::Date(date), IndexScalar::Interval(interval) => Scalar::Interval(interval), @@ -77,7 +103,16 @@ impl TryFrom for IndexScalar { Ok(match value { Scalar::Null => IndexScalar::Null, Scalar::Number(num_scalar) => IndexScalar::Number(num_scalar), - Scalar::Decimal(dec_scalar) => IndexScalar::Decimal(dec_scalar), + Scalar::Decimal(dec_scalar) => { + match dec_scalar { + // still save as old format for compatibility + DecimalScalar::Decimal64(v, size) => { + IndexScalar::Decimal(IndexDecimalScalar::Decimal128(v as i128, size)) + } + DecimalScalar::Decimal128(v, size) => IndexScalar::Decimal(IndexDecimalScalar::Decimal128(v, size)), + DecimalScalar::Decimal256(v, size) => IndexScalar::Decimal(IndexDecimalScalar::Decimal256(v, size)), + } + } Scalar::Timestamp(ts) => IndexScalar::Timestamp(ts), Scalar::Date(date) => IndexScalar::Date(date), Scalar::Interval(interval) => IndexScalar::Interval(interval), diff --git a/src/query/expression/src/values.rs b/src/query/expression/src/values.rs index 7efe1e9ff1080..bff7c60ff1703 100755 --- a/src/query/expression/src/values.rs +++ b/src/query/expression/src/values.rs @@ -104,6 +104,8 @@ pub enum Value { Column(T::Column), } +/// Note: +/// We must modify IndexScalar if we modify Scalar #[derive( Debug, Clone, EnumAsInner, Eq, Serialize, Deserialize, BorshSerialize, BorshDeserialize, )] diff --git a/tests/compat_fuse/compat-logictest/base/fuse_compat_write b/tests/compat_fuse/compat-logictest/base/fuse_compat_write index c827509089f57..88ac901bf0119 100644 --- a/tests/compat_fuse/compat-logictest/base/fuse_compat_write +++ b/tests/compat_fuse/compat-logictest/base/fuse_compat_write @@ -22,7 +22,10 @@ CREATE TABLE fuse_compat_table ( c_array VARIANT, c_object VARIANT, c_variant VARIANT, - c_array_str ARRAY(String) + c_array_str ARRAY(String), + c_decimal_64 DECIMAL(8, 4), + c_decimal_128 DECIMAL(28, 4), + c_decimal_256 DECIMAL(72, 4), ) Engine = Fuse; statement ok @@ -43,7 +46,10 @@ INSERT INTO fuse_compat_table VALUES( parse_json('[1,2,3,["a","b","c"]]'), parse_json('{"a":1,"b":{"c":2}}'), parse_json('[1,{"a":1,"b":{"c":2}}]'), - ['item1', 'item2_looooooooooooooooooong_val', 'item3', 'item4'] + ['item1', 'item2_looooooooooooooooooong_val', 'item3', 'item4'], + 123.345, + 123.3456, + 123.456789, ); statement ok From 8a4f9943076c079b645edd361069b33d13df4c66 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Wed, 2 Jul 2025 01:37:16 +0000 Subject: [PATCH 02/14] chore(query): refactor logic plan and reloperator --- src/query/sql/src/planner/format/display.rs | 2 +- .../src/planner/optimizer/ir/expr/extract.rs | 8 +- .../src/planner/optimizer/ir/expr/m_expr.rs | 6 +- .../src/planner/optimizer/ir/expr/s_expr.rs | 11 +- src/query/sql/src/planner/plans/aggregate.rs | 10 + .../sql/src/planner/plans/async_function.rs | 4 + src/query/sql/src/planner/plans/cache_scan.rs | 4 + .../src/planner/plans/constant_table_scan.rs | 4 + .../sql/src/planner/plans/dummy_table_scan.rs | 4 + .../sql/src/planner/plans/eval_scalar.rs | 7 + src/query/sql/src/planner/plans/exchange.rs | 3 + .../sql/src/planner/plans/expression_scan.rs | 3 + src/query/sql/src/planner/plans/filter.rs | 7 + src/query/sql/src/planner/plans/join.rs | 25 +- src/query/sql/src/planner/plans/limit.rs | 3 + src/query/sql/src/planner/plans/mutation.rs | 3 + src/query/sql/src/planner/plans/operator.rs | 837 +----------------- src/query/sql/src/planner/plans/optimize.rs | 3 + .../sql/src/planner/plans/project_set.rs | 4 + src/query/sql/src/planner/plans/r_cte_scan.rs | 3 + .../sql/src/planner/plans/scalar_expr.rs | 13 +- src/query/sql/src/planner/plans/scan.rs | 3 + src/query/sql/src/planner/plans/sort.rs | 3 + src/query/sql/src/planner/plans/udaf.rs | 3 + src/query/sql/src/planner/plans/udf.rs | 7 + src/query/sql/src/planner/plans/union_all.rs | 4 + src/query/sql/src/planner/plans/window.rs | 16 + 27 files changed, 155 insertions(+), 845 deletions(-) diff --git a/src/query/sql/src/planner/format/display.rs b/src/query/sql/src/planner/format/display.rs index 3f8d8efa18c71..df099b5cbe4ae 100644 --- a/src/query/sql/src/planner/format/display.rs +++ b/src/query/sql/src/planner/format/display.rs @@ -157,7 +157,7 @@ where tree.children.extend(stats); } - let subquerys = op.get_subquery(vec![]); + let mut subquerys = op.collect_subquery(); if !subquerys.is_empty() { let subquerys = subquerys .into_iter() diff --git a/src/query/sql/src/planner/optimizer/ir/expr/extract.rs b/src/query/sql/src/planner/optimizer/ir/expr/extract.rs index 90d73478be83c..918617e2e6ba1 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/extract.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/extract.rs @@ -22,8 +22,8 @@ use crate::optimizer::ir::expr::SExpr; use crate::optimizer::ir::Group; use crate::optimizer::ir::Memo; use crate::plans::Operator; +use crate::plans::OperatorRef; use crate::plans::RelOp; -use crate::plans::RelOperator; /// A matcher used to describe a pattern to be matched. pub enum Matcher { @@ -36,7 +36,7 @@ pub enum Matcher { /// A pattern to match an operator with a predicate. MatchFn { /// The function to match the operator. - predicate: Box bool + 'static>, + predicate: Box bool + 'static>, children: Vec, }, /// A leaf pattern to match any node. @@ -91,8 +91,8 @@ impl Matcher { } } - /// Check if the `RelOperator` can be matched by the `Matcher`. - pub fn matches_op(&self, op: &RelOperator) -> bool { + /// Check if the `OperatorRef` can be matched by the `Matcher`. + pub fn matches_op(&self, op: &OperatorRef) -> bool { match self { Matcher::MatchOp { op_type, children } => { op.rel_op() == *op_type && op.arity() == children.len() diff --git a/src/query/sql/src/planner/optimizer/ir/expr/m_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/m_expr.rs index 825e3160c7fe3..bb50cff6b3443 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/m_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/m_expr.rs @@ -23,7 +23,7 @@ use crate::optimizer::ir::Memo; use crate::optimizer::optimizers::rule::AppliedRules; use crate::optimizer::optimizers::rule::RulePtr; use crate::optimizer::optimizers::rule::TransformResult; -use crate::plans::RelOperator; +use crate::plans::OperatorRef; use crate::IndexType; /// `MExpr` is abbreviation of multiple expression, which is the representation of relational @@ -35,7 +35,7 @@ pub struct MExpr { // index of current `MExpr` within a `Group` pub(crate) index: IndexType, - pub(crate) plan: Arc, + pub(crate) plan: OperatorRef, pub(crate) children: Vec, // Disable rules for current `MExpr` @@ -46,7 +46,7 @@ impl MExpr { pub fn new( group_index: IndexType, index: IndexType, - plan: Arc, + plan: OperatorRef, children: Vec, applied_rules: AppliedRules, ) -> Self { diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 4900fe5167077..592699d877b67 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -28,6 +28,7 @@ use crate::optimizer::optimizers::rule::AppliedRules; use crate::optimizer::optimizers::rule::RuleID; use crate::plans::Exchange; use crate::plans::Operator; +use crate::plans::OperatorRef; use crate::plans::RelOperator; use crate::plans::Scan; use crate::plans::WindowFuncType; @@ -43,7 +44,7 @@ use crate::IndexType; Debug(bound = false, attrs = "#[recursive::recursive]") )] pub struct SExpr { - pub plan: Arc, + pub plan: OperatorRef, pub(crate) children: Vec>, pub(crate) original_group: Option, @@ -67,7 +68,7 @@ pub struct SExpr { impl SExpr { pub fn create( - plan: Arc, + plan: OperatorRef, children: impl Into>>, original_group: Option, rel_prop: Option>, @@ -83,12 +84,12 @@ impl SExpr { } } - pub fn create_unary(plan: Arc, child: impl Into>) -> Self { + pub fn create_unary(plan: OperatorRef, child: impl Into>) -> Self { Self::create(plan, [child.into()], None, None, None) } pub fn create_binary( - plan: Arc, + plan: OperatorRef, left_child: impl Into>, right_child: impl Into>, ) -> Self { @@ -115,7 +116,7 @@ impl SExpr { Self::create(plan, [self.clone()], None, None, None) } - pub fn plan(&self) -> &RelOperator { + pub fn plan(&self) -> &OperatorRef { &self.plan } diff --git a/src/query/sql/src/planner/plans/aggregate.rs b/src/query/sql/src/planner/plans/aggregate.rs index fe3611a29f18f..7f884f9cb98e4 100644 --- a/src/query/sql/src/planner/plans/aggregate.rs +++ b/src/query/sql/src/planner/plans/aggregate.rs @@ -179,6 +179,12 @@ impl Operator for Aggregate { RelOp::Aggregate } + fn scalar_expr_iter(&self) -> Box> { + let iter = self.group_items.iter().map(|expr| &expr.scalar); + let iter = iter.chain(self.aggregate_functions.iter().map(|expr| &expr.scalar)); + Box::new(iter) + } + fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result { let input_physical_prop = rel_expr.derive_physical_prop_child(0)?; @@ -377,4 +383,8 @@ impl Operator for Aggregate { Ok(children_required) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } diff --git a/src/query/sql/src/planner/plans/async_function.rs b/src/query/sql/src/planner/plans/async_function.rs index 4f2c714ebad0b..2931213ab7ba0 100644 --- a/src/query/sql/src/planner/plans/async_function.rs +++ b/src/query/sql/src/planner/plans/async_function.rs @@ -98,4 +98,8 @@ impl Operator for AsyncFunction { ) -> Result>> { Ok(vec![vec![required.clone()]]) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } diff --git a/src/query/sql/src/planner/plans/cache_scan.rs b/src/query/sql/src/planner/plans/cache_scan.rs index b48e6ae20ef98..ef99f185199ba 100644 --- a/src/query/sql/src/planner/plans/cache_scan.rs +++ b/src/query/sql/src/planner/plans/cache_scan.rs @@ -122,4 +122,8 @@ impl Operator for CacheScan { required.distribution = Distribution::Serial; Ok(required.clone()) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } diff --git a/src/query/sql/src/planner/plans/constant_table_scan.rs b/src/query/sql/src/planner/plans/constant_table_scan.rs index 3dd153b4fc926..612cafe5d4fa9 100644 --- a/src/query/sql/src/planner/plans/constant_table_scan.rs +++ b/src/query/sql/src/planner/plans/constant_table_scan.rs @@ -249,4 +249,8 @@ impl Operator for ConstantTableScan { "ConstantTableScan cannot compute required property for children".to_string(), )) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } diff --git a/src/query/sql/src/planner/plans/dummy_table_scan.rs b/src/query/sql/src/planner/plans/dummy_table_scan.rs index ba3b09e980a80..f89d9a9b8f480 100644 --- a/src/query/sql/src/planner/plans/dummy_table_scan.rs +++ b/src/query/sql/src/planner/plans/dummy_table_scan.rs @@ -46,6 +46,10 @@ impl Operator for DummyTableScan { fn arity(&self) -> usize { 0 } + + fn as_any(&self) -> &dyn std::any::Any { + self + } fn derive_relational_prop(&self, _rel_expr: &RelExpr) -> Result> { Ok(Arc::new(RelationalProperty { diff --git a/src/query/sql/src/planner/plans/eval_scalar.rs b/src/query/sql/src/planner/plans/eval_scalar.rs index fc108fbbdaadc..05a1c7f5c376c 100644 --- a/src/query/sql/src/planner/plans/eval_scalar.rs +++ b/src/query/sql/src/planner/plans/eval_scalar.rs @@ -79,10 +79,17 @@ impl EvalScalar { } impl Operator for EvalScalar { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::EvalScalar } + fn scalar_expr_iter(&self) -> Box> { + Box::new(self.items.iter().map(|expr| &expr.scalar)) + } + fn derive_relational_prop(&self, rel_expr: &RelExpr) -> Result> { let input_prop = rel_expr.derive_relational_prop_child(0)?; diff --git a/src/query/sql/src/planner/plans/exchange.rs b/src/query/sql/src/planner/plans/exchange.rs index a7aca885b2ed1..286f8b63cb61e 100644 --- a/src/query/sql/src/planner/plans/exchange.rs +++ b/src/query/sql/src/planner/plans/exchange.rs @@ -34,6 +34,9 @@ pub enum Exchange { } impl Operator for Exchange { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::Exchange } diff --git a/src/query/sql/src/planner/plans/expression_scan.rs b/src/query/sql/src/planner/plans/expression_scan.rs index f439a6ebbfc55..ab0799ec2b0b6 100644 --- a/src/query/sql/src/planner/plans/expression_scan.rs +++ b/src/query/sql/src/planner/plans/expression_scan.rs @@ -75,6 +75,9 @@ impl std::hash::Hash for ExpressionScan { } impl Operator for ExpressionScan { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::ExpressionScan } diff --git a/src/query/sql/src/planner/plans/filter.rs b/src/query/sql/src/planner/plans/filter.rs index d6b6b8beb73f6..aa2aec09df0d4 100644 --- a/src/query/sql/src/planner/plans/filter.rs +++ b/src/query/sql/src/planner/plans/filter.rs @@ -45,10 +45,17 @@ impl Filter { } impl Operator for Filter { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::Filter } + fn scalar_expr_iter(&self) -> Box> { + Box::new(self.predicates.iter()) + } + fn derive_relational_prop(&self, rel_expr: &RelExpr) -> Result> { let input_prop = rel_expr.derive_relational_prop_child(0)?; let output_columns = input_prop.output_columns.clone(); diff --git a/src/query/sql/src/planner/plans/join.rs b/src/query/sql/src/planner/plans/join.rs index 38ead2358aad5..b5d1b0dca5ec2 100644 --- a/src/query/sql/src/planner/plans/join.rs +++ b/src/query/sql/src/planner/plans/join.rs @@ -502,16 +502,6 @@ impl Join { Ok(()) } - - pub fn has_subquery(&self) -> bool { - self.equi_conditions - .iter() - .any(|condition| condition.left.has_subquery() || condition.right.has_subquery()) - || self - .non_equi_conditions - .iter() - .any(|expr| expr.has_subquery()) - } } impl Operator for Join { @@ -523,6 +513,17 @@ impl Operator for Join { 2 } + fn scalar_expr_iter(&self) -> Box> { + let iter = self.equi_conditions.iter().map(|condition| &condition.left); + let iter = iter.chain( + self.equi_conditions + .iter() + .map(|condition| &condition.right), + ); + let iter = iter.chain(self.non_equi_conditions.iter()); + Box::new(iter) + } + fn derive_relational_prop(&self, rel_expr: &RelExpr) -> Result> { let left_prop = rel_expr.derive_relational_prop_child(0)?; let right_prop = rel_expr.derive_relational_prop_child(1)?; @@ -798,6 +799,10 @@ impl Operator for Join { Ok(children_required) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } fn evaluate_by_histogram( diff --git a/src/query/sql/src/planner/plans/limit.rs b/src/query/sql/src/planner/plans/limit.rs index 8b4460d0edd1d..0060de4f65155 100644 --- a/src/query/sql/src/planner/plans/limit.rs +++ b/src/query/sql/src/planner/plans/limit.rs @@ -57,6 +57,9 @@ impl Limit { } impl Operator for Limit { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::Limit } diff --git a/src/query/sql/src/planner/plans/mutation.rs b/src/query/sql/src/planner/plans/mutation.rs index db274b813b102..e270d05984932 100644 --- a/src/query/sql/src/planner/plans/mutation.rs +++ b/src/query/sql/src/planner/plans/mutation.rs @@ -197,6 +197,9 @@ impl std::hash::Hash for Mutation { } impl Operator for Mutation { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::MergeInto } diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 3d3a67518fed0..2ceac7e6b661f 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -47,6 +47,9 @@ use crate::plans::Udf; use crate::plans::UnionAll; use crate::plans::Window; use crate::plans::WindowFuncType; +use crate::ScalarExpr; + +pub type OperatorRef = Arc; pub trait Operator { /// Get relational operator kind @@ -57,6 +60,25 @@ pub trait Operator { 1 } + fn as_any(&self) -> &dyn std::any::Any; + + fn scalar_expr_iter(&self) -> Box> { + Box::new(std::iter::empty()) + } + + fn has_subquery(&self) -> bool { + let mut iter = self.scalar_expr_iter(); + iter.any(|expr| expr.has_subquery()) + } + + fn collect_subquery(&self) -> Vec { + let mut subqueries = Vec::new(); + for scalar in self.scalar_expr_iter() { + scalar.collect_subquery(&mut subqueries); + } + subqueries + } + /// Derive relational property fn derive_relational_prop(&self, _rel_expr: &RelExpr) -> Result> { Ok(Arc::new(RelationalProperty::default())) @@ -123,818 +145,3 @@ pub enum RelOp { // Pattern Pattern, } - -/// Relational operators -#[derive(Educe)] -#[educe( - PartialEq(bound = false, attrs = "#[recursive::recursive]"), - Eq, - Hash(bound = false, attrs = "#[recursive::recursive]"), - Clone(bound = false, attrs = "#[recursive::recursive]"), - Debug(bound = false, attrs = "#[recursive::recursive]") -)] -pub enum RelOperator { - Scan(Scan), - Join(Join), - EvalScalar(EvalScalar), - Filter(Filter), - Aggregate(Aggregate), - Sort(Sort), - Limit(Limit), - Exchange(Exchange), - UnionAll(UnionAll), - DummyTableScan(DummyTableScan), - Window(Window), - ProjectSet(ProjectSet), - ConstantTableScan(ConstantTableScan), - ExpressionScan(ExpressionScan), - CacheScan(CacheScan), - Udf(Udf), - RecursiveCteScan(RecursiveCteScan), - AsyncFunction(AsyncFunction), - Mutation(Mutation), - CompactBlock(OptimizeCompactBlock), - MutationSource(MutationSource), -} - -impl RelOperator { - pub fn has_subquery(&self) -> bool { - match self { - RelOperator::Scan(_) - | RelOperator::Limit(_) - | RelOperator::Exchange(_) - | RelOperator::UnionAll(_) - | RelOperator::Sort(_) - | RelOperator::DummyTableScan(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::CacheScan(_) - | RelOperator::AsyncFunction(_) - | RelOperator::RecursiveCteScan(_) - | RelOperator::Mutation(_) - | RelOperator::CompactBlock(_) => false, - RelOperator::Join(op) => op.has_subquery(), - RelOperator::EvalScalar(op) => op.items.iter().any(|expr| expr.scalar.has_subquery()), - RelOperator::Filter(op) => op.predicates.iter().any(|expr| expr.has_subquery()), - RelOperator::Aggregate(op) => { - op.group_items.iter().any(|expr| expr.scalar.has_subquery()) - || op - .aggregate_functions - .iter() - .any(|expr| expr.scalar.has_subquery()) - } - RelOperator::Window(op) => { - op.order_by - .iter() - .any(|o| o.order_by_item.scalar.has_subquery()) - || op - .partition_by - .iter() - .any(|expr| expr.scalar.has_subquery()) - || match &op.function { - WindowFuncType::Aggregate(agg) => { - agg.exprs().any(|expr| expr.has_subquery()) - } - _ => false, - } - } - RelOperator::ProjectSet(op) => op.srfs.iter().any(|expr| expr.scalar.has_subquery()), - RelOperator::Udf(op) => op.items.iter().any(|expr| expr.scalar.has_subquery()), - RelOperator::MutationSource(_) => false, - } - } - - pub fn get_subquery(&self, mut result: Vec) -> Vec { - match self { - RelOperator::Scan(_) - | RelOperator::Limit(_) - | RelOperator::Exchange(_) - | RelOperator::UnionAll(_) - | RelOperator::Sort(_) - | RelOperator::DummyTableScan(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::CacheScan(_) - | RelOperator::AsyncFunction(_) - | RelOperator::RecursiveCteScan(_) - | RelOperator::Mutation(_) - | RelOperator::CompactBlock(_) - | RelOperator::MutationSource(_) => (), - RelOperator::Join(op) => { - for condition in &op.equi_conditions { - result = condition.left.get_subquery(result); - result = condition.right.get_subquery(result); - } - for expr in &op.non_equi_conditions { - result = expr.get_subquery(result); - } - } - RelOperator::EvalScalar(op) => { - for item in &op.items { - result = item.scalar.get_subquery(result); - } - } - RelOperator::Filter(op) => { - for pred in &op.predicates { - result = pred.get_subquery(result); - } - } - RelOperator::Aggregate(op) => { - for item in &op.group_items { - result = item.scalar.get_subquery(result); - } - for func in &op.aggregate_functions { - result = func.scalar.get_subquery(result); - } - } - RelOperator::Window(op) => { - for order in &op.order_by { - result = order.order_by_item.scalar.get_subquery(result); - } - for expr in &op.partition_by { - result = expr.scalar.get_subquery(result); - } - if let WindowFuncType::Aggregate(agg) = &op.function { - for expr in agg.exprs() { - result = expr.get_subquery(result); - } - } - } - RelOperator::ProjectSet(op) => { - for srf in &op.srfs { - result = srf.scalar.get_subquery(result); - } - } - RelOperator::Udf(op) => { - for item in &op.items { - result = item.scalar.get_subquery(result); - } - } - } - result - } -} - -impl Operator for RelOperator { - fn rel_op(&self) -> RelOp { - match self { - RelOperator::Scan(rel_op) => rel_op.rel_op(), - RelOperator::Join(rel_op) => rel_op.rel_op(), - RelOperator::EvalScalar(rel_op) => rel_op.rel_op(), - RelOperator::Filter(rel_op) => rel_op.rel_op(), - RelOperator::Aggregate(rel_op) => rel_op.rel_op(), - RelOperator::Sort(rel_op) => rel_op.rel_op(), - RelOperator::Limit(rel_op) => rel_op.rel_op(), - RelOperator::Exchange(rel_op) => rel_op.rel_op(), - RelOperator::UnionAll(rel_op) => rel_op.rel_op(), - RelOperator::DummyTableScan(rel_op) => rel_op.rel_op(), - RelOperator::ProjectSet(rel_op) => rel_op.rel_op(), - RelOperator::Window(rel_op) => rel_op.rel_op(), - RelOperator::ConstantTableScan(rel_op) => rel_op.rel_op(), - RelOperator::ExpressionScan(rel_op) => rel_op.rel_op(), - RelOperator::CacheScan(rel_op) => rel_op.rel_op(), - RelOperator::Udf(rel_op) => rel_op.rel_op(), - RelOperator::RecursiveCteScan(rel_op) => rel_op.rel_op(), - RelOperator::AsyncFunction(rel_op) => rel_op.rel_op(), - RelOperator::Mutation(rel_op) => rel_op.rel_op(), - RelOperator::CompactBlock(rel_op) => rel_op.rel_op(), - RelOperator::MutationSource(rel_op) => rel_op.rel_op(), - } - } - - fn arity(&self) -> usize { - match self { - RelOperator::Scan(rel_op) => rel_op.arity(), - RelOperator::Join(rel_op) => rel_op.arity(), - RelOperator::EvalScalar(rel_op) => rel_op.arity(), - RelOperator::Filter(rel_op) => rel_op.arity(), - RelOperator::Aggregate(rel_op) => rel_op.arity(), - RelOperator::Sort(rel_op) => rel_op.arity(), - RelOperator::Limit(rel_op) => rel_op.arity(), - RelOperator::Exchange(rel_op) => rel_op.arity(), - RelOperator::UnionAll(rel_op) => rel_op.arity(), - RelOperator::DummyTableScan(rel_op) => rel_op.arity(), - RelOperator::Window(rel_op) => rel_op.arity(), - RelOperator::ProjectSet(rel_op) => rel_op.arity(), - RelOperator::ConstantTableScan(rel_op) => rel_op.arity(), - RelOperator::ExpressionScan(rel_op) => rel_op.arity(), - RelOperator::CacheScan(rel_op) => rel_op.arity(), - RelOperator::Udf(rel_op) => rel_op.arity(), - RelOperator::RecursiveCteScan(rel_op) => rel_op.arity(), - RelOperator::AsyncFunction(rel_op) => rel_op.arity(), - RelOperator::Mutation(rel_op) => rel_op.arity(), - RelOperator::CompactBlock(rel_op) => rel_op.arity(), - RelOperator::MutationSource(rel_op) => rel_op.arity(), - } - } - - fn derive_relational_prop(&self, rel_expr: &RelExpr) -> Result> { - match self { - RelOperator::Scan(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Join(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::EvalScalar(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Filter(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Aggregate(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Sort(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Limit(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Exchange(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::UnionAll(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::DummyTableScan(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::ProjectSet(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Window(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::ConstantTableScan(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::ExpressionScan(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::CacheScan(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Udf(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::RecursiveCteScan(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::AsyncFunction(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::Mutation(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::CompactBlock(rel_op) => rel_op.derive_relational_prop(rel_expr), - RelOperator::MutationSource(rel_op) => rel_op.derive_relational_prop(rel_expr), - } - } - - fn derive_physical_prop(&self, rel_expr: &RelExpr) -> Result { - match self { - RelOperator::Scan(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Join(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::EvalScalar(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Filter(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Aggregate(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Sort(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Limit(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Exchange(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::UnionAll(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::DummyTableScan(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::ProjectSet(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Window(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::ConstantTableScan(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::ExpressionScan(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::CacheScan(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Udf(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::RecursiveCteScan(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::AsyncFunction(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::Mutation(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::CompactBlock(rel_op) => rel_op.derive_physical_prop(rel_expr), - RelOperator::MutationSource(rel_op) => rel_op.derive_physical_prop(rel_expr), - } - } - - fn derive_stats(&self, rel_expr: &RelExpr) -> Result> { - match self { - RelOperator::Scan(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Join(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::EvalScalar(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Filter(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Aggregate(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Sort(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Limit(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Exchange(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::UnionAll(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::DummyTableScan(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::ProjectSet(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Window(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::ConstantTableScan(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::ExpressionScan(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::CacheScan(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Udf(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::RecursiveCteScan(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::AsyncFunction(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::Mutation(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::CompactBlock(rel_op) => rel_op.derive_stats(rel_expr), - RelOperator::MutationSource(rel_op) => rel_op.derive_stats(rel_expr), - } - } - - fn compute_required_prop_child( - &self, - ctx: Arc, - rel_expr: &RelExpr, - child_index: usize, - required: &RequiredProperty, - ) -> Result { - match self { - RelOperator::Scan(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Join(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::EvalScalar(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Filter(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Aggregate(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Sort(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Limit(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Exchange(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::UnionAll(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::DummyTableScan(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Window(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::ProjectSet(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::ConstantTableScan(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::ExpressionScan(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::CacheScan(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Udf(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::RecursiveCteScan(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::AsyncFunction(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::Mutation(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::CompactBlock(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - RelOperator::MutationSource(rel_op) => { - rel_op.compute_required_prop_child(ctx, rel_expr, child_index, required) - } - } - } - - fn compute_required_prop_children( - &self, - ctx: Arc, - rel_expr: &RelExpr, - required: &RequiredProperty, - ) -> Result>> { - match self { - RelOperator::Scan(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Join(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::EvalScalar(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Filter(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Aggregate(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Sort(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Limit(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Exchange(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::UnionAll(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::DummyTableScan(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Window(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::ProjectSet(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::ConstantTableScan(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::ExpressionScan(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::CacheScan(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Udf(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::RecursiveCteScan(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::AsyncFunction(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::Mutation(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::CompactBlock(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - RelOperator::MutationSource(rel_op) => { - rel_op.compute_required_prop_children(ctx, rel_expr, required) - } - } - } -} - -impl From for RelOperator { - fn from(v: Scan) -> Self { - Self::Scan(v) - } -} - -impl TryFrom for Scan { - type Error = ErrorCode; - - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Scan(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Scan", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Join) -> Self { - Self::Join(v) - } -} - -impl TryFrom for Join { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Join(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Join", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: EvalScalar) -> Self { - Self::EvalScalar(v) - } -} - -impl TryFrom for EvalScalar { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::EvalScalar(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to EvalScalar", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Filter) -> Self { - Self::Filter(v) - } -} - -impl TryFrom for Filter { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Filter(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Filter", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Aggregate) -> Self { - Self::Aggregate(v) - } -} - -impl TryFrom for Aggregate { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Aggregate(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Aggregate", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Window) -> Self { - Self::Window(v) - } -} - -impl TryFrom for Window { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Window(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Window", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Sort) -> Self { - Self::Sort(v) - } -} - -impl TryFrom for Sort { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Sort(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Sort", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Limit) -> Self { - Self::Limit(v) - } -} - -impl TryFrom for Limit { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Limit(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Limit", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Exchange) -> Self { - Self::Exchange(v) - } -} - -impl TryFrom for Exchange { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Exchange(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Exchange", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: UnionAll) -> Self { - Self::UnionAll(v) - } -} - -impl TryFrom for UnionAll { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::UnionAll(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to UnionAll", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: DummyTableScan) -> Self { - Self::DummyTableScan(v) - } -} - -impl TryFrom for DummyTableScan { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::DummyTableScan(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to DummyTableScan", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(value: ProjectSet) -> Self { - Self::ProjectSet(value) - } -} - -impl TryFrom for ProjectSet { - type Error = ErrorCode; - - fn try_from(value: RelOperator) -> std::result::Result { - if let RelOperator::ProjectSet(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to ProjectSet", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(value: ConstantTableScan) -> Self { - Self::ConstantTableScan(value) - } -} - -impl From for RelOperator { - fn from(value: ExpressionScan) -> Self { - Self::ExpressionScan(value) - } -} - -impl TryFrom for ConstantTableScan { - type Error = ErrorCode; - - fn try_from(value: RelOperator) -> std::result::Result { - if let RelOperator::ConstantTableScan(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to ConstantTableScan", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(value: Udf) -> Self { - Self::Udf(value) - } -} - -impl TryFrom for Udf { - type Error = ErrorCode; - - fn try_from(value: RelOperator) -> std::result::Result { - if let RelOperator::Udf(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to Udf", - value.rel_op() - ))) - } - } -} - -impl TryFrom for RecursiveCteScan { - type Error = ErrorCode; - - fn try_from(value: RelOperator) -> std::result::Result { - if let RelOperator::RecursiveCteScan(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to RecursiveCteScan", - value.rel_op() - ))) - } - } -} -impl From for RelOperator { - fn from(value: AsyncFunction) -> Self { - Self::AsyncFunction(value) - } -} - -impl TryFrom for AsyncFunction { - type Error = ErrorCode; - - fn try_from(value: RelOperator) -> std::result::Result { - if let RelOperator::AsyncFunction(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to AsyncFunction", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: Mutation) -> Self { - Self::Mutation(v) - } -} - -impl TryFrom for Mutation { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::Mutation(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to MergeInto", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: OptimizeCompactBlock) -> Self { - Self::CompactBlock(v) - } -} - -impl TryFrom for OptimizeCompactBlock { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::CompactBlock(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to OptimizeCompactBlock", - value.rel_op() - ))) - } - } -} - -impl From for RelOperator { - fn from(v: MutationSource) -> Self { - Self::MutationSource(v) - } -} - -impl TryFrom for MutationSource { - type Error = ErrorCode; - fn try_from(value: RelOperator) -> Result { - if let RelOperator::MutationSource(value) = value { - Ok(value) - } else { - Err(ErrorCode::Internal(format!( - "Cannot downcast {:?} to MutationSource", - value.rel_op() - ))) - } - } -} diff --git a/src/query/sql/src/planner/plans/optimize.rs b/src/query/sql/src/planner/plans/optimize.rs index b71c1f2c653cf..dffec7d80be61 100644 --- a/src/query/sql/src/planner/plans/optimize.rs +++ b/src/query/sql/src/planner/plans/optimize.rs @@ -44,6 +44,9 @@ pub struct OptimizeCompactBlock { } impl Operator for OptimizeCompactBlock { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::CompactBlock } diff --git a/src/query/sql/src/planner/plans/project_set.rs b/src/query/sql/src/planner/plans/project_set.rs index 8efcb0c93fb29..2ef3602480f9a 100644 --- a/src/query/sql/src/planner/plans/project_set.rs +++ b/src/query/sql/src/planner/plans/project_set.rs @@ -47,6 +47,10 @@ impl Operator for ProjectSet { RelOp::ProjectSet } + fn scalar_expr_iter(&self) -> Box> { + Box::new(self.srfs.iter().map(|expr| &expr.scalar)) + } + fn derive_relational_prop( &self, rel_expr: &RelExpr, diff --git a/src/query/sql/src/planner/plans/r_cte_scan.rs b/src/query/sql/src/planner/plans/r_cte_scan.rs index b00aff2993c7e..79d5c517578df 100644 --- a/src/query/sql/src/planner/plans/r_cte_scan.rs +++ b/src/query/sql/src/planner/plans/r_cte_scan.rs @@ -56,6 +56,9 @@ impl Hash for RecursiveCteScan { } impl Operator for RecursiveCteScan { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::RecursiveCteScan } diff --git a/src/query/sql/src/planner/plans/scalar_expr.rs b/src/query/sql/src/planner/plans/scalar_expr.rs index 5563815cc4347..675410c2813fd 100644 --- a/src/query/sql/src/planner/plans/scalar_expr.rs +++ b/src/query/sql/src/planner/plans/scalar_expr.rs @@ -450,21 +450,20 @@ impl ScalarExpr { has_subquery.has_subquery } - pub fn get_subquery(&self, result: Vec) -> Vec { - struct GetSubquery { - subquerys: Vec, + pub fn collect_subquery(&self, result: &mut Vec) { + struct CollectSubQuery<'a> { + subquerys: &'a mut Vec, } - impl<'a> Visitor<'a> for GetSubquery { + impl<'a> Visitor<'a> for CollectSubQuery<'a> { fn visit_subquery(&mut self, subquery: &'a SubqueryExpr) -> Result<()> { self.subquerys.push(subquery.clone()); Ok(()) } } - let mut get_subquery = GetSubquery { subquerys: result }; - get_subquery.visit(self).unwrap(); - get_subquery.subquerys + let mut visitor = CollectSubQuery { subquerys: result }; + visitor.visit(self).unwrap(); } } diff --git a/src/query/sql/src/planner/plans/scan.rs b/src/query/sql/src/planner/plans/scan.rs index 2f2227bf16a96..a50faea4cd562 100644 --- a/src/query/sql/src/planner/plans/scan.rs +++ b/src/query/sql/src/planner/plans/scan.rs @@ -193,6 +193,9 @@ impl std::hash::Hash for Scan { } impl Operator for Scan { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::Scan } diff --git a/src/query/sql/src/planner/plans/sort.rs b/src/query/sql/src/planner/plans/sort.rs index 7ef783ab3ac43..4a2de263f55c3 100644 --- a/src/query/sql/src/planner/plans/sort.rs +++ b/src/query/sql/src/planner/plans/sort.rs @@ -94,6 +94,9 @@ pub struct SortItem { } impl Operator for Sort { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::Sort } diff --git a/src/query/sql/src/planner/plans/udaf.rs b/src/query/sql/src/planner/plans/udaf.rs index 79553335a12a6..b89b3c09b857f 100644 --- a/src/query/sql/src/planner/plans/udaf.rs +++ b/src/query/sql/src/planner/plans/udaf.rs @@ -45,6 +45,9 @@ impl Udaf { } impl Operator for Udaf { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::Udaf } diff --git a/src/query/sql/src/planner/plans/udf.rs b/src/query/sql/src/planner/plans/udf.rs index fb99a3a1e35d3..5cb43bb743ed7 100644 --- a/src/query/sql/src/planner/plans/udf.rs +++ b/src/query/sql/src/planner/plans/udf.rs @@ -45,10 +45,17 @@ impl Udf { } impl Operator for Udf { + fn as_any(&self) -> &dyn std::any::Any { + self + } fn rel_op(&self) -> RelOp { RelOp::Udf } + fn scalar_expr_iter(&self) -> Box> { + Box::new(self.items.iter().map(|expr| &expr.scalar)) + } + fn derive_relational_prop(&self, rel_expr: &RelExpr) -> Result> { let input_prop = rel_expr.derive_relational_prop_child(0)?; diff --git a/src/query/sql/src/planner/plans/union_all.rs b/src/query/sql/src/planner/plans/union_all.rs index 0e64c71655c9a..c30b0083d4c37 100644 --- a/src/query/sql/src/planner/plans/union_all.rs +++ b/src/query/sql/src/planner/plans/union_all.rs @@ -195,4 +195,8 @@ impl Operator for UnionAll { Ok(children_required) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } diff --git a/src/query/sql/src/planner/plans/window.rs b/src/query/sql/src/planner/plans/window.rs index c4f7f0a2b3cc9..f026384671df4 100644 --- a/src/query/sql/src/planner/plans/window.rs +++ b/src/query/sql/src/planner/plans/window.rs @@ -114,6 +114,18 @@ impl Operator for Window { RelOp::Window } + fn scalar_expr_iter(&self) -> Box> { + let iter = self.order_by.iter().map(|o| &o.order_by_item.scalar); + let iter = iter.chain(self.partition_by.iter().map(|expr| &expr.scalar)); + let iter = iter.chain(self.arguments.iter().map(|expr| &expr.scalar)); + + if let WindowFuncType::Aggregate(agg) = &self.function { + Box::new(iter.chain(agg.exprs().iter().map(|expr| &expr.scalar))) + } else { + iter + } + } + fn compute_required_prop_child( &self, _ctx: Arc, @@ -175,6 +187,10 @@ impl Operator for Window { fn derive_stats(&self, rel_expr: &RelExpr) -> Result> { rel_expr.derive_cardinality_child(0) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } #[derive(Default, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] From bfac420f5e371b8650b604e0397c749e086d4025 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Wed, 2 Jul 2025 03:39:48 +0000 Subject: [PATCH 03/14] update --- Cargo.lock | 1 + src/query/sql/Cargo.toml | 1 + .../sql/src/executor/physical_plan_builder.rs | 99 +++++++++---------- .../physical_aggregate_final.rs | 17 +++- .../physical_plans/physical_async_func.rs | 20 ++++ .../physical_plans/physical_cache_scan.rs | 19 ++++ .../physical_plans/physical_compact_source.rs | 22 +++++ .../physical_constant_table_scan.rs | 20 ++++ .../physical_plans/physical_eval_scalar.rs | 19 ++++ .../physical_plans/physical_exchange.rs | 20 ++++ .../physical_expression_scan.rs | 20 ++++ .../physical_plans/physical_filter.rs | 19 ++++ .../executor/physical_plans/physical_join.rs | 14 +++ .../executor/physical_plans/physical_limit.rs | 18 ++++ .../physical_plans/physical_mutation.rs | 22 +++++ .../physical_mutation_source.rs | 19 ++++ .../physical_plans/physical_project_set.rs | 19 ++++ .../physical_plans/physical_r_cte_scan.rs | 21 ++++ .../executor/physical_plans/physical_sort.rs | 17 ++++ .../physical_plans/physical_table_scan.rs | 30 ++++++ .../executor/physical_plans/physical_udf.rs | 18 ++++ .../physical_plans/physical_union_all.rs | 19 ++++ .../physical_plans/physical_window.rs | 19 ++++ .../src/planner/optimizer/ir/expr/s_expr.rs | 1 - src/query/sql/src/planner/plans/mod.rs | 4 +- src/query/sql/src/planner/plans/operator.rs | 34 ++++++- 26 files changed, 474 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3f731b45b8a4..cb9e23b02c19d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4193,6 +4193,7 @@ dependencies = [ "itertools 0.13.0", "jsonb", "log", + "match-template", "num-derive", "num-traits", "opendal", diff --git a/src/query/sql/Cargo.toml b/src/query/sql/Cargo.toml index 1ced7b5eb052e..4f10fe2440445 100644 --- a/src/query/sql/Cargo.toml +++ b/src/query/sql/Cargo.toml @@ -40,6 +40,7 @@ databend-storages-common-table-meta = { workspace = true } ahash = { workspace = true, features = ["no-rng"] } anyhow = { workspace = true } async-backtrace = { workspace = true } +match-template = { workspace = true } async-recursion = { workspace = true } async-trait = { workspace = true } chrono = { workspace = true } diff --git a/src/query/sql/src/executor/physical_plan_builder.rs b/src/query/sql/src/executor/physical_plan_builder.rs index c50adc9f30db4..1d449404d9d42 100644 --- a/src/query/sql/src/executor/physical_plan_builder.rs +++ b/src/query/sql/src/executor/physical_plan_builder.rs @@ -77,59 +77,10 @@ impl PhysicalPlanBuilder { ) -> Result { // Build stat info. let stat_info = self.build_plan_stat_info(s_expr)?; - match s_expr.plan() { - RelOperator::Scan(scan) => self.build_table_scan(scan, required, stat_info).await, - RelOperator::DummyTableScan(_) => self.build_dummy_table_scan().await, - RelOperator::Join(join) => self.build_join(s_expr, join, required, stat_info).await, - RelOperator::EvalScalar(eval_scalar) => { - self.build_eval_scalar(s_expr, eval_scalar, required, stat_info) - .await - } - RelOperator::Filter(filter) => { - self.build_filter(s_expr, filter, required, stat_info).await - } - RelOperator::Aggregate(agg) => { - self.build_aggregate(s_expr, agg, required, stat_info).await - } - RelOperator::Window(window) => { - self.build_window(s_expr, window, required, stat_info).await - } - RelOperator::Sort(sort) => self.build_sort(s_expr, sort, required, stat_info).await, - RelOperator::Limit(limit) => self.build_limit(s_expr, limit, required, stat_info).await, - RelOperator::Exchange(exchange) => { - self.build_exchange(s_expr, exchange, required).await - } - RelOperator::UnionAll(union_all) => { - self.build_union_all(s_expr, union_all, required, stat_info) - .await - } - RelOperator::ProjectSet(project_set) => { - self.build_project_set(s_expr, project_set, required, stat_info) - .await - } - RelOperator::ConstantTableScan(scan) => { - self.build_constant_table_scan(scan, required).await - } - RelOperator::ExpressionScan(scan) => { - self.build_expression_scan(s_expr, scan, required).await - } - RelOperator::CacheScan(scan) => self.build_cache_scan(scan, required).await, - RelOperator::Udf(udf) => self.build_udf(s_expr, udf, required, stat_info).await, - RelOperator::RecursiveCteScan(scan) => { - self.build_recursive_cte_scan(scan, stat_info).await - } - RelOperator::AsyncFunction(async_func) => { - self.build_async_func(s_expr, async_func, required, stat_info) - .await - } - RelOperator::Mutation(mutation) => { - self.build_mutation(s_expr, mutation, required).await - } - RelOperator::MutationSource(mutation_source) => { - self.build_mutation_source(mutation_source).await - } - RelOperator::CompactBlock(compact) => self.build_compact_block(compact).await, - } + with_match_rel_op!(|TY| match s_expr.plan().rel_op() { + crate::plans::RelOp::TY => TY::build(self, s_expr, required, stat_info).await, + _ => Err(ErrorCode::Internal("Unsupported operator")), + }) } pub fn set_mutation_build_info(&mut self, mutation_build_info: MutationBuildInfo) { @@ -150,3 +101,45 @@ pub struct MutationBuildInfo { pub statistics: PartStatistics, pub table_meta_timestamps: TableMetaTimestamps, } + +#[async_trait::async_trait] +pub trait BuildPhysicalPlan { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result; +} + +#[macro_export] +macro_rules! with_match_rel_op { + (| $t:tt | $($tail:tt)*) => { + match_template::match_template! { + $t = [ + Scan => TableScan, + DummyTableScan => DummyTableScan, + ConstantTableScan => ConstantTableScan, + ExpressionScan => ExpressionScan, + CacheScan => CacheScan, + Join => Join, + EvalScalar => EvalScalar, + Filter => Filter, + Aggregate => Aggregate, + Sort => Sort, + Limit => Limit, + Exchange => Exchange, + UnionAll => UnionAll, + Window => Window, + ProjectSet => ProjectSet, + Udf => Udf, + AsyncFunction => AsyncFunction, + RecursiveCteScan => RecursiveCteScan, + MergeInto => MergeInto, + CompactBlock => CompactBlock, + MutationSource => MutationSource, + ], + $($tail)* + } + } +} diff --git a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs index d3511fbb8cdaa..900ac74625f6c 100644 --- a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs +++ b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs @@ -31,6 +31,7 @@ use crate::executor::physical_plans::Exchange; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::SExpr; +use crate::plans::Aggregate; use crate::plans::AggregateMode; use crate::plans::DummyTableScan; use crate::ColumnSet; @@ -70,11 +71,25 @@ impl AggregateFinal { } } +impl BuildPhysicalPlan for AggregateFinal { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr.plan().as_any().downcast_ref::().unwrap(); + builder + .build_aggregate(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_aggregate( &mut self, s_expr: &SExpr, - agg: &crate::plans::Aggregate, + agg: &Aggregate, mut required: ColumnSet, stat_info: PlanStatsInfo, ) -> Result { diff --git a/src/query/sql/src/executor/physical_plans/physical_async_func.rs b/src/query/sql/src/executor/physical_plans/physical_async_func.rs index 503a90dfac72f..8ca70abed28af 100644 --- a/src/query/sql/src/executor/physical_plans/physical_async_func.rs +++ b/src/query/sql/src/executor/physical_plans/physical_async_func.rs @@ -20,6 +20,7 @@ use databend_common_expression::DataSchemaRef; use databend_common_expression::DataSchemaRefExt; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::SExpr; @@ -62,6 +63,25 @@ pub struct AsyncFunctionDesc { pub func_arg: AsyncFunctionArgument, } +#[async_trait::async_trait] +impl BuildPhysicalPlan for AsyncFunction { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_async_func(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_async_func( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs b/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs index 98575dca5b3d5..7016c7a72f615 100644 --- a/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs @@ -16,6 +16,7 @@ use databend_common_exception::Result; use databend_common_expression::DataSchemaRef; use databend_common_expression::DataSchemaRefExt; +use crate::executor::explain::PlanStatsInfo; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::plans::CacheSource; @@ -35,11 +36,29 @@ impl CacheScan { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for CacheScan { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder.build_cache_scan(plan, required, stat_info).await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_cache_scan( &mut self, scan: &crate::plans::CacheScan, required: ColumnSet, + _stat_info: PlanStatsInfo, ) -> Result { // 1. Prune unused Columns. let used: ColumnSet = required.intersection(&scan.columns).cloned().collect(); diff --git a/src/query/sql/src/executor/physical_plans/physical_compact_source.rs b/src/query/sql/src/executor/physical_plans/physical_compact_source.rs index 70bb52b44da9a..fbdc082af9df4 100644 --- a/src/query/sql/src/executor/physical_plans/physical_compact_source.rs +++ b/src/query/sql/src/executor/physical_plans/physical_compact_source.rs @@ -23,6 +23,8 @@ use databend_common_expression::ColumnId; use databend_common_meta_app::schema::TableInfo; use databend_storages_common_table_meta::meta::TableMetaTimestamps; +use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::CommitSink; use crate::executor::physical_plans::CommitType; use crate::executor::physical_plans::Exchange; @@ -30,6 +32,9 @@ use crate::executor::physical_plans::FragmentKind; use crate::executor::physical_plans::MutationKind; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; +use crate::ColumnSet; + +pub struct CompactBlock; #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct CompactSource { @@ -40,6 +45,23 @@ pub struct CompactSource { pub table_meta_timestamps: TableMetaTimestamps, } +#[async_trait::async_trait] +impl BuildPhysicalPlan for CompactBlock { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + _required: ColumnSet, + _stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder.build_compact_source(plan).await + } +} + impl PhysicalPlanBuilder { pub async fn build_compact_block( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs b/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs index a67a9859348b7..96505c3470a37 100644 --- a/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs @@ -44,11 +44,31 @@ impl ConstantTableScan { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for ConstantTableScan { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_constant_table_scan(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_constant_table_scan( &mut self, scan: &crate::plans::ConstantTableScan, required: ColumnSet, + _stat_info: PlanStatsInfo, ) -> Result { debug_assert!(scan .schema diff --git a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs index 89c30b3bc8e92..915a6995536ed 100644 --- a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs +++ b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs @@ -80,6 +80,25 @@ impl EvalScalar { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for EvalScalar { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_eval_scalar(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_eval_scalar( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_exchange.rs b/src/query/sql/src/executor/physical_plans/physical_exchange.rs index 1e831519c415b..09a5f558ddc41 100644 --- a/src/query/sql/src/executor/physical_plans/physical_exchange.rs +++ b/src/query/sql/src/executor/physical_plans/physical_exchange.rs @@ -43,12 +43,32 @@ impl Exchange { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for Exchange { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_exchange(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_exchange( &mut self, s_expr: &SExpr, exchange: &crate::plans::Exchange, mut required: ColumnSet, + _stat_info: PlanStatsInfo, ) -> Result { // 1. Prune unused Columns. if let crate::plans::Exchange::Hash(exprs) = exchange { diff --git a/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs b/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs index 5721f80368321..1304319bea838 100644 --- a/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs @@ -39,12 +39,32 @@ impl ExpressionScan { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for ExpressionScan { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_expression_scan(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_expression_scan( &mut self, s_expr: &SExpr, scan: &crate::plans::ExpressionScan, required: ColumnSet, + _stat_info: PlanStatsInfo, ) -> Result { let input = self.build(s_expr.child(0)?, required).await?; let input_schema = input.output_schema()?; diff --git a/src/query/sql/src/executor/physical_plans/physical_filter.rs b/src/query/sql/src/executor/physical_plans/physical_filter.rs index 3051e5ec9307b..025e99d6cae07 100644 --- a/src/query/sql/src/executor/physical_plans/physical_filter.rs +++ b/src/query/sql/src/executor/physical_plans/physical_filter.rs @@ -53,6 +53,25 @@ impl Filter { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for Filter { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_filter(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_filter( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_join.rs b/src/query/sql/src/executor/physical_plans/physical_join.rs index 1b09ecc6a2eed..afa4c32dee2be 100644 --- a/src/query/sql/src/executor/physical_plans/physical_join.rs +++ b/src/query/sql/src/executor/physical_plans/physical_join.rs @@ -16,6 +16,7 @@ use databend_common_exception::Result; use crate::binder::JoinPredicate; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::RelExpr; @@ -33,6 +34,19 @@ pub enum PhysicalJoinType { AsofJoin(Vec, Vec), } +#[async_trait::async_trait] +impl BuildPhysicalPlan for PhysicalJoinType { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr.plan().as_any().downcast_ref::().unwrap(); + builder.build_join(s_expr, plan, required, stat_info).await + } +} + // Choose physical join type by join conditions pub fn physical_join(join: &Join, s_expr: &SExpr) -> Result { let check_asof = matches!( diff --git a/src/query/sql/src/executor/physical_plans/physical_limit.rs b/src/query/sql/src/executor/physical_plans/physical_limit.rs index b0c3e64ecd713..1222b1e173504 100644 --- a/src/query/sql/src/executor/physical_plans/physical_limit.rs +++ b/src/query/sql/src/executor/physical_plans/physical_limit.rs @@ -19,6 +19,7 @@ use databend_common_expression::DataSchemaRef; use databend_common_expression::ROW_ID_COL_NAME; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::physical_row_fetch::RowFetch; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; @@ -44,6 +45,23 @@ impl Limit { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for Limit { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder.build_limit(s_expr, plan, required, stat_info).await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_limit( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_mutation.rs b/src/query/sql/src/executor/physical_plans/physical_mutation.rs index 9feb40c125a1d..d6757c04a6ffa 100644 --- a/src/query/sql/src/executor/physical_plans/physical_mutation.rs +++ b/src/query/sql/src/executor/physical_plans/physical_mutation.rs @@ -48,7 +48,9 @@ use super::CommitType; use crate::binder::wrap_cast; use crate::binder::MutationStrategy; use crate::binder::MutationType; +use crate::executor::explain::PlanStatsInfo; use crate::executor::physical_plan::PhysicalPlan; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::CommitSink; use crate::executor::physical_plans::Exchange; use crate::executor::physical_plans::FragmentKind; @@ -95,12 +97,32 @@ pub struct Mutation { pub table_meta_timestamps: TableMetaTimestamps, } +#[async_trait::async_trait] +impl BuildPhysicalPlan for Mutation { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_mutation(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub async fn build_mutation( &mut self, s_expr: &SExpr, mutation: &crate::plans::Mutation, required: ColumnSet, + _stat_info: PlanStatsInfo, ) -> Result { let crate::plans::Mutation { bind_context, diff --git a/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs b/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs index b04c294220ab5..60a28b452d2ed 100644 --- a/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs +++ b/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs @@ -28,6 +28,8 @@ use databend_common_meta_app::schema::TableInfo; use crate::binder::MutationType; use crate::executor::cast_expr_to_non_null_boolean; +use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::ColumnSet; @@ -50,6 +52,23 @@ pub struct MutationSource { pub statistics: PartStatistics, } +#[async_trait::async_trait] +impl BuildPhysicalPlan for MutationSource { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + _required: ColumnSet, + _stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder.build_mutation_source(plan).await + } +} + impl MutationSource { pub fn output_schema(&self) -> Result { Ok(self.output_schema.clone()) diff --git a/src/query/sql/src/executor/physical_plans/physical_project_set.rs b/src/query/sql/src/executor/physical_plans/physical_project_set.rs index 99b85519223b8..30543cf096c51 100644 --- a/src/query/sql/src/executor/physical_plans/physical_project_set.rs +++ b/src/query/sql/src/executor/physical_plans/physical_project_set.rs @@ -59,6 +59,25 @@ impl ProjectSet { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for ProjectSet { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_project_set(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_project_set( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs b/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs index 459a6c3c91bd2..424a0ff0c5fcb 100644 --- a/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs @@ -37,10 +37,31 @@ impl RecursiveCteScan { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for RecursiveCteScan { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_recursive_cte_scan(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_recursive_cte_scan( &mut self, + _s_expr: &SExpr, recursive_cte_scan: &crate::plans::RecursiveCteScan, + _required: ColumnSet, stat_info: PlanStatsInfo, ) -> Result { Ok(PhysicalPlan::RecursiveCteScan(RecursiveCteScan { diff --git a/src/query/sql/src/executor/physical_plans/physical_sort.rs b/src/query/sql/src/executor/physical_plans/physical_sort.rs index 94b765107f310..535df442096c9 100644 --- a/src/query/sql/src/executor/physical_plans/physical_sort.rs +++ b/src/query/sql/src/executor/physical_plans/physical_sort.rs @@ -102,6 +102,23 @@ impl Sort { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for Sort { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder.build_sort(s_expr, plan, required, stat_info).await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_sort( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_table_scan.rs b/src/query/sql/src/executor/physical_plans/physical_table_scan.rs index 0541b88c9abd1..a1aae9481fa49 100644 --- a/src/query/sql/src/executor/physical_plans/physical_table_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_table_scan.rs @@ -53,11 +53,14 @@ use rand::thread_rng; use crate::binder::INTERNAL_COLUMN_FACTORY; use crate::executor::cast_expr_to_non_null_boolean; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::AddStreamColumn; use crate::executor::table_read_plan::ToReadDataSourcePlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; +use crate::optimizer::ir::SExpr; use crate::plans::FunctionCall; +use crate::plans::Scan; use crate::BaseTableColumn; use crate::ColumnEntry; use crate::ColumnSet; @@ -114,6 +117,33 @@ impl TableScan { } } +pub struct DummyTableScan; + +#[async_trait::async_trait] +impl BuildPhysicalPlan for TableScan { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let scan = s_expr.plan().as_any().downcast_ref::().unwrap(); + builder.build_table_scan(scan, required, stat_info).await + } +} + +#[async_trait::async_trait] +impl BuildPhysicalPlan for DummyTableScan { + async fn build( + builder: &mut PhysicalPlanBuilder, + _s_expr: &SExpr, + _required: ColumnSet, + _stat_info: PlanStatsInfo, + ) -> Result { + builder.build_dummy_table_scan().await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_table_scan( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_udf.rs b/src/query/sql/src/executor/physical_plans/physical_udf.rs index acfd628b36af3..37d95bb35d249 100644 --- a/src/query/sql/src/executor/physical_plans/physical_udf.rs +++ b/src/query/sql/src/executor/physical_plans/physical_udf.rs @@ -23,6 +23,7 @@ use databend_common_expression::DataSchemaRefExt; use databend_common_functions::BUILTIN_FUNCTIONS; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::SExpr; @@ -68,6 +69,23 @@ pub struct UdfFunctionDesc { pub udf_type: UDFType, } +#[async_trait::async_trait] +impl BuildPhysicalPlan for Udf { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder.build_udf(s_expr, plan, required, stat_info).await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_udf( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_union_all.rs b/src/query/sql/src/executor/physical_plans/physical_union_all.rs index 26ea91d34f81f..ff5372e0f75a1 100644 --- a/src/query/sql/src/executor/physical_plans/physical_union_all.rs +++ b/src/query/sql/src/executor/physical_plans/physical_union_all.rs @@ -49,6 +49,25 @@ impl UnionAll { } } +#[async_trait::async_trait] +impl BuildPhysicalPlan for UnionAll { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_union_all(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_union_all( &mut self, diff --git a/src/query/sql/src/executor/physical_plans/physical_window.rs b/src/query/sql/src/executor/physical_plans/physical_window.rs index f2cac19cb0fa1..b1c789590e377 100644 --- a/src/query/sql/src/executor/physical_plans/physical_window.rs +++ b/src/query/sql/src/executor/physical_plans/physical_window.rs @@ -149,6 +149,25 @@ pub struct NtileFunctionDesc { pub return_type: DataType, } +#[async_trait::async_trait] +impl BuildPhysicalPlan for Window { + async fn build( + builder: &mut PhysicalPlanBuilder, + s_expr: &SExpr, + required: ColumnSet, + stat_info: PlanStatsInfo, + ) -> Result { + let plan = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + builder + .build_window(s_expr, plan, required, stat_info) + .await + } +} + impl PhysicalPlanBuilder { pub(crate) async fn build_window( &mut self, diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 592699d877b67..594e80b431dc7 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -503,7 +503,6 @@ impl SExpr { | crate::plans::RelOp::Window | crate::plans::RelOp::ProjectSet | crate::plans::RelOp::Udf - | crate::plans::RelOp::Udaf | crate::plans::RelOp::AsyncFunction | crate::plans::RelOp::MergeInto | crate::plans::RelOp::CompactBlock diff --git a/src/query/sql/src/planner/plans/mod.rs b/src/query/sql/src/planner/plans/mod.rs index 2f324de8199d8..2f5621f8485c0 100644 --- a/src/query/sql/src/planner/plans/mod.rs +++ b/src/query/sql/src/planner/plans/mod.rs @@ -48,7 +48,7 @@ mod set; mod set_priority; mod sort; mod system; -mod udaf; +// mod udaf; mod udf; mod union_all; mod virtual_column; @@ -95,7 +95,7 @@ pub use set::*; pub use set_priority::SetPriorityPlan; pub use sort::*; pub use system::*; -pub use udaf::*; +// pub use udaf::*; pub use udf::*; pub use union_all::UnionAll; pub use virtual_column::*; diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 2ceac7e6b661f..70a7c121068d4 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -135,7 +135,6 @@ pub enum RelOp { ExpressionScan, CacheScan, Udf, - Udaf, AsyncFunction, RecursiveCteScan, MergeInto, @@ -145,3 +144,36 @@ pub enum RelOp { // Pattern Pattern, } + +#[macro_export] +macro_rules! with_match_rel_op { + (| $t:tt | $($tail:tt)*) => { + match_template::match_template! { + $t = [ + Scan => Scan, + Join => Join, + EvalScalar => EvalScalar, + Filter => Filter, + Aggregate => Aggregate, + Sort => Sort, + Limit => Limit, + Exchange => Exchange, + UnionAll => UnionAll, + DummyTableScan => DummyTableScan, + Window => Window, + ProjectSet => ProjectSet, + ConstantTableScan => ConstantTableScan, + ExpressionScan => ExpressionScan, + CacheScan => CacheScan, + Udf => Udf, + Udaf => Udaf, + AsyncFunction => AsyncFunction, + RecursiveCteScan => RecursiveCteScan, + MergeInto => MergeInto, + CompactBlock => CompactBlock, + MutationSource => MutationSource, + ], + $($tail)* + } + } +} From d6c9441018d20580f84122479794e3e5717b5d8f Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Wed, 2 Jul 2025 08:51:03 +0000 Subject: [PATCH 04/14] update --- .../it/sql/planner/optimizer/test_utils.rs | 2 +- src/query/sql/Cargo.toml | 2 +- .../sql/src/executor/physical_plan_builder.rs | 2 +- .../physical_plans/physical_eval_scalar.rs | 5 +- src/query/sql/src/planner/binder/aggregate.rs | 4 +- .../src/planner/binder/bind_mutation/bind.rs | 5 +- .../bind_mutation/mutation_expression.rs | 19 +--- .../planner/binder/bind_mutation/update.rs | 2 +- .../planner/binder/bind_query/bind_limit.rs | 2 +- .../planner/binder/bind_query/bind_value.rs | 2 +- .../binder/bind_table_reference/bind_join.rs | 4 +- .../bind_table_function.rs | 8 +- src/query/sql/src/planner/binder/binder.rs | 2 +- src/query/sql/src/planner/binder/ddl/table.rs | 2 +- src/query/sql/src/planner/binder/distinct.rs | 2 +- src/query/sql/src/planner/binder/project.rs | 2 +- .../sql/src/planner/binder/project_set.rs | 2 +- src/query/sql/src/planner/binder/select.rs | 2 +- src/query/sql/src/planner/binder/sort.rs | 2 +- src/query/sql/src/planner/binder/table.rs | 2 +- src/query/sql/src/planner/binder/util.rs | 2 +- src/query/sql/src/planner/binder/window.rs | 4 +- src/query/sql/src/planner/dataframe.rs | 4 +- src/query/sql/src/planner/format/display.rs | 2 +- .../planner/format/display_rel_operator.rs | 2 +- .../src/planner/optimizer/ir/expr/s_expr.rs | 21 +++-- .../src/planner/optimizer/ir/expr/visitor.rs | 4 +- .../sql/src/planner/optimizer/ir/format.rs | 2 +- .../sql/src/planner/optimizer/ir/memo.rs | 2 +- .../planner/optimizer/ir/property/enforcer.rs | 4 +- .../sql/src/planner/optimizer/optimizer.rs | 1 - .../optimizers/cascades/cost/model.rs | 2 +- .../cascades/tasks/optimize_expr.rs | 4 +- .../optimizers/distributed/distributed.rs | 2 +- .../distributed/distributed_merge.rs | 2 +- .../optimizers/distributed/sort_and_limit.rs | 9 +- .../optimizer/optimizers/hyper_dp/dphyp.rs | 2 +- .../hyper_dp/dynamic_sample/dynamic_sample.rs | 2 +- .../filter_selectivity_sample.rs | 2 +- .../optimizers/hyper_dp/join_node.rs | 2 +- .../operator/aggregate/normalize_aggregate.rs | 2 +- .../operator/aggregate/stats_aggregate.rs | 24 ++--- .../operator/decorrelate/decorrelate.rs | 2 +- .../operator/decorrelate/flatten_plan.rs | 1 - .../decorrelate/subquery_decorrelator.rs | 27 +++--- .../filter/deduplicate_join_condition.rs | 2 +- .../operator/filter/pull_up_filter.rs | 2 +- .../operator/join/single_to_inner.rs | 2 +- .../rule/agg_rules/agg_index/query_rewrite.rs | 50 +++++----- .../rule/agg_rules/rule_eager_aggregation.rs | 94 +++++++------------ .../rule_push_down_limit_aggregate.rs | 13 +-- .../agg_rules/rule_try_apply_agg_index.rs | 22 ++--- .../filter_rules/rule_eliminate_filter.rs | 3 +- .../rule/filter_rules/rule_filter_nulls.rs | 12 +-- .../rule_merge_filter_into_mutation.rs | 4 +- .../rule_push_down_filter_eval_scalar.rs | 6 +- .../rule_push_down_filter_union.rs | 8 +- .../rule_push_down_filter_window_top_n.rs | 3 +- .../rule_push_down_sort_expression.rs | 12 +-- .../filter_rules/rule_push_down_sort_scan.rs | 2 +- .../mark_join_to_semi_join.rs | 8 +- .../join_rules/rule_semi_to_inner_join.rs | 2 +- .../rule/limit_rules/rule_push_down_limit.rs | 2 +- .../rule_push_down_limit_expression.rs | 2 +- .../limit_rules/rule_push_down_limit_join.rs | 2 +- .../limit_rules/rule_push_down_limit_scan.rs | 2 +- .../limit_rules/rule_push_down_limit_sort.rs | 2 +- .../limit_rules/rule_push_down_limit_union.rs | 14 +-- .../rule_push_down_limit_window.rs | 2 +- .../rule/union_rules/rule_eliminate_union.rs | 2 +- .../src/planner/optimizer/pipeline/common.rs | 10 +- .../statistics/collect_statistics.rs | 2 +- .../sql/src/planner/plans/mutation_source.rs | 4 + src/query/sql/src/planner/plans/operator.rs | 2 +- src/query/sql/src/planner/plans/plan.rs | 2 +- .../sql/src/planner/plans/project_set.rs | 5 + src/query/sql/src/planner/plans/recluster.rs | 24 ++--- src/query/sql/src/planner/plans/udf.rs | 1 + .../semantic/async_function_rewriter.rs | 22 +++-- .../sql/src/planner/semantic/udf_rewriter.rs | 30 +++--- 80 files changed, 258 insertions(+), 321 deletions(-) diff --git a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs index 5d772254abbba..59d912ed4a369 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs @@ -563,7 +563,7 @@ impl ExprBuilder { from_distinct: false, rank_limit: None, }; - SExpr::create_unary(Arc::new(RelOperator::Aggregate(agg)), Arc::new(input)) + SExpr::create_unary(agg, Arc::new(input)) } /// Create a limit diff --git a/src/query/sql/Cargo.toml b/src/query/sql/Cargo.toml index 4f10fe2440445..f385fcbd3d1c9 100644 --- a/src/query/sql/Cargo.toml +++ b/src/query/sql/Cargo.toml @@ -40,7 +40,6 @@ databend-storages-common-table-meta = { workspace = true } ahash = { workspace = true, features = ["no-rng"] } anyhow = { workspace = true } async-backtrace = { workspace = true } -match-template = { workspace = true } async-recursion = { workspace = true } async-trait = { workspace = true } chrono = { workspace = true } @@ -58,6 +57,7 @@ indexmap = { workspace = true } itertools = { workspace = true } jsonb = { workspace = true } log = { workspace = true } +match-template = { workspace = true } num-derive = { workspace = true } num-traits = { workspace = true } opendal = { workspace = true } diff --git a/src/query/sql/src/executor/physical_plan_builder.rs b/src/query/sql/src/executor/physical_plan_builder.rs index 1d449404d9d42..9237f8f6fd0d7 100644 --- a/src/query/sql/src/executor/physical_plan_builder.rs +++ b/src/query/sql/src/executor/physical_plan_builder.rs @@ -28,7 +28,7 @@ use crate::executor::explain::PlanStatsInfo; use crate::executor::PhysicalPlan; use crate::optimizer::ir::RelExpr; use crate::optimizer::ir::SExpr; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::ColumnSet; use crate::MetadataRef; diff --git a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs index 915a6995536ed..bab7c82062b24 100644 --- a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs +++ b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs @@ -34,7 +34,7 @@ use crate::plans::Filter; use crate::plans::FunctionCall; use crate::plans::ProjectSet; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Visitor; @@ -242,8 +242,7 @@ impl PhysicalPlanBuilder { }; let mut new_child = child.clone(); new_child.plan = Arc::new(new_project_set.into()); - let new_filter = - SExpr::create_unary(Arc::new(s_expr.plan().clone()), Arc::new(new_child)); + let new_filter = SExpr::create_unary(s_expr.plan().clone(), new_child); Ok(Some(new_filter)) } else { let project_set: ProjectSet = s_expr.plan().clone().try_into()?; diff --git a/src/query/sql/src/planner/binder/aggregate.rs b/src/query/sql/src/planner/binder/aggregate.rs index 8f4bac849bb4a..6bc7c97cd3dd5 100644 --- a/src/query/sql/src/planner/binder/aggregate.rs +++ b/src/query/sql/src/planner/binder/aggregate.rs @@ -699,7 +699,7 @@ impl Binder { let eval_scalar = EvalScalar { items: scalar_items, }; - new_expr = SExpr::create_unary(Arc::new(eval_scalar.into()), Arc::new(new_expr)); + new_expr = SExpr::create_unary(eval_scalar, Arc::new(new_expr)); } let aggregate_plan = Aggregate { @@ -715,7 +715,7 @@ impl Binder { dup_group_items: g.dup_group_items.clone(), }), }; - new_expr = SExpr::create_unary(Arc::new(aggregate_plan.into()), Arc::new(new_expr)); + new_expr = SExpr::create_unary(aggregate_plan, new_expr); Ok(new_expr) } diff --git a/src/query/sql/src/planner/binder/bind_mutation/bind.rs b/src/query/sql/src/planner/binder/bind_mutation/bind.rs index be9463d24be6e..5e9559759638f 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/bind.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/bind.rs @@ -44,8 +44,8 @@ use crate::plans::BoundColumnRef; use crate::plans::ConstantExpr; use crate::plans::FunctionCall; use crate::plans::MatchedEvaluator; +use crate::plans::Operator; use crate::plans::Plan; -use crate::plans::RelOperator; use crate::plans::UnmatchedEvaluator; use crate::BindContext; use crate::ColumnBinding; @@ -319,8 +319,7 @@ impl Binder { } let schema = mutation.schema(); - let mut s_expr = - SExpr::create_unary(Arc::new(RelOperator::Mutation(mutation)), Arc::new(input)); + let mut s_expr = SExpr::create_unary(mutation, input); // rewrite async function and udf s_expr = self.rewrite_udf(&mut bind_context, s_expr)?; diff --git a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs index 0938ea87dda2c..e132a69b968f3 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs @@ -42,7 +42,8 @@ use crate::plans::Filter; use crate::plans::Join; use crate::plans::JoinType; use crate::plans::MutationSource; -use crate::plans::RelOperator; +use crate::plans::Operator; +use crate::plans::Operator; use crate::plans::SubqueryExpr; use crate::plans::Visitor; use crate::BindContext; @@ -255,10 +256,7 @@ impl MutationExpression { SExpr::create_leaf(Arc::new(RelOperator::MutationSource(mutation_source))); if !predicates.is_empty() { - s_expr = SExpr::create_unary( - Arc::new(Filter { predicates }.into()), - Arc::new(s_expr), - ); + s_expr = SExpr::create_unary(Filter { predicates }, s_expr); } for column_index in bind_context.column_set().iter() { @@ -304,17 +302,10 @@ impl MutationExpression { single_to_inner: None, build_side_cache_info: None, }; - s_expr = SExpr::create_binary( - Arc::new(join_plan.into()), - Arc::new(s_expr.clone()), - Arc::new(from_s_expr), - ); + s_expr = SExpr::create_binary(join_plan, s_expr.clone(), from_s_expr); } - s_expr = SExpr::create_unary( - Arc::new(Filter { predicates }.into()), - Arc::new(s_expr), - ); + s_expr = SExpr::create_unary(Filter { predicates }, s_expr); let opt_ctx = OptimizerContext::new(binder.ctx.clone(), binder.metadata.clone()); diff --git a/src/query/sql/src/planner/binder/bind_mutation/update.rs b/src/query/sql/src/planner/binder/bind_mutation/update.rs index 56de12c2c2921..02ccfc1141f74 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/update.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/update.rs @@ -34,7 +34,7 @@ use crate::plans::BoundColumnRef; use crate::plans::EvalScalar; use crate::plans::Plan; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarItem; use crate::plans::VisitorMut; use crate::BindContext; diff --git a/src/query/sql/src/planner/binder/bind_query/bind_limit.rs b/src/query/sql/src/planner/binder/bind_query/bind_limit.rs index 137cef985c3de..63c9ae0774819 100644 --- a/src/query/sql/src/planner/binder/bind_query/bind_limit.rs +++ b/src/query/sql/src/planner/binder/bind_query/bind_limit.rs @@ -42,7 +42,7 @@ impl Binder { limit, offset, }; - SExpr::create_unary(Arc::new(limit_plan.into()), Arc::new(s_expr)) + SExpr::create_unary(limit_plan, s_expr) } pub(crate) fn extract_limit_and_offset(&self, query: &Query) -> Result<(Option, usize)> { diff --git a/src/query/sql/src/planner/binder/bind_query/bind_value.rs b/src/query/sql/src/planner/binder/bind_query/bind_value.rs index 83dfad124e22f..2f8faedbb0d5a 100644 --- a/src/query/sql/src/planner/binder/bind_query/bind_value.rs +++ b/src/query/sql/src/planner/binder/bind_query/bind_value.rs @@ -41,7 +41,7 @@ use crate::plans::CacheSource; use crate::plans::ConstantTableScan; use crate::plans::ExpressionScan; use crate::plans::HashJoinBuildCacheInfo; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarItem; use crate::BindContext; use crate::Binder; diff --git a/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs b/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs index 70f3db5135fa0..853ad3c521e8e 100644 --- a/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs +++ b/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs @@ -135,7 +135,7 @@ impl Binder { let eval_scalar = EvalScalar { items: left_derived_scalars, }; - SExpr::create_unary(Arc::new(eval_scalar.into()), Arc::new(left_child)) + SExpr::create_unary(eval_scalar, left_child) } else { left_child }; @@ -143,7 +143,7 @@ impl Binder { let eval_scalar = EvalScalar { items: right_derived_scalars, }; - SExpr::create_unary(Arc::new(eval_scalar.into()), Arc::new(right_child)) + SExpr::create_unary(eval_scalar, right_child) } else { right_child }; diff --git a/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs b/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs index 3cfe23223548f..61a4732aada10 100644 --- a/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs +++ b/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs @@ -47,7 +47,7 @@ use crate::optimizer::ir::SExpr; use crate::planner::semantic::normalize_identifier; use crate::plans::EvalScalar; use crate::plans::FunctionCall; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarItem; use crate::BindContext; use crate::ScalarExpr; @@ -295,8 +295,7 @@ impl Binder { }); } let eval_scalar = EvalScalar { items }; - let new_expr = - SExpr::create_unary(Arc::new(eval_scalar.into()), srf_expr.children[0].clone()); + let new_expr = SExpr::create_unary(eval_scalar, srf_expr.children[0].clone()); if let Some(alias) = alias { bind_context.apply_table_alias(alias, &self.name_resolution_ctx)?; @@ -399,8 +398,7 @@ impl Binder { // Add srf result column bind_context.add_column_binding(column_binding); - let flatten_expr = - SExpr::create_unary(Arc::new(eval_scalar.into()), Arc::new(srf_expr)); + let flatten_expr = SExpr::create_unary(eval_scalar, srf_expr); let (new_expr, mut bind_context) = self .extract_srf_table_function_columns( diff --git a/src/query/sql/src/planner/binder/binder.rs b/src/query/sql/src/planner/binder/binder.rs index 51d18d059ed39..a999b7568c999 100644 --- a/src/query/sql/src/planner/binder/binder.rs +++ b/src/query/sql/src/planner/binder/binder.rs @@ -64,7 +64,7 @@ use crate::plans::DropRolePlan; use crate::plans::DropStagePlan; use crate::plans::DropUserPlan; use crate::plans::Plan; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::RewriteKind; use crate::plans::ShowConnectionsPlan; use crate::plans::ShowFileFormatsPlan; diff --git a/src/query/sql/src/planner/binder/ddl/table.rs b/src/query/sql/src/planner/binder/ddl/table.rs index bed6e838eeb61..d4ba7a81b642f 100644 --- a/src/query/sql/src/planner/binder/ddl/table.rs +++ b/src/query/sql/src/planner/binder/ddl/table.rs @@ -132,7 +132,7 @@ use crate::plans::OptimizePurgePlan; use crate::plans::Plan; use crate::plans::ReclusterPlan; use crate::plans::RefreshTableCachePlan; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::RenameTableColumnPlan; use crate::plans::RenameTablePlan; use crate::plans::RevertTablePlan; diff --git a/src/query/sql/src/planner/binder/distinct.rs b/src/query/sql/src/planner/binder/distinct.rs index ae858946ab7d7..4baacddf96e09 100644 --- a/src/query/sql/src/planner/binder/distinct.rs +++ b/src/query/sql/src/planner/binder/distinct.rs @@ -65,7 +65,7 @@ impl Binder { let eval_scalar = EvalScalar { items: scalar_items, }; - new_expr = SExpr::create_unary(Arc::new(eval_scalar.into()), Arc::new(new_expr)); + new_expr = SExpr::create_unary(eval_scalar, new_expr); } // Like aggregate, we just use scalar directly. diff --git a/src/query/sql/src/planner/binder/project.rs b/src/query/sql/src/planner/binder/project.rs index 4e9f97802e011..e66efc33e60a2 100644 --- a/src/query/sql/src/planner/binder/project.rs +++ b/src/query/sql/src/planner/binder/project.rs @@ -205,7 +205,7 @@ impl Binder { scalars.sort_by_key(|s| s.index); let eval_scalar = EvalScalar { items: scalars }; - let new_expr = SExpr::create_unary(Arc::new(eval_scalar.into()), Arc::new(child)); + let new_expr = SExpr::create_unary(eval_scalar, child); // Set output columns bind_context.columns = columns; Ok(new_expr) diff --git a/src/query/sql/src/planner/binder/project_set.rs b/src/query/sql/src/planner/binder/project_set.rs index ab2edc093f27a..172cbf3ef761f 100644 --- a/src/query/sql/src/planner/binder/project_set.rs +++ b/src/query/sql/src/planner/binder/project_set.rs @@ -270,7 +270,7 @@ impl Binder { } let project_set = ProjectSet { srfs }; - let new_expr = SExpr::create_unary(Arc::new(project_set.into()), Arc::new(child)); + let new_expr = SExpr::create_unary(project_set, child); Ok(new_expr) } diff --git a/src/query/sql/src/planner/binder/select.rs b/src/query/sql/src/planner/binder/select.rs index 8ed22da0e6b61..5bd6ba159edd1 100644 --- a/src/query/sql/src/planner/binder/select.rs +++ b/src/query/sql/src/planner/binder/select.rs @@ -105,7 +105,7 @@ impl Binder { let filter_plan = Filter { predicates: split_conjunctions(&scalar), }; - let new_expr = SExpr::create_unary(Arc::new(filter_plan.into()), Arc::new(child)); + let new_expr = SExpr::create_unary(filter_plan, child); bind_context.set_expr_context(last_expr_context); Ok((new_expr, scalar)) } diff --git a/src/query/sql/src/planner/binder/sort.rs b/src/query/sql/src/planner/binder/sort.rs index 617aad8308f0b..632f926b790b3 100644 --- a/src/query/sql/src/planner/binder/sort.rs +++ b/src/query/sql/src/planner/binder/sort.rs @@ -225,7 +225,7 @@ impl Binder { pre_projection: None, window_partition: None, }; - let new_expr = SExpr::create_unary(Arc::new(sort_plan.into()), Arc::new(child)); + let new_expr = SExpr::create_unary(sort_plan, child); Ok(new_expr) } diff --git a/src/query/sql/src/planner/binder/table.rs b/src/query/sql/src/planner/binder/table.rs index c659a4b12910a..59a4a09062244 100644 --- a/src/query/sql/src/planner/binder/table.rs +++ b/src/query/sql/src/planner/binder/table.rs @@ -67,7 +67,7 @@ use crate::planner::semantic::normalize_identifier; use crate::planner::semantic::TypeChecker; use crate::plans::DummyTableScan; use crate::plans::RecursiveCteScan; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Scan; use crate::plans::Statistics; use crate::BaseTableColumn; diff --git a/src/query/sql/src/planner/binder/util.rs b/src/query/sql/src/planner/binder/util.rs index 039a42c2f806d..adfcee7bc5787 100644 --- a/src/query/sql/src/planner/binder/util.rs +++ b/src/query/sql/src/planner/binder/util.rs @@ -25,7 +25,7 @@ use databend_common_expression::types::DataType; use crate::normalize_identifier; use crate::optimizer::ir::SExpr; use crate::plans::Operator; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::Binder; use crate::NameResolutionContext; use crate::NameResolutionSuggest; diff --git a/src/query/sql/src/planner/binder/window.rs b/src/query/sql/src/planner/binder/window.rs index db6140b55129d..2d10b1434602c 100644 --- a/src/query/sql/src/planner/binder/window.rs +++ b/src/query/sql/src/planner/binder/window.rs @@ -622,7 +622,7 @@ pub fn bind_window_function_info( let eval_scalar_plan = EvalScalar { items: scalar_items, }; - SExpr::create_unary(Arc::new(eval_scalar_plan.into()), Arc::new(child)) + SExpr::create_unary(eval_scalar_plan, child) } else { child }; @@ -667,7 +667,7 @@ pub fn bind_window_function_info( }) }, }; - SExpr::create_unary(Arc::new(sort_plan.into()), Arc::new(child)) + SExpr::create_unary(sort_plan, child) } else { child }; diff --git a/src/query/sql/src/planner/dataframe.rs b/src/query/sql/src/planner/dataframe.rs index 277a010eace81..a9259f0fff53b 100644 --- a/src/query/sql/src/planner/dataframe.rs +++ b/src/query/sql/src/planner/dataframe.rs @@ -37,6 +37,7 @@ use parking_lot::RwLock; use crate::optimizer::ir::SExpr; use crate::plans::Limit; +use crate::plans::Operator; use crate::BindContext; use crate::Binder; use crate::Metadata; @@ -338,8 +339,7 @@ impl Dataframe { limit, offset, }; - self.s_expr = - SExpr::create_unary(Arc::new(limit_plan.into()), Arc::new(self.s_expr.clone())); + self.s_expr = SExpr::create_unary(limit_plan, self.s_expr.clone()); Ok(self) } diff --git a/src/query/sql/src/planner/format/display.rs b/src/query/sql/src/planner/format/display.rs index df099b5cbe4ae..80512ee242664 100644 --- a/src/query/sql/src/planner/format/display.rs +++ b/src/query/sql/src/planner/format/display.rs @@ -20,7 +20,7 @@ use crate::optimizer::ir::RelExpr; use crate::optimizer::ir::RelationalProperty; use crate::optimizer::ir::SExpr; use crate::optimizer::ir::StatInfo; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::ColumnEntry; use crate::IndexType; use crate::Metadata; diff --git a/src/query/sql/src/planner/format/display_rel_operator.rs b/src/query/sql/src/planner/format/display_rel_operator.rs index 9835bbedf0cdd..76df1da48aa16 100644 --- a/src/query/sql/src/planner/format/display_rel_operator.rs +++ b/src/query/sql/src/planner/format/display_rel_operator.rs @@ -28,7 +28,7 @@ use crate::plans::Join; use crate::plans::Limit; use crate::plans::Mutation; use crate::plans::Operator; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Scan; diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 594e80b431dc7..515f310f4d680 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -29,7 +29,7 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::plans::Exchange; use crate::plans::Operator; use crate::plans::OperatorRef; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Scan; use crate::plans::WindowFuncType; use crate::IndexType; @@ -67,13 +67,14 @@ pub struct SExpr { } impl SExpr { - pub fn create( - plan: OperatorRef, + pub fn create( + plan: P, children: impl Into>>, original_group: Option, rel_prop: Option>, stat_info: Option>, ) -> Self { + let plan = Arc::new(plan) as OperatorRef; SExpr { plan, children: children.into(), @@ -84,12 +85,12 @@ impl SExpr { } } - pub fn create_unary(plan: OperatorRef, child: impl Into>) -> Self { + pub fn create_unary(plan: P, child: impl Into>) -> Self { Self::create(plan, [child.into()], None, None, None) } - pub fn create_binary( - plan: OperatorRef, + pub fn create_binary( + plan: P, left_child: impl Into>, right_child: impl Into>, ) -> Self { @@ -106,14 +107,14 @@ impl SExpr { Self::create(plan, [], None, None, None) } - pub fn build_unary(self, plan: Arc) -> Self { + pub fn build_unary(self, plan: P) -> Self { debug_assert_eq!(plan.arity(), 1); - Self::create(plan, [self.into()], None, None, None) + Self::create_unary(plan, self) } - pub fn ref_build_unary(self: &Arc, plan: Arc) -> Self { + pub fn ref_build_unary(self: &Arc, plan: P) -> Self { debug_assert_eq!(plan.arity(), 1); - Self::create(plan, [self.clone()], None, None, None) + Self::create_unary(plan, self.clone()) } pub fn plan(&self) -> &OperatorRef { diff --git a/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs b/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs index 932085e35277f..ab2ca46a8d5db 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs @@ -59,7 +59,7 @@ //! use crate::optimizer::ir::expr::AsyncSExprVisitor; //! use crate::optimizer::ir::expr::SExpr; //! use crate::optimizer::ir::expr::VisitAction; -//! use crate::plans::RelOperator; +//! use crate::plans::Operator; //! //! // Visitor that eliminates unnecessary Sort operations with empty sort keys //! struct EmptySortEliminator; @@ -91,7 +91,7 @@ use std::sync::Arc; use databend_common_exception::Result; use crate::optimizer::ir::expr::SExpr; -// use crate::plans::RelOperator; +// use crate::plans::Operator; /// Action to take after visiting a node #[derive(Clone)] diff --git a/src/query/sql/src/planner/optimizer/ir/format.rs b/src/query/sql/src/planner/optimizer/ir/format.rs index f9613af6b35ef..6a97807eed049 100644 --- a/src/query/sql/src/planner/optimizer/ir/format.rs +++ b/src/query/sql/src/planner/optimizer/ir/format.rs @@ -21,7 +21,7 @@ use crate::optimizer::ir::Group; use crate::optimizer::ir::MExpr; use crate::optimizer::ir::Memo; use crate::plans::Exchange; -use crate::plans::RelOperator; +use crate::plans::Operator; impl Memo { /// Format the memo structure for display diff --git a/src/query/sql/src/planner/optimizer/ir/memo.rs b/src/query/sql/src/planner/optimizer/ir/memo.rs index d31c9801996a5..de0dfe1d94471 100644 --- a/src/query/sql/src/planner/optimizer/ir/memo.rs +++ b/src/query/sql/src/planner/optimizer/ir/memo.rs @@ -25,7 +25,7 @@ use crate::optimizer::ir::property::RelationalProperty; use crate::optimizer::ir::property::StatInfo; use crate::optimizer::ir::Group; use crate::optimizer::ir::GroupState; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::IndexType; /// `Memo` is a search space which memoize possible plans of a query. diff --git a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs index 1229898f5bef4..e630a3054ba4f 100644 --- a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs +++ b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs @@ -27,7 +27,7 @@ use crate::optimizer::ir::property::PhysicalProperty; use crate::optimizer::ir::property::RelExpr; use crate::optimizer::ir::property::RequiredProperty; use crate::plans::Exchange; -use crate::plans::RelOperator; +use crate::plans::Operator; /// Enforcer is a trait that can enforce the physical property pub trait Enforcer: std::fmt::Debug + Send + Sync { @@ -196,7 +196,7 @@ impl PropertyEnforcer { // Apply the enforcer let exchange_op = enforcer.enforce()?; - let result = SExpr::create_unary(Arc::new(exchange_op), Arc::new(s_expr.clone())); + let result = SExpr::create_unary(exchange_op, s_expr.clone()); Ok(result) } diff --git a/src/query/sql/src/planner/optimizer/optimizer.rs b/src/query/sql/src/planner/optimizer/optimizer.rs index 73213ecd31832..0764adf8a5354 100644 --- a/src/query/sql/src/planner/optimizer/optimizer.rs +++ b/src/query/sql/src/planner/optimizer/optimizer.rs @@ -49,7 +49,6 @@ use crate::plans::Mutation; use crate::plans::Operator; use crate::plans::Plan; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::SetScalarsOrQuery; use crate::InsertInputSource; diff --git a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs index 6d39e793a7231..9e55db0eebe4b 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs @@ -26,7 +26,7 @@ use crate::plans::ConstantTableScan; use crate::plans::Exchange; use crate::plans::Join; use crate::plans::JoinType; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Scan; #[derive(Default)] diff --git a/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs b/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs index 48432822b2e0f..beb4c237d05bd 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs @@ -34,7 +34,7 @@ use crate::optimizer::ir::SExpr; use crate::optimizer::optimizers::cascades::tasks::SharedCounter; use crate::optimizer::optimizers::cascades::tasks::TaskManager; use crate::optimizer::optimizers::cascades::CascadesOptimizer; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::IndexType; #[derive(Clone, Copy, Debug)] @@ -412,7 +412,7 @@ impl OptimizeExprTask { for enforcer in enforcers.iter() { let operator = enforcer.enforce()?; - let s_expr = SExpr::create_unary(Arc::new(operator), enforcer_child.clone()); + let s_expr = SExpr::create_unary(operator, enforcer_child.clone()); optimizer.memo.insert(Some(self.group_index), s_expr)?; } diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed.rs index c317c56ed5ed0..914728e17a45c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed.rs @@ -69,7 +69,7 @@ impl DistributedOptimizer { // Step 5: If not satisfied, manually enforce serial distribution if !root_required.satisfied_by(&physical_prop) { // Add an Exchange::Merge operator - result = SExpr::create_unary(Arc::new(Exchange::Merge.into()), Arc::new(result)); + result = SExpr::create_unary(Exchange::Merge, result); } Ok(result) diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs index 8da9082687815..30e3109df6e72 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs @@ -21,7 +21,7 @@ use crate::optimizer::ir::SExpr; use crate::plans::Exchange; use crate::plans::Join; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; pub struct BroadcastToShuffleOptimizer { pub matcher: Matcher, } diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs index 65b286bc06b78..abb7d4128b387 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs @@ -21,7 +21,7 @@ use crate::optimizer::ir::SExpr; use crate::plans::Exchange; use crate::plans::Limit; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Sort; pub struct SortAndLimitPushDownOptimizer { @@ -125,11 +125,10 @@ impl SortAndLimitPushDownOptimizer { let exchange_sexpr = exchange_sexpr.replace_plan(Arc::new(Exchange::MergeSort.into())); let child = exchange_sexpr.child(0)?.clone(); - let before_exchange_sort = - SExpr::create_unary(Arc::new(sort.clone().into()), Arc::new(child)); + let before_exchange_sort = SExpr::create_unary(sort.clone(), child); let new_exchange = exchange_sexpr.replace_children(vec![Arc::new(before_exchange_sort)]); sort.after_exchange = Some(true); - let new_plan = SExpr::create_unary(Arc::new(sort.into()), Arc::new(new_exchange)); + let new_plan = SExpr::create_unary(sort, new_exchange); Ok(new_plan) } @@ -157,7 +156,7 @@ impl SortAndLimitPushDownOptimizer { debug_assert!(exchange_sexpr.children.len() == 1); let child = exchange_sexpr.child(0)?.clone(); - let new_child = SExpr::create_unary(Arc::new(limit.into()), Arc::new(child)); + let new_child = SExpr::create_unary(limit.clone(), child); let new_exchange = exchange_sexpr.replace_children(vec![Arc::new(new_child)]); Ok(s_expr.replace_children(vec![Arc::new(new_exchange)])) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs index 868b55f05e935..a5cf8c8dd1639 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs @@ -36,7 +36,7 @@ use crate::optimizer::OptimizerContext; use crate::planner::QueryExecutor; use crate::plans::Filter; use crate::plans::JoinType; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::IndexType; use crate::MetadataRef; use crate::ScalarExpr; diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs index eb645151c4230..1177acc100cd7 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs @@ -31,7 +31,7 @@ use crate::plans::AggregateMode; use crate::plans::Limit; use crate::plans::Operator; use crate::plans::ProjectSet; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::UnionAll; use crate::MetadataRef; diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs index 4f4b1244d4e49..83f60a1ffb2c0 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs @@ -35,7 +35,7 @@ use crate::planner::QueryExecutor; use crate::plans::Aggregate; use crate::plans::AggregateFunction; use crate::plans::AggregateMode; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarItem; use crate::ColumnSet; use crate::MetadataRef; diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs index adb26fc7b2320..540837910c62c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs @@ -22,7 +22,7 @@ use crate::optimizer::optimizers::hyper_dp::JoinRelation; use crate::plans::Join; use crate::plans::JoinEquiCondition; use crate::plans::JoinType; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::IndexType; use crate::ScalarExpr; diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs index 86526124f5167..cd7c3b73d20b5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs @@ -21,7 +21,7 @@ use crate::optimizer::Optimizer; use crate::plans::Aggregate; use crate::plans::BoundColumnRef; use crate::plans::EvalScalar; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::ColumnBinding; diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs index 03a604ff86ebc..04c8a9c45c7ae 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs @@ -29,9 +29,9 @@ use crate::plans::DummyTableScan; use crate::plans::EvalScalar; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; +use crate::plans::Scan; use crate::ColumnBindingBuilder; use crate::MetadataRef; use crate::Visibility; @@ -58,7 +58,8 @@ impl RuleStatsAggregateOptimizer { children.push(Arc::new(child)); } let s_expr = s_expr.replace_children(children); - if let RelOperator::Aggregate(_) = s_expr.plan.as_ref() { + + if s_expr.plan.rel_op() == RelOp::Aggregate { self.normalize_aggregate(&s_expr).await } else { Ok(s_expr) @@ -66,7 +67,7 @@ impl RuleStatsAggregateOptimizer { } async fn normalize_aggregate(&self, s_expr: &SExpr) -> Result { - let agg: Aggregate = s_expr.plan().clone().try_into()?; + let agg: &Aggregate = s_expr.plan().as_any().downcast_ref().unwrap(); if s_expr.arity() != 1 || agg.grouping_sets.is_some() || !agg.group_items.is_empty() { return Ok(s_expr.clone()); } @@ -84,7 +85,7 @@ impl RuleStatsAggregateOptimizer { return Ok(s_expr.clone()); } - if let RelOperator::Scan(scan) = child.plan.as_ref() { + if let Some(scan) = child.plan.as_any().downcast_ref::() { if scan.prewhere.is_none() && scan.push_down_predicates.is_none() { let table = self.metadata.read().table(scan.table_index).table(); let schema = table.schema(); @@ -184,23 +185,14 @@ impl RuleStatsAggregateOptimizer { if agg_results.is_empty() { let leaf = SExpr::create_leaf(Arc::new(DummyTableScan.into())); - return Ok(SExpr::create_unary( - Arc::new(eval_scalar.into()), - Arc::new(leaf), - )); + return Ok(SExpr::create_unary(eval_scalar, leaf)); } else { let agg = Aggregate { aggregate_functions: agg_results, ..agg.clone() }; - let child = SExpr::create_unary( - Arc::new(agg.into()), - Arc::new(arg_eval_scalar.clone()), - ); - return Ok(SExpr::create_unary( - Arc::new(eval_scalar.into()), - Arc::new(child), - )); + let child = SExpr::create_unary(agg, arg_eval_scalar.clone()); + return Ok(SExpr::create_unary(eval_scalar, child)); } } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs index 0020fe11a7f46..04d8506d9cc7f 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs @@ -44,7 +44,7 @@ use crate::plans::Join; use crate::plans::JoinEquiCondition; use crate::plans::JoinType; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarExpr; use crate::plans::SubqueryComparisonOp; use crate::plans::SubqueryExpr; diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs index 16a8878897b8f..27ac85086920e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs @@ -41,7 +41,6 @@ use crate::plans::Join; use crate::plans::JoinEquiCondition; use crate::plans::Operator; use crate::plans::ProjectSet; -use crate::plans::RelOperator; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Scan; diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs index 079f80afcb9fe..e5852094f3c38 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs @@ -43,7 +43,7 @@ use crate::plans::Join; use crate::plans::JoinEquiCondition; use crate::plans::JoinType; use crate::plans::Limit; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Sort; @@ -183,7 +183,7 @@ impl SubqueryDecorrelatorOptimizer { for item in eval.items.iter_mut() { (item.scalar, outer) = self.try_rewrite_subquery(&item.scalar, outer, false)?; } - Ok(SExpr::create_unary(Arc::new(eval.into()), Arc::new(outer))) + Ok(SExpr::create_unary(eval, outer)) } RelOperator::Filter(plan) => { @@ -192,7 +192,7 @@ impl SubqueryDecorrelatorOptimizer { for pred in plan.predicates.iter_mut() { (*pred, outer) = self.try_rewrite_subquery(pred, outer, true)?; } - Ok(SExpr::create_unary(Arc::new(plan.into()), Arc::new(outer))) + Ok(SExpr::create_unary(plan, outer)) } RelOperator::ProjectSet(plan) => { @@ -201,7 +201,7 @@ impl SubqueryDecorrelatorOptimizer { for item in plan.srfs.iter_mut() { (item.scalar, outer) = self.try_rewrite_subquery(&item.scalar, outer, false)?; } - Ok(SExpr::create_unary(Arc::new(plan.into()), Arc::new(outer))) + Ok(SExpr::create_unary(plan, outer)) } RelOperator::Aggregate(plan) => { @@ -213,7 +213,7 @@ impl SubqueryDecorrelatorOptimizer { for item in plan.aggregate_functions.iter_mut() { (item.scalar, outer) = self.try_rewrite_subquery(&item.scalar, outer, false)?; } - Ok(SExpr::create_unary(Arc::new(plan.into()), Arc::new(outer))) + Ok(SExpr::create_unary(plan, outer)) } RelOperator::Window(plan) => { @@ -235,7 +235,7 @@ impl SubqueryDecorrelatorOptimizer { } } - Ok(SExpr::create_unary(Arc::new(plan.into()), Arc::new(outer))) + Ok(SExpr::create_unary(plan, outer)) } RelOperator::Sort(sort) => { @@ -253,18 +253,14 @@ impl SubqueryDecorrelatorOptimizer { ..sort.clone() }; - Ok(SExpr::create_unary(Arc::new(sort.into()), Arc::new(outer))) + Ok(SExpr::create_unary(sort, outer)) } RelOperator::Join(join) => { let mut left = self.optimize_sync(s_expr.left_child())?; let mut right = self.optimize_sync(s_expr.right_child())?; if !join.has_subquery() { - return Ok(SExpr::create_binary( - s_expr.plan.clone(), - Arc::new(left), - Arc::new(right), - )); + return Ok(SExpr::create_binary(join, left, right)); } let mut equi_conditions = join.equi_conditions.clone(); @@ -585,8 +581,7 @@ impl SubqueryDecorrelatorOptimizer { offset: 0, before_exchange: false, }; - subquery_expr = - SExpr::create_unary(Arc::new(limit.into()), Arc::new(subquery_expr)); + subquery_expr = SExpr::create_unary(limit, subquery_expr); // We will rewrite EXISTS subquery into the form `COUNT(*) = 1`. // For example, `EXISTS(SELECT a FROM t WHERE a > 1)` will be rewritten into @@ -656,7 +651,7 @@ impl SubqueryDecorrelatorOptimizer { }; // Filter: COUNT(*) = 1 or COUNT(*) != 1 // └── Aggregate: COUNT(*) - SExpr::create_unary(Arc::new(filter.into()), agg_s_expr) + SExpr::create_unary(filter, agg_s_expr) } else { let column_index = self.metadata.write().add_derived_column( "_exists_scalar_subquery".to_string(), @@ -670,7 +665,7 @@ impl SubqueryDecorrelatorOptimizer { index: column_index, }], }; - SExpr::create_unary(Arc::new(eval_scalar.into()), agg_s_expr) + SExpr::create_unary(eval_scalar, agg_s_expr) }; let cross_join = Join { diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs index c96800aec37f9..8cdd8a3dd0ea7 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs @@ -21,7 +21,7 @@ use crate::optimizer::ir::SExpr; use crate::optimizer::Optimizer; use crate::plans::Join; use crate::plans::JoinType; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::ScalarExpr; // The DeduplicateJoinConditionOptimizer uses the Union-Find algorithm to remove duplicate join conditions. diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs index 9425d2be65bc3..824f0d4bd526b 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs @@ -27,7 +27,7 @@ use crate::plans::Filter; use crate::plans::FunctionCall; use crate::plans::Join; use crate::plans::JoinType; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::ScalarItem; use crate::plans::WindowFuncType; use crate::MetadataRef; diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs index 94b7c863fbd4a..aa970f4329df2 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs @@ -19,7 +19,7 @@ use databend_common_exception::Result; use crate::optimizer::ir::SExpr; use crate::optimizer::Optimizer; use crate::plans::JoinType; -use crate::plans::RelOperator; +use crate::plans::Operator; // The SingleToInnerOptimizer will convert some single join to inner join. pub struct SingleToInnerOptimizer {} diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs index 22885188c78ee..78e7f0f667d57 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs @@ -35,9 +35,14 @@ use crate::plans::Aggregate; use crate::plans::AggregateFunctionScalarSortDesc; use crate::plans::BoundColumnRef; use crate::plans::ConstantExpr; +use crate::plans::EvalScalar; +use crate::plans::Filter; use crate::plans::FunctionCall; -use crate::plans::RelOperator; +use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::ScalarItem; +use crate::plans::Scan; +use crate::plans::Sort; use crate::plans::SortItem; use crate::ColumnBinding; use crate::ColumnEntry; @@ -89,28 +94,28 @@ impl QueryInfo { base_columns: &[ColumnEntry], s_expr: &SExpr, ) -> Result { - if let RelOperator::EvalScalar(eval) = s_expr.plan() { - let selection = eval; - + if let Some(selection) = s_expr.plan().as_any().downcast_ref::() { let mut predicates: std::option::Option<&[ScalarExpr]> = None; let mut sort_items = None; let mut aggregate = None; let mut column_map = HashMap::new(); - for item in &eval.items { + for item in &selection.items { column_map.insert(item.index, item.scalar.clone()); } // collect query info from the plan let mut s_expr = s_expr.child(0)?; loop { - match s_expr.plan() { - RelOperator::EvalScalar(eval) => { + match s_expr.plan().rel_op() { + RelOp::EvalScalar => { + let eval = s_expr.plan().as_any().downcast_ref::().unwrap(); for item in &eval.items { column_map.insert(item.index, item.scalar.clone()); } } - RelOperator::Aggregate(agg) => { + RelOp::Aggregate => { + let agg = s_expr.plan().as_any().downcast_ref::().unwrap(); if agg.grouping_sets.is_some() { return Err(ErrorCode::Internal("Grouping sets is not supported")); } @@ -123,7 +128,7 @@ impl QueryInfo { column_map.insert(item.index, item.scalar.clone()); } let child = s_expr.child(0)?; - if let RelOperator::EvalScalar(eval) = child.plan() { + if let Some(eval) = child.plan().as_any().downcast_ref::() { for item in &eval.items { column_map.insert(item.index, item.scalar.clone()); } @@ -131,13 +136,16 @@ impl QueryInfo { continue; } } - RelOperator::Sort(sort) => { + RelOp::Sort => { + let sort = s_expr.plan().as_any().downcast_ref::().unwrap(); sort_items = Some(sort.items.clone()); } - RelOperator::Filter(filter) => { + RelOp::Filter => { + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); predicates = Some(filter.predicates.as_ref()); } - RelOperator::Scan(scan) => { + RelOp::Scan => { + let scan = s_expr.plan().as_any().downcast_ref::().unwrap(); if let Some(prewhere) = &scan.prewhere { debug_assert!(predicates.is_none()); predicates = Some(prewhere.predicates.as_ref()); @@ -1338,15 +1346,11 @@ fn format_sort_desc( } fn push_down_index_scan(s_expr: &SExpr, agg_info: AggIndexInfo) -> Result { - Ok(match s_expr.plan() { - RelOperator::Scan(scan) => { - let mut new_scan = scan.clone(); - new_scan.agg_index = Some(agg_info); - s_expr.replace_plan(Arc::new(new_scan.into())) - } - _ => { - let child = push_down_index_scan(s_expr.child(0)?, agg_info)?; - s_expr.replace_children(vec![Arc::new(child)]) - } - }) + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { + let mut new_scan = scan.clone(); + new_scan.agg_index = Some(agg_info); + return Ok(s_expr.replace_plan(Arc::new(new_scan.into()))); + } + let child = push_down_index_scan(s_expr.child(0)?, agg_info)?; + Ok(s_expr.replace_children(vec![Arc::new(child)])) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs index 0c246862c8cc8..5b4f4144907e1 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs @@ -36,8 +36,8 @@ use crate::plans::EvalScalar; use crate::plans::FunctionCall; use crate::plans::Join; use crate::plans::JoinType; +use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::ScalarItem; use crate::ColumnSet; use crate::IndexType; @@ -694,16 +694,12 @@ impl Rule for RuleEagerAggregation { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate( - eager_group_by_and_eager_count[d].clone(), - )), + eager_group_by_and_eager_count[d].clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by_count_partial)), + eager_group_by_count_partial, if !eager_extra_eval_scalar_expr[0].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[0].clone(), - )), + eager_extra_eval_scalar_expr[0].clone(), Arc::new(join_expr.child(0)?.clone()), )) } else { @@ -719,16 +715,12 @@ impl Rule for RuleEagerAggregation { .replace_children(vec![Arc::new(join_expr.replace_children(vec![ Arc::new(join_expr.child(0)?.clone()), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate( - eager_group_by_and_eager_count[d].clone(), - )), + eager_group_by_and_eager_count[d].clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by_count_partial)), + eager_group_by_count_partial, if !eager_extra_eval_scalar_expr[1].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[1].clone(), - )), + eager_extra_eval_scalar_expr[1].clone(), Arc::new(join_expr.child(1)?.clone()), )) } else { @@ -759,18 +751,12 @@ impl Rule for RuleEagerAggregation { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate( - eager_group_by_and_eager_count[0].clone(), - )), + eager_group_by_and_eager_count[0].clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate( - eager_group_by_and_eager_count_partial[0].clone(), - )), + eager_group_by_and_eager_count_partial[0].clone(), if !eager_extra_eval_scalar_expr[0].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[0].clone(), - )), + eager_extra_eval_scalar_expr[0].clone(), Arc::new(join_expr.child(0)?.clone()), )) } else { @@ -779,18 +765,12 @@ impl Rule for RuleEagerAggregation { )), )), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate( - eager_group_by_and_eager_count[1].clone(), - )), + eager_group_by_and_eager_count[1].clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate( - eager_group_by_and_eager_count_partial[1].clone(), - )), + eager_group_by_and_eager_count_partial[1].clone(), if !eager_extra_eval_scalar_expr[1].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[1].clone(), - )), + eager_extra_eval_scalar_expr[1].clone(), Arc::new(join_expr.child(1)?.clone()), )) } else { @@ -968,14 +948,12 @@ impl Rule for RuleEagerAggregation { join_exprs.push(if d == 0 { join_expr.replace_children(vec![ Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by.clone())), + eager_group_by.clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by_partial)), + eager_group_by_partial, if !eager_extra_eval_scalar_expr[0].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[0].clone(), - )), + eager_extra_eval_scalar_expr[0].clone(), Arc::new(join_expr.child(0)?.clone()), )) } else { @@ -989,14 +967,12 @@ impl Rule for RuleEagerAggregation { join_expr.replace_children(vec![ Arc::new(join_expr.child(0)?.clone()), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by.clone())), + eager_group_by.clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by_partial)), + eager_group_by_partial, if !eager_extra_eval_scalar_expr[1].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[1].clone(), - )), + eager_extra_eval_scalar_expr[1].clone(), Arc::new(join_expr.child(1)?.clone()), )) } else { @@ -1023,9 +999,9 @@ impl Rule for RuleEagerAggregation { .replace_children(vec![Arc::new(join_expr.replace_children(vec![ Arc::new(join_expr.child(0)?.clone()), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count.clone())), + eager_count.clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count_partial)), + eager_count_partial, Arc::new(join_expr.child(1)?.clone()), )), )), @@ -1035,9 +1011,9 @@ impl Rule for RuleEagerAggregation { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count.clone())), + eager_count.clone(), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count_partial)), + eager_count_partial, Arc::new(join_expr.child(0)?.clone()), )), )), @@ -1062,14 +1038,12 @@ impl Rule for RuleEagerAggregation { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by)), + eager_group_by, Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_agg_partial)), + eager_agg_partial, if !eager_extra_eval_scalar_expr[0].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[0].clone(), - )), + eager_extra_eval_scalar_expr[0].clone(), Arc::new(join_expr.child(0)?.clone()), )) } else { @@ -1078,9 +1052,9 @@ impl Rule for RuleEagerAggregation { )), )), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count)), + eager_count, Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count_partial)), + eager_count_partial, Arc::new(join_expr.child(1)?.clone()), )), )), @@ -1090,21 +1064,19 @@ impl Rule for RuleEagerAggregation { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count)), + eager_count, Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_count_partial)), + eager_count_partial, Arc::new(join_expr.child(0)?.clone()), )), )), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_group_by)), + eager_group_by, Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Aggregate(eager_agg_partial)), + eager_agg_partial, if !eager_extra_eval_scalar_expr[1].items.is_empty() { Arc::new(SExpr::create_unary( - Arc::new(RelOperator::EvalScalar( - eager_extra_eval_scalar_expr[1].clone(), - )), + eager_extra_eval_scalar_expr[1].clone(), Arc::new(join_expr.child(1)?.clone()), )) } else { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs index bf2f1c1eb05ab..cb43212d3f684 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs @@ -23,7 +23,6 @@ use crate::plans::Aggregate; use crate::plans::Limit; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::Sort; use crate::plans::SortItem; @@ -115,11 +114,8 @@ impl RulePushDownRankLimitAggregate { window_partition: None, }; - let agg = SExpr::create_unary( - Arc::new(RelOperator::Aggregate(agg_limit)), - Arc::new(agg.child(0)?.clone()), - ); - let sort = SExpr::create_unary(Arc::new(RelOperator::Sort(sort)), agg); + let agg = SExpr::create_unary(agg_limit, Arc::new(agg.child(0)?.clone())); + let sort = SExpr::create_unary(sort, agg); let mut result = s_expr.replace_children(vec![Arc::new(sort)]); result.set_applied_rule(&self.id); @@ -179,10 +175,7 @@ impl RulePushDownRankLimitAggregate { agg_limit.rank_limit = Some((sort_items, limit)); - let agg = SExpr::create_unary( - Arc::new(RelOperator::Aggregate(agg_limit)), - Arc::new(agg_limit_expr.child(0)?.clone()), - ); + let agg = SExpr::create_unary(agg_limit, Arc::new(agg_limit_expr.child(0)?.clone())); let mut result = if has_eval_scalar { let eval_scalar = s_expr.child(0)?.replace_children(vec![Arc::new(agg)]); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_try_apply_agg_index.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_try_apply_agg_index.rs index 34deb672d077d..0c9885bc942b5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_try_apply_agg_index.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_try_apply_agg_index.rs @@ -19,8 +19,9 @@ use crate::optimizer::ir::Matcher; use crate::optimizer::ir::SExpr; use crate::optimizer::optimizers::rule::Rule; use crate::optimizer::optimizers::rule::RuleID; +use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Scan; use crate::IndexType; use crate::MetadataRef; @@ -260,16 +261,15 @@ impl Rule for RuleTryApplyAggIndex { impl RuleTryApplyAggIndex { fn get_table(&self, s_expr: &SExpr) -> (IndexType, String) { - match s_expr.plan() { - RelOperator::Scan(scan) => { - let metadata = self.metadata.read(); - let table = metadata.table(scan.table_index); - ( - scan.table_index, - format!("{}.{}.{}", table.catalog(), table.database(), table.name()), - ) - } - _ => self.get_table(s_expr.child(0).unwrap()), + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { + let metadata = self.metadata.read(); + let table = metadata.table(scan.table_index); + ( + scan.table_index, + format!("{}.{}.{}", table.catalog(), table.database(), table.name()), + ) + } else { + self.get_table(s_expr.child(0).unwrap()) } } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs index de1873f3562d8..dfbd5e79ab687 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs @@ -30,7 +30,6 @@ use crate::plans::ConstantTableScan; use crate::plans::Filter; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::ScalarExpr; use crate::MetadataRef; @@ -94,7 +93,7 @@ impl Rule for RuleEliminateFilter { } let empty_scan = ConstantTableScan::new_empty_scan(DataSchemaRefExt::create(fields), output_columns); - let result = SExpr::create_leaf(Arc::new(RelOperator::ConstantTableScan(empty_scan))); + let result = SExpr::create_leaf(empty_scan); state.add_result(result); return Ok(()); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs index 775e28b6326ea..22a3034c04c08 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs @@ -27,8 +27,8 @@ use crate::plans::Filter; use crate::plans::FunctionCall; use crate::plans::Join; use crate::plans::JoinType; +use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::ScalarExpr; const NULL_THRESHOLD_RATIO: f64 = 0.2; @@ -141,20 +141,14 @@ impl Rule for RuleFilterNulls { let left_null_filter = Filter { predicates: left_null_predicates, }; - left_child = SExpr::create_unary( - Arc::new(RelOperator::Filter(left_null_filter)), - Arc::new(left_child.clone()), - ); + left_child = SExpr::create_unary(left_null_filter, left_child.clone()); } if !right_null_predicates.is_empty() { let right_null_filter = Filter { predicates: right_null_predicates, }; - right_child = SExpr::create_unary( - Arc::new(RelOperator::Filter(right_null_filter)), - Arc::new(right_child.clone()), - ); + right_child = SExpr::create_unary(right_null_filter, right_child.clone()); } let mut res = s_expr.replace_children(vec![Arc::new(left_child), Arc::new(right_child)]); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs index 92f1083594cfd..f7228ae3cede8 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs @@ -25,8 +25,8 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Filter; use crate::plans::MutationSource; +use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::MetadataRef; pub struct RuleMergeFilterIntoMutation { @@ -76,7 +76,7 @@ impl Rule for RuleMergeFilterIntoMutation { mutation.predicate_column_index = Some(column_index); } - let new_expr = SExpr::create_leaf(Arc::new(RelOperator::MutationSource(mutation))); + let new_expr = SExpr::create_leaf(mutation); state.add_result(new_expr); Ok(()) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs index 8b79fb74569f1..263b67851b995 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs @@ -114,16 +114,16 @@ impl Rule for RulePushDownFilterEvalScalar { let pushed_down_filter = Filter { predicates: pushed_down_predicates, }; - result = SExpr::create_unary(Arc::new(pushed_down_filter.into()), Arc::new(result)); + result = SExpr::create_unary(pushed_down_filter, result); } - result = SExpr::create_unary(Arc::new(eval_scalar.into()), Arc::new(result)); + result = SExpr::create_unary(eval_scalar, result); if !remaining_predicates.is_empty() { let remaining_filter = Filter { predicates: remaining_predicates, }; - result = SExpr::create_unary(Arc::new(remaining_filter.into()), Arc::new(result)); + result = SExpr::create_unary(remaining_filter, result); result.set_applied_rule(&self.id); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs index 448696cdc992d..2ec3f845010de 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs @@ -105,15 +105,11 @@ impl Rule for RulePushDownFilterUnion { }; let s = (*union_sexpr).clone(); - **union_sexpr = SExpr::create_unary(Arc::new(filter.into()), Arc::new(s)); + **union_sexpr = SExpr::create_unary(filter, s); } // Create a filter which matches union's right child. - let result = SExpr::create_binary( - Arc::new(union.into()), - Arc::new(union_left_child), - Arc::new(union_right_child), - ); + let result = SExpr::create_binary(union, union_left_child, union_right_child); state.add_result(result); Ok(()) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs index 42347e145b96a..d448691a5aed4 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs @@ -32,7 +32,6 @@ use crate::plans::ConstantTableScan; use crate::plans::Filter; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::ScalarExpr; use crate::plans::Sort; use crate::plans::Window; @@ -116,7 +115,7 @@ impl Rule for RulePushDownFilterWindowTopN { .collect::>(); let empty_scan = ConstantTableScan::new_empty_scan(DataSchemaRefExt::create(fields), output_columns); - let result = SExpr::create_leaf(Arc::new(RelOperator::ConstantTableScan(empty_scan))); + let result = SExpr::create_leaf(empty_scan); state.add_result(result); return Ok(()); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs index 7b0f3ecc62a23..76f0d7349147c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs @@ -21,8 +21,8 @@ use crate::optimizer::optimizers::rule::Rule; use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::EvalScalar; +use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::Sort; use crate::MetadataRef; @@ -84,14 +84,8 @@ impl Rule for RulePushDownSortEvalScalar { } let eval_scalar: EvalScalar = eval_plan.plan().clone().try_into()?; - let sort_expr = SExpr::create_unary( - Arc::new(RelOperator::Sort(sort)), - Arc::new(eval_plan.child(0)?.clone()), - ); - let mut result = SExpr::create_unary( - Arc::new(RelOperator::EvalScalar(eval_scalar)), - Arc::new(sort_expr), - ); + let sort_expr = SExpr::create_unary(sort, eval_plan.child(0)?.clone()); + let mut result = SExpr::create_unary(eval_scalar, sort_expr); result.set_applied_rule(&self.id); state.add_result(result); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs index 937e0885295b3..708780b495a2f 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs @@ -22,8 +22,8 @@ use crate::optimizer::ir::SExpr; use crate::optimizer::optimizers::rule::Rule; use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; +use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; use crate::plans::Sort; /// Input: Sort diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs index ee56772021499..b2b3604d3eef5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs @@ -72,13 +72,13 @@ pub fn convert_mark_to_semi_join(s_expr: &SExpr) -> Result<(SExpr, bool)> { let s_join_expr = s_expr.child(0)?; let mut result = SExpr::create_binary( - Arc::new(join.into()), - Arc::new(s_join_expr.child(0)?.clone()), - Arc::new(s_join_expr.child(1)?.clone()), + join, + s_join_expr.child(0)?.clone(), + s_join_expr.child(1)?.clone(), ); if !filter.predicates.is_empty() { - result = SExpr::create_unary(Arc::new(filter.into()), Arc::new(result)); + result = SExpr::create_unary(filter, result); } Ok((result, true)) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs index 46ebf4648860d..e1e868e442894 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs @@ -27,7 +27,7 @@ use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Join; use crate::plans::JoinType; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::IndexType; use crate::ScalarExpr; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs index 050b813d79e3c..6961afd249888 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs @@ -28,7 +28,7 @@ use crate::plans::ConstantTableScan; use crate::plans::Limit; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::MetadataRef; pub struct RulePushDownLimit { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs index 481e6cfec8f1a..165e602c6d3bc 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs @@ -22,7 +22,7 @@ use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::EvalScalar; use crate::plans::Limit; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; /// Input: Limit /// \ diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs index 509b87d87292e..6a41bad96eba2 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs @@ -23,7 +23,7 @@ use crate::plans::Join; use crate::plans::JoinType; use crate::plans::Limit; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; /// Input: Limit /// | diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs index 0729f3c5b6cc3..4df803076359a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs @@ -24,7 +24,7 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Limit; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Scan; /// Input: Limit diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs index a0c540e43625d..301e46b480108 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs @@ -22,7 +22,7 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Limit; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Sort; /// Input: Limit diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs index 49a38925cf160..e874359181e76 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs @@ -79,18 +79,10 @@ impl Rule for RulePushDownLimitUnion { let mut union_right_child = union_s_expr.child(1)?.clone(); // Add limit to union children - union_left_child = SExpr::create_unary( - Arc::new(new_limit.clone().into()), - Arc::new(union_left_child), - ); - union_right_child = - SExpr::create_unary(Arc::new(new_limit.into()), Arc::new(union_right_child)); + union_left_child = SExpr::create_unary(new_limit.clone(), union_left_child); + union_right_child = SExpr::create_unary(new_limit, union_right_child); - let mut result = SExpr::create_binary( - Arc::new(union.into()), - Arc::new(union_left_child), - Arc::new(union_right_child), - ); + let mut result = SExpr::create_binary(union, union_left_child, union_right_child); // Add original limit to top result = s_expr.replace_children(vec![Arc::new(result)]); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs index 1a427ed642511..85eccfee4a373 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs @@ -23,7 +23,7 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Limit; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Window as LogicalWindow; use crate::plans::WindowFuncFrame; use crate::plans::WindowFuncFrameBound; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs index 46867867acde7..4f2b40e5cc4d9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs @@ -27,7 +27,7 @@ use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::ConstantTableScan; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::UnionAll; use crate::MetadataRef; diff --git a/src/query/sql/src/planner/optimizer/pipeline/common.rs b/src/query/sql/src/planner/optimizer/pipeline/common.rs index 26aa6e6556415..e6c139984f1d9 100644 --- a/src/query/sql/src/planner/optimizer/pipeline/common.rs +++ b/src/query/sql/src/planner/optimizer/pipeline/common.rs @@ -15,7 +15,9 @@ use databend_common_catalog::table::DistributionLevel; use crate::optimizer::ir::SExpr; -use crate::plans::RelOperator; +use crate::plans::Operator; +use crate::plans::RelOp; +use crate::plans::Scan; use crate::MetadataRef; /// Check if a query will read data from local tables(e.g. system tables). @@ -23,11 +25,11 @@ pub fn contains_local_table_scan(s_expr: &SExpr, metadata: &MetadataRef) -> bool s_expr .children() .any(|s_expr| contains_local_table_scan(s_expr, metadata)) - || if let RelOperator::Scan(get) = s_expr.plan() { + || if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { matches!( metadata .read() - .table(get.table_index) + .table(scan.table_index) .table() .distribution_level(), DistributionLevel::Local @@ -35,7 +37,7 @@ pub fn contains_local_table_scan(s_expr: &SExpr, metadata: &MetadataRef) -> bool } else { false } - || matches!(s_expr.plan(), RelOperator::RecursiveCteScan { .. }) + || matches!(s_expr.plan().rel_op(), RelOp::RecursiveCteScan) } pub fn contains_warehouse_table_scan(s_expr: &SExpr, metadata: &MetadataRef) -> bool { diff --git a/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs b/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs index 5d4cc35ade525..48d50d271b020 100644 --- a/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs +++ b/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs @@ -28,7 +28,7 @@ use crate::optimizer::OptimizerContext; use crate::plans::ConstantExpr; use crate::plans::Filter; use crate::plans::FunctionCall; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::Statistics; use crate::BaseTableColumn; use crate::ColumnEntry; diff --git a/src/query/sql/src/planner/plans/mutation_source.rs b/src/query/sql/src/planner/plans/mutation_source.rs index 37c42784d7146..955b6f58730e9 100644 --- a/src/query/sql/src/planner/plans/mutation_source.rs +++ b/src/query/sql/src/planner/plans/mutation_source.rs @@ -108,4 +108,8 @@ impl Operator for MutationSource { "Cannot compute required property for children of MutationSource".to_string(), )) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 70a7c121068d4..05b7c88abd7ce 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -51,7 +51,7 @@ use crate::ScalarExpr; pub type OperatorRef = Arc; -pub trait Operator { +pub trait Operator: Send + Sync + 'static { /// Get relational operator kind fn rel_op(&self) -> RelOp; diff --git a/src/query/sql/src/planner/plans/plan.rs b/src/query/sql/src/planner/plans/plan.rs index da1d925eead2d..2a28807ed6ce9 100644 --- a/src/query/sql/src/planner/plans/plan.rs +++ b/src/query/sql/src/planner/plans/plan.rs @@ -128,7 +128,7 @@ use crate::plans::RefreshIndexPlan; use crate::plans::RefreshTableCachePlan; use crate::plans::RefreshTableIndexPlan; use crate::plans::RefreshVirtualColumnPlan; -use crate::plans::RelOperator; +use crate::plans::Operator; use crate::plans::RemoveStagePlan; use crate::plans::RenameDatabasePlan; use crate::plans::RenameTableColumnPlan; diff --git a/src/query/sql/src/planner/plans/project_set.rs b/src/query/sql/src/planner/plans/project_set.rs index 2ef3602480f9a..66b7ef581a178 100644 --- a/src/query/sql/src/planner/plans/project_set.rs +++ b/src/query/sql/src/planner/plans/project_set.rs @@ -23,6 +23,7 @@ use crate::optimizer::ir::StatInfo; use crate::plans::Operator; use crate::plans::RelOp; use crate::plans::ScalarItem; +use crate::ScalarExpr; /// `ProjectSet` is a plan that evaluate a series of /// set-returning functions, zip the result together, @@ -93,4 +94,8 @@ impl Operator for ProjectSet { let mut input_stat = rel_expr.derive_cardinality_child(0)?.deref().clone(); self.derive_project_set_stats(&mut input_stat) } + + fn as_any(&self) -> &dyn std::any::Any { + self + } } diff --git a/src/query/sql/src/planner/plans/recluster.rs b/src/query/sql/src/planner/plans/recluster.rs index 2313d3320ea13..b9a8d7e79aac4 100644 --- a/src/query/sql/src/planner/plans/recluster.rs +++ b/src/query/sql/src/planner/plans/recluster.rs @@ -28,8 +28,9 @@ use crate::optimizer::ir::SExpr; use crate::optimizer::optimize; use crate::optimizer::OptimizerContext; use crate::plans::ConstantExpr; +use crate::plans::Operator; use crate::plans::Plan; -use crate::plans::RelOperator; +use crate::plans::Scan; use crate::Binder; use crate::MetadataRef; use crate::NameResolutionContext; @@ -47,21 +48,20 @@ pub struct ReclusterPlan { } pub fn set_update_stream_columns(s_expr: &SExpr) -> Result { - match s_expr.plan() { - RelOperator::Scan(scan) if scan.table_index == 0 => { + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { + if scan.table_index == 0 { let mut scan = scan.clone(); scan.set_update_stream_columns(true); - Ok(SExpr::create_leaf(Arc::new(scan.into()))) - } - _ => { - let mut children = Vec::with_capacity(s_expr.arity()); - for child in s_expr.children() { - let child = set_update_stream_columns(child)?; - children.push(Arc::new(child)); - } - Ok(s_expr.replace_children(children)) + return Ok(SExpr::create_leaf(Arc::new(scan.into()))); } } + + let mut children = Vec::with_capacity(s_expr.arity()); + for child in s_expr.children() { + let child = set_update_stream_columns(child)?; + children.push(Arc::new(child)); + } + Ok(s_expr.replace_children(children)) } #[async_backtrace::framed] diff --git a/src/query/sql/src/planner/plans/udf.rs b/src/query/sql/src/planner/plans/udf.rs index 5cb43bb743ed7..cc57866603103 100644 --- a/src/query/sql/src/planner/plans/udf.rs +++ b/src/query/sql/src/planner/plans/udf.rs @@ -25,6 +25,7 @@ use crate::plans::Operator; use crate::plans::RelOp; use crate::plans::ScalarItem; use crate::ColumnSet; +use crate::ScalarExpr; /// `Udf` is a plan that evaluate a series of udf functions. #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/query/sql/src/planner/semantic/async_function_rewriter.rs b/src/query/sql/src/planner/semantic/async_function_rewriter.rs index adc33a98edefd..4f1236f85d1b3 100644 --- a/src/query/sql/src/planner/semantic/async_function_rewriter.rs +++ b/src/query/sql/src/planner/semantic/async_function_rewriter.rs @@ -25,7 +25,10 @@ use crate::plans::AsyncFunction; use crate::plans::AsyncFunctionCall; use crate::plans::BoundColumnRef; use crate::plans::EvalScalar; -use crate::plans::RelOperator; +use crate::plans::Filter; +use crate::plans::Mutation; +use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::VisitorMut; @@ -71,8 +74,9 @@ impl AsyncFunctionRewriter { } // Rewrite async function and its arguments as derived column. - match (*s_expr.plan).clone() { - RelOperator::EvalScalar(mut plan) => { + match s_expr.plan.rel_op() { + RelOp::EvalScalar => { + let plan = s_expr.plan.as_any().downcast_mut::().unwrap(); for item in &plan.items { // The index of async function item can be reused. if let ScalarExpr::AsyncFunctionCall(async_func) = &item.scalar { @@ -84,18 +88,20 @@ impl AsyncFunctionRewriter { self.visit(&mut item.scalar)?; } let child_expr = self.create_async_func_expr(s_expr.children[0].clone()); - let new_expr = SExpr::create_unary(Arc::new(plan.into()), child_expr); + let new_expr = SExpr::create_unary(plan, child_expr); Ok(new_expr) } - RelOperator::Filter(mut plan) => { + RelOp::Filter => { + let plan = s_expr.plan.as_any().downcast_mut::().unwrap(); for scalar in &mut plan.predicates { self.visit(scalar)?; } let child_expr = self.create_async_func_expr(s_expr.children[0].clone()); - let new_expr = SExpr::create_unary(Arc::new(plan.into()), child_expr); + let new_expr = SExpr::create_unary(plan, child_expr); Ok(new_expr) } - RelOperator::Mutation(mut plan) => { + RelOp::Mutation => { + let plan = s_expr.plan.as_any().downcast_mut::().unwrap(); for matched_evaluator in plan.matched_evaluators.iter_mut() { if let Some(condition) = matched_evaluator.condition.as_mut() { self.visit(condition)?; @@ -107,7 +113,7 @@ impl AsyncFunctionRewriter { } } let child_expr = self.create_async_func_expr(s_expr.children[0].clone()); - let new_expr = SExpr::create_unary(Arc::new(plan.into()), child_expr); + let new_expr = SExpr::create_unary(plan, child_expr); Ok(new_expr) } _ => Ok(s_expr), diff --git a/src/query/sql/src/planner/semantic/udf_rewriter.rs b/src/query/sql/src/planner/semantic/udf_rewriter.rs index 31ec866119f7b..ae5ca9b6e863d 100644 --- a/src/query/sql/src/planner/semantic/udf_rewriter.rs +++ b/src/query/sql/src/planner/semantic/udf_rewriter.rs @@ -23,7 +23,10 @@ use crate::optimizer::ir::SExpr; use crate::plans::walk_expr_mut; use crate::plans::BoundColumnRef; use crate::plans::EvalScalar; -use crate::plans::RelOperator; +use crate::plans::Filter; +use crate::plans::Mutation; +use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::UDFCall; @@ -73,8 +76,9 @@ impl UdfRewriter { } // Rewrite Udf and its arguments as derived column. - match (*s_expr.plan).clone() { - RelOperator::EvalScalar(mut plan) => { + match s_expr.plan.rel_op() { + RelOp::EvalScalar => { + let plan = s_expr.plan.as_any().downcast_mut::().unwrap(); for item in &plan.items { // The index of Udf item can be reused. if let ScalarExpr::UDFCall(udf) = &item.scalar { @@ -82,22 +86,25 @@ impl UdfRewriter { .insert(udf.display_name.clone(), item.index); } } + for item in &mut plan.items { self.visit(&mut item.scalar)?; } let child_expr = self.create_udf_expr(s_expr.children[0].clone()); - let new_expr = SExpr::create_unary(Arc::new(plan.into()), child_expr); + let new_expr = SExpr::create_unary(plan, child_expr); Ok(new_expr) } - RelOperator::Filter(mut plan) => { + RelOp::Filter => { + let plan = s_expr.plan.as_any().downcast_mut::().unwrap(); for scalar in &mut plan.predicates { self.visit(scalar)?; } let child_expr = self.create_udf_expr(s_expr.children[0].clone()); - let new_expr = SExpr::create_unary(Arc::new(plan.into()), child_expr); + let new_expr = SExpr::create_unary(plan, child_expr); Ok(new_expr) } - RelOperator::Mutation(mut plan) => { + RelOp::Mutation => { + let plan = s_expr.plan.as_any().downcast_mut::().unwrap(); for matched_evaluator in plan.matched_evaluators.iter_mut() { if let Some(condition) = matched_evaluator.condition.as_mut() { self.visit(condition)?; @@ -109,7 +116,7 @@ impl UdfRewriter { } } let child_expr = self.create_udf_expr(s_expr.children[0].clone()); - let new_expr = SExpr::create_unary(Arc::new(plan.into()), child_expr); + let new_expr = SExpr::create_unary(plan, child_expr); Ok(new_expr) } _ => Ok(s_expr), @@ -127,10 +134,7 @@ impl UdfRewriter { items: scalar_items, }; - child_expr = Arc::new(SExpr::create_unary( - Arc::new(eval_scalar.into()), - child_expr, - )); + child_expr = Arc::new(SExpr::create_unary(eval_scalar, child_expr)); } let udf_functions = self.udf_functions.pop_front().unwrap(); @@ -138,7 +142,7 @@ impl UdfRewriter { items: udf_functions, script_udf: self.script_udf, }; - child_expr = Arc::new(SExpr::create_unary(Arc::new(udf_plan.into()), child_expr)); + child_expr = Arc::new(SExpr::create_unary(udf_plan, child_expr)); } child_expr } From c6c7b6c61f187529d8479bd62057aed928c701cd Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Thu, 3 Jul 2025 09:34:48 +0800 Subject: [PATCH 05/14] update --- .../src/planner/optimizer/ir/expr/s_expr.rs | 6 +-- .../filter_rules/rule_push_down_sort_scan.rs | 23 +++++++---- .../join_rules/rule_semi_to_inner_join.rs | 41 ++++++++++--------- .../rule/limit_rules/rule_push_down_limit.rs | 3 +- .../rule_push_down_limit_expression.rs | 12 ++---- .../limit_rules/rule_push_down_limit_join.rs | 23 ++++++----- .../limit_rules/rule_push_down_limit_scan.rs | 4 +- .../limit_rules/rule_push_down_limit_sort.rs | 7 +--- .../rule_push_down_limit_window.rs | 13 +++--- .../rule/union_rules/rule_eliminate_union.rs | 10 ++--- src/query/sql/src/planner/plans/operator.rs | 2 - 11 files changed, 67 insertions(+), 77 deletions(-) diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 515f310f4d680..8b6ad4c56b37b 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -29,7 +29,6 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::plans::Exchange; use crate::plans::Operator; use crate::plans::OperatorRef; -use crate::plans::Operator; use crate::plans::Scan; use crate::plans::WindowFuncType; use crate::IndexType; @@ -103,7 +102,7 @@ impl SExpr { ) } - pub fn create_leaf(plan: Arc) -> Self { + pub fn create_leaf(plan: P) -> Self { Self::create(plan, [], None, None, None) } @@ -507,8 +506,7 @@ impl SExpr { | crate::plans::RelOp::AsyncFunction | crate::plans::RelOp::MergeInto | crate::plans::RelOp::CompactBlock - | crate::plans::RelOp::MutationSource - | crate::plans::RelOp::Pattern => self.child(0)?.get_data_distribution(), + | crate::plans::RelOp::MutationSource => self.child(0)?.get_data_distribution(), } } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs index 708780b495a2f..792d4087be9d7 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs @@ -24,6 +24,7 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Operator; use crate::plans::RelOp; +use crate::plans::Scan; use crate::plans::Sort; /// Input: Sort @@ -74,14 +75,20 @@ impl Rule for RulePushDownSortScan { fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { let sort: Sort = s_expr.plan().clone().try_into()?; let child = s_expr.child(0)?; - let mut get = match child.plan() { - RelOperator::Scan(scan) => scan.clone(), - RelOperator::EvalScalar(_) => { + + let mut get = match child.plan().rel_op() { + RelOp::Scan => { + let s = child.plan().as_any().downcast_ref::().unwrap(); + s.clone() + } + RelOp::EvalScalar => { let child = child.child(0)?; - child.plan().clone().try_into()? + let s = child.plan().as_any().downcast_ref::().unwrap(); + s.clone() } _ => unreachable!(), }; + if get.order_by.is_none() { get.order_by = Some(sort.items); } @@ -89,11 +96,11 @@ impl Rule for RulePushDownSortScan { get.limit = Some(get.limit.map_or(limit, |c| cmp::max(c, limit))); } - let get = SExpr::create_leaf(Arc::new(RelOperator::Scan(get))); + let get = SExpr::create_leaf(get); - let mut result = match child.plan() { - RelOperator::Scan(_) => s_expr.replace_children(vec![Arc::new(get)]), - RelOperator::EvalScalar(_) => { + let mut result = match child.plan().rel_op() { + RelOp::Scan => s_expr.replace_children(vec![Arc::new(get)]), + RelOp::EvalScalar => { let child = child.replace_children(vec![Arc::new(get)]); s_expr.replace_children(vec![Arc::new(child)]) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs index e1e868e442894..b6baa14ea962a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs @@ -24,10 +24,11 @@ use crate::optimizer::ir::SExpr; use crate::optimizer::optimizers::rule::Rule; use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; +use crate::plans::Aggregate; use crate::plans::Join; use crate::plans::JoinType; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; use crate::IndexType; use crate::ScalarExpr; @@ -126,33 +127,33 @@ fn find_group_by_keys( group_by_keys: &mut HashMap>, ) -> Result<()> { match child.plan() { - RelOperator::EvalScalar(_) | RelOperator::Filter(_) | RelOperator::Window(_) => { + RelOp::EvalScalar | RelOp::Filter | RelOp::Window => { find_group_by_keys(child.child(0)?, group_by_keys)?; } - RelOperator::Aggregate(agg) => { + RelOp::Aggregate => { + let agg = child.plan().as_any().downcast_ref::().unwrap(); for item in agg.group_items.iter() { if let ScalarExpr::BoundColumnRef(c) = &item.scalar { group_by_keys.insert(c.column.index, c.column.data_type.clone()); } } } - RelOperator::Sort(_) - | RelOperator::Limit(_) - | RelOperator::Exchange(_) - | RelOperator::UnionAll(_) - | RelOperator::DummyTableScan(_) - | RelOperator::ProjectSet(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::CacheScan(_) - | RelOperator::Udf(_) - | RelOperator::Scan(_) - | RelOperator::AsyncFunction(_) - | RelOperator::Join(_) - | RelOperator::RecursiveCteScan(_) - | RelOperator::Mutation(_) - | RelOperator::MutationSource(_) - | RelOperator::CompactBlock(_) => {} + RelOp::Sort + | RelOp::Limit + | RelOp::Exchange + | RelOp::UnionAll + | RelOp::DummyTableScan + | RelOp::ProjectSet + | RelOp::ConstantTableScan + | RelOp::ExpressionScan + | RelOp::CacheScan + | RelOp::Udf + | RelOp::Scan + | RelOp::AsyncFunction + | RelOp::Join + | RelOp::RecursiveCteScan + | RelOp::MutationSource + | RelOp::CompactBlock => {} } Ok(()) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs index 6961afd249888..b79a6412711a8 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs @@ -28,7 +28,6 @@ use crate::plans::ConstantTableScan; use crate::plans::Limit; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::Operator; use crate::MetadataRef; pub struct RulePushDownLimit { @@ -74,7 +73,7 @@ impl Rule for RulePushDownLimit { } let empty_scan = ConstantTableScan::new_empty_scan(DataSchemaRefExt::create(fields), output_columns); - let result = SExpr::create_leaf(Arc::new(RelOperator::ConstantTableScan(empty_scan))); + let result = SExpr::create_leaf(empty_scan); state.add_result(result); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs index 165e602c6d3bc..26041a74ca9ae 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs @@ -21,8 +21,8 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::EvalScalar; use crate::plans::Limit; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; /// Input: Limit /// \ @@ -69,14 +69,8 @@ impl Rule for RulePushDownLimitEvalScalar { let eval_plan = s_expr.child(0)?; let eval_scalar: EvalScalar = eval_plan.plan().clone().try_into()?; - let limit_expr = SExpr::create_unary( - Arc::new(RelOperator::Limit(limit)), - Arc::new(eval_plan.child(0)?.clone()), - ); - let mut result = SExpr::create_unary( - Arc::new(RelOperator::EvalScalar(eval_scalar)), - Arc::new(limit_expr), - ); + let limit_expr = SExpr::create_unary(limit, eval_plan.child(0)?.clone()); + let mut result = SExpr::create_unary(eval_scalar, limit_expr); result.set_applied_rule(&self.id); state.add_result(result); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs index 6a41bad96eba2..fa13882ded1e3 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs @@ -22,8 +22,8 @@ use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Join; use crate::plans::JoinType; use crate::plans::Limit; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; /// Input: Limit /// | @@ -76,18 +76,15 @@ impl Rule for RulePushDownLimitOuterJoin { match join.join_type { JoinType::Left => { let child = child.replace_children(vec![ - Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Limit(limit.clone())), - Arc::new(child.child(0)?.clone()), - )), + Arc::new(SExpr::create_unary(limit, child.child(0)?.clone())), Arc::new(child.child(1)?.clone()), ]); let mut result = SExpr::create_unary( - Arc::new(RelOperator::Limit(Limit { + Arc::new(Limit { before_exchange: limit.before_exchange, limit: limit.limit, offset: 0, - })), + }), Arc::new(child), ); result.set_applied_rule(&self.id); @@ -97,16 +94,20 @@ impl Rule for RulePushDownLimitOuterJoin { let child = Arc::new(child.replace_children(vec![ Arc::new(child.child(0)?.clone()), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Limit(limit.clone())), - Arc::new(child.child(1)?.clone()), + Limit { + before_exchange: limit.before_exchange, + limit: limit.limit, + offset: 0, + }, + child.child(1)?.clone(), )), ])); let mut result = SExpr::create_unary( - Arc::new(RelOperator::Limit(Limit { + Limit { before_exchange: limit.before_exchange, limit: limit.limit, offset: 0, - })), + }, child, ); result.set_applied_rule(&self.id); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs index 4df803076359a..d9924eb31e087 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs @@ -23,8 +23,8 @@ use crate::optimizer::optimizers::rule::Rule; use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Limit; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::Scan; /// Input: Limit @@ -70,7 +70,7 @@ impl Rule for RulePushDownLimitScan { let child = s_expr.child(0)?; let mut get: Scan = child.plan().clone().try_into()?; get.limit = Some(get.limit.map_or(count, |c| cmp::max(c, count))); - let get = SExpr::create_leaf(Arc::new(RelOperator::Scan(get))); + let get = SExpr::create_leaf(get); let mut result = s_expr.replace_children(vec![Arc::new(get)]); result.set_applied_rule(&self.id); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs index 301e46b480108..eaedcfdc0ec86 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs @@ -21,8 +21,8 @@ use crate::optimizer::optimizers::rule::Rule; use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Limit; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::Sort; /// Input: Limit @@ -77,10 +77,7 @@ impl Rule for RulePushDownLimitSort { if limit <= self.max_limit { sort_limit.limit = Some(limit); - let sort = SExpr::create_unary( - Arc::new(RelOperator::Sort(sort_limit)), - Arc::new(sort.child(0)?.clone()), - ); + let sort = SExpr::create_unary(sort_limit, sort.child(0)?.clone()); let mut result = s_expr.replace_children(vec![Arc::new(sort)]); result.set_applied_rule(&self.id); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs index 85eccfee4a373..b9a1b5fa74341 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs @@ -22,8 +22,8 @@ use crate::optimizer::optimizers::rule::Rule; use crate::optimizer::optimizers::rule::RuleID; use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::Limit; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::Window as LogicalWindow; use crate::plans::WindowFuncFrame; use crate::plans::WindowFuncFrameBound; @@ -88,10 +88,7 @@ impl Rule for RulePushDownLimitWindow { } window_limit.limit = Some(limit); - let sort = SExpr::create_unary( - Arc::new(RelOperator::Window(window_limit)), - Arc::new(window.child(0)?.clone()), - ); + let sort = SExpr::create_unary(window_limit, window.child(0)?.clone()); let mut result = s_expr.replace_children(vec![Arc::new(sort)]); result.set_applied_rule(&self.id); state.add_result(result); @@ -128,9 +125,9 @@ fn is_valid_frame(frame: &WindowFuncFrame) -> bool { } fn child_has_window(child: &SExpr) -> bool { - match child.plan() { - RelOperator::Window(_) => true, - RelOperator::Scan(_) => false, // finish recursion + match child.plan().rel_op() { + RelOp::Window => true, + RelOp::Scan => false, // finish recursion _ => child.children().any(child_has_window), } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs index 4f2b40e5cc4d9..a9b7572e9dc8e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs @@ -27,7 +27,6 @@ use crate::optimizer::optimizers::rule::TransformResult; use crate::plans::ConstantTableScan; use crate::plans::Operator; use crate::plans::RelOp; -use crate::plans::Operator; use crate::plans::UnionAll; use crate::MetadataRef; @@ -55,10 +54,9 @@ impl RuleEliminateUnion { return Ok(false); } if child_num == 0 { - Ok(matches!( - s_expr.plan(), - RelOperator::ConstantTableScan(ConstantTableScan { num_rows: 0, .. }) - )) + if let Some(empty_scan) = s_expr.plan().as_any().downcast_ref::() { + return Ok(empty_scan.num_rows == 0); + } } else { Self::is_empty_scan(s_expr.child(0)?) } @@ -108,7 +106,7 @@ impl Rule for RuleEliminateUnion { DataSchemaRefExt::create(fields), union_output_columns, ); - let result = SExpr::create_leaf(Arc::new(RelOperator::ConstantTableScan(empty_scan))); + let result = SExpr::create_leaf(empty_scan); state.add_result(result); } else if Self::is_empty_scan(right_child)? { // If right child is empty, use left child diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 05b7c88abd7ce..613f93c2c415e 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -140,9 +140,7 @@ pub enum RelOp { MergeInto, CompactBlock, MutationSource, - // Pattern - Pattern, } #[macro_export] From a19a15df64c8e101135c7a96d23d5870ad7ddc1c Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Thu, 3 Jul 2025 14:59:07 +0800 Subject: [PATCH 06/14] update --- .../sql/planner/optimizer/ir/expr/visitor.rs | 18 +- .../sql/planner/optimizer/optimizer_test.rs | 7 +- .../filter/deduplicate_join_condition_test.rs | 8 +- .../rule/agg_rules/agg_index_query_rewrite.rs | 7 +- .../push_down_filter_join_test.rs | 82 ++++----- .../it/sql/planner/optimizer/test_utils.rs | 17 +- .../src/planner/optimizer/ir/expr/s_expr.rs | 4 +- .../sql/src/planner/optimizer/ir/format.rs | 54 +++--- .../sql/src/planner/optimizer/optimizer.rs | 15 +- .../distributed/distributed_merge.rs | 4 +- .../optimizers/distributed/sort_and_limit.rs | 4 +- .../filter/deduplicate_join_condition.rs | 3 +- .../operator/filter/pull_up_filter.rs | 4 +- .../operator/join/single_to_inner.rs | 5 +- .../rule/agg_rules/agg_index/query_rewrite.rs | 2 +- .../rule/agg_rules/rule_eager_aggregation.rs | 22 +-- .../rule_push_down_filter_window_top_n.rs | 5 +- .../src/planner/optimizer/pipeline/common.rs | 2 +- .../statistics/collect_statistics.rs | 167 +++++++++--------- src/query/sql/src/planner/plans/operator.rs | 4 + 20 files changed, 214 insertions(+), 220 deletions(-) diff --git a/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs b/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs index a804d2776b238..f3c9eb7c86c95 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs @@ -227,17 +227,14 @@ fn test_replace_node() { self.node_types .push(format!("{:?}", expr.plan.as_ref().rel_op())); let op = expr.plan(); - if let RelOperator::Limit(limit) = op { + if let Some(limit) = op.as_any().downcast_ref::() { if let Some(limit_value) = limit.limit { let new_limit = Limit { limit: Some(limit_value * 2), offset: limit.offset, before_exchange: limit.before_exchange, }; - let replacement = SExpr::create_unary( - Arc::new(RelOperator::Limit(new_limit)), - Arc::new(expr.child(0).unwrap().clone()), - ); + let replacement = SExpr::create_unary(new_limit, expr.child(0).unwrap()); return Ok(VisitAction::Replace(replacement)); } } @@ -267,7 +264,7 @@ fn test_replace_node() { // Check if the Limit has been doubled let op = transformed.plan(); - if let RelOperator::Limit(limit) = op { + if let Some(limit) = op.as_any().downcast_ref::() { assert_eq!(limit.limit, Some(20)); } else { panic!("Root should be a Limit node"); @@ -344,17 +341,14 @@ async fn test_async_replace_node() { self.node_types .push(format!("{:?}", expr.plan.as_ref().rel_op())); let op = expr.plan(); - if let RelOperator::Limit(limit) = op { + if let Some(limit) = op.as_any().downcast_ref::() { if let Some(limit_value) = limit.limit { let new_limit = Limit { limit: Some(limit_value * 2), offset: limit.offset, before_exchange: limit.before_exchange, }; - let replacement = SExpr::create_unary( - Arc::new(RelOperator::Limit(new_limit)), - Arc::new(expr.child(0).unwrap().clone()), - ); + let replacement = SExpr::create_unary(new_limit, expr.child(0).unwrap()); return Ok(VisitAction::Replace(replacement)); } } @@ -384,7 +378,7 @@ async fn test_async_replace_node() { // Check if the Limit has been doubled let op = transformed.plan(); - if let RelOperator::Limit(limit) = op { + if let Some(limit) = op.as_any().downcast_ref::() { assert_eq!(limit.limit, Some(20)); } else { panic!("Root should be a Limit node"); diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs index 937b45289f183..ff3dbcfe411fc 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs @@ -40,6 +40,7 @@ use databend_common_sql::optimizer::ir::VisitAction; use databend_common_sql::optimizer::OptimizerContext; use databend_common_sql::plans::Plan; use databend_common_sql::plans::RelOperator; +use databend_common_sql::plans::Scan; use databend_common_sql::plans::Statistics; use databend_common_sql::BaseTableColumn; use databend_common_sql::ColumnEntry; @@ -364,7 +365,7 @@ struct StatsApplier<'a> { impl<'a> SExprVisitor for StatsApplier<'a> { fn visit(&mut self, expr: &SExpr) -> Result { - if let RelOperator::Scan(scan) = expr.plan() { + if let Some(scan) = expr.plan().as_any().downcast_ref::() { let metadata = self.metadata.read(); let table = metadata.table(scan.table_index); @@ -387,9 +388,7 @@ impl<'a> SExprVisitor for StatsApplier<'a> { histograms: HashMap::new(), }); - return Ok(VisitAction::Replace( - expr.replace_plan(Arc::new(RelOperator::Scan(new_scan))), - )); + return Ok(VisitAction::Replace(expr.replace_plan(new_scan))); } } Ok(VisitAction::Continue) diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs index 688d23c6ae13c..14c9f6cc25bfc 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs @@ -21,6 +21,8 @@ use databend_common_sql::optimizer::optimizers::operator::DeduplicateJoinConditi use databend_common_sql::planner::plans::JoinType; use databend_common_sql::planner::plans::RelOperator; use databend_common_sql::planner::plans::ScalarExpr; +use databend_common_sql::plans::Join; +use databend_common_sql::plans::Scan; use crate::sql::planner::optimizer::test_utils::*; @@ -33,7 +35,7 @@ fn run_optimizer(s_expr: SExpr) -> Result { /// Converts an SExpr to a readable string representation using a simple indented format fn sexpr_to_string(s_expr: &SExpr) -> String { fn format_join_conditions(s_expr: &SExpr) -> String { - if let RelOperator::Join(join) = s_expr.plan() { + if let Some(join) = s_expr.plan().as_any().downcast_ref::() { let conditions: Vec = join .equi_conditions .iter() @@ -85,7 +87,7 @@ fn sexpr_to_string(s_expr: &SExpr) -> String { let indent = " ".repeat(depth); let mut result = String::new(); - if let RelOperator::Join(_) = s_expr.plan() { + if let Some(join) = s_expr.plan().as_any().downcast_ref::() { // Add the join node with conditions result.push_str(&format!( "{indent}Join {}\n", @@ -97,7 +99,7 @@ fn sexpr_to_string(s_expr: &SExpr) -> String { for child in children { result.push_str(&build_tree(child, depth + 1)); } - } else if let RelOperator::Scan(scan) = s_expr.plan() { + } else if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { // Leaf node (table scan) result.push_str(&format!("{indent}Table t{}\n", scan.table_index)); } else { diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs index cac366c530ad7..c87efeb542cfe 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs @@ -36,6 +36,7 @@ use databend_common_sql::plans::AggIndexInfo; use databend_common_sql::plans::CreateTablePlan; use databend_common_sql::plans::Plan; use databend_common_sql::plans::RelOperator; +use databend_common_sql::plans::Scan; use databend_common_sql::BindContext; use databend_common_sql::Binder; use databend_common_sql::Metadata; @@ -463,10 +464,10 @@ async fn plan_sql( } fn find_push_down_index_info(s_expr: &SExpr) -> Result<&Option> { - match s_expr.plan() { - RelOperator::Scan(scan) => Ok(&scan.agg_index), - _ => find_push_down_index_info(s_expr.child(0)?), + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { + return Ok(&scan.agg_index); } + find_push_down_index_info(s_expr.child(0)?) } fn format_selection(info: &AggIndexInfo) -> Vec { diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs index d1648eaee2150..b60bb46e16976 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs @@ -132,50 +132,46 @@ fn sexpr_to_string(s_expr: &SExpr) -> String { } fn format_operator(s_expr: &SExpr) -> String { - match s_expr.plan() { - RelOperator::Filter(filter) => { - let preds: Vec = filter.predicates.iter().map(format_scalar_expr).collect(); - format!("Filter [{}]", preds.join(", ")) - } - RelOperator::Join(join) => { - let join_type = match join.join_type { - JoinType::Inner => "Inner", - JoinType::Left => "Left", - JoinType::Right => "Right", - JoinType::Full => "Full", - JoinType::Cross => "Cross", - JoinType::LeftSemi => "LeftSemi", - JoinType::RightSemi => "RightSemi", - JoinType::LeftAnti => "LeftAnti", - JoinType::RightAnti => "RightAnti", - JoinType::LeftMark => "LeftMark", - JoinType::RightMark => "RightMark", - JoinType::LeftSingle => "LeftSingle", - JoinType::RightSingle => "RightSingle", - JoinType::Asof => "Asof", - JoinType::LeftAsof => "LeftAsof", - JoinType::RightAsof => "RightAsof", - }; - - let conditions: Vec = join - .equi_conditions - .iter() - .map(|cond| { - format!( - "{} = {}", - format_scalar_expr(&cond.left), - format_scalar_expr(&cond.right) - ) - }) - .collect(); - - format!("{} Join [{}]", join_type, conditions.join(", ")) - } - RelOperator::Scan(scan) => { - format!("Table {}", scan.table_index) - } - _ => format!("Unknown operator"), + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { + return format!("Table {}", scan.table_index); + } + if let Some(filter) = s_expr.plan().as_any().downcast_ref::() { + let preds: Vec = filter.predicates.iter().map(format_scalar_expr).collect(); + return format!("Filter [{}]", preds.join(", ")); + } + if let Some(join) = s_expr.plan().as_any().downcast_ref::() { + let join_type = match join.join_type { + JoinType::Inner => "Inner", + JoinType::Left => "Left", + JoinType::Right => "Right", + JoinType::Full => "Full", + JoinType::Cross => "Cross", + JoinType::LeftSemi => "LeftSemi", + JoinType::RightSemi => "RightSemi", + JoinType::LeftAnti => "LeftAnti", + JoinType::RightAnti => "RightAnti", + JoinType::LeftMark => "LeftMark", + JoinType::RightMark => "RightMark", + JoinType::LeftSingle => "LeftSingle", + JoinType::RightSingle => "RightSingle", + JoinType::Asof => "Asof", + JoinType::LeftAsof => "LeftAsof", + JoinType::RightAsof => "RightAsof", + }; + let conditions: Vec = join + .equi_conditions + .iter() + .map(|cond| { + format!( + "{} = {}", + format_scalar_expr(&cond.left), + format_scalar_expr(&cond.right) + ) + }) + .collect(); + return format!("{} Join [{}]", join_type, conditions.join(", ")); } + format!("Unknown operator") } fn build_tree(s_expr: &SExpr, depth: usize) -> String { diff --git a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs index 59d912ed4a369..a9105a5a01324 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs @@ -498,11 +498,7 @@ impl ExprBuilder { equi_conditions, ..Default::default() }; - SExpr::create_binary( - Arc::new(RelOperator::Join(join)), - Arc::new(left), - Arc::new(right), - ) + SExpr::create_binary(Arc::new(join), Arc::new(left), Arc::new(right)) } /// Create a join condition between two columns @@ -517,10 +513,7 @@ impl ExprBuilder { /// Create a filter pub fn filter(&self, input: SExpr, predicates: Vec) -> SExpr { - SExpr::create_unary( - Arc::new(RelOperator::Filter(Filter { predicates })), - Arc::new(input), - ) + SExpr::create_unary(Arc::new(Filter { predicates }), Arc::new(input)) } /// Create a table scan @@ -529,7 +522,7 @@ impl ExprBuilder { table_index, ..Default::default() }; - SExpr::create_leaf(Arc::new(RelOperator::Scan(scan))) + SExpr::create_leaf(scan) } /// Create a table scan with column indices @@ -544,7 +537,7 @@ impl ExprBuilder { columns, ..Default::default() }; - SExpr::create_leaf(Arc::new(RelOperator::Scan(scan))) + SExpr::create_leaf(scan) } /// Create an aggregate @@ -573,7 +566,7 @@ impl ExprBuilder { offset, before_exchange: false, }; - SExpr::create_unary(Arc::new(RelOperator::Limit(limit_op)), Arc::new(input)) + SExpr::create_unary(limit_op, Arc::new(input)) } /// Create a scalar item diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 8b6ad4c56b37b..75953cf2f7961 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -178,9 +178,9 @@ impl SExpr { } } - pub fn replace_plan(&self, plan: Arc) -> Self { + pub fn replace_plan(&self, plan: P) -> Self { Self { - plan, + plan: Arc::new(plan) as OperatorRef, original_group: None, rel_prop: Arc::new(Mutex::new(None)), stat_info: Arc::new(Mutex::new(None)), diff --git a/src/query/sql/src/planner/optimizer/ir/format.rs b/src/query/sql/src/planner/optimizer/ir/format.rs index 6a97807eed049..9f7ca12f8ce6d 100644 --- a/src/query/sql/src/planner/optimizer/ir/format.rs +++ b/src/query/sql/src/planner/optimizer/ir/format.rs @@ -20,8 +20,11 @@ use itertools::Itertools; use crate::optimizer::ir::Group; use crate::optimizer::ir::MExpr; use crate::optimizer::ir::Memo; +use crate::plans::ConstantTableScan; use crate::plans::Exchange; use crate::plans::Operator; +use crate::plans::OperatorRef; +use crate::plans::RelOp; impl Memo { /// Format the memo structure for display @@ -43,18 +46,24 @@ impl Memo { } } -fn display_rel_op(rel_op: &RelOperator) -> String { +fn display_rel_op(rel_op: &OperatorRef) -> String { match rel_op { - RelOperator::Scan(_) => "Scan".to_string(), - RelOperator::Join(_) => "Join".to_string(), - RelOperator::EvalScalar(_) => "EvalScalar".to_string(), - RelOperator::Filter(_) => "Filter".to_string(), - RelOperator::Aggregate(_) => "Aggregate".to_string(), - RelOperator::Sort(_) => "Sort".to_string(), - RelOperator::Limit(_) => "Limit".to_string(), - RelOperator::UnionAll(_) => "UnionAll".to_string(), - RelOperator::Exchange(op) => { - format!("Exchange: ({})", match op { + RelOp::Scan => "Scan".to_string(), + RelOp::Join => "Join".to_string(), + RelOp::EvalScalar => "EvalScalar".to_string(), + RelOp::Filter => "Filter".to_string(), + RelOp::Aggregate => "Aggregate".to_string(), + RelOp::Sort => "Sort".to_string(), + RelOp::Limit => "Limit".to_string(), + RelOp::UnionAll => "UnionAll".to_string(), + RelOp::ConstantTableScan => { + let s = ConstantTableScan::try_downcast_ref(rel_op).unwrap(); + s.name().to_string() + } + + RelOp::Exchange => { + let rel_op = Exchange::try_downcast_ref(rel_op).unwrap(); + format!("Exchange: ({})", match rel_op { Exchange::Hash(scalars) => format!( "Hash({})", scalars @@ -68,18 +77,17 @@ fn display_rel_op(rel_op: &RelOperator) -> String { Exchange::MergeSort => "MergeSort".to_string(), }) } - RelOperator::DummyTableScan(_) => "DummyTableScan".to_string(), - RelOperator::ProjectSet(_) => "ProjectSet".to_string(), - RelOperator::Window(_) => "WindowFunc".to_string(), - RelOperator::ConstantTableScan(s) => s.name().to_string(), - RelOperator::ExpressionScan(_) => "ExpressionScan".to_string(), - RelOperator::CacheScan(_) => "CacheScan".to_string(), - RelOperator::Udf(_) => "Udf".to_string(), - RelOperator::RecursiveCteScan(_) => "RecursiveCteScan".to_string(), - RelOperator::AsyncFunction(_) => "AsyncFunction".to_string(), - RelOperator::Mutation(_) => "MergeInto".to_string(), - RelOperator::MutationSource(_) => "MutationSource".to_string(), - RelOperator::CompactBlock(_) => "CompactBlock".to_string(), + RelOp::DummyTableScan => "DummyTableScan".to_string(), + RelOp::ProjectSet => "ProjectSet".to_string(), + RelOp::Window => "WindowFunc".to_string(), + RelOp::ExpressionScan => "ExpressionScan".to_string(), + RelOp::CacheScan => "CacheScan".to_string(), + RelOp::Udf => "Udf".to_string(), + RelOp::RecursiveCteScan => "RecursiveCteScan".to_string(), + RelOp::AsyncFunction => "AsyncFunction".to_string(), + RelOp::Mutation => "MergeInto".to_string(), + RelOp::MutationSource => "MutationSource".to_string(), + RelOp::CompactBlock => "CompactBlock".to_string(), } } diff --git a/src/query/sql/src/planner/optimizer/optimizer.rs b/src/query/sql/src/planner/optimizer/optimizer.rs index 0764adf8a5354..afdb0b5a71bd1 100644 --- a/src/query/sql/src/planner/optimizer/optimizer.rs +++ b/src/query/sql/src/planner/optimizer/optimizer.rs @@ -42,10 +42,12 @@ use crate::optimizer::statistics::CollectStatisticsOptimizer; use crate::optimizer::OptimizerContext; use crate::plans::ConstantTableScan; use crate::plans::CopyIntoLocationPlan; +use crate::plans::Exchange; use crate::plans::Join; use crate::plans::JoinType; use crate::plans::MatchedEvaluator; use crate::plans::Mutation; +use crate::plans::MutationSource; use crate::plans::Operator; use crate::plans::Plan; use crate::plans::RelOp; @@ -315,7 +317,7 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res .optimize_sync(&input_s_expr)?; // For distributed query optimization, we need to remove the Exchange operator at the top of the plan. - if let &RelOperator::Exchange(_) = input_s_expr.plan() { + if let Some(exchange) = input_s_expr.plan().as_any().downcast_ref::() { input_s_expr = input_s_expr.child(0)?.clone(); } // If there still exists an Exchange::Merge operator, we should disable distributed optimization and @@ -394,7 +396,11 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res } } MutationType::Update | MutationType::Delete => { - if let RelOperator::MutationSource(rel) = input_s_expr.plan() { + if let Some(rel) = input_s_expr + .plan() + .as_any() + .downcast_ref::() + { if rel.mutation_type == MutationType::Delete && rel.predicates.is_empty() { mutation.truncate_table = true; } @@ -410,10 +416,7 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res Ok(Plan::DataMutation { schema, - s_expr: Box::new(SExpr::create_unary( - Arc::new(RelOperator::Mutation(mutation)), - Arc::new(input_s_expr), - )), + s_expr: Box::new(SExpr::create_unary(mutation, input_s_expr)), metadata: opt_ctx.get_metadata(), }) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs index 30e3109df6e72..92227578427e5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs @@ -20,8 +20,8 @@ use crate::optimizer::ir::Matcher; use crate::optimizer::ir::SExpr; use crate::plans::Exchange; use crate::plans::Join; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; pub struct BroadcastToShuffleOptimizer { pub matcher: Matcher, } @@ -67,7 +67,7 @@ impl BroadcastToShuffleOptimizer { Arc::new(right_exchange_input.clone()), )), ]; - let mut join_s_expr = s_expr.replace_plan(Arc::new(RelOperator::Join(join))); + let mut join_s_expr = s_expr.replace_plan(join); join_s_expr = join_s_expr.replace_children(new_join_children); Ok(join_s_expr) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs index abb7d4128b387..e0b48f414f21e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs @@ -20,8 +20,8 @@ use crate::optimizer::ir::Matcher; use crate::optimizer::ir::SExpr; use crate::plans::Exchange; use crate::plans::Limit; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::Sort; pub struct SortAndLimitPushDownOptimizer { @@ -122,7 +122,7 @@ impl SortAndLimitPushDownOptimizer { )); debug_assert!(exchange_sexpr.children.len() == 1); - let exchange_sexpr = exchange_sexpr.replace_plan(Arc::new(Exchange::MergeSort.into())); + let exchange_sexpr = exchange_sexpr.replace_plan(Exchange::MergeSort); let child = exchange_sexpr.child(0)?.clone(); let before_exchange_sort = SExpr::create_unary(sort.clone(), child); diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs index 8cdd8a3dd0ea7..aec96f1296246 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs @@ -150,10 +150,9 @@ impl DeduplicateJoinConditionOptimizer { } // Create new expression - let new_plan = Arc::new(RelOperator::Join(join)); let new_children = vec![Arc::new(left), Arc::new(right)]; - Ok(s_expr.replace_plan(new_plan).replace_children(new_children)) + Ok(s_expr.replace_plan(join).replace_children(new_children)) } /// Recursively process children nodes diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs index 824f0d4bd526b..df3372f52d019 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs @@ -141,7 +141,7 @@ impl PullUpFilterOptimizer { join.non_equi_conditions.clear(); join.join_type = JoinType::Cross; } - let s_expr = s_expr.replace_plan(Arc::new(RelOperator::Join(join))); + let s_expr = s_expr.replace_plan(join); Ok(s_expr.replace_children(vec![Arc::new(left), Arc::new(right)])) } @@ -151,7 +151,7 @@ impl PullUpFilterOptimizer { for predicate in self.predicates.iter_mut() { Self::replace_predicate(predicate, &mut eval_scalar.items, &self.metadata)?; } - let s_expr = s_expr.replace_plan(Arc::new(RelOperator::EvalScalar(eval_scalar))); + let s_expr = s_expr.replace_plan(eval_scalar); Ok(s_expr.replace_children(vec![Arc::new(child)])) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs index aa970f4329df2..82e9ce923ba1b 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/join/single_to_inner.rs @@ -18,6 +18,7 @@ use databend_common_exception::Result; use crate::optimizer::ir::SExpr; use crate::optimizer::Optimizer; +use crate::plans::Join; use crate::plans::JoinType; use crate::plans::Operator; @@ -35,12 +36,12 @@ impl SingleToInnerOptimizer { #[recursive::recursive] fn single_to_inner(s_expr: &SExpr) -> Result { - let mut s_expr = if let RelOperator::Join(join) = s_expr.plan.as_ref() + let mut s_expr = if let Some(join) = s_expr.plan().as_any().downcast_ref::() && join.single_to_inner.is_some() { let mut join = join.clone(); join.join_type = JoinType::Inner; - s_expr.replace_plan(Arc::new(RelOperator::Join(join))) + s_expr.replace_plan(join) } else { s_expr.clone() }; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs index 78e7f0f667d57..be6a9e0179811 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs @@ -1349,7 +1349,7 @@ fn push_down_index_scan(s_expr: &SExpr, agg_info: AggIndexInfo) -> Result if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { let mut new_scan = scan.clone(); new_scan.agg_index = Some(agg_info); - return Ok(s_expr.replace_plan(Arc::new(new_scan.into()))); + return Ok(s_expr.replace_plan(new_scan)); } let child = push_down_index_scan(s_expr.child(0)?, agg_info)?; Ok(s_expr.replace_children(vec![Arc::new(child)])) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs index 5b4f4144907e1..b63d032c6a0bf 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs @@ -709,7 +709,7 @@ impl Rule for RuleEagerAggregation { )), Arc::new(join_expr.child(1)?.clone()), ]))]) - .replace_plan(Arc::new(eager_groupby_count_count_sum.into())) + .replace_plan(eager_groupby_count_count_sum) } else { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ @@ -729,7 +729,7 @@ impl Rule for RuleEagerAggregation { )), )), ]))]) - .replace_plan(Arc::new(eager_groupby_count_count_sum.into())) + .replace_plan(eager_groupby_count_count_sum) }); // Apply eager split on d and d^1. @@ -779,7 +779,7 @@ impl Rule for RuleEagerAggregation { )), )), ]))]) - .replace_plan(Arc::new(eager_split_count_sum.into())), + .replace_plan(eager_split_count_sum), ); } else if can_push_down[d] && eager_aggregations[d ^ 1].is_empty() { // (1) Try to apply eager group-by on d. @@ -1006,7 +1006,7 @@ impl Rule for RuleEagerAggregation { )), )), ]))]) - .replace_plan(Arc::new(eager_count_sum.into())) + .replace_plan(eager_count_sum) } else { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ @@ -1019,7 +1019,7 @@ impl Rule for RuleEagerAggregation { )), Arc::new(join_expr.child(1)?.clone()), ]))]) - .replace_plan(Arc::new(eager_count_sum.into())) + .replace_plan(eager_count_sum) }); // Apply double eager on d and d^1. @@ -1059,7 +1059,7 @@ impl Rule for RuleEagerAggregation { )), )), ]))]) - .replace_plan(Arc::new(double_eager_count_sum.into())) + .replace_plan(double_eager_count_sum) } else { eval_scalar_expr .replace_children(vec![Arc::new(join_expr.replace_children(vec![ @@ -1085,7 +1085,7 @@ impl Rule for RuleEagerAggregation { )), )), ]))]) - .replace_plan(Arc::new(double_eager_count_sum.into())) + .replace_plan(double_eager_count_sum) }); } } @@ -1108,19 +1108,19 @@ impl Rule for RuleEagerAggregation { .replace_children(vec![Arc::new( final_agg_partial_expr .replace_children(vec![Arc::new(join_exprs[idx].clone())]) - .replace_plan(Arc::new(final_agg_partials[idx].clone().into())), + .replace_plan(final_agg_partials[idx].clone()), )]) - .replace_plan(Arc::new(final_agg_finals[idx].clone().into())); + .replace_plan(final_agg_finals[idx].clone()); let mut result = if has_sort { eval_scalar_expr .replace_children(vec![Arc::new( sort_expr.replace_children(vec![Arc::new(temp_final_agg_expr)]), )]) - .replace_plan(Arc::new(final_eval_scalars[idx].clone().into())) + .replace_plan(final_eval_scalars[idx].clone()) } else { eval_scalar_expr .replace_children(vec![Arc::new(temp_final_agg_expr)]) - .replace_plan(Arc::new(final_eval_scalars[idx].clone().into())) + .replace_plan(final_eval_scalars[idx].clone()) }; result.set_applied_rule(&self.id); state.add_result(result); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs index d448691a5aed4..17433bd172153 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs @@ -124,10 +124,7 @@ impl Rule for RulePushDownFilterWindowTopN { let mut result = SExpr::create_unary( s_expr.plan.clone(), - SExpr::create_unary( - window_expr.plan.clone(), - sort_expr.replace_plan(Arc::new(sort.into())), - ), + SExpr::create_unary(window_expr.plan.clone(), sort_expr.replace_plan(sort)), ); result.set_applied_rule(&self.id); diff --git a/src/query/sql/src/planner/optimizer/pipeline/common.rs b/src/query/sql/src/planner/optimizer/pipeline/common.rs index e6c139984f1d9..9ebd80f83b944 100644 --- a/src/query/sql/src/planner/optimizer/pipeline/common.rs +++ b/src/query/sql/src/planner/optimizer/pipeline/common.rs @@ -48,7 +48,7 @@ pub fn contains_warehouse_table_scan(s_expr: &SExpr, metadata: &MetadataRef) -> return true; } - if let RelOperator::Scan(scan) = s_expr.plan() { + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { return matches!( metadata .read() diff --git a/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs b/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs index 48d50d271b020..75f41153f299b 100644 --- a/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs +++ b/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs @@ -29,6 +29,7 @@ use crate::plans::ConstantExpr; use crate::plans::Filter; use crate::plans::FunctionCall; use crate::plans::Operator; +use crate::plans::Scan; use crate::plans::Statistics; use crate::BaseTableColumn; use crate::ColumnEntry; @@ -55,101 +56,97 @@ impl CollectStatisticsOptimizer { #[async_recursion::async_recursion(#[recursive::recursive])] pub async fn collect(&mut self, s_expr: &SExpr) -> Result { - match s_expr.plan.as_ref() { - RelOperator::Scan(scan) => { - let table = self.metadata.read().table(scan.table_index).clone(); - let table = table.table(); - let columns = self - .metadata - .read() - .columns_by_table_index(scan.table_index); + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { + let table = self.metadata.read().table(scan.table_index).clone(); + let table = table.table(); + let columns = self + .metadata + .read() + .columns_by_table_index(scan.table_index); - let column_statistics_provider = table - .column_statistics_provider(self.table_ctx.clone()) - .await?; - let table_stats = table - .table_statistics(self.table_ctx.clone(), true, scan.change_type.clone()) - .await?; + let column_statistics_provider = table + .column_statistics_provider(self.table_ctx.clone()) + .await?; + let table_stats = table + .table_statistics(self.table_ctx.clone(), true, scan.change_type.clone()) + .await?; - let mut column_stats = HashMap::new(); - let mut histograms = HashMap::new(); - for column in columns.iter() { - if let ColumnEntry::BaseTableColumn(BaseTableColumn { - column_index, - column_id, - virtual_expr, - .. - }) = column - { - if virtual_expr.is_none() { - if let Some(column_id) = *column_id { - let col_stat = column_statistics_provider - .column_statistics(column_id as ColumnId); - column_stats.insert(*column_index, col_stat.cloned()); - let histogram = - column_statistics_provider.histogram(column_id as ColumnId); - histograms.insert(*column_index, histogram); - } + let mut column_stats = HashMap::new(); + let mut histograms = HashMap::new(); + for column in columns.iter() { + if let ColumnEntry::BaseTableColumn(BaseTableColumn { + column_index, + column_id, + virtual_expr, + .. + }) = column + { + if virtual_expr.is_none() { + if let Some(column_id) = *column_id { + let col_stat = + column_statistics_provider.column_statistics(column_id as ColumnId); + column_stats.insert(*column_index, col_stat.cloned()); + let histogram = + column_statistics_provider.histogram(column_id as ColumnId); + histograms.insert(*column_index, histogram); } } } + } - let mut scan = scan.clone(); - scan.statistics = Arc::new(Statistics { - table_stats, - column_stats, - histograms, - }); - let mut s_expr = s_expr.replace_plan(Arc::new(RelOperator::Scan(scan.clone()))); - if let Some(sample) = &scan.sample { - // Only process row-level sampling in optimizer phase. - if let Some(row_level) = &sample.row_level { - if let Some(stats) = &table_stats - && let Some(probability) = - row_level.sample_probability(stats.num_rows)? - { - let rand_expr = ScalarExpr::FunctionCall(FunctionCall { - span: None, - func_name: "rand".to_string(), - params: vec![], - arguments: vec![], - }); - let filter = ScalarExpr::FunctionCall(FunctionCall { - span: None, - func_name: "lte".to_string(), - params: vec![], - arguments: vec![ - rand_expr, - ScalarExpr::ConstantExpr(ConstantExpr { - span: None, - value: Scalar::Number(NumberScalar::Float64(F64::from( - probability, - ))), - }), - ], - }); - s_expr = SExpr::create_unary( - Arc::new( - Filter { - predicates: vec![filter], - } - .into(), - ), - Arc::new(s_expr), - ); - } + let mut scan = scan.clone(); + scan.statistics = Arc::new(Statistics { + table_stats, + column_stats, + histograms, + }); + let mut s_expr = s_expr.replace_plan(scan); + if let Some(sample) = &scan.sample { + // Only process row-level sampling in optimizer phase. + if let Some(row_level) = &sample.row_level { + if let Some(stats) = &table_stats + && let Some(probability) = row_level.sample_probability(stats.num_rows)? + { + let rand_expr = ScalarExpr::FunctionCall(FunctionCall { + span: None, + func_name: "rand".to_string(), + params: vec![], + arguments: vec![], + }); + let filter = ScalarExpr::FunctionCall(FunctionCall { + span: None, + func_name: "lte".to_string(), + params: vec![], + arguments: vec![ + rand_expr, + ScalarExpr::ConstantExpr(ConstantExpr { + span: None, + value: Scalar::Number(NumberScalar::Float64(F64::from( + probability, + ))), + }), + ], + }); + s_expr = SExpr::create_unary( + Arc::new( + Filter { + predicates: vec![filter], + } + .into(), + ), + Arc::new(s_expr), + ); } } - Ok(s_expr) } - _ => { - let mut children = Vec::with_capacity(s_expr.arity()); - for child in s_expr.children() { - let child = Box::pin(self.collect(child)).await?; - children.push(Arc::new(child)); - } - Ok(s_expr.replace_children(children)) + Ok(s_expr) + } else { + let mut children = Vec::with_capacity(s_expr.arity()); + for child in s_expr.children() { + let child = Box::pin(self.collect(child)).await?; + children.push(Arc::new(child)); } + Ok(s_expr.replace_children(children)) } } } diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 613f93c2c415e..1187caf8c812b 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -114,6 +114,10 @@ pub trait Operator: Send + Sync + 'static { ) -> Result>> { Ok(vec![vec![RequiredProperty::default(); self.arity()]]) } + + fn try_downcast_ref(&self) -> Option<&Self> { + self.as_any().downcast_ref::() + } } /// Relational operator From c3a48237dbfa3c25a01c932b158d4e77d3335227 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Thu, 3 Jul 2025 16:55:48 +0800 Subject: [PATCH 07/14] update --- .../tests/it/aggregating_index/index_scan.rs | 2 +- .../src/interpreters/hook/compact_hook.rs | 2 +- .../interpreters/interpreter_index_refresh.rs | 2 +- .../sql/planner/optimizer/ir/expr/visitor.rs | 1 - .../sql/planner/optimizer/optimizer_test.rs | 4 +- .../rule/agg_rules/agg_index_query_rewrite.rs | 1 - .../it/sql/planner/optimizer/test_utils.rs | 1 - .../src/planner/optimizer/ir/expr/s_expr.rs | 189 +----------------- .../src/planner/optimizer/ir/expr/visitor.rs | 2 +- .../planner/optimizer/ir/property/enforcer.rs | 6 +- .../optimizers/cascades/cost/model.rs | 44 ++-- .../cascades/tasks/optimize_expr.rs | 2 +- .../distributed/distributed_merge.rs | 16 +- .../optimizers/distributed/sort_and_limit.rs | 10 +- .../optimizer/optimizers/hyper_dp/dphyp.rs | 88 ++++---- .../hyper_dp/dynamic_sample/dynamic_sample.rs | 1 - .../optimizers/hyper_dp/join_node.rs | 29 +-- src/query/sql/src/planner/plans/operator.rs | 6 +- 18 files changed, 107 insertions(+), 299 deletions(-) diff --git a/src/query/ee/tests/it/aggregating_index/index_scan.rs b/src/query/ee/tests/it/aggregating_index/index_scan.rs index 4832ea3c356b1..608eb24507180 100644 --- a/src/query/ee/tests/it/aggregating_index/index_scan.rs +++ b/src/query/ee/tests/it/aggregating_index/index_scan.rs @@ -25,7 +25,7 @@ use databend_common_expression::SendableDataBlockStream; use databend_common_expression::SortColumnDescription; use databend_common_sql::optimizer::SExpr; use databend_common_sql::planner::plans::Plan; -use databend_common_sql::plans::RelOperator; + use databend_common_sql::Planner; use databend_enterprise_query::test_kits::context::EESetup; use databend_query::interpreters::InterpreterFactory; diff --git a/src/query/service/src/interpreters/hook/compact_hook.rs b/src/query/service/src/interpreters/hook/compact_hook.rs index e2112c19dae18..661633a8c6a19 100644 --- a/src/query/service/src/interpreters/hook/compact_hook.rs +++ b/src/query/service/src/interpreters/hook/compact_hook.rs @@ -27,7 +27,7 @@ use databend_common_sql::executor::physical_plans::MutationKind; use databend_common_sql::optimizer::ir::SExpr; use databend_common_sql::plans::OptimizeCompactBlock; use databend_common_sql::plans::ReclusterPlan; -use databend_common_sql::plans::RelOperator; + use databend_storages_common_table_meta::table::ClusterType; use log::info; diff --git a/src/query/service/src/interpreters/interpreter_index_refresh.rs b/src/query/service/src/interpreters/interpreter_index_refresh.rs index ee4147d52ee1d..1fc02905cf389 100644 --- a/src/query/service/src/interpreters/interpreter_index_refresh.rs +++ b/src/query/service/src/interpreters/interpreter_index_refresh.rs @@ -40,7 +40,7 @@ use databend_common_sql::executor::PhysicalPlanBuilder; use databend_common_sql::executor::PhysicalPlanReplacer; use databend_common_sql::plans::Plan; use databend_common_sql::plans::RefreshIndexPlan; -use databend_common_sql::plans::RelOperator; + use databend_common_storages_fuse::operations::AggIndexSink; use databend_common_storages_fuse::pruning::create_segment_location_vector; use databend_common_storages_fuse::FuseBlockPartInfo; diff --git a/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs b/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs index f3c9eb7c86c95..50a3efb60c53b 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/ir/expr/visitor.rs @@ -25,7 +25,6 @@ use databend_common_sql::plans::AggregateMode; use databend_common_sql::plans::JoinType; use databend_common_sql::plans::Limit; use databend_common_sql::plans::Operator; -use databend_common_sql::plans::RelOperator; use crate::sql::planner::optimizer::test_utils::ExprBuilder; diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs index ff3dbcfe411fc..07f09f5313546 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs @@ -38,8 +38,8 @@ use databend_common_sql::optimizer::ir::SExpr; use databend_common_sql::optimizer::ir::SExprVisitor; use databend_common_sql::optimizer::ir::VisitAction; use databend_common_sql::optimizer::OptimizerContext; +use databend_common_sql::plans::Operator; use databend_common_sql::plans::Plan; -use databend_common_sql::plans::RelOperator; use databend_common_sql::plans::Scan; use databend_common_sql::plans::Statistics; use databend_common_sql::BaseTableColumn; @@ -365,7 +365,7 @@ struct StatsApplier<'a> { impl<'a> SExprVisitor for StatsApplier<'a> { fn visit(&mut self, expr: &SExpr) -> Result { - if let Some(scan) = expr.plan().as_any().downcast_ref::() { + if let Some(scan) = Scan::try_downcast_ref(&expr.plan) { let metadata = self.metadata.read(); let table = metadata.table(scan.table_index); diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs index c87efeb542cfe..956aae1c44ffa 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/agg_rules/agg_index_query_rewrite.rs @@ -35,7 +35,6 @@ use databend_common_sql::optimizer::OptimizerContext; use databend_common_sql::plans::AggIndexInfo; use databend_common_sql::plans::CreateTablePlan; use databend_common_sql::plans::Plan; -use databend_common_sql::plans::RelOperator; use databend_common_sql::plans::Scan; use databend_common_sql::BindContext; use databend_common_sql::Binder; diff --git a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs index a9105a5a01324..2147a6f936415 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs @@ -36,7 +36,6 @@ use databend_common_sql::plans::JoinEquiCondition; use databend_common_sql::plans::JoinType; use databend_common_sql::plans::Limit; use databend_common_sql::plans::Plan; -use databend_common_sql::plans::RelOperator; use databend_common_sql::plans::ScalarExpr; use databend_common_sql::plans::ScalarItem; use databend_common_sql::plans::Scan; diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 75953cf2f7961..eeb4c7f4940f7 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -205,188 +205,15 @@ impl SExpr { self.plan.has_subquery() || self.children.iter().any(|child| child.has_subquery()) } - // - #[recursive::recursive] pub fn get_udfs(&self) -> Result> { let mut udfs = HashSet::new(); - - match self.plan.as_ref() { - RelOperator::Scan(scan) => { - let Scan { - push_down_predicates, - prewhere, - agg_index, - .. - } = scan; - - if let Some(push_down_predicates) = push_down_predicates { - for push_down_predicate in push_down_predicates { - push_down_predicate.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - if let Some(prewhere) = prewhere { - for predicate in &prewhere.predicates { - predicate.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - if let Some(agg_index) = agg_index { - for predicate in &agg_index.predicates { - predicate.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - for selection in &agg_index.selection { - selection.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - } - RelOperator::Exchange(exchange) => { - if let Exchange::Hash(hash) = exchange { - for hash in hash { - hash.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - } - RelOperator::Join(op) => { - for equi_condition in op.equi_conditions.iter() { - equi_condition.left.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - equi_condition - .right - .get_udf_names()? - .iter() - .for_each(|udf| { - udfs.insert(*udf); - }); - } - for non in &op.non_equi_conditions { - non.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::EvalScalar(op) => { - for item in &op.items { - item.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::Filter(op) => { - for predicate in &op.predicates { - predicate.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::Aggregate(op) => { - for group_items in &op.group_items { - group_items.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - for agg_func in &op.aggregate_functions { - agg_func.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::Window(op) => { - match &op.function { - WindowFuncType::Aggregate(agg) => { - for arg in agg.exprs() { - arg.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - WindowFuncType::LagLead(lag_lead) => { - // udfs_pad(&mut udfs, f, &lag_lead.arg)?; - lag_lead.arg.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - if let Some(default) = &lag_lead.default { - default.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - WindowFuncType::NthValue(nth) => { - nth.arg.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - _ => {} - } - for arg in &op.arguments { - arg.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - for order_by in &op.order_by { - order_by - .order_by_item - .scalar - .get_udf_names()? - .iter() - .for_each(|udf| { - udfs.insert(*udf); - }); - } - for partition_by in &op.partition_by { - partition_by.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } + let iter = self.plan.scalar_expr_iter(); + for scalar in iter { + for udf in scalar.get_udf_names()? { + udfs.insert(udf); } - RelOperator::ProjectSet(op) => { - for srf in &op.srfs { - srf.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::Udf(udf) => { - for item in &udf.items { - item.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::AsyncFunction(async_func) => { - for item in &async_func.items { - item.scalar.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::MutationSource(mutation_source) => { - for predicate in &mutation_source.predicates { - predicate.get_udf_names()?.iter().for_each(|udf| { - udfs.insert(*udf); - }); - } - } - RelOperator::Limit(_) - | RelOperator::UnionAll(_) - | RelOperator::Sort(_) - | RelOperator::DummyTableScan(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::CacheScan(_) - | RelOperator::RecursiveCteScan(_) - | RelOperator::Mutation(_) - | RelOperator::CompactBlock(_) => {} - }; + } + for child in &self.children { let udf = child.get_udfs()?; udf.iter().for_each(|udf| { @@ -411,7 +238,7 @@ impl SExpr { inverted_index: &Option, ) -> SExpr { let mut s_expr = s_expr.clone(); - s_expr.plan = if let RelOperator::Scan(mut p) = (*s_expr.plan).clone() { + s_expr.plan = if let Some(mut p) = Scan::try_downcast_mut(&mut s_expr.plan) { if p.table_index == table_index { p.columns.insert(column_index); if inverted_index.is_some() { @@ -462,7 +289,7 @@ impl SExpr { #[recursive::recursive] pub fn has_merge_exchange(&self) -> bool { - if let RelOperator::Exchange(Exchange::Merge) = self.plan.as_ref() { + if let Some(Exchange::Merge) = Exchange::try_downcast_ref(&self.plan) { return true; } self.children.iter().any(|child| child.has_merge_exchange()) diff --git a/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs b/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs index ab2ca46a8d5db..81f46919f5713 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs @@ -68,7 +68,7 @@ //! impl AsyncSExprVisitor for EmptySortEliminator { //! async fn visit(&mut self, expr: &SExpr) -> Result { //! // Check if this is a Sort operator with empty sort keys -//! if let RelOperator::Sort(sort) = expr.plan.as_ref() { +//! if let Some(sort) = Sort::try_downcast_ref(&expr.plan) { //! if sort.sort_keys.is_empty() { //! // If sort has no keys, it's unnecessary - replace with its child //! if expr.arity() == 1 { diff --git a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs index e630a3054ba4f..d27a07c5f2d70 100644 --- a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs +++ b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs @@ -27,6 +27,7 @@ use crate::optimizer::ir::property::PhysicalProperty; use crate::optimizer::ir::property::RelExpr; use crate::optimizer::ir::property::RequiredProperty; use crate::plans::Exchange; +use crate::plans::Join; use crate::plans::Operator; /// Enforcer is a trait that can enforce the physical property @@ -115,9 +116,8 @@ impl PropertyEnforcer { physical_properties.push(rel_expr.derive_physical_prop_child(index)?); } - let plan = s_expr.plan.as_ref().clone(); - - if let RelOperator::Join(_) = &plan { + let plan = s_expr.plan(); + if let Some(join) = Join::try_downcast_ref(plan) { let (probe_required_property, build_required_property) = required_properties.split_at_mut(1); if let Distribution::Hash(probe_keys) = &mut probe_required_property[0].distribution diff --git a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs index 9e55db0eebe4b..f6a0c0dbe5aec 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs @@ -77,24 +77,32 @@ impl DefaultCostModel { } fn compute_cost_impl(&self, memo: &Memo, m_expr: &MExpr) -> Result { - match m_expr.plan.as_ref() { - RelOperator::Scan(plan) => self.compute_cost_scan(memo, m_expr, plan), - RelOperator::ConstantTableScan(plan) => self.compute_cost_constant_scan(plan), - RelOperator::DummyTableScan(_) => Ok(Cost(0.0)), - RelOperator::Join(plan) => self.compute_cost_join(memo, m_expr, plan), - RelOperator::UnionAll(_) => self.compute_cost_union_all(memo, m_expr), - RelOperator::Aggregate(_) => self.compute_aggregate(memo, m_expr), - - RelOperator::EvalScalar(_) - | RelOperator::Filter(_) - | RelOperator::Window(_) - | RelOperator::Sort(_) - | RelOperator::ProjectSet(_) - | RelOperator::Udf(_) - | RelOperator::Limit(_) => self.compute_cost_unary_common_operator(memo, m_expr), - - RelOperator::Exchange(_) => self.compute_cost_exchange(memo, m_expr), - + match m_expr.plan.as_ref().rel_op() { + RelOp::Scan => { + let plan = Scan::try_downcast_ref(m_expr.plan()).unwrap(); + self.compute_cost_scan(memo, m_expr, plan) + } + RelOp::ConstantTableScan => { + let plan = ConstantTableScan::try_downcast_ref(m_expr.plan()).unwrap(); + self.compute_cost_constant_scan(plan) + } + RelOp::DummyTableScan => Ok(Cost(0.0)), + RelOp::Join => { + let plan = Join::try_downcast_ref(m_expr.plan()).unwrap(); + self.compute_cost_join(memo, m_expr, plan) + } + RelOp::UnionAll => self.compute_cost_union_all(memo, m_expr), + RelOp::Aggregate => self.compute_aggregate(memo, m_expr), + + RelOp::EvalScalar + | RelOp::Filter + | RelOp::Window + | RelOp::Sort + | RelOp::ProjectSet + | RelOp::Udf + | RelOp::Limit => self.compute_cost_unary_common_operator(memo, m_expr), + + RelOp::Exchange => self.compute_cost_exchange(memo, m_expr), _ => Err(ErrorCode::Internal("Cannot compute cost from logical plan")), } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs b/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs index beb4c237d05bd..04a54aa3f006d 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs @@ -188,7 +188,7 @@ impl OptimizeExprTask { .group(self.group_index)? .m_expr(self.m_expr_index)?; - if matches!(m_expr.plan.as_ref(), RelOperator::Exchange(_),) + if matches!(m_expr.plan.rel_op(), RelOp::Exchange) && matches!(self.required_prop.distribution, Distribution::Any) { return Ok(OptimizeExprEvent::OptimizedSelf); diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs index 92227578427e5..7bc9477665166 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs @@ -35,10 +35,10 @@ impl BroadcastToShuffleOptimizer { pub fn is_broadcast(&self, s_expr: &SExpr) -> Result { let right = s_expr.child(1)?; - Ok(matches!( - right.plan(), - RelOperator::Exchange(Exchange::Broadcast) - )) + if let Some(Exchange::Broadcast) = right.plan().as_any().downcast_ref::() { + return Ok(true); + } + Ok(false) } pub fn optimize(&self, s_expr: &SExpr) -> Result { @@ -59,12 +59,12 @@ impl BroadcastToShuffleOptimizer { let new_join_children = vec![ Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Exchange(Exchange::Hash(left_conditions))), - Arc::new(left_exchange_input.clone()), + Exchange::Hash(left_conditions), + left_exchange_input.into(), )), Arc::new(SExpr::create_unary( - Arc::new(RelOperator::Exchange(Exchange::Hash(right_conditions))), - Arc::new(right_exchange_input.clone()), + Exchange::Hash(right_conditions), + right_exchange_input.into(), )), ]; let mut join_s_expr = s_expr.replace_plan(join); diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs index e0b48f414f21e..7d7aed0541400 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs @@ -109,18 +109,10 @@ impl SortAndLimitPushDownOptimizer { let exchange_sexpr = s_expr.child(0)?; // this is window shuffle sort - if matches!( - exchange_sexpr.plan.as_ref(), - RelOperator::Exchange(Exchange::Hash(_)) - ) { + if let Some(Exchange::Hash(_)) = exchange_sexpr.plan.as_any().downcast_ref::() { return Ok(s_expr.clone()); } - debug_assert!(matches!( - exchange_sexpr.plan.as_ref(), - RelOperator::Exchange(Exchange::Merge) | RelOperator::Exchange(Exchange::MergeSort) - )); - debug_assert!(exchange_sexpr.children.len() == 1); let exchange_sexpr = exchange_sexpr.replace_plan(Exchange::MergeSort); diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs index a5cf8c8dd1639..1a335898913ca 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs @@ -35,8 +35,11 @@ use crate::optimizer::Optimizer; use crate::optimizer::OptimizerContext; use crate::planner::QueryExecutor; use crate::plans::Filter; +use crate::plans::Join; use crate::plans::JoinType; use crate::plans::Operator; +use crate::plans::RelOp; +use crate::plans::Scan; use crate::IndexType; use crate::MetadataRef; use crate::ScalarExpr; @@ -165,7 +168,7 @@ impl DPhpyOptimizer { JoinRelation::new(s_expr, self.sample_executor().clone()) }; - if let RelOperator::Scan(op) = s_expr.plan() { + if let Some(op) = Scan::try_downcast_ref(s_expr.plan()) { self.table_index_map .insert(op.table_index, self.join_relations.len() as IndexType); } @@ -175,16 +178,16 @@ impl DPhpyOptimizer { } /// Check if an operator represents a subquery - fn is_subquery_operator(op: &RelOperator) -> bool { + fn is_subquery_operator(op: RelOp) -> bool { matches!( op, - RelOperator::EvalScalar(_) - | RelOperator::Aggregate(_) - | RelOperator::Sort(_) - | RelOperator::Limit(_) - | RelOperator::ProjectSet(_) - | RelOperator::Window(_) - | RelOperator::Udf(_) + RelOp::EvalScalar + | RelOp::Aggregate + | RelOp::Sort + | RelOp::Limit + | RelOp::ProjectSet + | RelOp::Window + | RelOp::Udf ) } @@ -194,11 +197,7 @@ impl DPhpyOptimizer { s_expr: &SExpr, join_conditions: &mut Vec<(ScalarExpr, ScalarExpr)>, ) -> Result<(Arc, bool)> { - let op = match s_expr.plan() { - RelOperator::Join(op) => op, - _ => unreachable!(), - }; - + let op = Join::try_downcast_ref(s_expr.plan()).unwrap(); // Skip if build side cache info is present if op.build_side_cache_info.is_some() { return Ok((Arc::new(s_expr.clone()), true)); @@ -209,8 +208,8 @@ impl DPhpyOptimizer { matches!(op.join_type, JoinType::Inner) || matches!(op.join_type, JoinType::Cross); // Check if children are subqueries - let left_op = s_expr.child(0)?.plan.as_ref(); - let right_op = s_expr.child(1)?.plan.as_ref(); + let left_op = s_expr.child(0)?.plan.rel_op(); + let right_op = s_expr.child(1)?.plan.rel_op(); let left_is_subquery = Self::is_subquery_operator(left_op); let right_is_subquery = Self::is_subquery_operator(right_op); @@ -279,7 +278,7 @@ impl DPhpyOptimizer { join_relation: Option<&SExpr>, ) -> Result<(Arc, bool)> { // If plan is filter, save it - if let RelOperator::Filter(op) = s_expr.plan.as_ref() { + if let Some(op) = Filter::try_downcast_ref(s_expr.plan()) { if join_child { self.filters.insert(op.clone()); } @@ -327,38 +326,22 @@ impl DPhpyOptimizer { return self.process_subquery(s_expr).await; } - match s_expr.plan() { - RelOperator::Scan(_) => self.process_scan_node(s_expr, join_relation), - - RelOperator::Join(_) => self.process_join_node(s_expr, join_conditions).await, - - RelOperator::ProjectSet(_) - | RelOperator::Aggregate(_) - | RelOperator::Sort(_) - | RelOperator::Limit(_) - | RelOperator::EvalScalar(_) - | RelOperator::Window(_) - | RelOperator::Udf(_) - | RelOperator::Filter(_) => { + match s_expr.plan().rel_op() { + RelOp::Scan => self.process_scan_node(s_expr, join_relation), + RelOp::Join => self.process_join_node(s_expr, join_conditions).await, + RelOp::ProjectSet + | RelOp::Aggregate + | RelOp::Sort + | RelOp::Limit + | RelOp::EvalScalar + | RelOp::Window + | RelOp::Udf + | RelOp::Filter => { self.process_unary_node(s_expr, join_conditions, join_child, join_relation) .await } - - RelOperator::UnionAll(_) => self.process_union_all_node(s_expr).await, - - RelOperator::Exchange(_) => { - unreachable!() - } - - RelOperator::DummyTableScan(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::CacheScan(_) - | RelOperator::AsyncFunction(_) - | RelOperator::RecursiveCteScan(_) - | RelOperator::Mutation(_) - | RelOperator::MutationSource(_) - | RelOperator::CompactBlock(_) => Ok((Arc::new(s_expr.clone()), true)), + RelOp::UnionAll => self.process_union_all_node(s_expr).await, + _ => Ok((Arc::new(s_expr.clone()), true)), } } @@ -971,16 +954,13 @@ impl DPhpyOptimizer { predicates.extend(filter.clone().predicates.iter().cloned()) } - let mut new_s_expr = SExpr::create_unary( - Arc::new(RelOperator::Filter(Filter { predicates })), - Arc::new(s_expr.clone()), - ); + let mut new_s_expr = SExpr::create_unary(Filter { predicates }, s_expr.clone()); // Push down filters new_s_expr = self.push_down_filter(&new_s_expr)?; // Remove empty filter - if let RelOperator::Filter(filter) = new_s_expr.plan.as_ref() { + if let Some(filter) = Filter::try_downcast_ref(&new_s_expr.plan) { if filter.predicates.is_empty() { new_s_expr = new_s_expr.child(0)?.clone(); } @@ -1006,8 +986,8 @@ impl DPhpyOptimizer { #[allow(clippy::only_used_in_recursion)] #[recursive::recursive] fn replace_join_expr(&self, join_expr: &SExpr, s_expr: &SExpr) -> Result { - match s_expr.plan.as_ref() { - RelOperator::Join(_) => { + match s_expr.plan.rel_op() { + RelOp::Join => { let mut new_s_expr = s_expr.clone(); new_s_expr.plan = join_expr.plan.clone(); new_s_expr.children = join_expr.children.clone(); @@ -1026,7 +1006,7 @@ impl DPhpyOptimizer { /// Check if a filter exists in the expression and remove it from filters set fn check_filter(&mut self, expr: &SExpr) { - if let RelOperator::Filter(filter) = expr.plan.as_ref() { + if let Some(filter) = Filter::try_downcast_ref(&expr.plan) { if self.filters.contains(filter) { self.filters.remove(filter); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs index 1177acc100cd7..0edd715ff095d 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs @@ -31,7 +31,6 @@ use crate::plans::AggregateMode; use crate::plans::Limit; use crate::plans::Operator; use crate::plans::ProjectSet; -use crate::plans::Operator; use crate::plans::UnionAll; use crate::MetadataRef; diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs index 540837910c62c..27dcee5577fb4 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/join_node.rs @@ -81,7 +81,19 @@ impl JoinNode { .iter() .map(|(_, r)| r.clone()) .collect(); - let rel_op = RelOperator::Join(Join { + let children = self + .children + .iter() + .map(|child| { + if let Some(s_expr) = &child.s_expr { + Arc::new(s_expr.clone()) + } else { + Arc::new(child.s_expr(join_relations)) + } + }) + .collect::>(); + + let rel_op = Join { equi_conditions: JoinEquiCondition::new_conditions( left_conditions, right_conditions, @@ -95,18 +107,7 @@ impl JoinNode { is_lateral: false, single_to_inner: None, build_side_cache_info: None, - }); - let children = self - .children - .iter() - .map(|child| { - if let Some(s_expr) = &child.s_expr { - Arc::new(s_expr.clone()) - } else { - Arc::new(child.s_expr(join_relations)) - } - }) - .collect::>(); - SExpr::create(Arc::new(rel_op), children, None, None, None) + }; + SExpr::create(rel_op, children, None, None, None) } } diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 1187caf8c812b..d827e309144d9 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -118,10 +118,14 @@ pub trait Operator: Send + Sync + 'static { fn try_downcast_ref(&self) -> Option<&Self> { self.as_any().downcast_ref::() } + + fn try_downcast_mut(&mut self) -> Option<&mut Self> { + self.as_any().downcast_mut::() + } } /// Relational operator -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum RelOp { Scan, Join, From a62501ba3825c6509abf04e155653ba68133b5a9 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Sat, 5 Jul 2025 21:28:37 +0800 Subject: [PATCH 08/14] update --- .../tests/it/aggregating_index/index_scan.rs | 8 +- .../filter/deduplicate_join_condition_test.rs | 1 - .../push_down_filter_join_test.rs | 1 - .../sql/src/executor/physical_plan_builder.rs | 2 +- .../bind_mutation/mutation_expression.rs | 37 ++-- .../planner/binder/bind_mutation/update.rs | 6 +- .../planner/binder/bind_query/bind_value.rs | 207 +++++++++--------- .../bind_table_function.rs | 2 +- src/query/sql/src/planner/binder/ddl/table.rs | 12 +- src/query/sql/src/planner/binder/util.rs | 3 +- src/query/sql/src/planner/format/display.rs | 7 +- .../planner/format/display_rel_operator.rs | 81 +++++-- .../src/planner/optimizer/ir/expr/extract.rs | 2 +- .../src/planner/optimizer/ir/expr/s_expr.rs | 4 + .../sql/src/planner/optimizer/ir/memo.rs | 9 +- .../planner/optimizer/ir/property/enforcer.rs | 16 +- .../optimizer/optimizers/hyper_dp/dphyp.rs | 2 +- .../hyper_dp/dynamic_sample/dynamic_sample.rs | 50 ++--- .../filter_selectivity_sample.rs | 5 +- .../operator/aggregate/normalize_aggregate.rs | 2 +- .../operator/decorrelate/decorrelate.rs | 17 +- .../operator/decorrelate/flatten_plan.rs | 206 ++++++++++------- .../decorrelate/subquery_decorrelator.rs | 64 +++--- .../filter/deduplicate_join_condition.rs | 10 +- .../operator/filter/pull_up_filter.rs | 21 +- .../rule/agg_rules/agg_index/query_rewrite.rs | 2 +- .../rule_push_down_limit_aggregate.rs | 4 +- .../rule_push_down_filter_join.rs | 2 +- .../filter_rules/rule_push_down_sort_scan.rs | 4 +- .../rule_push_down_limit_window.rs | 2 +- .../src/planner/optimizer/pipeline/common.rs | 2 +- src/query/sql/src/planner/plans/plan.rs | 5 +- src/query/sql/src/planner/plans/recluster.rs | 10 +- 33 files changed, 449 insertions(+), 357 deletions(-) diff --git a/src/query/ee/tests/it/aggregating_index/index_scan.rs b/src/query/ee/tests/it/aggregating_index/index_scan.rs index 608eb24507180..3ffd8d5dcc433 100644 --- a/src/query/ee/tests/it/aggregating_index/index_scan.rs +++ b/src/query/ee/tests/it/aggregating_index/index_scan.rs @@ -25,7 +25,6 @@ use databend_common_expression::SendableDataBlockStream; use databend_common_expression::SortColumnDescription; use databend_common_sql::optimizer::SExpr; use databend_common_sql::planner::plans::Plan; - use databend_common_sql::Planner; use databend_enterprise_query::test_kits::context::EESetup; use databend_query::interpreters::InterpreterFactory; @@ -596,7 +595,7 @@ fn is_index_scan_plan(plan: &Plan) -> bool { } fn is_index_scan_sexpr(s_expr: &SExpr) -> bool { - if let RelOperator::Scan(scan) = s_expr.plan() { + if let Some(scan) = Scan::try_downcast_ref(&s_expr.plan) { scan.agg_index.is_some() } else { s_expr.children().any(is_index_scan_sexpr) @@ -1041,10 +1040,7 @@ async fn test_fuzz_impl(format: &str, spill: bool) -> Result<()> { "query_out_of_memory_behavior".to_string(), "spilling".to_string(), ), - ( - "max_query_memory_usage".to_string(), - "1".to_string(), - ), + ("max_query_memory_usage".to_string(), "1".to_string()), ])) } else { None diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs index 14c9f6cc25bfc..e387629a8b8e8 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition_test.rs @@ -19,7 +19,6 @@ use databend_common_expression::types::NumberDataType; use databend_common_sql::optimizer::ir::SExpr; use databend_common_sql::optimizer::optimizers::operator::DeduplicateJoinConditionOptimizer; use databend_common_sql::planner::plans::JoinType; -use databend_common_sql::planner::plans::RelOperator; use databend_common_sql::planner::plans::ScalarExpr; use databend_common_sql::plans::Join; use databend_common_sql::plans::Scan; diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs index b60bb46e16976..c43ae922e23d1 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizers/rule/filter_rules/push_down_filter_join_test.rs @@ -22,7 +22,6 @@ use databend_common_sql::optimizer::optimizers::rule::RulePushDownFilterJoin; use databend_common_sql::optimizer::optimizers::rule::TransformResult; use databend_common_sql::planner::plans::JoinEquiCondition; use databend_common_sql::planner::plans::JoinType; -use databend_common_sql::planner::plans::RelOperator; use databend_common_sql::ColumnSet; use databend_common_sql::MetadataRef; use databend_common_sql::ScalarExpr; diff --git a/src/query/sql/src/executor/physical_plan_builder.rs b/src/query/sql/src/executor/physical_plan_builder.rs index 9237f8f6fd0d7..76b547d969b36 100644 --- a/src/query/sql/src/executor/physical_plan_builder.rs +++ b/src/query/sql/src/executor/physical_plan_builder.rs @@ -77,7 +77,7 @@ impl PhysicalPlanBuilder { ) -> Result { // Build stat info. let stat_info = self.build_plan_stat_info(s_expr)?; - with_match_rel_op!(|TY| match s_expr.plan().rel_op() { + with_match_rel_op!(|TY| match s_expr.plan_rel_op() { crate::plans::RelOp::TY => TY::build(self, s_expr, required, stat_info).await, _ => Err(ErrorCode::Internal("Unsupported operator")), }) diff --git a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs index e132a69b968f3..d0570cc046e95 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs @@ -43,7 +43,7 @@ use crate::plans::Join; use crate::plans::JoinType; use crate::plans::MutationSource; use crate::plans::Operator; -use crate::plans::Operator; +use crate::plans::Scan; use crate::plans::SubqueryExpr; use crate::plans::Visitor; use crate::BindContext; @@ -252,8 +252,7 @@ impl MutationExpression { read_partition_columns: Default::default(), }; - s_expr = - SExpr::create_leaf(Arc::new(RelOperator::MutationSource(mutation_source))); + s_expr = SExpr::create_leaf(MutationSource(mutation_source)); if !predicates.is_empty() { s_expr = SExpr::create_unary(Filter { predicates }, s_expr); @@ -400,23 +399,19 @@ impl MutationExpression { if !is_lazy_table && !update_stream_columns { return Ok(s_expr.clone()); } - match s_expr.plan() { - RelOperator::Scan(scan) => { - let mut scan = scan.clone(); - scan.is_lazy_table = is_lazy_table; - scan.set_update_stream_columns(update_stream_columns); - Ok(SExpr::create_leaf(Arc::new(scan.into()))) - } - _ => { - let mut children = Vec::with_capacity(s_expr.arity()); - for child in s_expr.children() { - let child = - Self::update_target_scan(child, is_lazy_table, update_stream_columns)?; - children.push(Arc::new(child)); - } - Ok(s_expr.replace_children(children)) - } + + if let Some(scan) = Scan::try_downcast_ref(s_expr.plan()) { + let mut scan = scan.clone(); + scan.is_lazy_table = is_lazy_table; + scan.set_update_stream_columns(update_stream_columns); + return Ok(SExpr::create_leaf(Arc::new(scan.into()))); + } + let mut children = Vec::with_capacity(s_expr.arity()); + for child in s_expr.children() { + let child = Self::update_target_scan(child, is_lazy_table, update_stream_columns)?; + children.push(Arc::new(child)); } + Ok(s_expr.replace_children(children)) } } @@ -550,12 +545,12 @@ pub struct MutationExpressionBindResult { } pub fn target_probe(s_expr: &SExpr, target_table_index: usize) -> Result { - if !matches!(s_expr.plan(), RelOperator::Join(_)) { + if !matches!(s_expr.plan_rel_op(), RelOp::Join) { return Ok(false); } fn contains_target_table(s_expr: &SExpr, target_table_index: usize) -> bool { - if let RelOperator::Scan(ref scan) = s_expr.plan() { + if let Some(scan) = Scan::try_downcast_ref(s_expr.plan()) { scan.table_index == target_table_index } else { s_expr diff --git a/src/query/sql/src/planner/binder/bind_mutation/update.rs b/src/query/sql/src/planner/binder/bind_mutation/update.rs index 02ccfc1141f74..08074c0e8299c 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/update.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/update.rs @@ -32,9 +32,9 @@ use crate::optimizer::ir::Matcher; use crate::plans::AggregateFunction; use crate::plans::BoundColumnRef; use crate::plans::EvalScalar; +use crate::plans::Operator; use crate::plans::Plan; use crate::plans::RelOp; -use crate::plans::Operator; use crate::plans::ScalarItem; use crate::plans::VisitorMut; use crate::BindContext; @@ -124,9 +124,9 @@ impl Binder { let Plan::DataMutation { box s_expr, .. } = &plan else { return Ok(plan); }; - let RelOperator::Mutation(mutation) = s_expr.plan() else { + if s_expr.plan_rel_op() != RelOp::Mutation { return Ok(plan); - }; + } let matcher = Matcher::MatchOp { op_type: RelOp::Filter, children: vec![Matcher::MatchOp { diff --git a/src/query/sql/src/planner/binder/bind_query/bind_value.rs b/src/query/sql/src/planner/binder/bind_query/bind_value.rs index 2f8faedbb0d5a..f32fd7f1a20ea 100644 --- a/src/query/sql/src/planner/binder/bind_query/bind_value.rs +++ b/src/query/sql/src/planner/binder/bind_query/bind_value.rs @@ -41,6 +41,7 @@ use crate::plans::CacheSource; use crate::plans::ConstantTableScan; use crate::plans::ExpressionScan; use crate::plans::HashJoinBuildCacheInfo; +use crate::plans::Join; use crate::plans::Operator; use crate::plans::ScalarItem; use crate::BindContext; @@ -215,8 +216,8 @@ impl Binder { s_expr: &SExpr, metadata: MetadataRef, ) -> Result<(SExpr, ColumnSet)> { - match s_expr.plan.as_ref() { - RelOperator::Join(join) if join.build_side_cache_info.is_some() => { + if let Some(join) = Join::try_downcast_ref(&s_expr.plan) { + if join.build_side_cache_info.is_some() { let mut join = join.clone(); let build_side_cache_info = join.build_side_cache_info.as_mut().unwrap(); @@ -248,125 +249,117 @@ impl Binder { } let s_expr = s_expr - .replace_plan(Arc::new(RelOperator::Join(join))) + .replace_plan(join) .replace_children(vec![Arc::new(left), Arc::new(right)]); - Ok((s_expr, right_correlated_columns)) + return Ok((s_expr, right_correlated_columns)); } - RelOperator::ExpressionScan(scan) => { - // The join condition columns may consist of the following two parts: - // (1) expression scan columns. - // (2) correlated columns in values. - let mut join_condition_columns = ColumnSet::new(); - for row in scan.values.iter() { - for (scalar, column_index) in row - .iter() - .zip(scan.column_indexes.iter()) - .take(scan.num_scalar_columns) - { - join_condition_columns.insert(*column_index); - for index in scalar.used_columns() { - let derived_index = self - .expression_scan_context - .get_derived_column(scan.expression_scan_index, index); - join_condition_columns.insert(derived_index); - } - } - } - - let mut scan = scan.clone(); + } - // Remove ExpressionScan unused cache columns. - let mut cache_scan_columns = vec![]; - let mut cache_scan_column_indexes = vec![]; - for index in (scan.num_scalar_columns..scan.values[0].len()).rev() { - let column_index = scan.column_indexes[index]; - if join_condition_columns.contains(&column_index) { - cache_scan_columns.push(scan.values[0][index].clone()); - let original_index = self + if let Some(scan) = ExpressionScan::try_downcast_ref(&s_expr.plan) { + // The join condition columns may consist of the following two parts: + // (1) expression scan columns. + // (2) correlated columns in values. + let mut join_condition_columns = ColumnSet::new(); + for row in scan.values.iter() { + for (scalar, column_index) in row + .iter() + .zip(scan.column_indexes.iter()) + .take(scan.num_scalar_columns) + { + join_condition_columns.insert(*column_index); + for index in scalar.used_columns() { + let derived_index = self .expression_scan_context - .get_original_column(scan.expression_scan_index, column_index); - cache_scan_column_indexes.push(original_index); - self.expression_scan_context - .add_used_cache_column_index(scan.cache_index, original_index) - } else { - scan.remove_cache_column(index); + .get_derived_column(scan.expression_scan_index, index); + join_condition_columns.insert(derived_index); } } + } - // Construct ExpressionScan schema. - let mut expression_scan_field = Vec::with_capacity(scan.values[0].len()); - for (column_index, data_type) in - scan.column_indexes.iter().zip(scan.data_types.iter()) - { - let field = DataField::new(&column_index.to_string(), data_type.clone()); - expression_scan_field.push(field); - } - let expression_scan_schema = DataSchemaRefExt::create(expression_scan_field); - scan.schema = expression_scan_schema; - - // Construct CacheScan. - let mut cache_scan_fields = Vec::with_capacity(cache_scan_columns.len()); - for (column, column_index) in cache_scan_columns - .iter() - .zip(cache_scan_column_indexes.iter()) - { - let field = DataField::new(&column_index.to_string(), column.data_type()?); - cache_scan_fields.push(field); + let mut scan = scan.clone(); + + // Remove ExpressionScan unused cache columns. + let mut cache_scan_columns = vec![]; + let mut cache_scan_column_indexes = vec![]; + for index in (scan.num_scalar_columns..scan.values[0].len()).rev() { + let column_index = scan.column_indexes[index]; + if join_condition_columns.contains(&column_index) { + cache_scan_columns.push(scan.values[0][index].clone()); + let original_index = self + .expression_scan_context + .get_original_column(scan.expression_scan_index, column_index); + cache_scan_column_indexes.push(original_index); + self.expression_scan_context + .add_used_cache_column_index(scan.cache_index, original_index) + } else { + scan.remove_cache_column(index); } + } - let cache_source = CacheSource::HashJoinBuild(( - scan.cache_index, - cache_scan_column_indexes.clone(), - )); - let cache_scan = SExpr::create_leaf(Arc::new(RelOperator::CacheScan(CacheScan { - cache_source, - columns: ColumnSet::new(), - schema: DataSchemaRefExt::create(cache_scan_fields), - }))); - - let mut distinct_columns = Vec::new(); - for column in scan.values[0].iter().skip(scan.num_scalar_columns) { - distinct_columns.push(column); - } + // Construct ExpressionScan schema. + let mut expression_scan_field = Vec::with_capacity(scan.values[0].len()); + for (column_index, data_type) in scan.column_indexes.iter().zip(scan.data_types.iter()) + { + let field = DataField::new(&column_index.to_string(), data_type.clone()); + expression_scan_field.push(field); + } + let expression_scan_schema = DataSchemaRefExt::create(expression_scan_field); + scan.schema = expression_scan_schema; + + // Construct CacheScan. + let mut cache_scan_fields = Vec::with_capacity(cache_scan_columns.len()); + for (column, column_index) in cache_scan_columns + .iter() + .zip(cache_scan_column_indexes.iter()) + { + let field = DataField::new(&column_index.to_string(), column.data_type()?); + cache_scan_fields.push(field); + } - // Wrap CacheScan with distinct to eliminate duplicates rows. - let mut group_items = Vec::with_capacity(cache_scan_column_indexes.len()); - for (index, column_index) in cache_scan_column_indexes.iter().enumerate() { - group_items.push(ScalarItem { - scalar: cache_scan_columns[index].clone(), - index: *column_index, - }); - } + let cache_source = + CacheSource::HashJoinBuild((scan.cache_index, cache_scan_column_indexes.clone())); + let cache_scan = SExpr::create_leaf(CacheScan { + cache_source, + columns: ColumnSet::new(), + schema: DataSchemaRefExt::create(cache_scan_fields), + }); - let s_expr = SExpr::create_unary( - Arc::new(RelOperator::ExpressionScan(scan)), - Arc::new(SExpr::create_unary( - Arc::new( - Aggregate { - mode: AggregateMode::Initial, - group_items, - ..Default::default() - } - .into(), - ), - Arc::new(cache_scan), - )), - ); - - Ok((s_expr, join_condition_columns)) + let mut distinct_columns = Vec::new(); + for column in scan.values[0].iter().skip(scan.num_scalar_columns) { + distinct_columns.push(column); } - _ => { - let mut correlated_columns = ColumnSet::new(); - let mut children = Vec::with_capacity(s_expr.arity()); - for child in s_expr.children() { - let (child, columns) = - self.construct_expression_scan(child, metadata.clone())?; - children.push(Arc::new(child)); - correlated_columns.extend(columns); - } - Ok((s_expr.replace_children(children), correlated_columns)) + + // Wrap CacheScan with distinct to eliminate duplicates rows. + let mut group_items = Vec::with_capacity(cache_scan_column_indexes.len()); + for (index, column_index) in cache_scan_column_indexes.iter().enumerate() { + group_items.push(ScalarItem { + scalar: cache_scan_columns[index].clone(), + index: *column_index, + }); } + + let s_expr = SExpr::create_unary( + scan, + Arc::new(SExpr::create_unary( + Aggregate { + mode: AggregateMode::Initial, + group_items, + ..Default::default() + }, + cache_scan, + )), + ); + + return Ok((s_expr, join_condition_columns)); + } + let mut correlated_columns = ColumnSet::new(); + let mut children = Vec::with_capacity(s_expr.arity()); + for child in s_expr.children() { + let (child, columns) = self.construct_expression_scan(child, metadata.clone())?; + children.push(Arc::new(child)); + correlated_columns.extend(columns); } + Ok((s_expr.replace_children(children), correlated_columns)) } } diff --git a/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs b/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs index 61a4732aada10..2c2a9218d1680 100644 --- a/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs +++ b/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs @@ -252,7 +252,7 @@ impl Binder { }; if let Some(fields) = fields { - if let RelOperator::EvalScalar(plan) = (*srf_expr.plan).clone() { + if let Some(plan) = EvalScalar::try_downcast_ref(&srf_expr.plan) { if plan.items.len() != 1 { return Err(ErrorCode::Internal(format!( "Invalid table function subquery EvalScalar items, expect 1, but got {}", diff --git a/src/query/sql/src/planner/binder/ddl/table.rs b/src/query/sql/src/planner/binder/ddl/table.rs index d4ba7a81b642f..1a9d0e3e87eef 100644 --- a/src/query/sql/src/planner/binder/ddl/table.rs +++ b/src/query/sql/src/planner/binder/ddl/table.rs @@ -1251,7 +1251,7 @@ impl Binder { let limit = limit.map(|v| v as usize); let plan = match ast_action { AstOptimizeTableAction::All => { - let compact_block = RelOperator::CompactBlock(OptimizeCompactBlock { + let compact_block = R OptimizeCompactBlock { catalog, database, table, @@ -1259,8 +1259,8 @@ impl Binder { segment_limit: limit, block_limit: None, }, - }); - let s_expr = SExpr::create_leaf(Arc::new(compact_block)); + }; + let s_expr = SExpr::create_leaf( compact_block); Plan::OptimizeCompactBlock { s_expr: Box::new(s_expr), need_purge: true, @@ -1283,7 +1283,7 @@ impl Binder { } AstOptimizeTableAction::Compact { target } => match target { CompactTarget::Block => { - let compact_block = RelOperator::CompactBlock(OptimizeCompactBlock { + let compact_block = OptimizeCompactBlock { catalog, database, table, @@ -1291,8 +1291,8 @@ impl Binder { segment_limit: limit, block_limit: None, }, - }); - let s_expr = SExpr::create_leaf(Arc::new(compact_block)); + }; + let s_expr = SExpr::create_leaf(compact_block); Plan::OptimizeCompactBlock { s_expr: Box::new(s_expr), need_purge: false, diff --git a/src/query/sql/src/planner/binder/util.rs b/src/query/sql/src/planner/binder/util.rs index adfcee7bc5787..6d82b18145920 100644 --- a/src/query/sql/src/planner/binder/util.rs +++ b/src/query/sql/src/planner/binder/util.rs @@ -25,7 +25,6 @@ use databend_common_expression::types::DataType; use crate::normalize_identifier; use crate::optimizer::ir::SExpr; use crate::plans::Operator; -use crate::plans::Operator; use crate::Binder; use crate::NameResolutionContext; use crate::NameResolutionSuggest; @@ -86,7 +85,7 @@ impl Binder { | RelOperator::CompactBlock(_) => { return Err(ErrorCode::SyntaxException(format!( "{:?} is not allowed in recursive cte", - expr.plan().rel_op() + expr.plan_rel_op() ))); } } diff --git a/src/query/sql/src/planner/format/display.rs b/src/query/sql/src/planner/format/display.rs index 80512ee242664..b4c559fd267e9 100644 --- a/src/query/sql/src/planner/format/display.rs +++ b/src/query/sql/src/planner/format/display.rs @@ -21,6 +21,7 @@ use crate::optimizer::ir::RelationalProperty; use crate::optimizer::ir::SExpr; use crate::optimizer::ir::StatInfo; use crate::plans::Operator; +use crate::plans::OperatorRef; use crate::ColumnEntry; use crate::IndexType; use crate::Metadata; @@ -37,7 +38,7 @@ pub trait IdHumanizer { /// A trait for humanizing operators. pub trait OperatorHumanizer { - fn humanize_operator(&self, id_humanizer: &I, op: &RelOperator) -> FormatTreeNode; + fn humanize_operator(&self, id_humanizer: &I, op: &OperatorRef) -> FormatTreeNode; } #[derive(Debug, Clone, Default)] @@ -57,11 +58,11 @@ pub struct FormatOptions { /// use databend_query::planner::format::display_rel_operator::Filter; /// use databend_query::planner::format::display_rel_operator::IdHumanizer; /// use databend_query::planner::format::display_rel_operator::OperatorHumanizer; -/// use databend_query::planner::format::display_rel_operator::RelOperator; +/// use databend_query::planner::format::display_rel_operator::OperatorRef; /// /// let id_humanizer = DefaultIdHumanizer; /// let operator_humanizer = DefaultOperatorHumanizer; -/// let op = RelOperator::Filter(Filter { predicates: vec![] }); +/// let op = Arc::new(Filter { predicates: vec![] }); /// let tree = operator_humanizer.humanize_operator(&id_humanizer, &op); /// /// assert_eq!(tree.payload, "Filter"); diff --git a/src/query/sql/src/planner/format/display_rel_operator.rs b/src/query/sql/src/planner/format/display_rel_operator.rs index 76df1da48aa16..299e99533768d 100644 --- a/src/query/sql/src/planner/format/display_rel_operator.rs +++ b/src/query/sql/src/planner/format/display_rel_operator.rs @@ -28,7 +28,8 @@ use crate::plans::Join; use crate::plans::Limit; use crate::plans::Mutation; use crate::plans::Operator; -use crate::plans::Operator; +use crate::plans::OperatorRef; +use crate::plans::RelOp; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Scan; @@ -38,29 +39,71 @@ use crate::plans::UnionAll; use crate::plans::Window; impl OperatorHumanizer for DefaultOperatorHumanizer { - fn humanize_operator(&self, id_humanizer: &I, op: &RelOperator) -> FormatTreeNode { + fn humanize_operator(&self, id_humanizer: &I, op: &OperatorRef) -> FormatTreeNode { to_format_tree(id_humanizer, op) } } -/// Build `FormatTreeNode` for a `RelOperator`, which may returns a tree structure instead of +/// Build `FormatTreeNode` for a `OperatorRef`, which may returns a tree structure instead of /// a single node. -fn to_format_tree(id_humanizer: &I, op: &RelOperator) -> FormatTreeNode { - match op { - RelOperator::Join(op) => join_to_format_tree(id_humanizer, op), - RelOperator::Scan(op) => scan_to_format_tree(id_humanizer, op), - RelOperator::EvalScalar(op) => eval_scalar_to_format_tree(id_humanizer, op), - RelOperator::Filter(op) => filter_to_format_tree(id_humanizer, op), - RelOperator::Aggregate(op) => aggregate_to_format_tree(id_humanizer, op), - RelOperator::Window(op) => window_to_format_tree(id_humanizer, op), - RelOperator::Udf(op) => udf_to_format_tree(id_humanizer, op), - RelOperator::AsyncFunction(op) => async_func_to_format_tree(id_humanizer, op), - RelOperator::Sort(op) => sort_to_format_tree(id_humanizer, op), - RelOperator::Limit(op) => limit_to_format_tree(id_humanizer, op), - RelOperator::Exchange(op) => exchange_to_format_tree(id_humanizer, op), - RelOperator::ConstantTableScan(op) => constant_scan_to_format_tree(id_humanizer, op), - RelOperator::UnionAll(op) => union_all_to_format_tree(id_humanizer, op), - RelOperator::Mutation(op) => merge_into_to_format_tree(id_humanizer, op), +fn to_format_tree(id_humanizer: &I, op: &OperatorRef) -> FormatTreeNode { + match op.rel_op() { + RelOp::Join => { + let join = Join::try_downcast_ref(op).unwrap(); + join_to_format_tree(id_humanizer, join) + } + RelOp::Scan => { + let scan = Scan::try_downcast_ref(op).unwrap(); + scan_to_format_tree(id_humanizer, scan) + } + RelOp::EvalScalar => { + let eval_scalar = EvalScalar::try_downcast_ref(op).unwrap(); + eval_scalar_to_format_tree(id_humanizer, eval_scalar) + } + RelOp::Filter => { + let filter = Filter::try_downcast_ref(op).unwrap(); + filter_to_format_tree(id_humanizer, filter) + } + RelOp::Aggregate => { + let aggregate = Aggregate::try_downcast_ref(op).unwrap(); + aggregate_to_format_tree(id_humanizer, aggregate) + } + RelOp::Window => { + let window = Window::try_downcast_ref(op).unwrap(); + window_to_format_tree(id_humanizer, window) + } + RelOp::Udf => { + let udf = Udf::try_downcast_ref(op).unwrap(); + udf_to_format_tree(id_humanizer, udf) + } + RelOp::AsyncFunction => { + let async_func = AsyncFunction::try_downcast_ref(op).unwrap(); + async_func_to_format_tree(id_humanizer, async_func) + } + RelOp::Sort => { + let sort = Sort::try_downcast_ref(op).unwrap(); + sort_to_format_tree(id_humanizer, sort) + } + RelOp::Limit => { + let limit = Limit::try_downcast_ref(op).unwrap(); + limit_to_format_tree(id_humanizer, limit) + } + RelOp::Exchange => { + let exchange = Exchange::try_downcast_ref(op).unwrap(); + exchange_to_format_tree(id_humanizer, exchange) + } + RelOp::ConstantTableScan => { + let constant_scan = ConstantTableScan::try_downcast_ref(op).unwrap(); + constant_scan_to_format_tree(id_humanizer, constant_scan) + } + RelOp::UnionAll => { + let union_all = UnionAll::try_downcast_ref(op).unwrap(); + union_all_to_format_tree(id_humanizer, union_all) + } + RelOp::MergeInto => { + let merge_into = MergeInto::try_downcast_ref(op).unwrap(); + merge_into_to_format_tree(id_humanizer, merge_into) + } _ => FormatTreeNode::with_children(format!("{:?}", op), vec![]), } } diff --git a/src/query/sql/src/planner/optimizer/ir/expr/extract.rs b/src/query/sql/src/planner/optimizer/ir/expr/extract.rs index 918617e2e6ba1..00548a2ee1120 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/extract.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/extract.rs @@ -49,7 +49,7 @@ impl Matcher { pub fn matches(&self, s_expr: &SExpr) -> bool { match self { Matcher::MatchOp { op_type, children } => { - if s_expr.plan().rel_op() != *op_type { + if s_expr.plan_rel_op() != *op_type { return false; } diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index eeb4c7f4940f7..8f3bdc62738e5 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -120,6 +120,10 @@ impl SExpr { &self.plan } + pub fn plan_rel_op(&self) -> RelOp { + self.plan.rel_op() + } + pub fn children(&self) -> impl Iterator { self.children.iter().map(|v| v.as_ref()) } diff --git a/src/query/sql/src/planner/optimizer/ir/memo.rs b/src/query/sql/src/planner/optimizer/ir/memo.rs index de0dfe1d94471..a05c027180ae7 100644 --- a/src/query/sql/src/planner/optimizer/ir/memo.rs +++ b/src/query/sql/src/planner/optimizer/ir/memo.rs @@ -26,6 +26,7 @@ use crate::optimizer::ir::property::StatInfo; use crate::optimizer::ir::Group; use crate::optimizer::ir::GroupState; use crate::plans::Operator; +use crate::plans::OperatorRef; use crate::IndexType; /// `Memo` is a search space which memoize possible plans of a query. @@ -38,7 +39,7 @@ pub struct Memo { /// Hash table for detecting duplicated expressions. /// The entry is `(plan, children) -> (group_index, m_expr_index)`. - pub m_expr_lookup_table: HashMap<(Arc, Vec), (IndexType, IndexType)>, + pub m_expr_lookup_table: HashMap<(OperatorRef, Vec), (IndexType, IndexType)>, } impl Memo { @@ -153,10 +154,10 @@ impl Memo { /// Get an estimate of the memory size of the memo. pub fn mem_size(&self) -> usize { - // Since all the `RelOperator` are interned, + // Since all the `OperatorRef` are interned, // we only need to count the size of `m_expr_lookup_table`. - // We assume the `RelOperator`s are the major part of the memo. - self.m_expr_lookup_table.len() * std::mem::size_of::() + // We assume the `OperatorRef`s are the major part of the memo. + self.m_expr_lookup_table.len() * std::mem::size_of::() } /// Get the number of groups in the memo. diff --git a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs index d27a07c5f2d70..a1324ae6345a7 100644 --- a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs +++ b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs @@ -29,6 +29,7 @@ use crate::optimizer::ir::property::RequiredProperty; use crate::plans::Exchange; use crate::plans::Join; use crate::plans::Operator; +use crate::plans::OperatorRef; /// Enforcer is a trait that can enforce the physical property pub trait Enforcer: std::fmt::Debug + Send + Sync { @@ -36,7 +37,7 @@ pub trait Enforcer: std::fmt::Debug + Send + Sync { fn check_enforce(&self, input_prop: &PhysicalProperty) -> bool; /// Enforce the physical property - fn enforce(&self) -> Result; + fn enforce(&self) -> Result; } /// Enforcer for distribution properties @@ -66,15 +67,16 @@ impl Enforcer for DistributionEnforcer { !self.0.satisfied_by(&input_prop.distribution) } - fn enforce(&self) -> Result { - match &self.0 { - Distribution::Serial => Ok(Exchange::Merge.into()), - Distribution::Broadcast => Ok(Exchange::Broadcast.into()), - Distribution::Hash(hash_keys) => Ok(Exchange::Hash(hash_keys.clone()).into()), + fn enforce(&self) -> Result { + let m = match &self.0 { + Distribution::Serial => Ok(Exchange::Merge), + Distribution::Broadcast => Ok(Exchange::Broadcast), + Distribution::Hash(hash_keys) => Ok(Exchange::Hash(hash_keys.clone())), Distribution::Random | Distribution::Any => Err(ErrorCode::Internal( "Cannot enforce random or any distribution", )), - } + }?; + Ok(Arc::new(m)) } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs index 1a335898913ca..a225708b9e161 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs @@ -326,7 +326,7 @@ impl DPhpyOptimizer { return self.process_subquery(s_expr).await; } - match s_expr.plan().rel_op() { + match s_expr.plan_rel_op() { RelOp::Scan => self.process_scan_node(s_expr, join_relation), RelOp::Join => self.process_join_node(s_expr, join_conditions).await, RelOp::ProjectSet diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs index 0edd715ff095d..9a9b3fc3513a1 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs @@ -31,6 +31,7 @@ use crate::plans::AggregateMode; use crate::plans::Limit; use crate::plans::Operator; use crate::plans::ProjectSet; +use crate::plans::RelOp; use crate::plans::UnionAll; use crate::MetadataRef; @@ -67,8 +68,8 @@ pub async fn dynamic_sample( } } - match s_expr.plan() { - RelOperator::Filter(_) => { + match s_expr.plan_rel_op() { + RelOp::Filter => { sample_with_budget( start_time, time_budget, @@ -80,37 +81,33 @@ pub async fn dynamic_sample( ) .await } - RelOperator::Join(_) => { - join_selectivity_sample(ctx, metadata, s_expr, sample_executor).await - } - RelOperator::Scan(_) - | RelOperator::DummyTableScan(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::CacheScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::RecursiveCteScan(_) - | RelOperator::Mutation(_) - | RelOperator::CompactBlock(_) - | RelOperator::MutationSource(_) => { - s_expr.plan().derive_stats(&RelExpr::with_s_expr(s_expr)) - } + RelOp::Join => join_selectivity_sample(ctx, metadata, s_expr, sample_executor).await, + RelOp::Scan + | RelOp::DummyTableScan + | RelOp::ConstantTableScan + | RelOp::CacheScan + | RelOp::ExpressionScan + | RelOp::RecursiveCteScan + | RelOp::Mutation + | RelOp::CompactBlock + | RelOp::MutationSource => s_expr.plan().derive_stats(&RelExpr::with_s_expr(s_expr)), - RelOperator::Aggregate(agg) => { + RelOp::Aggregate => { + let agg = Aggregate::try_from(s_expr.plan().clone()).unwrap(); let child_stat_info = dynamic_sample(ctx, metadata, s_expr.child(0)?, sample_executor).await?; if agg.mode == AggregateMode::Final { return Ok(child_stat_info); } - let agg = Aggregate::try_from(s_expr.plan().clone())?; agg.derive_agg_stats(child_stat_info) } - RelOperator::Limit(_) => { + RelOp::Limit => { let child_stat_info = dynamic_sample(ctx, metadata, s_expr.child(0)?, sample_executor).await?; let limit = Limit::try_from(s_expr.plan().clone())?; limit.derive_limit_stats(child_stat_info) } - RelOperator::UnionAll(_) => { + RelOp::UnionAll => { let left_stat_info = dynamic_sample( ctx.clone(), metadata.clone(), @@ -123,23 +120,16 @@ pub async fn dynamic_sample( let union = UnionAll::try_from(s_expr.plan().clone())?; union.derive_union_stats(left_stat_info, right_stat_info) } - RelOperator::ProjectSet(_) => { + RelOp::ProjectSet => { let mut child_stat_info = dynamic_sample(ctx, metadata, s_expr.child(0)?, sample_executor) .await? .deref() .clone(); - let project_set = ProjectSet::try_from(s_expr.plan().clone())?; + let project_set = ProjectSet::try_downcast_ref(s_expr.plan()).unwrap(); project_set.derive_project_set_stats(&mut child_stat_info) } - RelOperator::EvalScalar(_) - | RelOperator::Sort(_) - | RelOperator::Exchange(_) - | RelOperator::Window(_) - | RelOperator::Udf(_) - | RelOperator::AsyncFunction(_) => { - dynamic_sample(ctx, metadata, s_expr.child(0)?, sample_executor).await - } + _ => dynamic_sample(ctx, metadata, s_expr.child(0)?, sample_executor).await, } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs index 83f60a1ffb2c0..2545063f3a67a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs @@ -37,6 +37,7 @@ use crate::plans::AggregateFunction; use crate::plans::AggregateMode; use crate::plans::Operator; use crate::plans::ScalarItem; +use crate::plans::Scan; use crate::ColumnSet; use crate::MetadataRef; use crate::ScalarExpr; @@ -51,7 +52,7 @@ pub async fn filter_selectivity_sample( // Because it's meaningless for filter cardinality by sample in single table query. let child = s_expr.child(0)?; let child_rel_expr = RelExpr::with_s_expr(child); - if let RelOperator::Scan(mut scan) = child.plan().clone() { + if let Some(scan) = Scan::try_downcast_ref(child.plan.as_ref()) { let num_rows = scan .statistics .table_stats @@ -68,7 +69,7 @@ pub async fn filter_selectivity_sample( block_level: Some(50.0), }; scan.sample = Some(sample_conf); - let new_child = SExpr::create_leaf(Arc::new(RelOperator::Scan(scan))); + let new_child = SExpr::create_leaf(Arc::new(scan)); new_s_expr = s_expr.replace_children(vec![Arc::new(new_child)]); let opt_ctx = OptimizerContext::new(ctx.clone(), metadata.clone()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs index cd7c3b73d20b5..ad8a266cc2048 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs @@ -42,7 +42,7 @@ impl RuleNormalizeAggregateOptimizer { children.push(Arc::new(child)); } let s_expr = s_expr.replace_children(children); - if let RelOperator::Aggregate(_) = s_expr.plan.as_ref() { + if let Some(aggregate) = Aggregate::try_downcast_ref(s_expr.plan.as_ref()) { self.normalize_aggregate(&s_expr) } else { Ok(s_expr) diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs index 04d8506d9cc7f..214e85f88a8b3 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs @@ -38,13 +38,15 @@ use crate::optimizer::optimizers::operator::UnnestResult; use crate::plans::BoundColumnRef; use crate::plans::CastExpr; use crate::plans::ConstantExpr; +use crate::plans::EvalScalar; use crate::plans::Filter; use crate::plans::FunctionCall; use crate::plans::Join; use crate::plans::JoinEquiCondition; use crate::plans::JoinType; -use crate::plans::RelOp; use crate::plans::Operator; +use crate::plans::ProjectSet; +use crate::plans::RelOp; use crate::plans::ScalarExpr; use crate::plans::SubqueryComparisonOp; use crate::plans::SubqueryExpr; @@ -583,10 +585,11 @@ impl SubqueryDecorrelatorOptimizer { } let child = subquery.subquery.child(0)?; - if let RelOperator::DummyTableScan(_) = child.plan() { + if let RelOp::DummyTableScan = child.plan_rel_op() { // subquery is a simple constant value. // for example: `SELECT * FROM t WHERE id = (select 1);` - if let RelOperator::EvalScalar(eval) = subquery.subquery.plan() { + if let RelOp::EvalScalar = subquery.subquery.plan_rel_op() { + let eval = EvalScalar::try_downcast_ref(subquery.subquery.plan.as_ref()).unwrap(); if eval.items.len() != 1 { return Ok(None); } @@ -628,7 +631,7 @@ impl SubqueryDecorrelatorOptimizer { // subquery is a set returning function return constant values. // for example: `SELECT * FROM t WHERE id IN (SELECT * FROM UNNEST(SPLIT('1,2,3', ',')) AS t1);` let mut output_column_index = None; - if let RelOperator::EvalScalar(eval) = subquery.subquery.plan() { + if let Some(eval) = EvalScalar::try_downcast_ref(subquery.subquery.plan.as_ref()) { if eval.items.len() != 1 { return Ok(None); } @@ -642,7 +645,8 @@ impl SubqueryDecorrelatorOptimizer { let output_column_index = output_column_index.unwrap(); let mut srf_column_index = None; - if let RelOperator::EvalScalar(eval) = child.plan() { + + if let Some(eval) = EvalScalar::try_downcast_ref(child.plan.as_ref()) { if eval.items.len() != 1 || eval.items[0].index != output_column_index { return Ok(None); } @@ -664,7 +668,8 @@ impl SubqueryDecorrelatorOptimizer { let srf_column_index = srf_column_index.unwrap(); let project_set_expr = child.child(0)?; - if let RelOperator::ProjectSet(project_set) = project_set_expr.plan() { + if let Some(project_set) = ProjectSet::try_downcast_ref(project_set_expr.plan.as_ref()) + { if project_set.srfs.len() != 1 || project_set.srfs[0].index != srf_column_index || !matches!( diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs index 27ac85086920e..fee29050496ee 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs @@ -39,8 +39,11 @@ use crate::plans::ExpressionScan; use crate::plans::Filter; use crate::plans::Join; use crate::plans::JoinEquiCondition; +use crate::plans::Limit; use crate::plans::Operator; +use crate::plans::OperatorRef; use crate::plans::ProjectSet; +use crate::plans::RelOp; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Scan; @@ -70,69 +73,94 @@ impl SubqueryDecorrelatorOptimizer { return self.rewrite_to_join_then_aggr(outer, subquery, correlated_columns); } - match subquery.plan() { - RelOperator::EvalScalar(eval_scalar) => self.flatten_sub_eval_scalar( - outer, - subquery, - eval_scalar, - correlated_columns, - flatten_info, - need_cross_join, - ), - RelOperator::ProjectSet(project_set) => self.flatten_sub_project_set( - outer, - subquery, - project_set, - correlated_columns, - flatten_info, - need_cross_join, - ), - RelOperator::Filter(filter) => self.flatten_sub_filter( - outer, - subquery, - filter, - correlated_columns, - flatten_info, - need_cross_join, - ), - RelOperator::Join(join) => { + match subquery.plan_rel_op() { + RelOp::EvalScalar => { + let eval_scalar = EvalScalar::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_eval_scalar( + outer, + subquery, + eval_scalar, + correlated_columns, + flatten_info, + need_cross_join, + ) + } + RelOp::ProjectSet => { + let project_set = ProjectSet::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_project_set( + outer, + subquery, + project_set, + correlated_columns, + flatten_info, + need_cross_join, + ) + } + RelOp::Filter => { + let filter = Filter::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_filter( + outer, + subquery, + filter, + correlated_columns, + flatten_info, + need_cross_join, + ) + } + RelOp::Join => { + let join = Join::try_downcast_ref(subquery.plan()).unwrap(); self.flatten_sub_join(outer, subquery, join, correlated_columns, flatten_info) } - RelOperator::Aggregate(aggregate) => self.flatten_sub_aggregate( - outer, - subquery, - aggregate, - correlated_columns, - flatten_info, - need_cross_join, - ), - RelOperator::Sort(sort) => self.flatten_sub_sort( - outer, - subquery, - sort, - correlated_columns, - flatten_info, - need_cross_join, - ), - RelOperator::Limit(_) => self.flatten_sub_limit( - outer, - subquery, - correlated_columns, - flatten_info, - need_cross_join, - ), - RelOperator::UnionAll(op) => self.flatten_sub_union_all( - outer, - subquery, - op, - correlated_columns, - flatten_info, - need_cross_join, - ), - RelOperator::Window(op) => { - self.flatten_sub_window(outer, subquery, op, correlated_columns, flatten_info) + RelOp::Aggregate => { + let aggregate = Aggregate::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_aggregate( + outer, + subquery, + aggregate, + correlated_columns, + flatten_info, + need_cross_join, + ) + } + RelOp::Sort => { + let sort = Sort::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_sort( + outer, + subquery, + sort, + correlated_columns, + flatten_info, + need_cross_join, + ) } - RelOperator::ExpressionScan(scan) => { + RelOp::Limit => { + let limit = Limit::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_limit( + outer, + subquery, + limit, + correlated_columns, + flatten_info, + need_cross_join, + ) + } + RelOp::UnionAll => { + let union_all = UnionAll::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_union_all( + outer, + subquery, + union_all, + correlated_columns, + flatten_info, + need_cross_join, + ) + } + RelOp::Window => { + let window = Window::try_downcast_ref(subquery.plan()).unwrap(); + self.flatten_sub_window(outer, subquery, window, correlated_columns, flatten_info) + } + RelOp::ExpressionScan => { + let scan = ExpressionScan::try_downcast_ref(subquery.plan()).unwrap(); self.flatten_sub_expression_scan(subquery, scan, correlated_columns) } _ => Err(ErrorCode::SemanticError( @@ -807,21 +835,35 @@ impl SubqueryDecorrelatorOptimizer { }) } - fn clone_outer_plan(&mut self, plan: &RelOperator) -> Result { - let op = match plan { - RelOperator::DummyTableScan(_) => DummyTableScan.into(), - RelOperator::ConstantTableScan(scan) => self.clone_outer_constant_table_scan(scan)?, - RelOperator::Scan(scan) => self.clone_outer_scan(scan), - RelOperator::EvalScalar(eval) => self.clone_outer_eval_scalar(eval)?, - RelOperator::Limit(limit) => limit.clone().into(), - RelOperator::Sort(sort) => { + fn clone_outer_plan(&mut self, plan: &OperatorRef) -> Result { + let op = match plan.rel_op() { + RelOp::DummyTableScan => DummyTableScan.into(), + RelOp::ConstantTableScan => { + let scan = ConstantTableScan::try_downcast_ref(plan).unwrap(); + self.clone_outer_constant_table_scan(scan)? + } + RelOp::Scan => { + let scan = Scan::try_downcast_ref(plan).unwrap(); + self.clone_outer_scan(scan) + } + RelOp::EvalScalar => { + let eval = EvalScalar::try_downcast_ref(plan).unwrap(); + self.clone_outer_eval_scalar(eval)? + } + RelOp::Limit => { + let limit = Limit::try_downcast_ref(plan).unwrap(); + limit.clone().into() + } + RelOp::Sort => { + let sort = Sort::try_downcast_ref(plan).unwrap(); let mut sort = sort.clone(); for old in sort.used_columns() { sort.replace_column(old, self.get_derived(old)?); } sort.into() } - RelOperator::Filter(filter) => { + RelOp::Filter => { + let filter = Filter::try_downcast_ref(plan).unwrap(); let mut filter = filter.clone(); for predicate in &mut filter.predicates { for old in predicate.used_columns() { @@ -830,7 +872,8 @@ impl SubqueryDecorrelatorOptimizer { } filter.into() } - RelOperator::Join(join) => { + RelOp::Join => { + let join = Join::try_downcast_ref(plan).unwrap(); let mut join = join.clone(); for old in join.used_columns()? { join.replace_column(old, self.get_derived(old)?)?; @@ -846,7 +889,8 @@ impl SubqueryDecorrelatorOptimizer { } join.into() } - RelOperator::Aggregate(aggregate) => { + RelOp::Aggregate => { + let aggregate = Aggregate::try_downcast_ref(plan).unwrap(); let mut aggregate = aggregate.clone(); let metadata = self.metadata.clone(); let mut metadata = metadata.write(); @@ -874,7 +918,7 @@ impl SubqueryDecorrelatorOptimizer { Ok(op) } - fn clone_outer_constant_table_scan(&mut self, scan: &ConstantTableScan) -> Result { + fn clone_outer_constant_table_scan(&mut self, scan: &ConstantTableScan) -> Result { let mut metadata = self.metadata.write(); let ((values, fields), columns) = scan .columns @@ -892,16 +936,16 @@ impl SubqueryDecorrelatorOptimizer { }) .collect::, Vec<_>), ColumnSet)>>()?; - Ok(ConstantTableScan { + let scan = ConstantTableScan { values, num_rows: scan.num_rows, schema: Arc::new(DataSchema::new(fields)), columns, - } - .into()) + }; + Ok(Arc::new(scan)) } - fn clone_outer_scan(&mut self, scan: &Scan) -> RelOperator { + fn clone_outer_scan(&mut self, scan: &Scan) -> OperatorRef { let mut metadata = self.metadata.write(); let columns = scan .columns @@ -918,16 +962,16 @@ impl SubqueryDecorrelatorOptimizer { derived_index }) .collect(); - Scan { + let scan = Scan { table_index: scan.table_index, columns, scan_id: metadata.next_scan_id(), ..Default::default() - } - .into() + }; + Ok(Arc::new(scan)) } - fn clone_outer_eval_scalar(&mut self, eval: &EvalScalar) -> Result { + fn clone_outer_eval_scalar(&mut self, eval: &EvalScalar) -> Result { let metadata = self.metadata.clone(); let mut metadata = metadata.write(); let items = eval @@ -935,7 +979,7 @@ impl SubqueryDecorrelatorOptimizer { .iter() .map(|item| self.clone_outer_scalar_item(item, &mut metadata)) .collect::>()?; - Ok(EvalScalar { items }.into()) + Ok(Arc::new(EvalScalar { items })) } fn clone_outer_scalar_item( diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs index e5852094f3c38..4926137ab8d78 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs @@ -44,6 +44,7 @@ use crate::plans::JoinEquiCondition; use crate::plans::JoinType; use crate::plans::Limit; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Sort; @@ -176,8 +177,9 @@ impl SubqueryDecorrelatorOptimizer { return Ok(s_expr.clone()); } - match s_expr.plan() { - RelOperator::EvalScalar(eval) => { + match s_expr.plan_rel_op() { + RelOp::EvalScalar => { + let eval = EvalScalar::try_downcast_ref(s_expr.plan()).unwrap(); let mut outer = self.optimize_sync(s_expr.unary_child())?; let mut eval = eval.clone(); for item in eval.items.iter_mut() { @@ -186,8 +188,9 @@ impl SubqueryDecorrelatorOptimizer { Ok(SExpr::create_unary(eval, outer)) } - RelOperator::Filter(plan) => { - let mut plan = plan.clone(); + RelOp::Filter => { + let filter = Filter::try_downcast_ref(s_expr.plan()).unwrap(); + let mut plan = filter.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; for pred in plan.predicates.iter_mut() { (*pred, outer) = self.try_rewrite_subquery(pred, outer, true)?; @@ -195,8 +198,9 @@ impl SubqueryDecorrelatorOptimizer { Ok(SExpr::create_unary(plan, outer)) } - RelOperator::ProjectSet(plan) => { - let mut plan = plan.clone(); + RelOp::ProjectSet => { + let project_set = ProjectSet::try_downcast_ref(s_expr.plan()).unwrap(); + let mut plan = project_set.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; for item in plan.srfs.iter_mut() { (item.scalar, outer) = self.try_rewrite_subquery(&item.scalar, outer, false)?; @@ -204,8 +208,9 @@ impl SubqueryDecorrelatorOptimizer { Ok(SExpr::create_unary(plan, outer)) } - RelOperator::Aggregate(plan) => { - let mut plan = plan.clone(); + RelOp::Aggregate => { + let aggregate = Aggregate::try_downcast_ref(s_expr.plan()).unwrap(); + let mut plan = aggregate.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; for item in plan.group_items.iter_mut() { (item.scalar, outer) = self.try_rewrite_subquery(&item.scalar, outer, false)?; @@ -216,8 +221,9 @@ impl SubqueryDecorrelatorOptimizer { Ok(SExpr::create_unary(plan, outer)) } - RelOperator::Window(plan) => { - let mut plan = plan.clone(); + RelOp::Window => { + let window = Window::try_downcast_ref(s_expr.plan()).unwrap(); + let mut plan = window.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; for item in plan.partition_by.iter_mut() { @@ -238,7 +244,8 @@ impl SubqueryDecorrelatorOptimizer { Ok(SExpr::create_unary(plan, outer)) } - RelOperator::Sort(sort) => { + RelOp::Sort => { + let sort = Sort::try_downcast_ref(s_expr.plan()).unwrap(); let mut outer = self.optimize_sync(s_expr.unary_child())?; let Some(mut window) = sort.window_partition.clone() else { @@ -256,7 +263,8 @@ impl SubqueryDecorrelatorOptimizer { Ok(SExpr::create_unary(sort, outer)) } - RelOperator::Join(join) => { + RelOp::Join => { + let join = Join::try_downcast_ref(s_expr.plan()).unwrap(); let mut left = self.optimize_sync(s_expr.left_child())?; let mut right = self.optimize_sync(s_expr.right_child())?; if !join.has_subquery() { @@ -308,29 +316,27 @@ impl SubqueryDecorrelatorOptimizer { )); } - RelOperator::UnionAll(_) => Ok(SExpr::create_binary( + RelOp::UnionAll => Ok(SExpr::create_binary( s_expr.plan.clone(), Arc::new(self.optimize_sync(s_expr.left_child())?), Arc::new(self.optimize_sync(s_expr.right_child())?), )), - RelOperator::Limit(_) | RelOperator::Udf(_) | RelOperator::AsyncFunction(_) => { - Ok(SExpr::create_unary( - s_expr.plan.clone(), - Arc::new(self.optimize_sync(s_expr.unary_child())?), - )) - } + RelOp::Limit | RelOp::Udf | RelOp::AsyncFunction => Ok(SExpr::create_unary( + s_expr.plan.clone(), + Arc::new(self.optimize_sync(s_expr.unary_child())?), + )), - RelOperator::DummyTableScan(_) - | RelOperator::Scan(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::CacheScan(_) - | RelOperator::Exchange(_) - | RelOperator::RecursiveCteScan(_) - | RelOperator::Mutation(_) - | RelOperator::MutationSource(_) - | RelOperator::CompactBlock(_) => Ok(s_expr.clone()), + RelOp::DummyTableScan + | RelOp::Scan + | RelOp::ConstantTableScan + | RelOp::ExpressionScan + | RelOp::CacheScan + | RelOp::Exchange => Ok(SExpr::create_unary( + s_expr.plan.clone(), + Arc::new(self.optimize_sync(s_expr.unary_child())?), + )), + _ => Ok(s_expr.clone()), } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs index aec96f1296246..8a11bd4a374c7 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs @@ -105,14 +105,12 @@ impl DeduplicateJoinConditionOptimizer { #[recursive::recursive] pub fn deduplicate(&mut self, s_expr: &SExpr) -> Result { - match s_expr.plan.as_ref() { - // Only optimize inner joins - RelOperator::Join(join) if join.join_type == JoinType::Inner => { - self.optimize_inner_join(s_expr, join) + if let Some(join) = Join::try_downcast_ref(s_expr.plan.as_ref()) { + if join.join_type == JoinType::Inner { + return self.optimize_inner_join(s_expr, join); } - // Recursively process other nodes - _ => self.deduplicate_children(s_expr), } + self.deduplicate_children(s_expr) } /// Optimize inner join by removing redundant conditions diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs index df3372f52d019..98f325977f23c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs @@ -73,12 +73,23 @@ impl PullUpFilterOptimizer { #[recursive::recursive] pub fn pull_up(&mut self, s_expr: &SExpr) -> Result { - match s_expr.plan.as_ref() { - RelOperator::Filter(filter) => self.pull_up_filter(s_expr, filter), - RelOperator::Join(join) if !join.is_lateral && !join.has_null_equi_condition() => { - self.pull_up_join(s_expr, join) + match s_expr.plan.rel_op() { + RelOp::Filter => { + let filter = Filter::try_downcast_ref(&s_expr.plan).unwrap(); + self.pull_up_filter(s_expr, filter) + } + RelOp::Join => { + let join = Join::try_downcast_ref(&s_expr.plan).unwrap(); + if !join.is_lateral && !join.has_null_equi_condition() { + self.pull_up_join(s_expr, join) + } else { + self.pull_up_others(s_expr) + } + } + RelOp::EvalScalar => { + let eval_scalar = EvalScalar::try_downcast_ref(&s_expr.plan).unwrap(); + self.pull_up_eval_scalar(s_expr, eval_scalar) } - RelOperator::EvalScalar(eval_scalar) => self.pull_up_eval_scalar(s_expr, eval_scalar), _ => self.pull_up_others(s_expr), } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs index be6a9e0179811..ed50170040deb 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/agg_index/query_rewrite.rs @@ -107,7 +107,7 @@ impl QueryInfo { // collect query info from the plan let mut s_expr = s_expr.child(0)?; loop { - match s_expr.plan().rel_op() { + match s_expr.plan_rel_op() { RelOp::EvalScalar => { let eval = s_expr.plan().as_any().downcast_ref::().unwrap(); for item in &eval.items { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs index cb43212d3f684..497030a34a169 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs @@ -130,7 +130,7 @@ impl RulePushDownRankLimitAggregate { ) -> databend_common_exception::Result<()> { let sort: Sort = s_expr.plan().clone().try_into()?; let mut has_eval_scalar = false; - let agg_limit_expr = match s_expr.child(0)?.plan().rel_op() { + let agg_limit_expr = match s_expr.child(0)?.plan_rel_op() { RelOp::Aggregate => s_expr.child(0)?, RelOp::EvalScalar => { has_eval_scalar = true; @@ -199,7 +199,7 @@ impl Rule for RulePushDownRankLimitAggregate { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - match s_expr.plan().rel_op() { + match s_expr.plan_rel_op() { RelOp::Limit => self.apply_limit(s_expr, state), RelOp::Sort | RelOp::EvalScalar => self.apply_sort(s_expr, state), _ => Ok(()), diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs index 65a25e55f0717..bb21d06ad6f50 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs @@ -83,7 +83,7 @@ impl Rule for RulePushDownFilterJoin { // Second, check if can convert mark join to semi join let (s_expr, mark_to_semi) = convert_mark_to_semi_join(&s_expr)?; - if s_expr.plan().rel_op() != RelOp::Filter { + if s_expr.plan_rel_op() != RelOp::Filter { state.add_result(s_expr); return Ok(()); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs index 792d4087be9d7..f92cec5ce5a75 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs @@ -76,7 +76,7 @@ impl Rule for RulePushDownSortScan { let sort: Sort = s_expr.plan().clone().try_into()?; let child = s_expr.child(0)?; - let mut get = match child.plan().rel_op() { + let mut get = match child.plan_rel_op() { RelOp::Scan => { let s = child.plan().as_any().downcast_ref::().unwrap(); s.clone() @@ -98,7 +98,7 @@ impl Rule for RulePushDownSortScan { let get = SExpr::create_leaf(get); - let mut result = match child.plan().rel_op() { + let mut result = match child.plan_rel_op() { RelOp::Scan => s_expr.replace_children(vec![Arc::new(get)]), RelOp::EvalScalar => { let child = child.replace_children(vec![Arc::new(get)]); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs index b9a1b5fa74341..9ed2671a61e2a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs @@ -125,7 +125,7 @@ fn is_valid_frame(frame: &WindowFuncFrame) -> bool { } fn child_has_window(child: &SExpr) -> bool { - match child.plan().rel_op() { + match child.plan_rel_op() { RelOp::Window => true, RelOp::Scan => false, // finish recursion _ => child.children().any(child_has_window), diff --git a/src/query/sql/src/planner/optimizer/pipeline/common.rs b/src/query/sql/src/planner/optimizer/pipeline/common.rs index 9ebd80f83b944..68e5dbd561377 100644 --- a/src/query/sql/src/planner/optimizer/pipeline/common.rs +++ b/src/query/sql/src/planner/optimizer/pipeline/common.rs @@ -37,7 +37,7 @@ pub fn contains_local_table_scan(s_expr: &SExpr, metadata: &MetadataRef) -> bool } else { false } - || matches!(s_expr.plan().rel_op(), RelOp::RecursiveCteScan) + || matches!(s_expr.plan_rel_op(), RelOp::RecursiveCteScan) } pub fn contains_warehouse_table_scan(s_expr: &SExpr, metadata: &MetadataRef) -> bool { diff --git a/src/query/sql/src/planner/plans/plan.rs b/src/query/sql/src/planner/plans/plan.rs index 2a28807ed6ce9..1d2bbbea13035 100644 --- a/src/query/sql/src/planner/plans/plan.rs +++ b/src/query/sql/src/planner/plans/plan.rs @@ -119,6 +119,7 @@ use crate::plans::InspectWarehousePlan; use crate::plans::KillPlan; use crate::plans::ModifyTableColumnPlan; use crate::plans::ModifyTableCommentPlan; +use crate::plans::Operator; use crate::plans::OptimizeCompactSegmentPlan; use crate::plans::OptimizePurgePlan; use crate::plans::PresignPlan; @@ -128,7 +129,6 @@ use crate::plans::RefreshIndexPlan; use crate::plans::RefreshTableCachePlan; use crate::plans::RefreshTableIndexPlan; use crate::plans::RefreshVirtualColumnPlan; -use crate::plans::Operator; use crate::plans::RemoveStagePlan; use crate::plans::RenameDatabasePlan; use crate::plans::RenameTableColumnPlan; @@ -591,7 +591,8 @@ impl Plan { ignore_result, } = self { - if let RelOperator::Exchange(Exchange::Merge) = s_expr.plan.as_ref() { + let s = Exchange::try_downcast_ref(&s_expr.plan); + if let Some(Exchange::Merge) = s { let s_expr = Box::new(s_expr.child(0).unwrap().clone()); return Plan::Query { s_expr, diff --git a/src/query/sql/src/planner/plans/recluster.rs b/src/query/sql/src/planner/plans/recluster.rs index b9a8d7e79aac4..3cd272057158f 100644 --- a/src/query/sql/src/planner/plans/recluster.rs +++ b/src/query/sql/src/planner/plans/recluster.rs @@ -27,7 +27,9 @@ use databend_common_expression::Scalar; use crate::optimizer::ir::SExpr; use crate::optimizer::optimize; use crate::optimizer::OptimizerContext; +use crate::plans::Aggregate; use crate::plans::ConstantExpr; +use crate::plans::EvalScalar; use crate::plans::Operator; use crate::plans::Plan; use crate::plans::Scan; @@ -126,15 +128,17 @@ pub fn replace_with_constant(expr: &SExpr, variables: &VecDeque, partiti partitions: u16, ) -> SExpr { let mut s_expr = s_expr.clone(); - s_expr.plan = match s_expr.plan.as_ref() { - RelOperator::EvalScalar(expr) if !variables.is_empty() => { + s_expr.plan = match s_expr.plan.rel_op() { + RelOp::EvalScalar if !variables.is_empty() => { + let expr = EvalScalar::try_downcast_ref(&s_expr.plan).unwrap(); let mut expr = expr.clone(); for item in &mut expr.items { visit_expr_column(&mut item.scalar, variables); } Arc::new(expr.into()) } - RelOperator::Aggregate(aggr) => { + RelOp::Aggregate => { + let aggr = Aggregate::try_downcast_ref(&s_expr.plan).unwrap(); let mut aggr = aggr.clone(); for item in &mut aggr.aggregate_functions { if let ScalarExpr::AggregateFunction(func) = &mut item.scalar { From ed1cdc82d8fbc37df0f1287b56fcf863343b0134 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Mon, 7 Jul 2025 09:57:14 +0000 Subject: [PATCH 09/14] update --- .../src/interpreters/hook/compact_hook.rs | 7 +- .../interpreters/interpreter_index_refresh.rs | 5 +- .../it/sql/planner/optimizer/test_utils.rs | 4 +- .../physical_aggregate_final.rs | 2 +- .../physical_plans/physical_eval_scalar.rs | 4 +- .../bind_mutation/mutation_expression.rs | 2 +- .../planner/binder/bind_query/bind_value.rs | 36 +++--- src/query/sql/src/planner/binder/binder.rs | 106 +----------------- src/query/sql/src/planner/binder/table.rs | 33 ++---- src/query/sql/src/planner/binder/util.rs | 37 +++--- .../planner/format/display_rel_operator.rs | 2 +- .../filter_selectivity_sample.rs | 4 +- .../operator/aggregate/stats_aggregate.rs | 2 +- .../operator/decorrelate/flatten_plan.rs | 2 +- .../decorrelate/subquery_decorrelator.rs | 3 +- .../agg_rules/rule_fold_count_aggregate.rs | 5 +- .../rule_push_down_filter_scan.rs | 5 +- .../filter_rules/rule_push_down_prewhere.rs | 2 +- src/query/sql/src/planner/plans/recluster.rs | 2 +- 19 files changed, 67 insertions(+), 196 deletions(-) diff --git a/src/query/service/src/interpreters/hook/compact_hook.rs b/src/query/service/src/interpreters/hook/compact_hook.rs index 661633a8c6a19..b6f890a80f07e 100644 --- a/src/query/service/src/interpreters/hook/compact_hook.rs +++ b/src/query/service/src/interpreters/hook/compact_hook.rs @@ -27,7 +27,6 @@ use databend_common_sql::executor::physical_plans::MutationKind; use databend_common_sql::optimizer::ir::SExpr; use databend_common_sql::plans::OptimizeCompactBlock; use databend_common_sql::plans::ReclusterPlan; - use databend_storages_common_table_meta::table::ClusterType; use log::info; @@ -169,13 +168,13 @@ async fn compact_table( { // do compact. - let compact_block = RelOperator::CompactBlock(OptimizeCompactBlock { + let compact_block = OptimizeCompactBlock { catalog: compact_target.catalog.clone(), database: compact_target.database.clone(), table: compact_target.table.clone(), limit: compaction_limits.clone(), - }); - let s_expr = SExpr::create_leaf(Arc::new(compact_block)); + }; + let s_expr = SExpr::create_leaf(compact_block); let compact_interpreter = OptimizeCompactBlockInterpreter::try_create( ctx.clone(), s_expr, diff --git a/src/query/service/src/interpreters/interpreter_index_refresh.rs b/src/query/service/src/interpreters/interpreter_index_refresh.rs index 1fc02905cf389..1626e9df69fa9 100644 --- a/src/query/service/src/interpreters/interpreter_index_refresh.rs +++ b/src/query/service/src/interpreters/interpreter_index_refresh.rs @@ -38,9 +38,10 @@ use databend_common_sql::executor::physical_plans::TableScan; use databend_common_sql::executor::PhysicalPlan; use databend_common_sql::executor::PhysicalPlanBuilder; use databend_common_sql::executor::PhysicalPlanReplacer; +use databend_common_sql::plans::EvalScalar; +use databend_common_sql::plans::Operator; use databend_common_sql::plans::Plan; use databend_common_sql::plans::RefreshIndexPlan; - use databend_common_storages_fuse::operations::AggIndexSink; use databend_common_storages_fuse::pruning::create_segment_location_vector; use databend_common_storages_fuse::FuseBlockPartInfo; @@ -223,7 +224,7 @@ impl Interpreter for RefreshIndexInterpreter { bind_context, .. } => { - let schema = if let RelOperator::EvalScalar(eval) = s_expr.plan() { + let schema = if let Some(eval) = EvalScalar::try_downcast_ref(s_expr.plan()) { let fields = eval .items .iter() diff --git a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs index 2147a6f936415..46c4ca8029232 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/test_utils.rs @@ -497,7 +497,7 @@ impl ExprBuilder { equi_conditions, ..Default::default() }; - SExpr::create_binary(Arc::new(join), Arc::new(left), Arc::new(right)) + SExpr::create_binary(join, left, right) } /// Create a join condition between two columns @@ -512,7 +512,7 @@ impl ExprBuilder { /// Create a filter pub fn filter(&self, input: SExpr, predicates: Vec) -> SExpr { - SExpr::create_unary(Arc::new(Filter { predicates }), Arc::new(input)) + SExpr::create_unary(Filter { predicates }, input) } /// Create a table scan diff --git a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs index 900ac74625f6c..bdde7a54e5ea1 100644 --- a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs +++ b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs @@ -109,7 +109,7 @@ impl PhysicalPlanBuilder { }); if agg.group_items.is_empty() && used.is_empty() { - let expr = SExpr::create_leaf(Arc::new(DummyTableScan.into())); + let expr = SExpr::create_leaf(DummyTableScan); return self.build(&expr, required).await; } diff --git a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs index bab7c82062b24..e9d02279aba4b 100644 --- a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs +++ b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs @@ -32,9 +32,9 @@ use crate::optimizer::ir::Matcher; use crate::optimizer::ir::SExpr; use crate::plans::Filter; use crate::plans::FunctionCall; +use crate::plans::Operator; use crate::plans::ProjectSet; use crate::plans::RelOp; -use crate::plans::Operator; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; use crate::plans::Visitor; @@ -232,7 +232,7 @@ impl PhysicalPlanBuilder { return Ok(None); } - if let RelOperator::Filter(filter) = s_expr.plan() { + if let Some(filter) = Filter::try_downcast_ref(s_expr.plan()) { let child = s_expr.child(0)?; let project_set: ProjectSet = child.plan().clone().try_into()?; let Some(new_project_set) = diff --git a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs index d0570cc046e95..98992c3eb490c 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs @@ -404,7 +404,7 @@ impl MutationExpression { let mut scan = scan.clone(); scan.is_lazy_table = is_lazy_table; scan.set_update_stream_columns(update_stream_columns); - return Ok(SExpr::create_leaf(Arc::new(scan.into()))); + return Ok(SExpr::create_leaf(scan)); } let mut children = Vec::with_capacity(s_expr.arity()); for child in s_expr.children() { diff --git a/src/query/sql/src/planner/binder/bind_query/bind_value.rs b/src/query/sql/src/planner/binder/bind_query/bind_value.rs index f32fd7f1a20ea..b85217202a15c 100644 --- a/src/query/sql/src/planner/binder/bind_query/bind_value.rs +++ b/src/query/sql/src/planner/binder/bind_query/bind_value.rs @@ -597,18 +597,15 @@ pub fn bind_expression_scan( ); } - let s_expr = SExpr::create_leaf(Arc::new( - ExpressionScan { - expression_scan_index, - values: scalars, - num_scalar_columns: num_columns, - cache_index, - data_types: column_common_type, - column_indexes, - schema: DataSchemaRefExt::create(vec![]), - } - .into(), - )); + let s_expr = SExpr::create_leaf(ExpressionScan { + expression_scan_index, + values: scalars, + num_scalar_columns: num_columns, + cache_index, + data_types: column_common_type, + column_indexes, + schema: DataSchemaRefExt::create(vec![]), + }); Ok((s_expr, bind_context.clone())) } @@ -698,15 +695,12 @@ pub fn bind_constant_scan( } let schema = DataSchemaRefExt::create(fields); - let s_expr = SExpr::create_leaf(Arc::new( - ConstantTableScan { - values: value_columns, - num_rows: num_values, - schema, - columns, - } - .into(), - )); + let s_expr = SExpr::create_leaf(ConstantTableScan { + values: value_columns, + num_rows: num_values, + schema, + columns, + }); Ok((s_expr, bind_context.clone())) } diff --git a/src/query/sql/src/planner/binder/binder.rs b/src/query/sql/src/planner/binder/binder.rs index a999b7568c999..ce8803302b358 100644 --- a/src/query/sql/src/planner/binder/binder.rs +++ b/src/query/sql/src/planner/binder/binder.rs @@ -63,8 +63,8 @@ use crate::plans::DropFileFormatPlan; use crate::plans::DropRolePlan; use crate::plans::DropStagePlan; use crate::plans::DropUserPlan; -use crate::plans::Plan; use crate::plans::Operator; +use crate::plans::Plan; use crate::plans::RewriteKind; use crate::plans::ShowConnectionsPlan; use crate::plans::ShowFileFormatsPlan; @@ -952,110 +952,6 @@ impl<'a> Binder { Ok(finder.scalars().is_empty()) } - #[allow(dead_code)] - pub(crate) fn check_sexpr_top(&self, s_expr: &SExpr) -> Result { - let f = |scalar: &ScalarExpr| matches!(scalar, ScalarExpr::UDFCall(_)); - let mut finder = Finder::new(&f); - Self::check_sexpr(s_expr, &mut finder) - } - - #[recursive::recursive] - pub(crate) fn check_sexpr(s_expr: &'a SExpr, f: &'a mut Finder<'a, F>) -> Result - where F: Fn(&ScalarExpr) -> bool { - let result = match s_expr.plan.as_ref() { - RelOperator::Scan(scan) => { - f.reset_finder(); - if let Some(agg_info) = &scan.agg_index { - for predicate in &agg_info.predicates { - f.visit(predicate)?; - } - for selection in &agg_info.selection { - f.visit(&selection.scalar)?; - } - } - if let Some(predicates) = &scan.push_down_predicates { - for predicate in predicates { - f.visit(predicate)?; - } - } - f.scalars().is_empty() - } - RelOperator::Join(join) => { - f.reset_finder(); - for condition in join.equi_conditions.iter() { - f.visit(&condition.left)?; - f.visit(&condition.right)?; - } - for condition in &join.non_equi_conditions { - f.visit(condition)?; - } - f.scalars().is_empty() - } - RelOperator::EvalScalar(eval) => { - f.reset_finder(); - for item in &eval.items { - f.visit(&item.scalar)?; - } - f.scalars().is_empty() - } - RelOperator::Filter(filter) => { - f.reset_finder(); - for predicate in &filter.predicates { - f.visit(predicate)?; - } - f.scalars().is_empty() - } - RelOperator::Aggregate(aggregate) => { - f.reset_finder(); - for item in &aggregate.group_items { - f.visit(&item.scalar)?; - } - for item in &aggregate.aggregate_functions { - f.visit(&item.scalar)?; - } - f.scalars().is_empty() - } - RelOperator::Exchange(exchange) => { - f.reset_finder(); - if let crate::plans::Exchange::Hash(hash) = exchange { - for scalar in hash { - f.visit(scalar)?; - } - } - f.scalars().is_empty() - } - RelOperator::Window(window) => { - f.reset_finder(); - for scalar_item in &window.arguments { - f.visit(&scalar_item.scalar)?; - } - for scalar_item in &window.partition_by { - f.visit(&scalar_item.scalar)?; - } - for info in &window.order_by { - f.visit(&info.order_by_item.scalar)?; - } - f.scalars().is_empty() - } - RelOperator::Udf(_) => false, - _ => true, - }; - - match result { - true => { - for child in &s_expr.children { - let mut finder = Finder::new(f.find_fn()); - let flag = Self::check_sexpr(child.as_ref(), &mut finder)?; - if !flag { - return Ok(false); - } - } - Ok(true) - } - false => Ok(false), - } - } - pub(crate) fn check_allowed_scalar_expr_with_subquery_for_copy_table( &self, scalar: &ScalarExpr, diff --git a/src/query/sql/src/planner/binder/table.rs b/src/query/sql/src/planner/binder/table.rs index 59a4a09062244..a6101502187b3 100644 --- a/src/query/sql/src/planner/binder/table.rs +++ b/src/query/sql/src/planner/binder/table.rs @@ -66,8 +66,8 @@ use crate::optimizer::ir::SExpr; use crate::planner::semantic::normalize_identifier; use crate::planner::semantic::TypeChecker; use crate::plans::DummyTableScan; -use crate::plans::RecursiveCteScan; use crate::plans::Operator; +use crate::plans::RecursiveCteScan; use crate::plans::Scan; use crate::plans::Statistics; use crate::BaseTableColumn; @@ -99,10 +99,7 @@ impl Binder { } } let bind_context = BindContext::with_parent(bind_context.clone())?; - Ok(( - SExpr::create_leaf(Arc::new(DummyTableScan.into())), - bind_context, - )) + Ok((SExpr::create_leaf(DummyTableScan), bind_context)) } #[async_backtrace::framed] @@ -305,10 +302,7 @@ impl Binder { }; Ok(( - SExpr::create_leaf(Arc::new(RelOperator::RecursiveCteScan(RecursiveCteScan { - fields, - table_name, - }))), + SExpr::create_leaf(RecursiveCteScan { fields, table_name }), new_bind_ctx, )) } @@ -436,18 +430,15 @@ impl Binder { .add_base_column_scan_id(base_column_scan_id); Ok(( - SExpr::create_leaf(Arc::new( - Scan { - table_index, - columns: columns.into_iter().map(|col| col.index()).collect(), - statistics: Arc::new(Statistics::default()), - change_type, - sample: sample.clone(), - scan_id, - ..Default::default() - } - .into(), - )), + SExpr::create_leaf(Scan { + table_index, + columns: columns.into_iter().map(|col| col.index()).collect(), + statistics: Arc::new(Statistics::default()), + change_type, + sample: sample.clone(), + scan_id, + ..Default::default() + }), bind_context, )) } diff --git a/src/query/sql/src/planner/binder/util.rs b/src/query/sql/src/planner/binder/util.rs index 6d82b18145920..a46e7e32cecfe 100644 --- a/src/query/sql/src/planner/binder/util.rs +++ b/src/query/sql/src/planner/binder/util.rs @@ -25,6 +25,7 @@ use databend_common_expression::types::DataType; use crate::normalize_identifier; use crate::optimizer::ir::SExpr; use crate::plans::Operator; +use crate::plans::RelOp; use crate::Binder; use crate::NameResolutionContext; use crate::NameResolutionSuggest; @@ -46,43 +47,37 @@ impl Binder { cte_scan_names: &mut Vec, cte_types: &mut Vec, ) -> Result<()> { - match expr.plan() { - RelOperator::Join(_) | RelOperator::UnionAll(_) => { + match expr.plan_rel_op() { + RelOp::Join | RelOp::UnionAll => { self.count_r_cte_scan(expr.child(0)?, cte_scan_names, cte_types)?; self.count_r_cte_scan(expr.child(1)?, cte_scan_names, cte_types)?; } - RelOperator::ProjectSet(_) - | RelOperator::AsyncFunction(_) - | RelOperator::Udf(_) - | RelOperator::EvalScalar(_) - | RelOperator::Filter(_) => { + RelOp::ProjectSet + | RelOp::AsyncFunction + | RelOp::Udf + | RelOp::EvalScalar + | RelOp::Filter => { self.count_r_cte_scan(expr.child(0)?, cte_scan_names, cte_types)?; } - RelOperator::RecursiveCteScan(plan) => { + RelOp::RecursiveCteScan => { cte_scan_names.push(plan.table_name.clone()); if cte_types.is_empty() { cte_types.extend(plan.fields.iter().map(|f| f.data_type().clone())); } } - RelOperator::Exchange(_) - | RelOperator::Scan(_) - | RelOperator::DummyTableScan(_) - | RelOperator::ConstantTableScan(_) - | RelOperator::ExpressionScan(_) - | RelOperator::CacheScan(_) => {} + RelOp::Exchange + | RelOp::Scan + | RelOp::DummyTableScan + | RelOp::ConstantTableScan + | RelOp::ExpressionScan + | RelOp::CacheScan => {} // Each recursive step in a recursive query generates new rows, and these rows are used for the next recursion. // Each step depends on the results of the previous step, so it's essential to ensure that the result set is built incrementally. // These operators need to operate on the entire result set, // which is incompatible with the way a recursive query incrementally builds the result set. - RelOperator::Sort(_) - | RelOperator::Limit(_) - | RelOperator::Aggregate(_) - | RelOperator::Window(_) - | RelOperator::Mutation(_) - | RelOperator::MutationSource(_) - | RelOperator::CompactBlock(_) => { + _ => { return Err(ErrorCode::SyntaxException(format!( "{:?} is not allowed in recursive cte", expr.plan_rel_op() diff --git a/src/query/sql/src/planner/format/display_rel_operator.rs b/src/query/sql/src/planner/format/display_rel_operator.rs index 299e99533768d..78192a4cebcdd 100644 --- a/src/query/sql/src/planner/format/display_rel_operator.rs +++ b/src/query/sql/src/planner/format/display_rel_operator.rs @@ -101,7 +101,7 @@ fn to_format_tree(id_humanizer: &I, op: &OperatorRef) -> FormatT union_all_to_format_tree(id_humanizer, union_all) } RelOp::MergeInto => { - let merge_into = MergeInto::try_downcast_ref(op).unwrap(); + let merge_into = Mutation::try_downcast_ref(op).unwrap(); merge_into_to_format_tree(id_humanizer, merge_into) } _ => FormatTreeNode::with_children(format!("{:?}", op), vec![]), diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs index 2545063f3a67a..a17dc6a5c69cc 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs @@ -69,8 +69,8 @@ pub async fn filter_selectivity_sample( block_level: Some(50.0), }; scan.sample = Some(sample_conf); - let new_child = SExpr::create_leaf(Arc::new(scan)); - new_s_expr = s_expr.replace_children(vec![Arc::new(new_child)]); + let new_child = SExpr::create_leaf(scan); + new_s_expr = s_expr.replace_children(vec![new_child]); let opt_ctx = OptimizerContext::new(ctx.clone(), metadata.clone()); let mut collect_statistics_optimizer = CollectStatisticsOptimizer::new(opt_ctx); diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs index 04c8a9c45c7ae..9a66a6758c504 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/stats_aggregate.rs @@ -184,7 +184,7 @@ impl RuleStatsAggregateOptimizer { }; if agg_results.is_empty() { - let leaf = SExpr::create_leaf(Arc::new(DummyTableScan.into())); + let leaf = SExpr::create_leaf(DummyTableScan); return Ok(SExpr::create_unary(eval_scalar, leaf)); } else { let agg = Aggregate { diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs index fee29050496ee..6a9e25283e3c9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs @@ -945,7 +945,7 @@ impl SubqueryDecorrelatorOptimizer { Ok(Arc::new(scan)) } - fn clone_outer_scan(&mut self, scan: &Scan) -> OperatorRef { + fn clone_outer_scan(&mut self, scan: &Scan) -> Result { let mut metadata = self.metadata.write(); let columns = scan .columns diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs index 4926137ab8d78..27ac015655ca3 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs @@ -303,8 +303,7 @@ impl SubqueryDecorrelatorOptimizer { non_equi_conditions: vec![], ..join.clone() }; - let mut outer = - SExpr::create_binary(Arc::new(join.into()), Arc::new(left), Arc::new(right)); + let mut outer = SExpr::create_binary(join, left, right); for pred in predicates.iter_mut() { (*pred, outer) = self.try_rewrite_subquery(pred, outer, true)?; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs index e62f2c65b0ac6..18d076c7775fa 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs @@ -108,10 +108,9 @@ impl Rule for RuleFoldCountAggregate { } } let eval_scalar = EvalScalar { items: scalars }; - let dummy_table_scan = DummyTableScan; state.add_result(SExpr::create_unary( - Arc::new(eval_scalar.into()), - Arc::new(SExpr::create_leaf(Arc::new(dummy_table_scan.into()))), + eval_scalar, + SExpr::create_leaf(DummyTableScan), )); } Ok(()) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs index 62b9913fb0ecf..57ad23499bbf9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs @@ -198,10 +198,7 @@ impl Rule for RulePushDownFilterScan { None => scan.push_down_predicates = Some(add_filters), } - let mut result = SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(SExpr::create_leaf(Arc::new(scan.into()))), - ); + let mut result = SExpr::create_unary(filter, SExpr::create_leaf(scan)); result.set_applied_rule(&self.id); state.add_result(result); Ok(()) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs index 8a5dd9c3d1c00..b3c225edf386c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs @@ -169,7 +169,7 @@ impl RulePushDownPrewhere { predicates: prewhere_pred, }); } - Ok(SExpr::create_leaf(Arc::new(scan.into()))) + Ok(SExpr::create_leaf(scan)) } } diff --git a/src/query/sql/src/planner/plans/recluster.rs b/src/query/sql/src/planner/plans/recluster.rs index 3cd272057158f..9d1fef66e8a80 100644 --- a/src/query/sql/src/planner/plans/recluster.rs +++ b/src/query/sql/src/planner/plans/recluster.rs @@ -54,7 +54,7 @@ pub fn set_update_stream_columns(s_expr: &SExpr) -> Result { if scan.table_index == 0 { let mut scan = scan.clone(); scan.set_update_stream_columns(true); - return Ok(SExpr::create_leaf(Arc::new(scan.into()))); + return Ok(SExpr::create_leaf(scan)); } } From 9ee0b228aa8fb2ff6da993df54bd8c1f2016eab0 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Tue, 8 Jul 2025 13:40:55 +0000 Subject: [PATCH 10/14] update --- .../tests/it/aggregating_index/index_scan.rs | 2 +- .../interpreters/interpreter_index_refresh.rs | 3 +- .../sql/planner/optimizer/optimizer_test.rs | 2 +- .../physical_plans/physical_eval_scalar.rs | 2 +- .../bind_mutation/mutation_expression.rs | 4 +- .../planner/binder/bind_query/bind_value.rs | 4 +- .../bind_table_function.rs | 2 +- .../planner/format/display_rel_operator.rs | 32 +++++++----- .../src/planner/optimizer/ir/expr/s_expr.rs | 4 +- .../src/planner/optimizer/ir/expr/visitor.rs | 2 +- .../sql/src/planner/optimizer/ir/format.rs | 8 ++- .../planner/optimizer/ir/property/enforcer.rs | 2 +- .../sql/src/planner/optimizer/optimizer.rs | 2 +- .../optimizers/cascades/cost/model.rs | 21 ++++++-- .../optimizer/optimizers/hyper_dp/dphyp.rs | 15 ++++-- .../hyper_dp/dynamic_sample/dynamic_sample.rs | 7 ++- .../filter_selectivity_sample.rs | 2 +- .../dynamic_sample/join_selectivity_sample.rs | 2 +- .../operator/aggregate/normalize_aggregate.rs | 2 +- .../operator/decorrelate/decorrelate.rs | 23 ++++++-- .../operator/decorrelate/flatten_plan.rs | 52 ++++++++++++------- .../decorrelate/subquery_decorrelator.rs | 14 ++--- .../filter/deduplicate_join_condition.rs | 2 +- .../operator/filter/pull_up_filter.rs | 6 +-- src/query/sql/src/planner/plans/operator.rs | 8 --- src/query/sql/src/planner/plans/plan.rs | 2 +- src/query/sql/src/planner/plans/recluster.rs | 4 +- 27 files changed, 143 insertions(+), 86 deletions(-) diff --git a/src/query/ee/tests/it/aggregating_index/index_scan.rs b/src/query/ee/tests/it/aggregating_index/index_scan.rs index 3ffd8d5dcc433..5b9d9b81d7c60 100644 --- a/src/query/ee/tests/it/aggregating_index/index_scan.rs +++ b/src/query/ee/tests/it/aggregating_index/index_scan.rs @@ -595,7 +595,7 @@ fn is_index_scan_plan(plan: &Plan) -> bool { } fn is_index_scan_sexpr(s_expr: &SExpr) -> bool { - if let Some(scan) = Scan::try_downcast_ref(&s_expr.plan) { + if let Some(scan) = s_expr.plan.as_any().downcast_ref::() { scan.agg_index.is_some() } else { s_expr.children().any(is_index_scan_sexpr) diff --git a/src/query/service/src/interpreters/interpreter_index_refresh.rs b/src/query/service/src/interpreters/interpreter_index_refresh.rs index 1626e9df69fa9..83a3957ce5648 100644 --- a/src/query/service/src/interpreters/interpreter_index_refresh.rs +++ b/src/query/service/src/interpreters/interpreter_index_refresh.rs @@ -224,7 +224,8 @@ impl Interpreter for RefreshIndexInterpreter { bind_context, .. } => { - let schema = if let Some(eval) = EvalScalar::try_downcast_ref(s_expr.plan()) { + let schema = if let Some(eval) = s_expr.plan().as_any().downcast_ref::() + { let fields = eval .items .iter() diff --git a/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs b/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs index 07f09f5313546..60b0e6d8e9e0d 100644 --- a/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs +++ b/src/query/service/tests/it/sql/planner/optimizer/optimizer_test.rs @@ -365,7 +365,7 @@ struct StatsApplier<'a> { impl<'a> SExprVisitor for StatsApplier<'a> { fn visit(&mut self, expr: &SExpr) -> Result { - if let Some(scan) = Scan::try_downcast_ref(&expr.plan) { + if let Some(scan) = expr.plan().as_any().downcast_ref::() { let metadata = self.metadata.read(); let table = metadata.table(scan.table_index); diff --git a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs index e9d02279aba4b..26744a2130014 100644 --- a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs +++ b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs @@ -232,7 +232,7 @@ impl PhysicalPlanBuilder { return Ok(None); } - if let Some(filter) = Filter::try_downcast_ref(s_expr.plan()) { + if let Some(filter) = s_expr.plan().as_any().downcast_ref::() { let child = s_expr.child(0)?; let project_set: ProjectSet = child.plan().clone().try_into()?; let Some(new_project_set) = diff --git a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs index 98992c3eb490c..4cb04f76af511 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs @@ -400,7 +400,7 @@ impl MutationExpression { return Ok(s_expr.clone()); } - if let Some(scan) = Scan::try_downcast_ref(s_expr.plan()) { + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { let mut scan = scan.clone(); scan.is_lazy_table = is_lazy_table; scan.set_update_stream_columns(update_stream_columns); @@ -550,7 +550,7 @@ pub fn target_probe(s_expr: &SExpr, target_table_index: usize) -> Result { } fn contains_target_table(s_expr: &SExpr, target_table_index: usize) -> bool { - if let Some(scan) = Scan::try_downcast_ref(s_expr.plan()) { + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { scan.table_index == target_table_index } else { s_expr diff --git a/src/query/sql/src/planner/binder/bind_query/bind_value.rs b/src/query/sql/src/planner/binder/bind_query/bind_value.rs index b85217202a15c..1cc6f16b80673 100644 --- a/src/query/sql/src/planner/binder/bind_query/bind_value.rs +++ b/src/query/sql/src/planner/binder/bind_query/bind_value.rs @@ -216,7 +216,7 @@ impl Binder { s_expr: &SExpr, metadata: MetadataRef, ) -> Result<(SExpr, ColumnSet)> { - if let Some(join) = Join::try_downcast_ref(&s_expr.plan) { + if let Some(join) = s_expr.plan().as_any().downcast_ref::() { if join.build_side_cache_info.is_some() { let mut join = join.clone(); let build_side_cache_info = join.build_side_cache_info.as_mut().unwrap(); @@ -255,7 +255,7 @@ impl Binder { } } - if let Some(scan) = ExpressionScan::try_downcast_ref(&s_expr.plan) { + if let Some(scan) = s_expr.plan().as_any().downcast_ref::() { // The join condition columns may consist of the following two parts: // (1) expression scan columns. // (2) correlated columns in values. diff --git a/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs b/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs index 2c2a9218d1680..4bf274eafcd00 100644 --- a/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs +++ b/src/query/sql/src/planner/binder/bind_table_reference/bind_table_function.rs @@ -252,7 +252,7 @@ impl Binder { }; if let Some(fields) = fields { - if let Some(plan) = EvalScalar::try_downcast_ref(&srf_expr.plan) { + if let Some(plan) = srf_expr.plan().as_any().downcast_ref::() { if plan.items.len() != 1 { return Err(ErrorCode::Internal(format!( "Invalid table function subquery EvalScalar items, expect 1, but got {}", diff --git a/src/query/sql/src/planner/format/display_rel_operator.rs b/src/query/sql/src/planner/format/display_rel_operator.rs index 78192a4cebcdd..8744a09f0944b 100644 --- a/src/query/sql/src/planner/format/display_rel_operator.rs +++ b/src/query/sql/src/planner/format/display_rel_operator.rs @@ -49,59 +49,63 @@ impl OperatorHumanizer for DefaultOperatorHumanizer { fn to_format_tree(id_humanizer: &I, op: &OperatorRef) -> FormatTreeNode { match op.rel_op() { RelOp::Join => { - let join = Join::try_downcast_ref(op).unwrap(); + let join = op.plan().as_any().downcast_ref::().unwrap(); join_to_format_tree(id_humanizer, join) } RelOp::Scan => { - let scan = Scan::try_downcast_ref(op).unwrap(); + let scan = op.plan().as_any().downcast_ref::().unwrap(); scan_to_format_tree(id_humanizer, scan) } RelOp::EvalScalar => { - let eval_scalar = EvalScalar::try_downcast_ref(op).unwrap(); + let eval_scalar = op.plan().as_any().downcast_ref::().unwrap(); eval_scalar_to_format_tree(id_humanizer, eval_scalar) } RelOp::Filter => { - let filter = Filter::try_downcast_ref(op).unwrap(); + let filter = op.plan().as_any().downcast_ref::().unwrap(); filter_to_format_tree(id_humanizer, filter) } RelOp::Aggregate => { - let aggregate = Aggregate::try_downcast_ref(op).unwrap(); + let aggregate = op.plan().as_any().downcast_ref::().unwrap(); aggregate_to_format_tree(id_humanizer, aggregate) } RelOp::Window => { - let window = Window::try_downcast_ref(op).unwrap(); + let window = op.plan().as_any().downcast_ref::().unwrap(); window_to_format_tree(id_humanizer, window) } RelOp::Udf => { - let udf = Udf::try_downcast_ref(op).unwrap(); + let udf = op.plan().as_any().downcast_ref::().unwrap(); udf_to_format_tree(id_humanizer, udf) } RelOp::AsyncFunction => { - let async_func = AsyncFunction::try_downcast_ref(op).unwrap(); + let async_func = op.plan().as_any().downcast_ref::().unwrap(); async_func_to_format_tree(id_humanizer, async_func) } RelOp::Sort => { - let sort = Sort::try_downcast_ref(op).unwrap(); + let sort = op.plan().as_any().downcast_ref::().unwrap(); sort_to_format_tree(id_humanizer, sort) } RelOp::Limit => { - let limit = Limit::try_downcast_ref(op).unwrap(); + let limit = op.plan().as_any().downcast_ref::().unwrap(); limit_to_format_tree(id_humanizer, limit) } RelOp::Exchange => { - let exchange = Exchange::try_downcast_ref(op).unwrap(); + let exchange = op.plan().as_any().downcast_ref::().unwrap(); exchange_to_format_tree(id_humanizer, exchange) } RelOp::ConstantTableScan => { - let constant_scan = ConstantTableScan::try_downcast_ref(op).unwrap(); + let constant_scan = op + .plan() + .as_any() + .downcast_ref::() + .unwrap(); constant_scan_to_format_tree(id_humanizer, constant_scan) } RelOp::UnionAll => { - let union_all = UnionAll::try_downcast_ref(op).unwrap(); + let union_all = op.plan().as_any().downcast_ref::().unwrap(); union_all_to_format_tree(id_humanizer, union_all) } RelOp::MergeInto => { - let merge_into = Mutation::try_downcast_ref(op).unwrap(); + let merge_into = op.plan().as_any().downcast_ref::().unwrap(); merge_into_to_format_tree(id_humanizer, merge_into) } _ => FormatTreeNode::with_children(format!("{:?}", op), vec![]), diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 8f3bdc62738e5..21fd9b81e72bb 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -242,7 +242,7 @@ impl SExpr { inverted_index: &Option, ) -> SExpr { let mut s_expr = s_expr.clone(); - s_expr.plan = if let Some(mut p) = Scan::try_downcast_mut(&mut s_expr.plan) { + s_expr.plan = if let Some(mut p) = s_expr.plan().as_any().downcast_mut::() { if p.table_index == table_index { p.columns.insert(column_index); if inverted_index.is_some() { @@ -293,7 +293,7 @@ impl SExpr { #[recursive::recursive] pub fn has_merge_exchange(&self) -> bool { - if let Some(Exchange::Merge) = Exchange::try_downcast_ref(&self.plan) { + if let Some(Exchange::Merge) = self.plan.as_any().downcast_ref::() { return true; } self.children.iter().any(|child| child.has_merge_exchange()) diff --git a/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs b/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs index 81f46919f5713..d82705f0a6262 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/visitor.rs @@ -68,7 +68,7 @@ //! impl AsyncSExprVisitor for EmptySortEliminator { //! async fn visit(&mut self, expr: &SExpr) -> Result { //! // Check if this is a Sort operator with empty sort keys -//! if let Some(sort) = Sort::try_downcast_ref(&expr.plan) { +//! if let Some(sort) = expr.plan.as_any().downcast_ref::() { //! if sort.sort_keys.is_empty() { //! // If sort has no keys, it's unnecessary - replace with its child //! if expr.arity() == 1 { diff --git a/src/query/sql/src/planner/optimizer/ir/format.rs b/src/query/sql/src/planner/optimizer/ir/format.rs index 9f7ca12f8ce6d..31f55d2784adc 100644 --- a/src/query/sql/src/planner/optimizer/ir/format.rs +++ b/src/query/sql/src/planner/optimizer/ir/format.rs @@ -57,12 +57,16 @@ fn display_rel_op(rel_op: &OperatorRef) -> String { RelOp::Limit => "Limit".to_string(), RelOp::UnionAll => "UnionAll".to_string(), RelOp::ConstantTableScan => { - let s = ConstantTableScan::try_downcast_ref(rel_op).unwrap(); + let s = rel_op + .plan() + .as_any() + .downcast_ref::() + .unwrap(); s.name().to_string() } RelOp::Exchange => { - let rel_op = Exchange::try_downcast_ref(rel_op).unwrap(); + let rel_op = rel_op.plan().as_any().downcast_ref::().unwrap(); format!("Exchange: ({})", match rel_op { Exchange::Hash(scalars) => format!( "Hash({})", diff --git a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs index a1324ae6345a7..94417c1aa588e 100644 --- a/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs +++ b/src/query/sql/src/planner/optimizer/ir/property/enforcer.rs @@ -119,7 +119,7 @@ impl PropertyEnforcer { } let plan = s_expr.plan(); - if let Some(join) = Join::try_downcast_ref(plan) { + if let Some(join) = plan.as_any().downcast_ref::() { let (probe_required_property, build_required_property) = required_properties.split_at_mut(1); if let Distribution::Hash(probe_keys) = &mut probe_required_property[0].distribution diff --git a/src/query/sql/src/planner/optimizer/optimizer.rs b/src/query/sql/src/planner/optimizer/optimizer.rs index afdb0b5a71bd1..cf68410e0410c 100644 --- a/src/query/sql/src/planner/optimizer/optimizer.rs +++ b/src/query/sql/src/planner/optimizer/optimizer.rs @@ -369,7 +369,7 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res input_s_expr = match mutation.mutation_type { MutationType::Merge => { if mutation.distributed && inner_rel_op == RelOp::Join { - let join = Join::try_from(input_s_expr.plan().clone())?; + let join = input_s_expr.plan().as_any().downcast_ref::().unwrap(); let broadcast_to_shuffle = BroadcastToShuffleOptimizer::create(); let is_broadcast = broadcast_to_shuffle.matcher.matches(&input_s_expr) && broadcast_to_shuffle.is_broadcast(&input_s_expr)?; diff --git a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs index f6a0c0dbe5aec..39d4f84fad857 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs @@ -79,16 +79,31 @@ impl DefaultCostModel { fn compute_cost_impl(&self, memo: &Memo, m_expr: &MExpr) -> Result { match m_expr.plan.as_ref().rel_op() { RelOp::Scan => { - let plan = Scan::try_downcast_ref(m_expr.plan()).unwrap(); + let plan = m_expr + .plan + .as_ref() + .as_any() + .downcast_ref::() + .unwrap(); self.compute_cost_scan(memo, m_expr, plan) } RelOp::ConstantTableScan => { - let plan = ConstantTableScan::try_downcast_ref(m_expr.plan()).unwrap(); + let plan = m_expr + .plan + .as_ref() + .as_any() + .downcast_ref::() + .unwrap(); self.compute_cost_constant_scan(plan) } RelOp::DummyTableScan => Ok(Cost(0.0)), RelOp::Join => { - let plan = Join::try_downcast_ref(m_expr.plan()).unwrap(); + let plan = m_expr + .plan + .as_ref() + .as_any() + .downcast_ref::() + .unwrap(); self.compute_cost_join(memo, m_expr, plan) } RelOp::UnionAll => self.compute_cost_union_all(memo, m_expr), diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs index a225708b9e161..ad69b4e46bb1e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dphyp.rs @@ -168,7 +168,7 @@ impl DPhpyOptimizer { JoinRelation::new(s_expr, self.sample_executor().clone()) }; - if let Some(op) = Scan::try_downcast_ref(s_expr.plan()) { + if let Some(op) = s_expr.plan.as_ref().as_any().downcast_ref::() { self.table_index_map .insert(op.table_index, self.join_relations.len() as IndexType); } @@ -197,7 +197,12 @@ impl DPhpyOptimizer { s_expr: &SExpr, join_conditions: &mut Vec<(ScalarExpr, ScalarExpr)>, ) -> Result<(Arc, bool)> { - let op = Join::try_downcast_ref(s_expr.plan()).unwrap(); + let op = s_expr + .plan + .as_ref() + .as_any() + .downcast_ref::() + .unwrap(); // Skip if build side cache info is present if op.build_side_cache_info.is_some() { return Ok((Arc::new(s_expr.clone()), true)); @@ -278,7 +283,7 @@ impl DPhpyOptimizer { join_relation: Option<&SExpr>, ) -> Result<(Arc, bool)> { // If plan is filter, save it - if let Some(op) = Filter::try_downcast_ref(s_expr.plan()) { + if let Some(op) = s_expr.plan.as_ref().as_any().downcast_ref::() { if join_child { self.filters.insert(op.clone()); } @@ -960,7 +965,7 @@ impl DPhpyOptimizer { new_s_expr = self.push_down_filter(&new_s_expr)?; // Remove empty filter - if let Some(filter) = Filter::try_downcast_ref(&new_s_expr.plan) { + if let Some(filter) = new_s_expr.plan.as_ref().as_any().downcast_ref::() { if filter.predicates.is_empty() { new_s_expr = new_s_expr.child(0)?.clone(); } @@ -1006,7 +1011,7 @@ impl DPhpyOptimizer { /// Check if a filter exists in the expression and remove it from filters set fn check_filter(&mut self, expr: &SExpr) { - if let Some(filter) = Filter::try_downcast_ref(&expr.plan) { + if let Some(filter) = expr.plan.as_ref().as_any().downcast_ref::() { if self.filters.contains(filter) { self.filters.remove(filter); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs index 9a9b3fc3513a1..0ea047c51b376 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/dynamic_sample.rs @@ -126,7 +126,12 @@ pub async fn dynamic_sample( .await? .deref() .clone(); - let project_set = ProjectSet::try_downcast_ref(s_expr.plan()).unwrap(); + let project_set = s_expr + .plan + .as_ref() + .as_any() + .downcast_ref::() + .unwrap(); project_set.derive_project_set_stats(&mut child_stat_info) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs index a17dc6a5c69cc..70ce98d2bf93a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs @@ -52,7 +52,7 @@ pub async fn filter_selectivity_sample( // Because it's meaningless for filter cardinality by sample in single table query. let child = s_expr.child(0)?; let child_rel_expr = RelExpr::with_s_expr(child); - if let Some(scan) = Scan::try_downcast_ref(child.plan.as_ref()) { + if let Some(scan) = child.plan.as_ref().as_any().downcast_ref::() { let num_rows = scan .statistics .table_stats diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/join_selectivity_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/join_selectivity_sample.rs index 8c65a3a02a57a..46b43ce8f3e00 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/join_selectivity_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/join_selectivity_sample.rs @@ -44,6 +44,6 @@ pub async fn join_selectivity_sample( sample_executor.clone(), ) .await?; - let join = Join::try_from(s_expr.plan().clone())?; + let join = s_expr.plan().as_any().downcast_ref::().unwrap(); join.derive_join_stats(left_stat_info, right_stat_info) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs index ad8a266cc2048..aa6afc38c4a4c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs @@ -42,7 +42,7 @@ impl RuleNormalizeAggregateOptimizer { children.push(Arc::new(child)); } let s_expr = s_expr.replace_children(children); - if let Some(aggregate) = Aggregate::try_downcast_ref(s_expr.plan.as_ref()) { + if let Some(aggregate) = s_expr.plan.as_ref().as_any().downcast_ref::() { self.normalize_aggregate(&s_expr) } else { Ok(s_expr) diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs index 214e85f88a8b3..fa25c5b4ea36d 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs @@ -589,7 +589,12 @@ impl SubqueryDecorrelatorOptimizer { // subquery is a simple constant value. // for example: `SELECT * FROM t WHERE id = (select 1);` if let RelOp::EvalScalar = subquery.subquery.plan_rel_op() { - let eval = EvalScalar::try_downcast_ref(subquery.subquery.plan.as_ref()).unwrap(); + let eval = child + .plan + .as_ref() + .as_any() + .downcast_ref::() + .unwrap(); if eval.items.len() != 1 { return Ok(None); } @@ -631,7 +636,13 @@ impl SubqueryDecorrelatorOptimizer { // subquery is a set returning function return constant values. // for example: `SELECT * FROM t WHERE id IN (SELECT * FROM UNNEST(SPLIT('1,2,3', ',')) AS t1);` let mut output_column_index = None; - if let Some(eval) = EvalScalar::try_downcast_ref(subquery.subquery.plan.as_ref()) { + if let Some(eval) = subquery + .subquery + .plan + .as_ref() + .as_any() + .downcast_ref::() + { if eval.items.len() != 1 { return Ok(None); } @@ -646,7 +657,7 @@ impl SubqueryDecorrelatorOptimizer { let mut srf_column_index = None; - if let Some(eval) = EvalScalar::try_downcast_ref(child.plan.as_ref()) { + if let Some(eval) = child.plan.as_ref().as_any().downcast_ref::() { if eval.items.len() != 1 || eval.items[0].index != output_column_index { return Ok(None); } @@ -668,7 +679,11 @@ impl SubqueryDecorrelatorOptimizer { let srf_column_index = srf_column_index.unwrap(); let project_set_expr = child.child(0)?; - if let Some(project_set) = ProjectSet::try_downcast_ref(project_set_expr.plan.as_ref()) + if let Some(project_set) = project_set_expr + .plan + .as_ref() + .as_any() + .downcast_ref::() { if project_set.srfs.len() != 1 || project_set.srfs[0].index != srf_column_index diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs index 6a9e25283e3c9..4066b0323b16c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs @@ -75,7 +75,11 @@ impl SubqueryDecorrelatorOptimizer { match subquery.plan_rel_op() { RelOp::EvalScalar => { - let eval_scalar = EvalScalar::try_downcast_ref(subquery.plan()).unwrap(); + let eval_scalar = subquery + .plan() + .as_any() + .downcast_ref::() + .unwrap(); self.flatten_sub_eval_scalar( outer, subquery, @@ -86,7 +90,11 @@ impl SubqueryDecorrelatorOptimizer { ) } RelOp::ProjectSet => { - let project_set = ProjectSet::try_downcast_ref(subquery.plan()).unwrap(); + let project_set = subquery + .plan() + .as_any() + .downcast_ref::() + .unwrap(); self.flatten_sub_project_set( outer, subquery, @@ -97,7 +105,7 @@ impl SubqueryDecorrelatorOptimizer { ) } RelOp::Filter => { - let filter = Filter::try_downcast_ref(subquery.plan()).unwrap(); + let filter = subquery.plan().as_any().downcast_ref::().unwrap(); self.flatten_sub_filter( outer, subquery, @@ -108,11 +116,15 @@ impl SubqueryDecorrelatorOptimizer { ) } RelOp::Join => { - let join = Join::try_downcast_ref(subquery.plan()).unwrap(); + let join = subquery.plan().as_any().downcast_ref::().unwrap(); self.flatten_sub_join(outer, subquery, join, correlated_columns, flatten_info) } RelOp::Aggregate => { - let aggregate = Aggregate::try_downcast_ref(subquery.plan()).unwrap(); + let aggregate = subquery + .plan() + .as_any() + .downcast_ref::() + .unwrap(); self.flatten_sub_aggregate( outer, subquery, @@ -123,7 +135,7 @@ impl SubqueryDecorrelatorOptimizer { ) } RelOp::Sort => { - let sort = Sort::try_downcast_ref(subquery.plan()).unwrap(); + let sort = subquery.plan().as_any().downcast_ref::().unwrap(); self.flatten_sub_sort( outer, subquery, @@ -134,7 +146,7 @@ impl SubqueryDecorrelatorOptimizer { ) } RelOp::Limit => { - let limit = Limit::try_downcast_ref(subquery.plan()).unwrap(); + let limit = subquery.plan().as_any().downcast_ref::().unwrap(); self.flatten_sub_limit( outer, subquery, @@ -145,7 +157,7 @@ impl SubqueryDecorrelatorOptimizer { ) } RelOp::UnionAll => { - let union_all = UnionAll::try_downcast_ref(subquery.plan()).unwrap(); + let union_all = subquery.plan().as_any().downcast_ref::().unwrap(); self.flatten_sub_union_all( outer, subquery, @@ -156,11 +168,15 @@ impl SubqueryDecorrelatorOptimizer { ) } RelOp::Window => { - let window = Window::try_downcast_ref(subquery.plan()).unwrap(); + let window = subquery.plan().as_any().downcast_ref::().unwrap(); self.flatten_sub_window(outer, subquery, window, correlated_columns, flatten_info) } RelOp::ExpressionScan => { - let scan = ExpressionScan::try_downcast_ref(subquery.plan()).unwrap(); + let scan = subquery + .plan() + .as_any() + .downcast_ref::() + .unwrap(); self.flatten_sub_expression_scan(subquery, scan, correlated_columns) } _ => Err(ErrorCode::SemanticError( @@ -839,23 +855,23 @@ impl SubqueryDecorrelatorOptimizer { let op = match plan.rel_op() { RelOp::DummyTableScan => DummyTableScan.into(), RelOp::ConstantTableScan => { - let scan = ConstantTableScan::try_downcast_ref(plan).unwrap(); + let scan = plan.as_any().downcast_ref::().unwrap(); self.clone_outer_constant_table_scan(scan)? } RelOp::Scan => { - let scan = Scan::try_downcast_ref(plan).unwrap(); + let scan = plan.as_any().downcast_ref::().unwrap(); self.clone_outer_scan(scan) } RelOp::EvalScalar => { - let eval = EvalScalar::try_downcast_ref(plan).unwrap(); + let eval = plan.as_any().downcast_ref::().unwrap(); self.clone_outer_eval_scalar(eval)? } RelOp::Limit => { - let limit = Limit::try_downcast_ref(plan).unwrap(); + let limit = plan.as_any().downcast_ref::().unwrap(); limit.clone().into() } RelOp::Sort => { - let sort = Sort::try_downcast_ref(plan).unwrap(); + let sort = plan.as_any().downcast_ref::().unwrap(); let mut sort = sort.clone(); for old in sort.used_columns() { sort.replace_column(old, self.get_derived(old)?); @@ -863,7 +879,7 @@ impl SubqueryDecorrelatorOptimizer { sort.into() } RelOp::Filter => { - let filter = Filter::try_downcast_ref(plan).unwrap(); + let filter = plan.as_any().downcast_ref::().unwrap(); let mut filter = filter.clone(); for predicate in &mut filter.predicates { for old in predicate.used_columns() { @@ -873,7 +889,7 @@ impl SubqueryDecorrelatorOptimizer { filter.into() } RelOp::Join => { - let join = Join::try_downcast_ref(plan).unwrap(); + let join = plan.as_any().downcast_ref::().unwrap(); let mut join = join.clone(); for old in join.used_columns()? { join.replace_column(old, self.get_derived(old)?)?; @@ -890,7 +906,7 @@ impl SubqueryDecorrelatorOptimizer { join.into() } RelOp::Aggregate => { - let aggregate = Aggregate::try_downcast_ref(plan).unwrap(); + let aggregate = plan.as_any().downcast_ref::().unwrap(); let mut aggregate = aggregate.clone(); let metadata = self.metadata.clone(); let mut metadata = metadata.write(); diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs index 27ac015655ca3..117d347620662 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs @@ -179,7 +179,7 @@ impl SubqueryDecorrelatorOptimizer { match s_expr.plan_rel_op() { RelOp::EvalScalar => { - let eval = EvalScalar::try_downcast_ref(s_expr.plan()).unwrap(); + let eval = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut outer = self.optimize_sync(s_expr.unary_child())?; let mut eval = eval.clone(); for item in eval.items.iter_mut() { @@ -189,7 +189,7 @@ impl SubqueryDecorrelatorOptimizer { } RelOp::Filter => { - let filter = Filter::try_downcast_ref(s_expr.plan()).unwrap(); + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut plan = filter.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; for pred in plan.predicates.iter_mut() { @@ -199,7 +199,7 @@ impl SubqueryDecorrelatorOptimizer { } RelOp::ProjectSet => { - let project_set = ProjectSet::try_downcast_ref(s_expr.plan()).unwrap(); + let project_set = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut plan = project_set.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; for item in plan.srfs.iter_mut() { @@ -209,7 +209,7 @@ impl SubqueryDecorrelatorOptimizer { } RelOp::Aggregate => { - let aggregate = Aggregate::try_downcast_ref(s_expr.plan()).unwrap(); + let aggregate = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut plan = aggregate.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; for item in plan.group_items.iter_mut() { @@ -222,7 +222,7 @@ impl SubqueryDecorrelatorOptimizer { } RelOp::Window => { - let window = Window::try_downcast_ref(s_expr.plan()).unwrap(); + let window = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut plan = window.clone(); let mut outer = self.optimize_sync(s_expr.unary_child())?; @@ -245,7 +245,7 @@ impl SubqueryDecorrelatorOptimizer { } RelOp::Sort => { - let sort = Sort::try_downcast_ref(s_expr.plan()).unwrap(); + let sort = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut outer = self.optimize_sync(s_expr.unary_child())?; let Some(mut window) = sort.window_partition.clone() else { @@ -264,7 +264,7 @@ impl SubqueryDecorrelatorOptimizer { } RelOp::Join => { - let join = Join::try_downcast_ref(s_expr.plan()).unwrap(); + let join = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut left = self.optimize_sync(s_expr.left_child())?; let mut right = self.optimize_sync(s_expr.right_child())?; if !join.has_subquery() { diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs index 8a11bd4a374c7..e341bc806db9e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/deduplicate_join_condition.rs @@ -105,7 +105,7 @@ impl DeduplicateJoinConditionOptimizer { #[recursive::recursive] pub fn deduplicate(&mut self, s_expr: &SExpr) -> Result { - if let Some(join) = Join::try_downcast_ref(s_expr.plan.as_ref()) { + if let Some(join) = s_expr.plan().as_any().downcast_ref::() { if join.join_type == JoinType::Inner { return self.optimize_inner_join(s_expr, join); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs index 98f325977f23c..6e241ef322d07 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs @@ -75,11 +75,11 @@ impl PullUpFilterOptimizer { pub fn pull_up(&mut self, s_expr: &SExpr) -> Result { match s_expr.plan.rel_op() { RelOp::Filter => { - let filter = Filter::try_downcast_ref(&s_expr.plan).unwrap(); + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); self.pull_up_filter(s_expr, filter) } RelOp::Join => { - let join = Join::try_downcast_ref(&s_expr.plan).unwrap(); + let join = s_expr.plan().as_any().downcast_ref::().unwrap(); if !join.is_lateral && !join.has_null_equi_condition() { self.pull_up_join(s_expr, join) } else { @@ -87,7 +87,7 @@ impl PullUpFilterOptimizer { } } RelOp::EvalScalar => { - let eval_scalar = EvalScalar::try_downcast_ref(&s_expr.plan).unwrap(); + let eval_scalar = s_expr.plan().as_any().downcast_ref::().unwrap(); self.pull_up_eval_scalar(s_expr, eval_scalar) } _ => self.pull_up_others(s_expr), diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index d827e309144d9..d3ea15ecd2695 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -114,14 +114,6 @@ pub trait Operator: Send + Sync + 'static { ) -> Result>> { Ok(vec![vec![RequiredProperty::default(); self.arity()]]) } - - fn try_downcast_ref(&self) -> Option<&Self> { - self.as_any().downcast_ref::() - } - - fn try_downcast_mut(&mut self) -> Option<&mut Self> { - self.as_any().downcast_mut::() - } } /// Relational operator diff --git a/src/query/sql/src/planner/plans/plan.rs b/src/query/sql/src/planner/plans/plan.rs index 1d2bbbea13035..ea02762b80f6f 100644 --- a/src/query/sql/src/planner/plans/plan.rs +++ b/src/query/sql/src/planner/plans/plan.rs @@ -591,7 +591,7 @@ impl Plan { ignore_result, } = self { - let s = Exchange::try_downcast_ref(&s_expr.plan); + let s = s_expr.plan().as_any().downcast_ref::(); if let Some(Exchange::Merge) = s { let s_expr = Box::new(s_expr.child(0).unwrap().clone()); return Plan::Query { diff --git a/src/query/sql/src/planner/plans/recluster.rs b/src/query/sql/src/planner/plans/recluster.rs index 9d1fef66e8a80..e9fcfa47a990e 100644 --- a/src/query/sql/src/planner/plans/recluster.rs +++ b/src/query/sql/src/planner/plans/recluster.rs @@ -130,7 +130,7 @@ pub fn replace_with_constant(expr: &SExpr, variables: &VecDeque, partiti let mut s_expr = s_expr.clone(); s_expr.plan = match s_expr.plan.rel_op() { RelOp::EvalScalar if !variables.is_empty() => { - let expr = EvalScalar::try_downcast_ref(&s_expr.plan).unwrap(); + let expr = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut expr = expr.clone(); for item in &mut expr.items { visit_expr_column(&mut item.scalar, variables); @@ -138,7 +138,7 @@ pub fn replace_with_constant(expr: &SExpr, variables: &VecDeque, partiti Arc::new(expr.into()) } RelOp::Aggregate => { - let aggr = Aggregate::try_downcast_ref(&s_expr.plan).unwrap(); + let aggr = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut aggr = aggr.clone(); for item in &mut aggr.aggregate_functions { if let ScalarExpr::AggregateFunction(func) = &mut item.scalar { From ab58458317e94b173292086c9d1260a0844d0435 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Tue, 8 Jul 2025 13:44:24 +0000 Subject: [PATCH 11/14] update --- src/query/sql/src/planner/binder/ddl/table.rs | 8 ++--- .../filter_selectivity_sample.rs | 13 +++----- src/query/sql/src/planner/plans/operator.rs | 33 ------------------- 3 files changed, 8 insertions(+), 46 deletions(-) diff --git a/src/query/sql/src/planner/binder/ddl/table.rs b/src/query/sql/src/planner/binder/ddl/table.rs index 1a9d0e3e87eef..1cfba9a048100 100644 --- a/src/query/sql/src/planner/binder/ddl/table.rs +++ b/src/query/sql/src/planner/binder/ddl/table.rs @@ -126,13 +126,13 @@ use crate::plans::ModifyColumnAction as ModifyColumnActionInPlan; use crate::plans::ModifyTableColumnPlan; use crate::plans::ModifyTableCommentPlan; use crate::plans::ModifyTableConnectionPlan; +use crate::plans::Operator as OperatorTrait; use crate::plans::OptimizeCompactBlock; use crate::plans::OptimizeCompactSegmentPlan; use crate::plans::OptimizePurgePlan; use crate::plans::Plan; use crate::plans::ReclusterPlan; use crate::plans::RefreshTableCachePlan; -use crate::plans::Operator; use crate::plans::RenameTableColumnPlan; use crate::plans::RenameTablePlan; use crate::plans::RevertTablePlan; @@ -1251,7 +1251,7 @@ impl Binder { let limit = limit.map(|v| v as usize); let plan = match ast_action { AstOptimizeTableAction::All => { - let compact_block = R OptimizeCompactBlock { + let compact_block = OptimizeCompactBlock { catalog, database, table, @@ -1260,7 +1260,7 @@ impl Binder { block_limit: None, }, }; - let s_expr = SExpr::create_leaf( compact_block); + let s_expr = SExpr::create_leaf(compact_block); Plan::OptimizeCompactBlock { s_expr: Box::new(s_expr), need_purge: true, @@ -1283,7 +1283,7 @@ impl Binder { } AstOptimizeTableAction::Compact { target } => match target { CompactTarget::Block => { - let compact_block = OptimizeCompactBlock { + let compact_block = OptimizeCompactBlock { catalog, database, table, diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs index 70ce98d2bf93a..431ad8d5b5c31 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs @@ -70,7 +70,7 @@ pub async fn filter_selectivity_sample( }; scan.sample = Some(sample_conf); let new_child = SExpr::create_leaf(scan); - new_s_expr = s_expr.replace_children(vec![new_child]); + new_s_expr = s_expr.replace_children(vec![new_child.into()]); let opt_ctx = OptimizerContext::new(ctx.clone(), metadata.clone()); let mut collect_statistics_optimizer = CollectStatisticsOptimizer::new(opt_ctx); @@ -79,14 +79,9 @@ pub async fn filter_selectivity_sample( .await?; } - new_s_expr = SExpr::create_unary( - Arc::new(create_count_aggregate(AggregateMode::Partial).into()), - Arc::new(new_s_expr), - ); - new_s_expr = SExpr::create_unary( - Arc::new(create_count_aggregate(AggregateMode::Final).into()), - Arc::new(new_s_expr), - ); + new_s_expr = + SExpr::create_unary(create_count_aggregate(AggregateMode::Partial), new_s_expr); + new_s_expr = SExpr::create_unary(create_count_aggregate(AggregateMode::Final), new_s_expr); let mut builder = PhysicalPlanBuilder::new(metadata.clone(), ctx.clone(), false); let mut required = ColumnSet::new(); diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index d3ea15ecd2695..42b649c1570a4 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -142,36 +142,3 @@ pub enum RelOp { MutationSource, // Pattern } - -#[macro_export] -macro_rules! with_match_rel_op { - (| $t:tt | $($tail:tt)*) => { - match_template::match_template! { - $t = [ - Scan => Scan, - Join => Join, - EvalScalar => EvalScalar, - Filter => Filter, - Aggregate => Aggregate, - Sort => Sort, - Limit => Limit, - Exchange => Exchange, - UnionAll => UnionAll, - DummyTableScan => DummyTableScan, - Window => Window, - ProjectSet => ProjectSet, - ConstantTableScan => ConstantTableScan, - ExpressionScan => ExpressionScan, - CacheScan => CacheScan, - Udf => Udf, - Udaf => Udaf, - AsyncFunction => AsyncFunction, - RecursiveCteScan => RecursiveCteScan, - MergeInto => MergeInto, - CompactBlock => CompactBlock, - MutationSource => MutationSource, - ], - $($tail)* - } - } -} From 9b0b85fb043fd0aa6600448d5e0e14668f1fcd43 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Tue, 8 Jul 2025 14:38:24 +0000 Subject: [PATCH 12/14] update --- .../interpreters/access/privilege_access.rs | 4 ++-- .../src/interpreters/interpreter_explain.rs | 14 ++++++------- .../src/interpreters/interpreter_factory.rs | 2 +- .../src/interpreters/interpreter_mutation.rs | 10 ++++++--- .../interpreter_optimize_compact_block.rs | 7 ++++++- .../interpreter_table_add_column.rs | 2 +- src/query/service/src/test_kits/fuse.rs | 2 +- .../physical_plans/physical_eval_scalar.rs | 4 ++-- .../sql/src/planner/optimizer/optimizer.rs | 17 +++++++++++---- .../optimizers/cascades/cost/model.rs | 1 + .../cascades/tasks/optimize_expr.rs | 1 + .../distributed/distributed_merge.rs | 2 +- .../optimizers/distributed/sort_and_limit.rs | 4 ++-- .../filter_selectivity_sample.rs | 1 + .../operator/aggregate/normalize_aggregate.rs | 2 +- .../operator/decorrelate/decorrelate.rs | 6 +++++- .../decorrelate/subquery_decorrelator.rs | 2 ++ .../operator/filter/pull_up_filter.rs | 1 + .../rule/agg_rules/rule_eager_aggregation.rs | 21 +++++++++++++++---- .../agg_rules/rule_fold_count_aggregate.rs | 2 +- .../rule_push_down_filter_aggregate.rs | 8 +++++-- .../rule_push_down_limit_aggregate.rs | 12 +++++++---- .../rule/agg_rules/rule_split_aggregate.rs | 2 +- .../filter_rules/rule_eliminate_filter.rs | 2 +- .../rule/filter_rules/rule_filter_nulls.rs | 2 +- .../rule/filter_rules/rule_merge_filter.rs | 9 ++++++-- .../rule_merge_filter_into_mutation.rs | 10 +++++++-- .../rule_push_down_filter_eval_scalar.rs | 9 ++++++-- .../rule_push_down_filter_join.rs | 4 ++-- .../rule_push_down_filter_project_set.rs | 8 +++++-- .../rule_push_down_filter_scan.rs | 13 ++++++++---- .../rule_push_down_filter_sort.rs | 9 ++++++-- .../rule_push_down_filter_union.rs | 8 +++++-- .../rule_push_down_filter_window.rs | 8 +++++-- .../rule_push_down_filter_window_top_n.rs | 10 ++++++--- .../filter_rules/rule_push_down_prewhere.rs | 9 ++++++-- .../rule_push_down_sort_expression.rs | 14 +++++++++++-- .../filter_rules/rule_push_down_sort_scan.rs | 2 +- .../extract_or_predicates.rs | 7 ++++++- .../mark_join_to_semi_join.rs | 15 +++++++++++-- .../outer_join_to_inner_join.rs | 17 +++++++++++++-- .../rule/join_rules/rule_commute_join.rs | 7 ++++++- .../rule_commute_join_base_table.rs | 7 ++++++- .../join_rules/rule_semi_to_inner_join.rs | 7 ++++++- .../rule/limit_rules/rule_push_down_limit.rs | 2 +- .../rule_push_down_limit_expression.rs | 8 +++++-- .../limit_rules/rule_push_down_limit_join.rs | 4 ++-- .../limit_rules/rule_push_down_limit_scan.rs | 9 ++++++-- .../limit_rules/rule_push_down_limit_sort.rs | 4 ++-- .../limit_rules/rule_push_down_limit_union.rs | 8 +++++-- .../rule_push_down_limit_window.rs | 9 ++++++-- .../rule_eliminate_eval_scalar.rs | 2 +- .../scalar_rules/rule_merge_eval_scalar.rs | 9 ++++++-- .../scalar_rules/rule_normalize_scalar.rs | 6 +++--- .../rule/sort_rules/rule_eliminate_sort.rs | 2 +- .../rule/union_rules/rule_eliminate_union.rs | 2 +- 56 files changed, 271 insertions(+), 98 deletions(-) diff --git a/src/query/service/src/interpreters/access/privilege_access.rs b/src/query/service/src/interpreters/access/privilege_access.rs index 72e07a9f43881..83b53b45a9586 100644 --- a/src/query/service/src/interpreters/access/privilege_access.rs +++ b/src/query/service/src/interpreters/access/privilege_access.rs @@ -1038,7 +1038,7 @@ impl AccessChecker for PrivilegeAccess { self.validate_table_access(&plan.catalog, &plan.database, &plan.table, UserPrivilegeType::Super, false, false).await? } Plan::OptimizeCompactBlock { s_expr, .. } => { - let plan: OptimizeCompactBlock = s_expr.plan().clone().try_into()?; + let plan = s_expr.plan().as_any().downcast_ref::().unwrap(); self.validate_table_access(&plan.catalog, &plan.database, &plan.table, UserPrivilegeType::Super, false, false).await? } Plan::VacuumTable(plan) => { @@ -1095,7 +1095,7 @@ impl AccessChecker for PrivilegeAccess { self.validate_insert_source(ctx, &plan.source).await?; } Plan::DataMutation { s_expr, .. } => { - let plan: Mutation = s_expr.plan().clone().try_into()?; + let plan = s_expr.plan().as_any().downcast_ref::().unwrap(); if enable_experimental_rbac_check { let s_expr = s_expr.child(0)?; match s_expr.get_udfs() { diff --git a/src/query/service/src/interpreters/interpreter_explain.rs b/src/query/service/src/interpreters/interpreter_explain.rs index 88da04bed02bf..47bc6a6e1e905 100644 --- a/src/query/service/src/interpreters/interpreter_explain.rs +++ b/src/query/service/src/interpreters/interpreter_explain.rs @@ -150,14 +150,14 @@ impl Interpreter for ExplainInterpreter { schema, metadata, } => { - let mutation: Mutation = s_expr.plan().clone().try_into()?; + let mutation = s_expr.plan().as_any().downcast_ref::().unwrap(); let interpreter = MutationInterpreter::try_create( self.ctx.clone(), *s_expr.clone(), schema.clone(), metadata.clone(), )?; - let mut plan = interpreter.build_physical_plan(&mutation, true).await?; + let mut plan = interpreter.build_physical_plan(mutation, true).await?; self.inject_pruned_partitions_stats(&mut plan, metadata)?; self.explain_physical_plan(&plan, metadata, &None).await? } @@ -199,13 +199,13 @@ impl Interpreter for ExplainInterpreter { .await? } Plan::DataMutation { s_expr, .. } => { - let plan: Mutation = s_expr.plan().clone().try_into()?; + let mutation = s_expr.plan().as_any().downcast_ref::().unwrap(); let mutation_build_info = - build_mutation_info(self.ctx.clone(), &plan, true).await?; + build_mutation_info(self.ctx.clone(), mutation, true).await?; self.explain_analyze( s_expr.child(0)?, - &plan.metadata, - *plan.required_columns.clone(), + &mutation.metadata, + mutation.required_columns.clone(), Some(mutation_build_info), true, ) @@ -562,7 +562,7 @@ impl ExplainInterpreter { s_expr: SExpr, schema: DataSchemaRef, ) -> Result> { - let mutation: Mutation = s_expr.plan().clone().try_into()?; + let mutation = s_expr.plan().as_any().downcast_ref::().unwrap(); let interpreter = MutationInterpreter::try_create( self.ctx.clone(), s_expr, diff --git a/src/query/service/src/interpreters/interpreter_factory.rs b/src/query/service/src/interpreters/interpreter_factory.rs index cbf191892f200..ff40fb1b19f8b 100644 --- a/src/query/service/src/interpreters/interpreter_factory.rs +++ b/src/query/service/src/interpreters/interpreter_factory.rs @@ -488,7 +488,7 @@ impl InterpreterFactory { Plan::Replace(replace) => ReplaceInterpreter::try_create(ctx, *replace.clone()), Plan::DataMutation { s_expr, schema, .. } => { - let mutation: Mutation = s_expr.plan().clone().try_into()?; + let mutation = s_expr.plan().as_any().downcast_ref::().unwrap(); Ok(Arc::new(MutationInterpreter::try_create( ctx, *s_expr.clone(), diff --git a/src/query/service/src/interpreters/interpreter_mutation.rs b/src/query/service/src/interpreters/interpreter_mutation.rs index 2e41ed14faaec..f2fa0b5e64c58 100644 --- a/src/query/service/src/interpreters/interpreter_mutation.rs +++ b/src/query/service/src/interpreters/interpreter_mutation.rs @@ -93,11 +93,15 @@ impl Interpreter for MutationInterpreter { return Ok(PipelineBuildResult::create()); } - let mutation: Mutation = self.s_expr.plan().clone().try_into()?; + let mutation = self + .s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); // Build physical plan. - let physical_plan = self.build_physical_plan(&mutation, false).await?; - + let physical_plan = self.build_physical_plan(mutation, false).await?; let query_plan = physical_plan .format(self.metadata.clone(), Default::default())? .format_pretty()?; diff --git a/src/query/service/src/interpreters/interpreter_optimize_compact_block.rs b/src/query/service/src/interpreters/interpreter_optimize_compact_block.rs index 70560eb5021b5..7fc38b8cd85f8 100644 --- a/src/query/service/src/interpreters/interpreter_optimize_compact_block.rs +++ b/src/query/service/src/interpreters/interpreter_optimize_compact_block.rs @@ -72,7 +72,12 @@ impl Interpreter for OptimizeCompactBlockInterpreter { database, table, limit, - } = self.s_expr.plan().clone().try_into()?; + } = self + .s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); // try add lock table. let lock_guard = self diff --git a/src/query/service/src/interpreters/interpreter_table_add_column.rs b/src/query/service/src/interpreters/interpreter_table_add_column.rs index 85804d8b1c0f5..93cef1e1e538f 100644 --- a/src/query/service/src/interpreters/interpreter_table_add_column.rs +++ b/src/query/service/src/interpreters/interpreter_table_add_column.rs @@ -176,7 +176,7 @@ impl Interpreter for AddTableColumnInterpreter { let mut planner = Planner::new(self.ctx.clone()); let (plan, _) = planner.plan_sql(&query).await?; if let Plan::DataMutation { s_expr, schema, .. } = plan { - let mutation: Mutation = s_expr.plan().clone().try_into()?; + let mutation = s_expr.plan().as_any().downcast_ref::().unwrap(); let interpreter = MutationInterpreter::try_create( self.ctx.clone(), *s_expr, diff --git a/src/query/service/src/test_kits/fuse.rs b/src/query/service/src/test_kits/fuse.rs index a7d7c56fbf1ea..5b79a382fe33a 100644 --- a/src/query/service/src/test_kits/fuse.rs +++ b/src/query/service/src/test_kits/fuse.rs @@ -332,7 +332,7 @@ pub async fn do_mutation( s_expr: SExpr, schema: DataSchemaRef, ) -> Result<()> { - let mutation: Mutation = s_expr.plan().clone().try_into()?; + let mutation = s_expr.plan().as_any().downcast_ref::().unwrap(); let interpreter = MutationInterpreter::try_create(ctx.clone(), s_expr, schema, mutation.metadata.clone())?; let _ = interpreter.execute(ctx).await?; diff --git a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs index 26744a2130014..7ffb935e624a3 100644 --- a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs +++ b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs @@ -234,7 +234,7 @@ impl PhysicalPlanBuilder { if let Some(filter) = s_expr.plan().as_any().downcast_ref::() { let child = s_expr.child(0)?; - let project_set: ProjectSet = child.plan().clone().try_into()?; + let project_set = child.plan().as_any().downcast_ref::().unwrap(); let Some(new_project_set) = self.eliminate_flatten_columns(scalar_items, Some(filter), &project_set) else { @@ -245,7 +245,7 @@ impl PhysicalPlanBuilder { let new_filter = SExpr::create_unary(s_expr.plan().clone(), new_child); Ok(Some(new_filter)) } else { - let project_set: ProjectSet = s_expr.plan().clone().try_into()?; + let project_set = s_expr.plan().as_any().downcast_ref::().unwrap(); let Some(new_project_set) = self.eliminate_flatten_columns(scalar_items, None, &project_set) else { diff --git a/src/query/sql/src/planner/optimizer/optimizer.rs b/src/query/sql/src/planner/optimizer/optimizer.rs index cf68410e0410c..77dfdfb05e1b6 100644 --- a/src/query/sql/src/planner/optimizer/optimizer.rs +++ b/src/query/sql/src/planner/optimizer/optimizer.rs @@ -327,7 +327,7 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res input_s_expr = optimize_query(opt_ctx.clone(), s_expr.child(0)?.clone()).await?; } - let mut mutation: Mutation = s_expr.plan().clone().try_into()?; + let mut mutation = s_expr.plan().as_any().downcast_mut::().unwrap(); mutation.distributed = opt_ctx.get_enable_distributed_optimization(); let schema = mutation.schema(); @@ -338,7 +338,12 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res if !mutation.matched_evaluators.is_empty() { match inner_rel_op { RelOp::ConstantTableScan => { - let constant_table_scan = ConstantTableScan::try_from(input_s_expr.plan().clone())?; + let constant_table_scan = input_s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + if constant_table_scan.num_rows == 0 { mutation.no_effect = true; } @@ -351,8 +356,12 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res right_child = right_child.child(0)?; } if right_child_rel == RelOp::ConstantTableScan { - let constant_table_scan = - ConstantTableScan::try_from(right_child.plan().clone())?; + let constant_table_scan = right_child + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + if constant_table_scan.num_rows == 0 { mutation.matched_evaluators = vec![MatchedEvaluator { condition: None, diff --git a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs index 39d4f84fad857..d13e095d2f754 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/cascades/cost/model.rs @@ -27,6 +27,7 @@ use crate::plans::Exchange; use crate::plans::Join; use crate::plans::JoinType; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::Scan; #[derive(Default)] diff --git a/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs b/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs index 04a54aa3f006d..c0cf3e2fb21a9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/cascades/tasks/optimize_expr.rs @@ -35,6 +35,7 @@ use crate::optimizer::optimizers::cascades::tasks::SharedCounter; use crate::optimizer::optimizers::cascades::tasks::TaskManager; use crate::optimizer::optimizers::cascades::CascadesOptimizer; use crate::plans::Operator; +use crate::plans::RelOp; use crate::IndexType; #[derive(Clone, Copy, Debug)] diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs index 7bc9477665166..3ea52183677d2 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/distributed_merge.rs @@ -48,7 +48,7 @@ impl BroadcastToShuffleOptimizer { assert_eq!(right_exchange.children.len(), 1); let right_exchange_input = right_exchange.child(0)?; - let mut join: Join = s_expr.plan().clone().try_into()?; + let mut join: Join = s_expr.plan().as_any().downcast_mut::().unwrap(); join.need_hold_hash_table = true; let (left_conditions, right_conditions): (Vec<_>, Vec<_>) = join diff --git a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs index 7d7aed0541400..973b80cbbcc5e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/distributed/sort_and_limit.rs @@ -104,7 +104,7 @@ impl SortAndLimitPushDownOptimizer { return Ok(s_expr.clone()); } - let mut sort: Sort = s_expr.plan().clone().try_into()?; + let mut sort: Sort = s_expr.plan().as_any().downcast_mut::().unwrap(); sort.after_exchange = Some(false); let exchange_sexpr = s_expr.child(0)?; @@ -130,7 +130,7 @@ impl SortAndLimitPushDownOptimizer { } let exchange_sexpr = s_expr.child(0)?; - let mut limit: Limit = s_expr.plan().clone().try_into()?; + let mut limit: Limit = s_expr.plan().as_any().downcast_mut::().unwrap(); if limit.limit.is_none() { if limit.offset != 0 { diff --git a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs index 431ad8d5b5c31..5e97b2c9eeba5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/hyper_dp/dynamic_sample/filter_selectivity_sample.rs @@ -68,6 +68,7 @@ pub async fn filter_selectivity_sample( row_level: Some(SampleRowLevel::RowsNum(sample_size)), block_level: Some(50.0), }; + let mut scan = scan.clone(); scan.sample = Some(sample_conf); let new_child = SExpr::create_leaf(scan); new_s_expr = s_expr.replace_children(vec![new_child.into()]); diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs index aa6afc38c4a4c..d31227dc81830 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs @@ -50,7 +50,7 @@ impl RuleNormalizeAggregateOptimizer { } fn normalize_aggregate(&self, s_expr: &SExpr) -> Result { - let aggregate: Aggregate = s_expr.plan().clone().try_into()?; + let aggregate = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut work_expr = None; let mut alias_functions_index = vec![]; let mut new_aggregate_functions = Vec::with_capacity(aggregate.aggregate_functions.len()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs index fa25c5b4ea36d..1724e317d3b90 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs @@ -117,7 +117,11 @@ impl SubqueryDecorrelatorOptimizer { let filter_tree = subquery .subquery // EvalScalar .unary_child(); // Filter - let filter: Filter = filter_tree.plan().clone().try_into()?; + let filter = filter_tree + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let filter_expr = RelExpr::with_s_expr(filter_tree); let filter_prop = filter_expr.derive_relational_prop()?; diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs index 117d347620662..a5458926a599e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs @@ -44,6 +44,7 @@ use crate::plans::JoinEquiCondition; use crate::plans::JoinType; use crate::plans::Limit; use crate::plans::Operator; +use crate::plans::ProjectSet; use crate::plans::RelOp; use crate::plans::ScalarExpr; use crate::plans::ScalarItem; @@ -54,6 +55,7 @@ use crate::plans::SubqueryType; use crate::plans::UDAFCall; use crate::plans::UDFCall; use crate::plans::UDFLambdaCall; +use crate::plans::Window; use crate::plans::WindowFuncType; use crate::Binder; use crate::IndexType; diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs index 6e241ef322d07..be109fb9f5d71 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs @@ -28,6 +28,7 @@ use crate::plans::FunctionCall; use crate::plans::Join; use crate::plans::JoinType; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::ScalarItem; use crate::plans::WindowFuncType; use crate::MetadataRef; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs index b63d032c6a0bf..5da5e9df2ad26 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_eager_aggregation.rs @@ -298,7 +298,7 @@ impl Rule for RuleEagerAggregation { false => extra_eval_scalar_expr, }; - let join: Join = join_expr.plan().clone().try_into()?; + let join = join_expr.plan().as_any().downcast_ref::().unwrap(); // Only supports inner/cross join and equal conditions. if !matches!(join.join_type, JoinType::Inner | JoinType::Cross) | !join.non_equi_conditions.is_empty() @@ -306,8 +306,16 @@ impl Rule for RuleEagerAggregation { return Ok(()); } - let eval_scalar: EvalScalar = eval_scalar_expr.plan().clone().try_into()?; - let mut final_agg: Aggregate = final_agg_expr.plan().clone().try_into()?; + let eval_scalar: EvalScalar = eval_scalar_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); + let mut final_agg = final_agg_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); // Get the original column set from the left child and right child of join. let mut columns_sets = Vec::with_capacity(2); @@ -318,7 +326,12 @@ impl Rule for RuleEagerAggregation { } let extra_eval_scalar = if has_extra_eval { - extra_eval_scalar_expr.plan().clone().try_into()? + extra_eval_scalar_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone() } else { EvalScalar { items: vec![] } }; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs index 18d076c7775fa..f8625824e8eba 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs @@ -59,7 +59,7 @@ impl Rule for RuleFoldCountAggregate { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let agg: Aggregate = s_expr.plan().clone().try_into()?; + let agg = s_expr.plan().as_any().downcast_ref::().unwrap(); if agg.mode == AggregateMode::Final || agg.mode == AggregateMode::Partial { return Ok(()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs index 226667ac48403..46bec9fdfe8f2 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs @@ -76,9 +76,13 @@ impl Rule for RulePushDownFilterAggregate { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); let aggregate_expr = s_expr.child(0)?; - let aggregate: Aggregate = aggregate_expr.plan().clone().try_into()?; + let aggregate = aggregate_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let aggregate_child_prop = RelExpr::with_s_expr(aggregate_expr).derive_relational_prop_child(0)?; let aggregate_group_columns = aggregate.group_columns()?; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs index 497030a34a169..d0db89ce17d9a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_limit_aggregate.rs @@ -84,7 +84,7 @@ impl RulePushDownRankLimitAggregate { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); let Some(mut count) = limit.limit else { return Ok(()); }; @@ -93,7 +93,7 @@ impl RulePushDownRankLimitAggregate { return Ok(()); } let agg = s_expr.child(0)?; - let mut agg_limit: Aggregate = agg.plan().clone().try_into()?; + let mut agg_limit = agg.plan().as_any().downcast_ref::().unwrap(); let sort_items = agg_limit .group_items @@ -128,7 +128,7 @@ impl RulePushDownRankLimitAggregate { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let sort: Sort = s_expr.plan().clone().try_into()?; + let sort = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut has_eval_scalar = false; let agg_limit_expr = match s_expr.child(0)?.plan_rel_op() { RelOp::Aggregate => s_expr.child(0)?, @@ -143,7 +143,11 @@ impl RulePushDownRankLimitAggregate { return Ok(()); }; - let mut agg_limit: Aggregate = agg_limit_expr.plan().clone().try_into()?; + let mut agg_limit = agg_limit_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let is_order_subset = sort .items diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs index ff8feb8da8780..f1f9ef9535840 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs @@ -52,7 +52,7 @@ impl Rule for RuleSplitAggregate { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let mut agg: Aggregate = s_expr.plan().clone().try_into()?; + let mut agg = s_expr.plan().as_any().downcast_ref::().unwrap(); if agg.mode != AggregateMode::Initial { return Ok(()); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs index dfbd5e79ab687..afde523cae737 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs @@ -61,7 +61,7 @@ impl Rule for RuleEliminateFilter { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let eval_scalar: Filter = s_expr.plan().clone().try_into()?; + let eval_scalar = s_expr.plan().as_any().downcast_ref::().unwrap(); // First, de-duplication predicates. let origin_predicates = eval_scalar.predicates.clone(); let predicates = origin_predicates diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs index 22a3034c04c08..9c33b57dbe0d5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_filter_nulls.rs @@ -99,7 +99,7 @@ impl Rule for RuleFilterNulls { state.add_result(s_expr.clone()); return Ok(()); } - let join: Join = s_expr.plan().clone().try_into()?; + let join = s_expr.plan().as_any().downcast_ref::().unwrap(); if !matches!( join.join_type, JoinType::Inner | JoinType::LeftSemi | JoinType::RightSemi diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs index 7caa778051cd1..b52056f5178ae 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs @@ -56,8 +56,13 @@ impl Rule for RuleMergeFilter { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let up_filter: Filter = s_expr.plan().clone().try_into()?; - let down_filter: Filter = s_expr.child(0)?.plan().clone().try_into()?; + let up_filter = s_expr.plan().as_any().downcast_ref::().unwrap(); + let down_filter = s_expr + .child(0)? + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let predicates = up_filter .predicates diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs index f7228ae3cede8..d7e6a8a3e0b65 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter_into_mutation.rs @@ -60,8 +60,14 @@ impl Rule for RuleMergeFilterIntoMutation { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; - let mut mutation: MutationSource = s_expr.child(0)?.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); + let mut mutation = s_expr + .child(0)? + .plan() + .as_any() + .downcast_mut::() + .unwrap(); + mutation .read_partition_columns .extend(filter.predicates.iter().flat_map(|v| v.used_columns())); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs index 263b67851b995..3407a67b29e6b 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_eval_scalar.rs @@ -87,8 +87,13 @@ impl Rule for RulePushDownFilterEvalScalar { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; - let eval_scalar: EvalScalar = s_expr.child(0)?.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); + let eval_scalar = s_expr + .child(0)? + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let scalar_rel_expr = RelExpr::with_s_expr(s_expr); let eval_scalar_prop = scalar_rel_expr.derive_relational_prop_child(0)?; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs index bb21d06ad6f50..5e075f24721d8 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs @@ -87,7 +87,7 @@ impl Rule for RulePushDownFilterJoin { state.add_result(s_expr); return Ok(()); } - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); if filter.predicates.is_empty() { state.add_result(s_expr); return Ok(()); @@ -117,7 +117,7 @@ pub fn try_push_down_filter_join(s_expr: &SExpr, metadata: MetadataRef) -> Resul // So `(t1.a=1 or t1.a=1), (t2.b=2 or t2.b=1)` may be pushed down join and reduce rows between join let mut predicates = rewrite_predicates(s_expr)?; let join_expr = s_expr.child(0)?; - let mut join: Join = join_expr.plan().clone().try_into()?; + let mut join = join_expr.plan().as_any().downcast_mut::().unwrap(); let rel_expr = RelExpr::with_s_expr(join_expr); let left_prop = rel_expr.derive_relational_prop_child(0)?; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs index 2e27740d4901f..0f98694f96844 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs @@ -73,9 +73,13 @@ impl Rule for RulePushDownFilterProjectSet { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); let project_set_expr = s_expr.child(0)?; - let project_set: ProjectSet = project_set_expr.plan().clone().try_into()?; + let project_set = project_set_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let project_set_child_prop = RelExpr::with_s_expr(project_set_expr).derive_relational_prop_child(0)?; let mut pushed_down_predicates = vec![]; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs index 57ad23499bbf9..e649a72ec6ecc 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_scan.rs @@ -181,10 +181,15 @@ impl Rule for RulePushDownFilterScan { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; - let mut scan: Scan = s_expr.child(0)?.plan().clone().try_into()?; - - let add_filters = self.find_push_down_predicates(&filter.predicates, &scan)?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); + let mut scan = s_expr + .child(0)? + .plan() + .as_any() + .downcast_mut::() + .unwrap(); + + let add_filters = self.find_push_down_predicates(&filter.predicates, scan)?; match scan.push_down_predicates.as_mut() { Some(vs) => { // Add `add_filters` to vs if there's not already there. diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs index 37928928de890..8c4f5b155c759 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs @@ -62,8 +62,13 @@ impl Rule for RulePushDownFilterSort { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; - let sort: Sort = s_expr.child(0)?.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); + let sort = s_expr + .child(0)? + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let sort_expr = s_expr.child(0)?; let mut result = SExpr::create_unary( diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs index 2ec3f845010de..acdcac783d6e2 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs @@ -69,9 +69,13 @@ impl Rule for RulePushDownFilterUnion { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); let union_s_expr = s_expr.child(0)?; - let union: UnionAll = union_s_expr.plan().clone().try_into()?; + let union = union_s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); if !union.cte_scan_names.is_empty() { // If the union has cte scan names, it's not allowed to push down filter. state.add_result(s_expr.clone()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs index 382afb854e2fc..c78489bb52248 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs @@ -77,9 +77,13 @@ impl Rule for RulePushDownFilterWindow { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let Filter { predicates } = s_expr.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); let window_expr = s_expr.child(0)?; - let window: Window = window_expr.plan().clone().try_into()?; + let window = window_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let allowed = window.partition_by_columns()?; let rejected = ColumnSet::from_iter( window diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs index 17433bd172153..fc9fe21eb77bf 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs @@ -80,11 +80,15 @@ impl Rule for RulePushDownFilterWindowTopN { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); let window_expr = s_expr.child(0)?; - let window: Window = window_expr.plan().clone().try_into()?; + let window = window_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let sort_expr = window_expr.child(0)?; - let mut sort: Sort = sort_expr.plan().clone().try_into()?; + let mut sort = sort_expr.plan().as_any().downcast_ref::().unwrap(); if !is_ranking_function(&window.function) || sort.window_partition.is_none() { return Ok(()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs index b3c225edf386c..cd9353a279676 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs @@ -130,7 +130,12 @@ impl RulePushDownPrewhere { } pub fn prewhere_optimize(&self, s_expr: &SExpr) -> Result { - let mut scan: Scan = s_expr.child(0)?.plan().clone().try_into()?; + let mut scan = s_expr + .child(0)? + .plan() + .as_any() + .downcast_ref::() + .unwrap(); if scan.update_stream_columns { return Ok(s_expr.clone()); } @@ -141,7 +146,7 @@ impl RulePushDownPrewhere { // cannot optimize return Ok(s_expr.clone()); } - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut prewhere_columns = ColumnSet::new(); let mut prewhere_pred = Vec::new(); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs index 76f0d7349147c..ed12bd450e6a3 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_expression.rs @@ -73,7 +73,12 @@ impl Rule for RulePushDownSortEvalScalar { if self.metadata.read().lazy_columns().is_empty() { return Ok(()); } - let sort: Sort = s_expr.plan().clone().try_into()?; + let sort = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let eval_plan = s_expr.child(0)?; let eval_child_output_cols = &RelExpr::with_s_expr(eval_plan.child(0)?) .derive_relational_prop()? @@ -82,7 +87,12 @@ impl Rule for RulePushDownSortEvalScalar { if !sort.used_columns().is_subset(eval_child_output_cols) { return Ok(()); } - let eval_scalar: EvalScalar = eval_plan.plan().clone().try_into()?; + let eval_scalar = eval_plan + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let sort_expr = SExpr::create_unary(sort, eval_plan.child(0)?.clone()); let mut result = SExpr::create_unary(eval_scalar, sort_expr); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs index f92cec5ce5a75..0d348a7fa76f9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs @@ -73,7 +73,7 @@ impl Rule for RulePushDownSortScan { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let sort: Sort = s_expr.plan().clone().try_into()?; + let sort = s_expr.plan().as_any().downcast_ref::().unwrap(); let child = s_expr.child(0)?; let mut get = match child.plan_rel_op() { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/extract_or_predicates.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/extract_or_predicates.rs index 26cd0bea558d1..bbd8949d2560f 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/extract_or_predicates.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/extract_or_predicates.rs @@ -23,7 +23,12 @@ use crate::ColumnSet; use crate::ScalarExpr; pub fn rewrite_predicates(s_expr: &SExpr) -> Result> { - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let join = s_expr.child(0)?; let mut new_predicates = Vec::new(); let mut origin_predicates = filter.predicates.clone(); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs index b2b3604d3eef5..e48630bd6710e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/mark_join_to_semi_join.rs @@ -23,8 +23,19 @@ use crate::plans::JoinType; use crate::ScalarExpr; pub fn convert_mark_to_semi_join(s_expr: &SExpr) -> Result<(SExpr, bool)> { - let mut filter: Filter = s_expr.plan().clone().try_into()?; - let mut join: Join = s_expr.child(0)?.plan().clone().try_into()?; + let mut filter = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); + let mut join = s_expr + .child(0)? + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let has_disjunction = filter.predicates.iter().any( |predicate| matches!(predicate, ScalarExpr::FunctionCall(func) if func.func_name == "or"), diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs index 1e6799427729b..f6af3bbb62a25 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs @@ -42,12 +42,25 @@ use crate::ScalarExpr; use crate::TypeCheck; pub fn outer_join_to_inner_join(s_expr: &SExpr, metadata: MetadataRef) -> Result<(SExpr, bool)> { - let mut join: Join = s_expr.child(0)?.plan().clone().try_into()?; + let mut join = s_expr + .child(0)? + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); + if !join.join_type.is_outer_join() { return Ok((s_expr.clone(), false)); } - let filter: Filter = s_expr.plan().clone().try_into()?; + let filter = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); + let join_s_expr = s_expr.child(0)?; let join_rel_expr = RelExpr::with_s_expr(join_s_expr); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs index 02ab335a920b1..00fa45e7c0864 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs @@ -56,7 +56,12 @@ impl Rule for RuleCommuteJoin { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let mut join: Join = s_expr.plan().clone().try_into()?; + let mut join = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); if join.build_side_cache_info.is_some() { return Ok(()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs index b5ece6db11279..6e076a90f6973 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs @@ -55,7 +55,12 @@ impl Rule for RuleCommuteJoinBaseTable { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let mut join: Join = s_expr.plan().clone().try_into()?; + let mut join = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let left_child = s_expr.child(0)?; let right_child = s_expr.child(1)?; diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs index b6baa14ea962a..658c696c67b48 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs @@ -58,7 +58,12 @@ impl Rule for RuleSemiToInnerJoin { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let mut join: Join = s_expr.plan().clone().try_into()?; + let mut join = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); if !matches!(join.join_type, JoinType::LeftSemi | JoinType::RightSemi) { return Ok(()); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs index b79a6412711a8..57a5f78e9ffe4 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit.rs @@ -55,7 +55,7 @@ impl Rule for RulePushDownLimit { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); if let Some(limit_val) = limit.limit && limit_val == 0 { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs index 26041a74ca9ae..494507580b287 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs @@ -65,9 +65,13 @@ impl Rule for RulePushDownLimitEvalScalar { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); let eval_plan = s_expr.child(0)?; - let eval_scalar: EvalScalar = eval_plan.plan().clone().try_into()?; + let eval_scalar = eval_plan + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let limit_expr = SExpr::create_unary(limit, eval_plan.child(0)?.clone()); let mut result = SExpr::create_unary(eval_scalar, limit_expr); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs index fa13882ded1e3..a0200969a81ee 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs @@ -69,10 +69,10 @@ impl Rule for RulePushDownLimitOuterJoin { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); if limit.limit.is_some() { let child = s_expr.child(0)?; - let join: Join = child.plan().clone().try_into()?; + let join = child.plan().as_any().downcast_ref::().unwrap(); match join.join_type { JoinType::Left => { let child = child.replace_children(vec![ diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs index d9924eb31e087..9ab0750e8cd41 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_scan.rs @@ -61,14 +61,19 @@ impl Rule for RulePushDownLimitScan { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); let Some(mut count) = limit.limit else { return Ok(()); }; count += limit.offset; let child = s_expr.child(0)?; - let mut get: Scan = child.plan().clone().try_into()?; + let mut get = child + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); get.limit = Some(get.limit.map_or(count, |c| cmp::max(c, count))); let get = SExpr::create_leaf(get); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs index eaedcfdc0ec86..4108a3863666a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_sort.rs @@ -68,11 +68,11 @@ impl Rule for RulePushDownLimitSort { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); if let Some(mut count) = limit.limit { count += limit.offset; let sort = s_expr.child(0)?; - let mut sort_limit: Sort = sort.plan().clone().try_into()?; + let mut sort_limit = sort.plan().as_any().downcast_ref::().unwrap().clone(); let limit = sort_limit.limit.map_or(count, |c| cmp::max(c, count)); if limit <= self.max_limit { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs index e874359181e76..59d55fc6ca567 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs @@ -57,9 +57,13 @@ impl Rule for RulePushDownLimitUnion { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); let union_s_expr = s_expr.child(0)?; - let union: UnionAll = union_s_expr.plan().clone().try_into()?; + let union = union_s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); if limit.limit.is_none() { return Ok(()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs index 9ed2671a61e2a..fa77af8f6ce07 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_window.rs @@ -69,7 +69,7 @@ impl Rule for RulePushDownLimitWindow { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let limit: Limit = s_expr.plan().clone().try_into()?; + let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); let Some(mut count) = limit.limit else { return Ok(()); }; @@ -78,7 +78,12 @@ impl Rule for RulePushDownLimitWindow { return Ok(()); } let window = s_expr.child(0)?; - let mut window_limit: LogicalWindow = window.plan().clone().try_into()?; + let mut window_limit = window + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let limit = window_limit.limit.map_or(count, |c| c.max(count)); if limit > self.max_limit { return Ok(()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_eliminate_eval_scalar.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_eliminate_eval_scalar.rs index e04f2058f70ce..2bda3c5c09787 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_eliminate_eval_scalar.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_eliminate_eval_scalar.rs @@ -55,7 +55,7 @@ impl Rule for RuleEliminateEvalScalar { fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { // Eliminate empty EvalScalar - let eval_scalar: EvalScalar = s_expr.plan().clone().try_into()?; + let eval_scalar = s_expr.plan().as_any().downcast_ref::().unwrap(); if eval_scalar.items.is_empty() { state.add_result(s_expr.child(0)?.clone()); return Ok(()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs index ce3589089b7e2..e74f3ae98eeed 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs @@ -58,8 +58,13 @@ impl Rule for RuleMergeEvalScalar { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let up_eval_scalar: EvalScalar = s_expr.plan().clone().try_into()?; - let down_eval_scalar: EvalScalar = s_expr.child(0)?.plan().clone().try_into()?; + let up_eval_scalar = s_expr.plan().as_any().downcast_ref::().unwrap(); + let down_eval_scalar = s_expr + .child(0)? + .plan() + .as_any() + .downcast_ref::() + .unwrap(); let mut used_columns = ColumnSet::new(); for item in up_eval_scalar.items.iter() { used_columns = used_columns diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs index 1ad702d401fb4..1ba6ed19a535e 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs @@ -84,7 +84,7 @@ impl Rule for RuleNormalizeScalarFilter { s_expr: &SExpr, state: &mut crate::optimizer::optimizers::rule::TransformResult, ) -> Result<()> { - let mut filter: Filter = s_expr.plan().clone().try_into()?; + let mut filter = s_expr.plan().as_any().downcast_ref::().unwrap(); if filter .predicates @@ -93,8 +93,8 @@ impl Rule for RuleNormalizeScalarFilter { { filter.predicates = normalize_predicates(filter.predicates); state.add_result(SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(s_expr.child(0)?.clone()), + filter.clone().into(), + s_expr.child(0)?.clone(), )); Ok(()) } else { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/sort_rules/rule_eliminate_sort.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/sort_rules/rule_eliminate_sort.rs index 7ea877bca15b1..d7627a3f6aad4 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/sort_rules/rule_eliminate_sort.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/sort_rules/rule_eliminate_sort.rs @@ -49,7 +49,7 @@ impl Rule for RuleEliminateSort { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let sort: Sort = s_expr.plan().clone().try_into()?; + let sort = s_expr.plan().as_any().downcast_ref::().unwrap(); let input = s_expr.child(0)?; let rel_expr = RelExpr::with_s_expr(input); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs index a9b7572e9dc8e..b7bf154cbbf38 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs @@ -69,7 +69,7 @@ impl Rule for RuleEliminateUnion { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let union: UnionAll = s_expr.plan().clone().try_into()?; + let union = s_expr.plan().as_any().downcast_ref::().unwrap(); // Need to check that union's output indexes are the same as left child's output indexes // currently this is always !false now, so the following codes are not necessary From 9dff54836965200a56faccdc89aeb3fe8d615360 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Wed, 9 Jul 2025 02:17:32 +0000 Subject: [PATCH 13/14] update --- .../sql/src/executor/physical_plan_builder.rs | 69 ++++++++++--------- .../sql/src/executor/physical_plans/mod.rs | 1 + .../physical_aggregate_final.rs | 1 + .../physical_plans/physical_cache_scan.rs | 2 + .../physical_plans/physical_compact_source.rs | 1 + .../physical_constant_table_scan.rs | 3 + .../physical_plans/physical_eval_scalar.rs | 3 +- .../physical_plans/physical_exchange.rs | 2 + .../physical_expression_scan.rs | 2 + .../physical_plans/physical_filter.rs | 1 + .../physical_mutation_source.rs | 1 + .../physical_plans/physical_project_set.rs | 1 + .../physical_plans/physical_r_cte_scan.rs | 3 + .../executor/physical_plans/physical_sort.rs | 1 + .../physical_plans/physical_union_all.rs | 1 + .../physical_plans/physical_window.rs | 1 + .../bind_mutation/mutation_expression.rs | 3 +- .../planner/binder/bind_mutation/update.rs | 2 + src/query/sql/src/planner/binder/util.rs | 6 ++ .../planner/format/display_rel_operator.rs | 26 +++---- .../src/planner/optimizer/ir/expr/s_expr.rs | 1 + .../sql/src/planner/optimizer/optimizer.rs | 9 ++- .../operator/decorrelate/decorrelate.rs | 6 +- .../decorrelate/subquery_decorrelator.rs | 6 +- .../agg_rules/rule_fold_count_aggregate.rs | 2 +- .../rule_push_down_filter_join.rs | 6 +- .../rule_push_down_filter_union.rs | 4 +- .../rule_push_down_filter_window.rs | 24 +++---- .../rule_push_down_filter_window_top_n.rs | 7 +- .../filter_rules/rule_push_down_prewhere.rs | 3 +- .../filter_rules/rule_push_down_sort_scan.rs | 7 +- .../outer_join_to_inner_join.rs | 12 ++-- .../rule/join_rules/rule_commute_join.rs | 6 +- .../rule_commute_join_base_table.rs | 7 +- .../join_rules/rule_left_exchange_join.rs | 27 ++++---- .../join_rules/rule_semi_to_inner_join.rs | 10 ++- .../rule_push_down_limit_expression.rs | 10 ++- .../limit_rules/rule_push_down_limit_join.rs | 15 ++-- .../limit_rules/rule_push_down_limit_union.rs | 2 +- .../scalar_rules/rule_merge_eval_scalar.rs | 17 +++-- .../scalar_rules/rule_normalize_scalar.rs | 9 ++- .../rule/union_rules/rule_eliminate_union.rs | 3 +- .../statistics/collect_statistics.rs | 13 ++-- src/query/sql/src/planner/plans/aggregate.rs | 2 +- .../sql/src/planner/plans/eval_scalar.rs | 2 +- src/query/sql/src/planner/plans/filter.rs | 2 +- src/query/sql/src/planner/plans/join.rs | 2 +- src/query/sql/src/planner/plans/operator.rs | 2 +- .../sql/src/planner/plans/project_set.rs | 2 +- src/query/sql/src/planner/plans/recluster.rs | 5 +- src/query/sql/src/planner/plans/udf.rs | 2 +- src/query/sql/src/planner/plans/window.rs | 7 +- 52 files changed, 205 insertions(+), 157 deletions(-) diff --git a/src/query/sql/src/executor/physical_plan_builder.rs b/src/query/sql/src/executor/physical_plan_builder.rs index 76b547d969b36..a04c8b3820efb 100644 --- a/src/query/sql/src/executor/physical_plan_builder.rs +++ b/src/query/sql/src/executor/physical_plan_builder.rs @@ -41,6 +41,38 @@ pub struct PhysicalPlanBuilder { pub(crate) mutation_build_info: Option, } +#[macro_export] +macro_rules! with_match_rel_op { + (| $t:tt | $($tail:tt)*) => { + match_template::match_template! { + $t = [ + Scan => TableScan, + DummyTableScan => DummyTableScan, + ConstantTableScan => ConstantTableScan, + ExpressionScan => ExpressionScan, + CacheScan => CacheScan, + Join => PhysicalJoinType, + EvalScalar => EvalScalar, + Filter => Filter, + Aggregate => Aggregate, + Sort => Sort, + Limit => Limit, + Exchange => Exchange, + UnionAll => UnionAll, + Window => Window, + ProjectSet => ProjectSet, + Udf => Udf, + AsyncFunction => AsyncFunction, + RecursiveCteScan => RecursiveCteScan, + MergeInto => Mutation, + CompactBlock => CompactBlock, + MutationSource => MutationSource, + ], + $($tail)* + } + } +} + impl PhysicalPlanBuilder { pub fn new(metadata: MetadataRef, ctx: Arc, dry_run: bool) -> Self { let func_ctx = ctx.get_function_context().unwrap(); @@ -77,6 +109,11 @@ impl PhysicalPlanBuilder { ) -> Result { // Build stat info. let stat_info = self.build_plan_stat_info(s_expr)?; + + use databend_common_exception::ErrorCode; + + use crate::executor::physical_plans::*; + with_match_rel_op!(|TY| match s_expr.plan_rel_op() { crate::plans::RelOp::TY => TY::build(self, s_expr, required, stat_info).await, _ => Err(ErrorCode::Internal("Unsupported operator")), @@ -111,35 +148,3 @@ pub trait BuildPhysicalPlan { stat_info: PlanStatsInfo, ) -> Result; } - -#[macro_export] -macro_rules! with_match_rel_op { - (| $t:tt | $($tail:tt)*) => { - match_template::match_template! { - $t = [ - Scan => TableScan, - DummyTableScan => DummyTableScan, - ConstantTableScan => ConstantTableScan, - ExpressionScan => ExpressionScan, - CacheScan => CacheScan, - Join => Join, - EvalScalar => EvalScalar, - Filter => Filter, - Aggregate => Aggregate, - Sort => Sort, - Limit => Limit, - Exchange => Exchange, - UnionAll => UnionAll, - Window => Window, - ProjectSet => ProjectSet, - Udf => Udf, - AsyncFunction => AsyncFunction, - RecursiveCteScan => RecursiveCteScan, - MergeInto => MergeInto, - CompactBlock => CompactBlock, - MutationSource => MutationSource, - ], - $($tail)* - } - } -} diff --git a/src/query/sql/src/executor/physical_plans/mod.rs b/src/query/sql/src/executor/physical_plans/mod.rs index 2f2afb69d3368..6bd77984b9d69 100644 --- a/src/query/sql/src/executor/physical_plans/mod.rs +++ b/src/query/sql/src/executor/physical_plans/mod.rs @@ -107,6 +107,7 @@ pub use physical_replace_deduplicate::*; pub use physical_replace_into::ReplaceInto; pub use physical_row_fetch::RowFetch; pub use physical_sort::Sort; +pub use physical_table_scan::DummyTableScan; pub use physical_table_scan::TableScan; pub use physical_udf::Udf; pub use physical_udf::UdfFunctionDesc; diff --git a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs index bdde7a54e5ea1..c9a7319552cd6 100644 --- a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs +++ b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs @@ -23,6 +23,7 @@ use databend_common_expression::RemoteExpr; use super::SortDesc; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::AggregateExpand; use crate::executor::physical_plans::AggregateFunctionDesc; use crate::executor::physical_plans::AggregateFunctionSignature; diff --git a/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs b/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs index 7016c7a72f615..80a5ab1b76ad2 100644 --- a/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_cache_scan.rs @@ -17,8 +17,10 @@ use databend_common_expression::DataSchemaRef; use databend_common_expression::DataSchemaRefExt; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; +use crate::optimizer::ir::SExpr; use crate::plans::CacheSource; use crate::ColumnSet; diff --git a/src/query/sql/src/executor/physical_plans/physical_compact_source.rs b/src/query/sql/src/executor/physical_plans/physical_compact_source.rs index fbdc082af9df4..f230f1c7c2263 100644 --- a/src/query/sql/src/executor/physical_plans/physical_compact_source.rs +++ b/src/query/sql/src/executor/physical_plans/physical_compact_source.rs @@ -32,6 +32,7 @@ use crate::executor::physical_plans::FragmentKind; use crate::executor::physical_plans::MutationKind; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; +use crate::optimizer::ir::SExpr; use crate::ColumnSet; pub struct CompactBlock; diff --git a/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs b/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs index 96505c3470a37..e8f2be453e8d2 100644 --- a/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs @@ -16,8 +16,11 @@ use databend_common_exception::Result; use databend_common_expression::Column; use databend_common_expression::DataSchemaRef; +use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; +use crate::optimizer::ir::SExpr; use crate::ColumnSet; use crate::IndexType; diff --git a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs index 7ffb935e624a3..f4cca875f266d 100644 --- a/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs +++ b/src/query/sql/src/executor/physical_plans/physical_eval_scalar.rs @@ -27,6 +27,7 @@ use databend_common_functions::BUILTIN_FUNCTIONS; use crate::executor::explain::PlanStatsInfo; use crate::executor::physical_plan::PhysicalPlan; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plan_builder::PhysicalPlanBuilder; use crate::optimizer::ir::Matcher; use crate::optimizer::ir::SExpr; @@ -242,7 +243,7 @@ impl PhysicalPlanBuilder { }; let mut new_child = child.clone(); new_child.plan = Arc::new(new_project_set.into()); - let new_filter = SExpr::create_unary(s_expr.plan().clone(), new_child); + let new_filter = SExpr::create_unary(filter.clone(), new_child); Ok(Some(new_filter)) } else { let project_set = s_expr.plan().as_any().downcast_ref::().unwrap(); diff --git a/src/query/sql/src/executor/physical_plans/physical_exchange.rs b/src/query/sql/src/executor/physical_plans/physical_exchange.rs index 09a5f558ddc41..e9cf927f077c8 100644 --- a/src/query/sql/src/executor/physical_plans/physical_exchange.rs +++ b/src/query/sql/src/executor/physical_plans/physical_exchange.rs @@ -18,6 +18,8 @@ use databend_common_expression::DataSchemaRef; use databend_common_expression::RemoteExpr; use databend_common_functions::BUILTIN_FUNCTIONS; +use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::common::FragmentKind; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; diff --git a/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs b/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs index 1304319bea838..17faa3ed4223b 100644 --- a/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_expression_scan.rs @@ -18,6 +18,8 @@ use databend_common_expression::DataSchemaRef; use databend_common_expression::RemoteExpr; use databend_common_functions::BUILTIN_FUNCTIONS; +use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::SExpr; diff --git a/src/query/sql/src/executor/physical_plans/physical_filter.rs b/src/query/sql/src/executor/physical_plans/physical_filter.rs index 025e99d6cae07..fb3413baca7a1 100644 --- a/src/query/sql/src/executor/physical_plans/physical_filter.rs +++ b/src/query/sql/src/executor/physical_plans/physical_filter.rs @@ -21,6 +21,7 @@ use databend_common_functions::BUILTIN_FUNCTIONS; use crate::executor::cast_expr_to_non_null_boolean; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::SExpr; diff --git a/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs b/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs index 60a28b452d2ed..265654666d4ad 100644 --- a/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs +++ b/src/query/sql/src/executor/physical_plans/physical_mutation_source.rs @@ -32,6 +32,7 @@ use crate::executor::explain::PlanStatsInfo; use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; +use crate::optimizer::ir::SExpr; use crate::ColumnSet; use crate::IndexType; use crate::ScalarExpr; diff --git a/src/query/sql/src/executor/physical_plans/physical_project_set.rs b/src/query/sql/src/executor/physical_plans/physical_project_set.rs index 30543cf096c51..ce3a0e68e51de 100644 --- a/src/query/sql/src/executor/physical_plans/physical_project_set.rs +++ b/src/query/sql/src/executor/physical_plans/physical_project_set.rs @@ -21,6 +21,7 @@ use databend_common_expression::RemoteExpr; use databend_common_functions::BUILTIN_FUNCTIONS; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::SExpr; diff --git a/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs b/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs index 424a0ff0c5fcb..52fbdf106e6a4 100644 --- a/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_r_cte_scan.rs @@ -19,8 +19,11 @@ use databend_common_expression::DataSchemaRef; use databend_common_expression::DataSchemaRefExt; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; +use crate::optimizer::ir::SExpr; +use crate::ColumnSet; #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct RecursiveCteScan { diff --git a/src/query/sql/src/executor/physical_plans/physical_sort.rs b/src/query/sql/src/executor/physical_plans/physical_sort.rs index 535df442096c9..d339d256012bb 100644 --- a/src/query/sql/src/executor/physical_plans/physical_sort.rs +++ b/src/query/sql/src/executor/physical_plans/physical_sort.rs @@ -21,6 +21,7 @@ use databend_common_expression::DataSchemaRefExt; use databend_common_pipeline_transforms::processors::sort::utils::ORDER_COL_NAME; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::common::SortDesc; use crate::executor::physical_plans::WindowPartition; use crate::executor::physical_plans::WindowPartitionTopN; diff --git a/src/query/sql/src/executor/physical_plans/physical_union_all.rs b/src/query/sql/src/executor/physical_plans/physical_union_all.rs index ff5372e0f75a1..3c9833b269bca 100644 --- a/src/query/sql/src/executor/physical_plans/physical_union_all.rs +++ b/src/query/sql/src/executor/physical_plans/physical_union_all.rs @@ -20,6 +20,7 @@ use databend_common_expression::DataSchemaRefExt; use databend_common_expression::RemoteExpr; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::PhysicalPlan; use crate::executor::PhysicalPlanBuilder; use crate::optimizer::ir::SExpr; diff --git a/src/query/sql/src/executor/physical_plans/physical_window.rs b/src/query/sql/src/executor/physical_plans/physical_window.rs index b1c789590e377..be6c0d8e0fb9c 100644 --- a/src/query/sql/src/executor/physical_plans/physical_window.rs +++ b/src/query/sql/src/executor/physical_plans/physical_window.rs @@ -32,6 +32,7 @@ use databend_common_functions::BUILTIN_FUNCTIONS; use crate::binder::wrap_cast; use crate::executor::explain::PlanStatsInfo; +use crate::executor::physical_plan_builder::BuildPhysicalPlan; use crate::executor::physical_plans::common::AggregateFunctionDesc; use crate::executor::physical_plans::common::AggregateFunctionSignature; use crate::executor::physical_plans::common::SortDesc; diff --git a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs index 4cb04f76af511..37fd5b98824b5 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs @@ -43,6 +43,7 @@ use crate::plans::Join; use crate::plans::JoinType; use crate::plans::MutationSource; use crate::plans::Operator; +use crate::plans::RelOp; use crate::plans::Scan; use crate::plans::SubqueryExpr; use crate::plans::Visitor; @@ -252,7 +253,7 @@ impl MutationExpression { read_partition_columns: Default::default(), }; - s_expr = SExpr::create_leaf(MutationSource(mutation_source)); + s_expr = SExpr::create_leaf(mutation_source); if !predicates.is_empty() { s_expr = SExpr::create_unary(Filter { predicates }, s_expr); diff --git a/src/query/sql/src/planner/binder/bind_mutation/update.rs b/src/query/sql/src/planner/binder/bind_mutation/update.rs index 08074c0e8299c..3856bbd1dde43 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/update.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/update.rs @@ -127,6 +127,7 @@ impl Binder { if s_expr.plan_rel_op() != RelOp::Mutation { return Ok(plan); } + let matcher = Matcher::MatchOp { op_type: RelOp::Filter, children: vec![Matcher::MatchOp { @@ -138,6 +139,7 @@ impl Binder { return Ok(plan); } + let mutation = s_expr.plan().as_any().downcast_ref::().unwrap(); let mut mutation = mutation.clone(); let row_id = mutation diff --git a/src/query/sql/src/planner/binder/util.rs b/src/query/sql/src/planner/binder/util.rs index a46e7e32cecfe..d003207dfdbf6 100644 --- a/src/query/sql/src/planner/binder/util.rs +++ b/src/query/sql/src/planner/binder/util.rs @@ -25,6 +25,7 @@ use databend_common_expression::types::DataType; use crate::normalize_identifier; use crate::optimizer::ir::SExpr; use crate::plans::Operator; +use crate::plans::RecursiveCteScan; use crate::plans::RelOp; use crate::Binder; use crate::NameResolutionContext; @@ -61,6 +62,11 @@ impl Binder { self.count_r_cte_scan(expr.child(0)?, cte_scan_names, cte_types)?; } RelOp::RecursiveCteScan => { + let plan = expr + .plan() + .as_any() + .downcast_ref::() + .unwrap(); cte_scan_names.push(plan.table_name.clone()); if cte_types.is_empty() { cte_types.extend(plan.fields.iter().map(|f| f.data_type().clone())); diff --git a/src/query/sql/src/planner/format/display_rel_operator.rs b/src/query/sql/src/planner/format/display_rel_operator.rs index 8744a09f0944b..7ec44a50037fc 100644 --- a/src/query/sql/src/planner/format/display_rel_operator.rs +++ b/src/query/sql/src/planner/format/display_rel_operator.rs @@ -49,47 +49,47 @@ impl OperatorHumanizer for DefaultOperatorHumanizer { fn to_format_tree(id_humanizer: &I, op: &OperatorRef) -> FormatTreeNode { match op.rel_op() { RelOp::Join => { - let join = op.plan().as_any().downcast_ref::().unwrap(); + let join = op.as_any().downcast_ref::().unwrap(); join_to_format_tree(id_humanizer, join) } RelOp::Scan => { - let scan = op.plan().as_any().downcast_ref::().unwrap(); + let scan = op.as_any().downcast_ref::().unwrap(); scan_to_format_tree(id_humanizer, scan) } RelOp::EvalScalar => { - let eval_scalar = op.plan().as_any().downcast_ref::().unwrap(); + let eval_scalar = op.as_any().downcast_ref::().unwrap(); eval_scalar_to_format_tree(id_humanizer, eval_scalar) } RelOp::Filter => { - let filter = op.plan().as_any().downcast_ref::().unwrap(); + let filter = op.as_any().downcast_ref::().unwrap(); filter_to_format_tree(id_humanizer, filter) } RelOp::Aggregate => { - let aggregate = op.plan().as_any().downcast_ref::().unwrap(); + let aggregate = op.as_any().downcast_ref::().unwrap(); aggregate_to_format_tree(id_humanizer, aggregate) } RelOp::Window => { - let window = op.plan().as_any().downcast_ref::().unwrap(); + let window = op.as_any().downcast_ref::().unwrap(); window_to_format_tree(id_humanizer, window) } RelOp::Udf => { - let udf = op.plan().as_any().downcast_ref::().unwrap(); + let udf = op.as_any().downcast_ref::().unwrap(); udf_to_format_tree(id_humanizer, udf) } RelOp::AsyncFunction => { - let async_func = op.plan().as_any().downcast_ref::().unwrap(); + let async_func = op.as_any().downcast_ref::().unwrap(); async_func_to_format_tree(id_humanizer, async_func) } RelOp::Sort => { - let sort = op.plan().as_any().downcast_ref::().unwrap(); + let sort = op.as_any().downcast_ref::().unwrap(); sort_to_format_tree(id_humanizer, sort) } RelOp::Limit => { - let limit = op.plan().as_any().downcast_ref::().unwrap(); + let limit = op.as_any().downcast_ref::().unwrap(); limit_to_format_tree(id_humanizer, limit) } RelOp::Exchange => { - let exchange = op.plan().as_any().downcast_ref::().unwrap(); + let exchange = op.as_any().downcast_ref::().unwrap(); exchange_to_format_tree(id_humanizer, exchange) } RelOp::ConstantTableScan => { @@ -101,11 +101,11 @@ fn to_format_tree(id_humanizer: &I, op: &OperatorRef) -> FormatT constant_scan_to_format_tree(id_humanizer, constant_scan) } RelOp::UnionAll => { - let union_all = op.plan().as_any().downcast_ref::().unwrap(); + let union_all = op.as_any().downcast_ref::().unwrap(); union_all_to_format_tree(id_humanizer, union_all) } RelOp::MergeInto => { - let merge_into = op.plan().as_any().downcast_ref::().unwrap(); + let merge_into = op.as_any().downcast_ref::().unwrap(); merge_into_to_format_tree(id_humanizer, merge_into) } _ => FormatTreeNode::with_children(format!("{:?}", op), vec![]), diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 21fd9b81e72bb..8c8a50a2c3cc7 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -29,6 +29,7 @@ use crate::optimizer::optimizers::rule::RuleID; use crate::plans::Exchange; use crate::plans::Operator; use crate::plans::OperatorRef; +use crate::plans::RelOp; use crate::plans::Scan; use crate::plans::WindowFuncType; use crate::IndexType; diff --git a/src/query/sql/src/planner/optimizer/optimizer.rs b/src/query/sql/src/planner/optimizer/optimizer.rs index 77dfdfb05e1b6..52aafe98ff119 100644 --- a/src/query/sql/src/planner/optimizer/optimizer.rs +++ b/src/query/sql/src/planner/optimizer/optimizer.rs @@ -327,7 +327,12 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res input_s_expr = optimize_query(opt_ctx.clone(), s_expr.child(0)?.clone()).await?; } - let mut mutation = s_expr.plan().as_any().downcast_mut::().unwrap(); + let mut mutation = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); mutation.distributed = opt_ctx.get_enable_distributed_optimization(); let schema = mutation.schema(); @@ -425,7 +430,7 @@ async fn optimize_mutation(opt_ctx: Arc, s_expr: SExpr) -> Res Ok(Plan::DataMutation { schema, - s_expr: Box::new(SExpr::create_unary(mutation, input_s_expr)), + s_expr: Box::new(SExpr::create_unary(mutation.clone(), input_s_expr)), metadata: opt_ctx.get_metadata(), }) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs index 1724e317d3b90..b43901f7e9ba5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs @@ -223,11 +223,7 @@ impl SubqueryDecorrelatorOptimizer { ); } - let result = SExpr::create_binary( - Arc::new(join.into()), - Arc::new(left_child), - Arc::new(right_child), - ); + let result = SExpr::create_binary(join, left_child, right_child); Ok(Some(result)) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs index a5458926a599e..50b3a32e2cdd2 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs @@ -292,11 +292,7 @@ impl SubqueryDecorrelatorOptimizer { equi_conditions, ..join.clone() }; - return Ok(SExpr::create_binary( - Arc::new(join.into()), - Arc::new(left), - Arc::new(right), - )); + return Ok(SExpr::create_binary(join, left, right)); } let mut predicates = join.non_equi_conditions.clone(); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs index f8625824e8eba..8e540131faac9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_fold_count_aggregate.rs @@ -81,7 +81,7 @@ impl Rule for RuleFoldCountAggregate { &input_stat_info.statistics.column_stats, &input_stat_info.statistics.precise_cardinality, ) { - let mut scalars = agg.aggregate_functions; + let mut scalars = agg.aggregate_functions.clone(); for item in scalars.iter_mut() { if let ScalarExpr::AggregateFunction(agg_func) = item.scalar.clone() { if agg_func.args.is_empty() { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs index 5e075f24721d8..f25db4f167e70 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs @@ -308,11 +308,7 @@ pub fn try_push_down_filter_join(s_expr: &SExpr, metadata: MetadataRef) -> Resul ); } - let mut result = SExpr::create_binary( - Arc::new(join.into()), - Arc::new(left_child), - Arc::new(right_child), - ); + let mut result = SExpr::create_binary(join, left_child, right_child); if !original_predicates.is_empty() { result = SExpr::create_unary( diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs index acdcac783d6e2..6a23fdc0ad113 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_union.rs @@ -75,7 +75,9 @@ impl Rule for RulePushDownFilterUnion { .plan() .as_any() .downcast_ref::() - .unwrap(); + .unwrap() + .clone(); + if !union.cte_scan_names.is_empty() { // If the union has cte scan names, it's not allowed to push down filter. state.add_result(s_expr.clone()); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs index c78489bb52248..444d61f969cb4 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs @@ -83,7 +83,9 @@ impl Rule for RulePushDownFilterWindow { .plan() .as_any() .downcast_ref::() - .unwrap(); + .unwrap() + .clone(); + let allowed = window.partition_by_columns()?; let rejected = ColumnSet::from_iter( window @@ -106,25 +108,19 @@ impl Rule for RulePushDownFilterWindow { }; let result = if remaining.is_empty() { SExpr::create_unary( - Arc::new(window.into()), - Arc::new(SExpr::create_unary( - Arc::new(pushed_down_filter.into()), - Arc::new(window_expr.child(0)?.clone()), - )), + window, + SExpr::create_unary(pushed_down_filter, window_expr.child(0)?.clone()), ) } else { let remaining_filter = Filter { predicates: remaining, }; let mut s_expr = SExpr::create_unary( - Arc::new(remaining_filter.into()), - Arc::new(SExpr::create_unary( - Arc::new(window.into()), - Arc::new(SExpr::create_unary( - Arc::new(pushed_down_filter.into()), - Arc::new(window_expr.child(0)?.clone()), - )), - )), + remaining_filter, + SExpr::create_unary( + window, + SExpr::create_unary(pushed_down_filter, window_expr.child(0)?.clone()), + ), ); s_expr.set_applied_rule(&self.id); s_expr diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs index fc9fe21eb77bf..bc33e0cd793e3 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window_top_n.rs @@ -127,8 +127,11 @@ impl Rule for RulePushDownFilterWindowTopN { sort.window_partition.as_mut().unwrap().top = Some(top_n); let mut result = SExpr::create_unary( - s_expr.plan.clone(), - SExpr::create_unary(window_expr.plan.clone(), sort_expr.replace_plan(sort)), + filter.clone(), + SExpr::create_unary( + window_expr.plan.clone(), + sort_expr.replace_plan(sort.clone()), + ), ); result.set_applied_rule(&self.id); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs index cd9353a279676..92b96302b1f19 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_prewhere.rs @@ -135,7 +135,8 @@ impl RulePushDownPrewhere { .plan() .as_any() .downcast_ref::() - .unwrap(); + .unwrap() + .clone(); if scan.update_stream_columns { return Ok(s_expr.clone()); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs index 0d348a7fa76f9..586ce5ca9b4b7 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_sort_scan.rs @@ -73,7 +73,12 @@ impl Rule for RulePushDownSortScan { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let sort = s_expr.plan().as_any().downcast_ref::().unwrap(); + let sort = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let child = s_expr.child(0)?; let mut get = match child.plan_rel_op() { diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs index f6af3bbb62a25..d664766a791b2 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/push_down_filter_join/outer_join_to_inner_join.rs @@ -129,12 +129,12 @@ pub fn outer_join_to_inner_join(s_expr: &SExpr, metadata: MetadataRef) -> Result } let result = SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(SExpr::create_binary( - Arc::new(join.into()), - Arc::new(join_s_expr.child(0)?.clone()), - Arc::new(join_s_expr.child(1)?.clone()), - )), + filter, + SExpr::create_binary( + join, + join_s_expr.child(0)?.clone(), + join_s_expr.child(1)?.clone(), + ), ); Ok((result, true)) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs index 00fa45e7c0864..e0812ad1ae3a9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join.rs @@ -105,11 +105,7 @@ impl Rule for RuleCommuteJoin { (condition.right.clone(), condition.left.clone()); } join.join_type = join.join_type.opposite(); - let mut result = SExpr::create_binary( - Arc::new(join.into()), - Arc::new(right_child.clone()), - Arc::new(left_child.clone()), - ); + let mut result = SExpr::create_binary(join, right_child.clone(), left_child.clone()); result.set_applied_rule(&self.id); state.add_result(result); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs index 6e076a90f6973..f566e97dfe159 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_commute_join_base_table.rs @@ -87,11 +87,8 @@ impl Rule for RuleCommuteJoinBaseTable { (condition.right.clone(), condition.left.clone()); } join.join_type = join.join_type.opposite(); - let mut result = SExpr::create_binary( - Arc::new(join.into()), - Arc::new(right_child.clone()), - Arc::new(left_child.clone()), - ); + let mut result = + SExpr::create_binary(join, right_child.clone(), left_child.clone()); // Disable the following rules for the generated expression result.set_applied_rule(&RuleID::CommuteJoinBaseTable); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs index 89ade1662a87b..68cd0f2d1c0a7 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs @@ -96,8 +96,15 @@ impl Rule for RuleLeftExchangeJoin { // join4 t2 // / \ // t1 t3 - let join1: Join = s_expr.plan.deref().clone().try_into()?; - let join2: Join = s_expr.child(0)?.plan.deref().clone().try_into()?; + let join1 = s_expr.plan.as_any().downcast_ref::().unwrap().clone(); + let join2 = s_expr + .child(0)? + .plan + .as_any() + .downcast_ref::() + .unwrap() + .clone(); + let t1 = s_expr.child(0)?.child(0)?; let t2 = s_expr.child(0)?.child(1)?; let t3 = s_expr.child(1)?; @@ -123,9 +130,9 @@ impl Rule for RuleLeftExchangeJoin { let t2_prop = RelExpr::with_s_expr(t2).derive_relational_prop()?; let t3_prop = RelExpr::with_s_expr(t3).derive_relational_prop()?; let join4_prop = RelExpr::with_s_expr(&SExpr::create_binary( - Arc::new(join_4.clone().into()), - Arc::new(t1.clone()), - Arc::new(t3.clone()), + join_4.clone().into(), + t1.clone(), + t3.clone(), )) .derive_relational_prop()?; @@ -211,14 +218,10 @@ impl Rule for RuleLeftExchangeJoin { } let mut result = SExpr::create( - Arc::new(join_3.into()), + join_3, vec![ - Arc::new(SExpr::create_binary( - Arc::new(join_4.into()), - Arc::new(t1.clone()), - Arc::new(t3.clone()), - )), - Arc::new(t2.clone()), + SExpr::create_binary(join_4, t1.clone(), t3.clone()), + t2.clone(), ], None, None, diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs index 658c696c67b48..2e17b231502e6 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs @@ -111,11 +111,8 @@ impl Rule for RuleSemiToInnerJoin { } }) { join.join_type = JoinType::Inner; - let mut join_expr = SExpr::create_binary( - Arc::new(join.into()), - Arc::new(s_expr.child(0)?.clone()), - Arc::new(s_expr.child(1)?.clone()), - ); + let mut join_expr = + SExpr::create_binary(join, s_expr.child(0)?.clone(), s_expr.child(1)?.clone()); join_expr.set_applied_rule(&self.id); state.add_result(join_expr); } @@ -131,7 +128,7 @@ fn find_group_by_keys( child: &SExpr, group_by_keys: &mut HashMap>, ) -> Result<()> { - match child.plan() { + match child.plan_rel_op() { RelOp::EvalScalar | RelOp::Filter | RelOp::Window => { find_group_by_keys(child.child(0)?, group_by_keys)?; } @@ -158,6 +155,7 @@ fn find_group_by_keys( | RelOp::Join | RelOp::RecursiveCteScan | RelOp::MutationSource + | RelOp::MergeInto | RelOp::CompactBlock => {} } Ok(()) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs index 494507580b287..6a51cd8a6c7e0 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_expression.rs @@ -65,13 +65,19 @@ impl Rule for RulePushDownLimitEvalScalar { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); + let limit = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let eval_plan = s_expr.child(0)?; let eval_scalar = eval_plan .plan() .as_any() .downcast_ref::() - .unwrap(); + .unwrap() + .clone(); let limit_expr = SExpr::create_unary(limit, eval_plan.child(0)?.clone()); let mut result = SExpr::create_unary(eval_scalar, limit_expr); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs index a0200969a81ee..698836cde017b 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_join.rs @@ -69,7 +69,12 @@ impl Rule for RulePushDownLimitOuterJoin { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let limit = s_expr.plan().as_any().downcast_ref::().unwrap(); + let limit = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); if limit.limit.is_some() { let child = s_expr.child(0)?; let join = child.plan().as_any().downcast_ref::().unwrap(); @@ -80,12 +85,12 @@ impl Rule for RulePushDownLimitOuterJoin { Arc::new(child.child(1)?.clone()), ]); let mut result = SExpr::create_unary( - Arc::new(Limit { + Limit { before_exchange: limit.before_exchange, - limit: limit.limit, + limit: limit.limit.clone(), offset: 0, - }), - Arc::new(child), + }, + child, ); result.set_applied_rule(&self.id); state.add_result(result) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs index 59d55fc6ca567..16b63d97be273 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/limit_rules/rule_push_down_limit_union.rs @@ -86,7 +86,7 @@ impl Rule for RulePushDownLimitUnion { union_left_child = SExpr::create_unary(new_limit.clone(), union_left_child); union_right_child = SExpr::create_unary(new_limit, union_right_child); - let mut result = SExpr::create_binary(union, union_left_child, union_right_child); + let mut result = SExpr::create_binary(union.clone(), union_left_child, union_right_child); // Add original limit to top result = s_expr.replace_children(vec![Arc::new(result)]); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs index e74f3ae98eeed..7e178f44c338c 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_merge_eval_scalar.rs @@ -58,13 +58,19 @@ impl Rule for RuleMergeEvalScalar { } fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> { - let up_eval_scalar = s_expr.plan().as_any().downcast_ref::().unwrap(); + let up_eval_scalar = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let down_eval_scalar = s_expr .child(0)? .plan() .as_any() .downcast_ref::() - .unwrap(); + .unwrap() + .clone(); let mut used_columns = ColumnSet::new(); for item in up_eval_scalar.items.iter() { used_columns = used_columns @@ -77,7 +83,7 @@ impl Rule for RuleMergeEvalScalar { let input_prop = rel_expr.derive_relational_prop_child(0)?; // Check if the up EvalScalar depends on the down EvalScalar if used_columns.is_subset(&input_prop.output_columns) { - // TODO(leiysky): eliminate duplicated scalars + // TODO(sundy): eliminate duplicated scalars let items = up_eval_scalar .items .into_iter() @@ -85,10 +91,7 @@ impl Rule for RuleMergeEvalScalar { .collect(); let merged = EvalScalar { items }; - let new_expr = SExpr::create_unary( - Arc::new(merged.into()), - Arc::new(s_expr.child(0)?.child(0)?.clone()), - ); + let new_expr = SExpr::create_unary(merged, s_expr.child(0)?.child(0)?.clone()); state.add_result(new_expr); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs index 1ba6ed19a535e..97e065ce55ff5 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/scalar_rules/rule_normalize_scalar.rs @@ -84,7 +84,12 @@ impl Rule for RuleNormalizeScalarFilter { s_expr: &SExpr, state: &mut crate::optimizer::optimizers::rule::TransformResult, ) -> Result<()> { - let mut filter = s_expr.plan().as_any().downcast_ref::().unwrap(); + let mut filter = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); if filter .predicates @@ -93,7 +98,7 @@ impl Rule for RuleNormalizeScalarFilter { { filter.predicates = normalize_predicates(filter.predicates); state.add_result(SExpr::create_unary( - filter.clone().into(), + filter.clone(), s_expr.child(0)?.clone(), )); Ok(()) diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs index b7bf154cbbf38..899903593c90a 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs @@ -57,9 +57,8 @@ impl RuleEliminateUnion { if let Some(empty_scan) = s_expr.plan().as_any().downcast_ref::() { return Ok(empty_scan.num_rows == 0); } - } else { - Self::is_empty_scan(s_expr.child(0)?) } + Self::is_empty_scan(s_expr.child(0)?) } } diff --git a/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs b/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs index 75f41153f299b..0b3812b26f852 100644 --- a/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs +++ b/src/query/sql/src/planner/optimizer/statistics/collect_statistics.rs @@ -100,7 +100,7 @@ impl CollectStatisticsOptimizer { column_stats, histograms, }); - let mut s_expr = s_expr.replace_plan(scan); + let mut s_expr = s_expr.replace_plan(scan.clone()); if let Some(sample) = &scan.sample { // Only process row-level sampling in optimizer phase. if let Some(row_level) = &sample.row_level { @@ -128,13 +128,10 @@ impl CollectStatisticsOptimizer { ], }); s_expr = SExpr::create_unary( - Arc::new( - Filter { - predicates: vec![filter], - } - .into(), - ), - Arc::new(s_expr), + Filter { + predicates: vec![filter], + }, + s_expr.child(0)?.clone(), ); } } diff --git a/src/query/sql/src/planner/plans/aggregate.rs b/src/query/sql/src/planner/plans/aggregate.rs index 7f884f9cb98e4..ebf158ab0ec4c 100644 --- a/src/query/sql/src/planner/plans/aggregate.rs +++ b/src/query/sql/src/planner/plans/aggregate.rs @@ -179,7 +179,7 @@ impl Operator for Aggregate { RelOp::Aggregate } - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { let iter = self.group_items.iter().map(|expr| &expr.scalar); let iter = iter.chain(self.aggregate_functions.iter().map(|expr| &expr.scalar)); Box::new(iter) diff --git a/src/query/sql/src/planner/plans/eval_scalar.rs b/src/query/sql/src/planner/plans/eval_scalar.rs index 05a1c7f5c376c..0dad552346000 100644 --- a/src/query/sql/src/planner/plans/eval_scalar.rs +++ b/src/query/sql/src/planner/plans/eval_scalar.rs @@ -86,7 +86,7 @@ impl Operator for EvalScalar { RelOp::EvalScalar } - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { Box::new(self.items.iter().map(|expr| &expr.scalar)) } diff --git a/src/query/sql/src/planner/plans/filter.rs b/src/query/sql/src/planner/plans/filter.rs index aa2aec09df0d4..d75255a4cdbce 100644 --- a/src/query/sql/src/planner/plans/filter.rs +++ b/src/query/sql/src/planner/plans/filter.rs @@ -52,7 +52,7 @@ impl Operator for Filter { RelOp::Filter } - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { Box::new(self.predicates.iter()) } diff --git a/src/query/sql/src/planner/plans/join.rs b/src/query/sql/src/planner/plans/join.rs index b5d1b0dca5ec2..9922719c1a243 100644 --- a/src/query/sql/src/planner/plans/join.rs +++ b/src/query/sql/src/planner/plans/join.rs @@ -513,7 +513,7 @@ impl Operator for Join { 2 } - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { let iter = self.equi_conditions.iter().map(|condition| &condition.left); let iter = iter.chain( self.equi_conditions diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 42b649c1570a4..30e20bd687078 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -62,7 +62,7 @@ pub trait Operator: Send + Sync + 'static { fn as_any(&self) -> &dyn std::any::Any; - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { Box::new(std::iter::empty()) } diff --git a/src/query/sql/src/planner/plans/project_set.rs b/src/query/sql/src/planner/plans/project_set.rs index 66b7ef581a178..f66eaa5cc7fc4 100644 --- a/src/query/sql/src/planner/plans/project_set.rs +++ b/src/query/sql/src/planner/plans/project_set.rs @@ -48,7 +48,7 @@ impl Operator for ProjectSet { RelOp::ProjectSet } - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { Box::new(self.srfs.iter().map(|expr| &expr.scalar)) } diff --git a/src/query/sql/src/planner/plans/recluster.rs b/src/query/sql/src/planner/plans/recluster.rs index e9fcfa47a990e..1ad8080f48538 100644 --- a/src/query/sql/src/planner/plans/recluster.rs +++ b/src/query/sql/src/planner/plans/recluster.rs @@ -32,6 +32,7 @@ use crate::plans::ConstantExpr; use crate::plans::EvalScalar; use crate::plans::Operator; use crate::plans::Plan; +use crate::plans::RelOp; use crate::plans::Scan; use crate::Binder; use crate::MetadataRef; @@ -135,7 +136,7 @@ pub fn replace_with_constant(expr: &SExpr, variables: &VecDeque, partiti for item in &mut expr.items { visit_expr_column(&mut item.scalar, variables); } - Arc::new(expr.into()) + Arc::new(expr), } RelOp::Aggregate => { let aggr = s_expr.plan().as_any().downcast_ref::().unwrap(); @@ -147,7 +148,7 @@ pub fn replace_with_constant(expr: &SExpr, variables: &VecDeque, partiti } } } - Arc::new(aggr.into()) + Arc::new(aggr), } _ => s_expr.plan.clone(), }; diff --git a/src/query/sql/src/planner/plans/udf.rs b/src/query/sql/src/planner/plans/udf.rs index cc57866603103..de49c54f25567 100644 --- a/src/query/sql/src/planner/plans/udf.rs +++ b/src/query/sql/src/planner/plans/udf.rs @@ -53,7 +53,7 @@ impl Operator for Udf { RelOp::Udf } - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { Box::new(self.items.iter().map(|expr| &expr.scalar)) } diff --git a/src/query/sql/src/planner/plans/window.rs b/src/query/sql/src/planner/plans/window.rs index f026384671df4..d7ab2969186e0 100644 --- a/src/query/sql/src/planner/plans/window.rs +++ b/src/query/sql/src/planner/plans/window.rs @@ -43,6 +43,7 @@ use crate::plans::RelOp; use crate::plans::ScalarItem; use crate::ColumnSet; use crate::IndexType; +use crate::ScalarExpr; #[derive(Clone, Debug, Educe)] #[educe(PartialEq, Eq, Hash)] @@ -114,15 +115,15 @@ impl Operator for Window { RelOp::Window } - fn scalar_expr_iter(&self) -> Box> { + fn scalar_expr_iter(&self) -> Box + '_> { let iter = self.order_by.iter().map(|o| &o.order_by_item.scalar); let iter = iter.chain(self.partition_by.iter().map(|expr| &expr.scalar)); let iter = iter.chain(self.arguments.iter().map(|expr| &expr.scalar)); if let WindowFuncType::Aggregate(agg) = &self.function { - Box::new(iter.chain(agg.exprs().iter().map(|expr| &expr.scalar))) + Box::new(iter.chain(agg.exprs())) } else { - iter + Box::new(iter) } } From 2d9e72ca691a084a2bd50b49bbf2797fcaa14f39 Mon Sep 17 00:00:00 2001 From: sundyli <543950155@qq.com> Date: Wed, 9 Jul 2025 07:15:36 +0000 Subject: [PATCH 14/14] fix --- .../sql/src/executor/physical_plan_builder.rs | 6 +- .../sql/src/executor/physical_plans/mod.rs | 1 + .../physical_aggregate_final.rs | 1 + .../physical_plans/physical_compact_source.rs | 2 +- .../physical_constant_table_scan.rs | 2 +- .../planner/binder/bind_mutation/update.rs | 4 +- .../sql/src/planner/binder/bind_query/bind.rs | 5 +- .../binder/bind_table_reference/bind_join.rs | 28 +-- src/query/sql/src/planner/binder/distinct.rs | 5 +- src/query/sql/src/planner/binder/having.rs | 5 +- src/query/sql/src/planner/binder/qualify.rs | 5 +- src/query/sql/src/planner/binder/select.rs | 6 +- src/query/sql/src/planner/binder/window.rs | 5 +- .../planner/format/display_rel_operator.rs | 2 +- .../src/planner/optimizer/ir/expr/extract.rs | 2 +- .../src/planner/optimizer/ir/expr/s_expr.rs | 24 ++- .../sql/src/planner/optimizer/ir/format.rs | 2 +- .../operator/aggregate/normalize_aggregate.rs | 16 +- .../operator/decorrelate/decorrelate.rs | 40 ++-- .../operator/decorrelate/flatten_plan.rs | 171 +++++++----------- .../decorrelate/subquery_decorrelator.rs | 28 +-- .../operator/filter/pull_up_filter.rs | 5 +- .../rule_push_down_filter_aggregate.rs | 26 +-- .../rule/agg_rules/rule_split_aggregate.rs | 9 +- .../filter_rules/rule_eliminate_filter.rs | 5 +- .../rule/filter_rules/rule_merge_filter.rs | 5 +- .../rule_push_down_filter_join.rs | 33 ++-- .../rule_push_down_filter_project_set.rs | 23 +-- .../rule_push_down_filter_sort.rs | 7 +- .../rule_push_down_filter_window.rs | 9 +- .../join_rules/rule_left_exchange_join.rs | 6 +- .../join_rules/rule_semi_to_inner_join.rs | 2 +- src/query/sql/src/planner/plans/mutation.rs | 2 +- src/query/sql/src/planner/plans/operator.rs | 4 +- src/query/sql/src/planner/plans/recluster.rs | 4 +- .../semantic/async_function_rewriter.rs | 10 +- .../sql/src/planner/semantic/type_check.rs | 27 ++- 37 files changed, 211 insertions(+), 326 deletions(-) diff --git a/src/query/sql/src/executor/physical_plan_builder.rs b/src/query/sql/src/executor/physical_plan_builder.rs index a04c8b3820efb..4e2880a19c08d 100644 --- a/src/query/sql/src/executor/physical_plan_builder.rs +++ b/src/query/sql/src/executor/physical_plan_builder.rs @@ -54,7 +54,7 @@ macro_rules! with_match_rel_op { Join => PhysicalJoinType, EvalScalar => EvalScalar, Filter => Filter, - Aggregate => Aggregate, + Aggregate => AggregateFinal, Sort => Sort, Limit => Limit, Exchange => Exchange, @@ -64,7 +64,7 @@ macro_rules! with_match_rel_op { Udf => Udf, AsyncFunction => AsyncFunction, RecursiveCteScan => RecursiveCteScan, - MergeInto => Mutation, + Mutation => Mutation, CompactBlock => CompactBlock, MutationSource => MutationSource, ], @@ -116,7 +116,7 @@ impl PhysicalPlanBuilder { with_match_rel_op!(|TY| match s_expr.plan_rel_op() { crate::plans::RelOp::TY => TY::build(self, s_expr, required, stat_info).await, - _ => Err(ErrorCode::Internal("Unsupported operator")), + // _ => Err(ErrorCode::Internal("Unsupported operator")), }) } diff --git a/src/query/sql/src/executor/physical_plans/mod.rs b/src/query/sql/src/executor/physical_plans/mod.rs index 6bd77984b9d69..8f55b8f31167e 100644 --- a/src/query/sql/src/executor/physical_plans/mod.rs +++ b/src/query/sql/src/executor/physical_plans/mod.rs @@ -73,6 +73,7 @@ pub use physical_broadcast::*; pub use physical_cache_scan::CacheScan; pub use physical_column_mutation::ColumnMutation; pub use physical_commit_sink::*; +pub use physical_compact_source::CompactBlock; pub use physical_compact_source::CompactSource; pub use physical_constant_table_scan::ConstantTableScan; pub use physical_copy_into_location::CopyIntoLocation; diff --git a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs index c9a7319552cd6..a95b769310f14 100644 --- a/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs +++ b/src/query/sql/src/executor/physical_plans/physical_aggregate_final.rs @@ -72,6 +72,7 @@ impl AggregateFinal { } } +#[async_trait::async_trait] impl BuildPhysicalPlan for AggregateFinal { async fn build( builder: &mut PhysicalPlanBuilder, diff --git a/src/query/sql/src/executor/physical_plans/physical_compact_source.rs b/src/query/sql/src/executor/physical_plans/physical_compact_source.rs index f230f1c7c2263..4f2eaf4439606 100644 --- a/src/query/sql/src/executor/physical_plans/physical_compact_source.rs +++ b/src/query/sql/src/executor/physical_plans/physical_compact_source.rs @@ -64,7 +64,7 @@ impl BuildPhysicalPlan for CompactBlock { } impl PhysicalPlanBuilder { - pub async fn build_compact_block( + pub async fn build_compact_source( &mut self, compact_block: &crate::plans::OptimizeCompactBlock, ) -> Result { diff --git a/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs b/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs index e8f2be453e8d2..62b94e178a395 100644 --- a/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs +++ b/src/query/sql/src/executor/physical_plans/physical_constant_table_scan.rs @@ -61,7 +61,7 @@ impl BuildPhysicalPlan for ConstantTableScan { .downcast_ref::() .unwrap(); builder - .build_constant_table_scan(s_expr, plan, required, stat_info) + .build_constant_table_scan(plan, required, stat_info) .await } } diff --git a/src/query/sql/src/planner/binder/bind_mutation/update.rs b/src/query/sql/src/planner/binder/bind_mutation/update.rs index 3856bbd1dde43..5ac83409504fd 100644 --- a/src/query/sql/src/planner/binder/bind_mutation/update.rs +++ b/src/query/sql/src/planner/binder/bind_mutation/update.rs @@ -327,10 +327,10 @@ impl Binder { let input = if eval_scalar.items.is_empty() { aggr_expr } else { - aggr_expr.build_unary(Arc::new(eval_scalar.into())) + aggr_expr.build_unary(eval_scalar) }; - let s_expr = Box::new(input.build_unary(Arc::new(mutation.into()))); + let s_expr = Box::new(input.build_unary(mutation)); let Plan::DataMutation { schema, metadata, .. } = plan diff --git a/src/query/sql/src/planner/binder/bind_query/bind.rs b/src/query/sql/src/planner/binder/bind_query/bind.rs index 46867955cb746..44b601ec1c960 100644 --- a/src/query/sql/src/planner/binder/bind_query/bind.rs +++ b/src/query/sql/src/planner/binder/bind_query/bind.rs @@ -238,10 +238,7 @@ impl Binder { pre_projection: None, window_partition: None, }; - Ok(SExpr::create_unary( - Arc::new(sort_plan.into()), - Arc::new(child), - )) + Ok(SExpr::create_unary(sort_plan, child)) } fn m_cte_to_temp_table(&mut self, cte: &CTE, cte_index: usize, mut with: With) -> Result<()> { diff --git a/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs b/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs index 853ad3c521e8e..f5a49fff2d41d 100644 --- a/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs +++ b/src/query/sql/src/planner/binder/bind_table_reference/bind_join.rs @@ -456,11 +456,7 @@ impl Binder { single_to_inner: None, build_side_cache_info, }; - Ok(SExpr::create_binary( - Arc::new(logical_join.into()), - Arc::new(left_child), - Arc::new(right_child), - )) + Ok(SExpr::create_binary(logical_join, left_child, right_child)) } fn push_down_other_conditions( @@ -528,25 +524,19 @@ impl Binder { if !left_push_down.is_empty() { *left_child = SExpr::create_unary( - Arc::new( - Filter { - predicates: left_push_down, - } - .into(), - ), - Arc::new(left_child.clone()), + Filter { + predicates: left_push_down, + }, + left_child.clone(), ); } if !right_push_down.is_empty() { *right_child = SExpr::create_unary( - Arc::new( - Filter { - predicates: right_push_down, - } - .into(), - ), - Arc::new(right_child.clone()), + Filter { + predicates: right_push_down, + }, + right_child.clone(), ); } diff --git a/src/query/sql/src/planner/binder/distinct.rs b/src/query/sql/src/planner/binder/distinct.rs index 4baacddf96e09..621f1483bf04b 100644 --- a/src/query/sql/src/planner/binder/distinct.rs +++ b/src/query/sql/src/planner/binder/distinct.rs @@ -87,9 +87,6 @@ impl Binder { ..Default::default() }; - Ok(SExpr::create_unary( - Arc::new(distinct_plan.into()), - Arc::new(new_expr), - )) + Ok(SExpr::create_unary(distinct_plan, new_expr)) } } diff --git a/src/query/sql/src/planner/binder/having.rs b/src/query/sql/src/planner/binder/having.rs index f8d37d8fe52f7..4fbf29b6aa440 100644 --- a/src/query/sql/src/planner/binder/having.rs +++ b/src/query/sql/src/planner/binder/having.rs @@ -89,9 +89,6 @@ impl Binder { let filter = Filter { predicates }; - Ok(SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(child), - )) + Ok(SExpr::create_unary(filter, child)) } } diff --git a/src/query/sql/src/planner/binder/qualify.rs b/src/query/sql/src/planner/binder/qualify.rs index d72269f2aedb2..5de97aceb3267 100644 --- a/src/query/sql/src/planner/binder/qualify.rs +++ b/src/query/sql/src/planner/binder/qualify.rs @@ -95,10 +95,7 @@ impl Binder { let filter = Filter { predicates }; - Ok(SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(child), - )) + Ok(SExpr::create_unary(filter, child)) } } diff --git a/src/query/sql/src/planner/binder/select.rs b/src/query/sql/src/planner/binder/select.rs index 5bd6ba159edd1..d21b696e65fe1 100644 --- a/src/query/sql/src/planner/binder/select.rs +++ b/src/query/sql/src/planner/binder/select.rs @@ -280,11 +280,7 @@ impl Binder { output_indexes, }; - let mut new_expr = SExpr::create_binary( - Arc::new(union_plan.into()), - Arc::new(left_expr), - Arc::new(right_expr), - ); + let mut new_expr = SExpr::create_binary(union_plan, left_expr, right_expr); if distinct { let columns = new_bind_context.all_column_bindings().to_vec(); diff --git a/src/query/sql/src/planner/binder/window.rs b/src/query/sql/src/planner/binder/window.rs index 2d10b1434602c..31ece8630afbf 100644 --- a/src/query/sql/src/planner/binder/window.rs +++ b/src/query/sql/src/planner/binder/window.rs @@ -672,10 +672,7 @@ pub fn bind_window_function_info( child }; - Ok(SExpr::create_unary( - Arc::new(window_plan.into()), - Arc::new(child), - )) + Ok(SExpr::create_unary(window_plan, child)) } impl Binder { diff --git a/src/query/sql/src/planner/format/display_rel_operator.rs b/src/query/sql/src/planner/format/display_rel_operator.rs index 7ec44a50037fc..e8125f9e1ea8e 100644 --- a/src/query/sql/src/planner/format/display_rel_operator.rs +++ b/src/query/sql/src/planner/format/display_rel_operator.rs @@ -104,7 +104,7 @@ fn to_format_tree(id_humanizer: &I, op: &OperatorRef) -> FormatT let union_all = op.as_any().downcast_ref::().unwrap(); union_all_to_format_tree(id_humanizer, union_all) } - RelOp::MergeInto => { + RelOp::Mutation => { let merge_into = op.as_any().downcast_ref::().unwrap(); merge_into_to_format_tree(id_humanizer, merge_into) } diff --git a/src/query/sql/src/planner/optimizer/ir/expr/extract.rs b/src/query/sql/src/planner/optimizer/ir/expr/extract.rs index 00548a2ee1120..1b344d3685e69 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/extract.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/extract.rs @@ -268,7 +268,7 @@ impl PatternExtractor { children.push(Arc::new(Self::expand_pattern(memo, child_m_expr)?)); } - Ok(SExpr::create( + Ok(SExpr::create_with_plan( m_expr.plan.clone(), children, Some(m_expr.group_index), diff --git a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs index 8c8a50a2c3cc7..d9a84a982495f 100644 --- a/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs +++ b/src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs @@ -85,6 +85,23 @@ impl SExpr { } } + pub fn create_with_plan( + plan: OperatorRef, + children: impl Into>>, + original_group: Option, + rel_prop: Option>, + stat_info: Option>, + ) -> Self { + SExpr { + plan, + children: children.into(), + original_group, + rel_prop: Arc::new(Mutex::new(rel_prop)), + stat_info: Arc::new(Mutex::new(stat_info)), + applied_rules: AppliedRules::default(), + } + } + pub fn create_unary(plan: P, child: impl Into>) -> Self { Self::create(plan, [child.into()], None, None, None) } @@ -250,7 +267,7 @@ impl SExpr { p.inverted_index = inverted_index.clone(); } } - Arc::new(p.into()) + Arc::new(p.clone()) } else { s_expr.plan }; @@ -323,7 +340,8 @@ impl SExpr { crate::plans::RelOp::Join => self.probe_side_child().get_data_distribution(), crate::plans::RelOp::Exchange => { - Ok(Some(self.plan.as_ref().clone().try_into().unwrap())) + let exchange = self.plan.as_any().downcast_ref::().unwrap(); + Ok(Some(exchange.clone())) } crate::plans::RelOp::EvalScalar @@ -336,7 +354,7 @@ impl SExpr { | crate::plans::RelOp::ProjectSet | crate::plans::RelOp::Udf | crate::plans::RelOp::AsyncFunction - | crate::plans::RelOp::MergeInto + | crate::plans::RelOp::Mutation | crate::plans::RelOp::CompactBlock | crate::plans::RelOp::MutationSource => self.child(0)?.get_data_distribution(), } diff --git a/src/query/sql/src/planner/optimizer/ir/format.rs b/src/query/sql/src/planner/optimizer/ir/format.rs index 31f55d2784adc..4b4544b8d887d 100644 --- a/src/query/sql/src/planner/optimizer/ir/format.rs +++ b/src/query/sql/src/planner/optimizer/ir/format.rs @@ -47,7 +47,7 @@ impl Memo { } fn display_rel_op(rel_op: &OperatorRef) -> String { - match rel_op { + match rel_op.rel_op() { RelOp::Scan => "Scan".to_string(), RelOp::Join => "Join".to_string(), RelOp::EvalScalar => "EvalScalar".to_string(), diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs index d31227dc81830..540f710cc7471 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/aggregate/normalize_aggregate.rs @@ -125,10 +125,7 @@ impl RuleNormalizeAggregateOptimizer { grouping_sets: aggregate.grouping_sets, }; - let mut new_aggregate = SExpr::create_unary( - Arc::new(new_aggregate.into()), - Arc::new(s_expr.child(0)?.clone()), - ); + let mut new_aggregate = SExpr::create_unary(new_aggregate, s_expr.child(0)?.clone()); if let Some((work_index, work_c)) = work_expr { if alias_functions_index.len() < 2 { @@ -158,13 +155,10 @@ impl RuleNormalizeAggregateOptimizer { } new_aggregate = SExpr::create_unary( - Arc::new( - EvalScalar { - items: scalar_items, - } - .into(), - ), - Arc::new(new_aggregate), + EvalScalar { + items: scalar_items, + }, + new_aggregate, ); } Ok(new_aggregate) diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs index b43901f7e9ba5..861cab5a5ca4b 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/decorrelate.rs @@ -197,13 +197,10 @@ impl SubqueryDecorrelatorOptimizer { let mut left_child = outer.clone(); if !left_filters.is_empty() { left_child = SExpr::create_unary( - Arc::new( - Filter { - predicates: left_filters, - } - .into(), - ), - Arc::new(left_child), + Filter { + predicates: left_filters, + }, + left_child, ); } @@ -213,13 +210,10 @@ impl SubqueryDecorrelatorOptimizer { .replace_children(vec![Arc::new(filter_tree.child(0)?.clone())]); if !right_filters.is_empty() { right_child = SExpr::create_unary( - Arc::new( - Filter { - predicates: right_filters, - } - .into(), - ), - Arc::new(right_child), + Filter { + predicates: right_filters, + }, + right_child, ); } @@ -283,11 +277,7 @@ impl SubqueryDecorrelatorOptimizer { single_to_inner: None, build_side_cache_info: None, }; - let s_expr = SExpr::create_binary( - Arc::new(join_plan.into()), - Arc::new(outer.clone()), - Arc::new(flatten_plan), - ); + let s_expr = SExpr::create_binary(join_plan, outer.clone(), flatten_plan); Ok((s_expr, UnnestResult::SingleJoin)) } SubqueryType::Exists | SubqueryType::NotExists => { @@ -348,11 +338,7 @@ impl SubqueryDecorrelatorOptimizer { single_to_inner: None, build_side_cache_info: None, }; - let s_expr = SExpr::create_binary( - Arc::new(join_plan.into()), - Arc::new(outer.clone()), - Arc::new(flatten_plan), - ); + let s_expr = SExpr::create_binary(join_plan, outer.clone(), flatten_plan); Ok((s_expr, UnnestResult::MarkJoin { marker_index })) } SubqueryType::Any => { @@ -433,11 +419,7 @@ impl SubqueryDecorrelatorOptimizer { } .into(); Ok(( - SExpr::create_binary( - Arc::new(mark_join), - Arc::new(outer.clone()), - Arc::new(flatten_plan), - ), + SExpr::create_binary(mark_join, outer.clone(), flatten_plan), UnnestResult::MarkJoin { marker_index }, )) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs index 4066b0323b16c..527c8988d9773 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/flatten_plan.rs @@ -145,17 +145,13 @@ impl SubqueryDecorrelatorOptimizer { need_cross_join, ) } - RelOp::Limit => { - let limit = subquery.plan().as_any().downcast_ref::().unwrap(); - self.flatten_sub_limit( - outer, - subquery, - limit, - correlated_columns, - flatten_info, - need_cross_join, - ) - } + RelOp::Limit => self.flatten_sub_limit( + outer, + subquery, + correlated_columns, + flatten_info, + need_cross_join, + ), RelOp::UnionAll => { let union_all = subquery.plan().as_any().downcast_ref::().unwrap(); self.flatten_sub_union_all( @@ -262,10 +258,7 @@ impl SubqueryDecorrelatorOptimizer { }); } - Ok(SExpr::create_unary( - Arc::new(EvalScalar { items }.into()), - Arc::new(flatten_plan), - )) + Ok(SExpr::create_unary(EvalScalar { items }, flatten_plan)) } fn flatten_sub_project_set( @@ -311,16 +304,13 @@ impl SubqueryDecorrelatorOptimizer { .map(|index| Self::scalar_item_from_index(*index, "outer.", &metadata)) .collect(); Ok(SExpr::create_unary( - Arc::new(ProjectSet { srfs }.into()), - Arc::new(SExpr::create_unary( - Arc::new( - EvalScalar { - items: scalar_items, - } - .into(), - ), - Arc::new(flatten_plan), - )), + ProjectSet { srfs }, + SExpr::create_unary( + EvalScalar { + items: scalar_items, + }, + flatten_plan, + ), )) } @@ -351,11 +341,8 @@ impl SubqueryDecorrelatorOptimizer { predicates.push(self.flatten_scalar(predicate, correlated_columns)?); } - let filter_plan = Filter { predicates }.into(); - Ok(SExpr::create_unary( - Arc::new(filter_plan), - Arc::new(flatten_plan), - )) + let filter_plan = Filter { predicates }; + Ok(SExpr::create_unary(filter_plan, flatten_plan)) } fn flatten_sub_join( @@ -476,26 +463,23 @@ impl SubqueryDecorrelatorOptimizer { )?; Ok(SExpr::create_binary( - Arc::new( - Join { - equi_conditions: JoinEquiCondition::new_conditions( - left_conditions, - right_conditions, - vec![], - ), - non_equi_conditions, - join_type: join.join_type.clone(), - marker_index: join.marker_index, - from_correlated_subquery: false, - need_hold_hash_table: false, - is_lateral: false, - single_to_inner: None, - build_side_cache_info: None, - } - .into(), - ), - Arc::new(left_flatten_plan), - Arc::new(right_flatten_plan), + Join { + equi_conditions: JoinEquiCondition::new_conditions( + left_conditions, + right_conditions, + vec![], + ), + non_equi_conditions, + join_type: join.join_type.clone(), + marker_index: join.marker_index, + from_correlated_subquery: false, + need_hold_hash_table: false, + is_lateral: false, + single_to_inner: None, + build_side_cache_info: None, + }, + left_flatten_plan, + right_flatten_plan, )) } @@ -563,18 +547,15 @@ impl SubqueryDecorrelatorOptimizer { }) } Ok(SExpr::create_unary( - Arc::new( - Aggregate { - mode: AggregateMode::Initial, - group_items, - aggregate_functions: agg_items, - from_distinct: aggregate.from_distinct, - rank_limit: aggregate.rank_limit.clone(), - grouping_sets: aggregate.grouping_sets.clone(), - } - .into(), - ), - Arc::new(flatten_plan), + Aggregate { + mode: AggregateMode::Initial, + group_items, + aggregate_functions: agg_items, + from_distinct: aggregate.from_distinct, + rank_limit: aggregate.rank_limit.clone(), + grouping_sets: aggregate.grouping_sets.clone(), + }, + flatten_plan, )) } @@ -608,10 +589,7 @@ impl SubqueryDecorrelatorOptimizer { }) { flatten_info.from_count_func = false; } - Ok(SExpr::create_unary( - subquery.plan.clone(), - Arc::new(flatten_plan), - )) + Ok(SExpr::create_unary(subquery.plan.clone(), flatten_plan)) } fn flatten_sub_limit( @@ -630,10 +608,7 @@ impl SubqueryDecorrelatorOptimizer { flatten_info, need_cross_join, )?; - Ok(SExpr::create_unary( - subquery.plan.clone(), - Arc::new(flatten_plan), - )) + Ok(SExpr::create_unary(subquery.plan.clone(), flatten_plan)) } fn flatten_sub_window( @@ -673,20 +648,17 @@ impl SubqueryDecorrelatorOptimizer { drop(metadata); Ok(SExpr::create_unary( - Arc::new( - Window { - span: window.span, - index: window.index, - function: window.function.clone(), - arguments: window.arguments.clone(), - partition_by, - order_by: window.order_by.clone(), - frame: window.frame.clone(), - limit: window.limit, - } - .into(), - ), - Arc::new(flatten_plan), + Window { + span: window.span, + index: window.index, + function: window.function.clone(), + arguments: window.arguments.clone(), + partition_by, + order_by: window.order_by.clone(), + frame: window.frame.clone(), + limit: window.limit, + }, + flatten_plan, )) } @@ -770,9 +742,9 @@ impl SubqueryDecorrelatorOptimizer { })); Ok(SExpr::create_binary( - Arc::new(union_all.clone().into()), - Arc::new(left_flatten_plan), - Arc::new(right_flatten_plan), + union_all.clone(), + left_flatten_plan, + right_flatten_plan, )) } @@ -816,21 +788,18 @@ impl SubqueryDecorrelatorOptimizer { .collect::>()?; let aggr = SExpr::create_unary( - Arc::new( - Aggregate { - mode: AggregateMode::Initial, - group_items, - ..Default::default() - } - .into(), - ), - Arc::new(outer), + Aggregate { + mode: AggregateMode::Initial, + group_items, + ..Default::default() + }, + outer, ); Ok(SExpr::create_binary( - Arc::new(Join::default().into()), - Arc::new(aggr), - Arc::new(subquery.clone()), + Join::default(), + aggr, + subquery.clone(), )) } @@ -868,7 +837,7 @@ impl SubqueryDecorrelatorOptimizer { } RelOp::Limit => { let limit = plan.as_any().downcast_ref::().unwrap(); - limit.clone().into() + limit.clone() } RelOp::Sort => { let sort = plan.as_any().downcast_ref::().unwrap(); @@ -876,7 +845,7 @@ impl SubqueryDecorrelatorOptimizer { for old in sort.used_columns() { sort.replace_column(old, self.get_derived(old)?); } - sort.into() + sort } RelOp::Filter => { let filter = plan.as_any().downcast_ref::().unwrap(); diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs index 50b3a32e2cdd2..27cae6b07828f 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs @@ -307,10 +307,7 @@ impl SubqueryDecorrelatorOptimizer { (*pred, outer) = self.try_rewrite_subquery(pred, outer, true)?; } let filter = Filter { predicates }; - return Ok(SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(outer), - )); + return Ok(SExpr::create_unary(filter, outer)); } RelOp::UnionAll => Ok(SExpr::create_binary( @@ -569,11 +566,7 @@ impl SubqueryDecorrelatorOptimizer { join_type: JoinType::LeftSingle, ..Join::default() }; - let s_expr = SExpr::create_binary( - Arc::new(join_plan.into()), - Arc::new(outer), - Arc::new(*subquery.subquery.clone()), - ); + let s_expr = SExpr::create_binary(join_plan, outer, *subquery.subquery.clone()); Ok((s_expr, UnnestResult::SingleJoin)) } SubqueryType::Exists | SubqueryType::NotExists => { @@ -642,10 +635,7 @@ impl SubqueryDecorrelatorOptimizer { ], }; - let agg_s_expr = Arc::new(SExpr::create_unary( - Arc::new(agg.into()), - Arc::new(subquery_expr), - )); + let agg_s_expr = SExpr::create_unary(agg, subquery_expr); let mut output_index = None; let rewritten_subquery = if is_conjunctive_predicate { @@ -677,11 +667,7 @@ impl SubqueryDecorrelatorOptimizer { ..Join::default() }; Ok(( - SExpr::create_binary( - Arc::new(cross_join.into()), - Arc::new(outer), - Arc::new(rewritten_subquery), - ), + SExpr::create_binary(cross_join, outer, rewritten_subquery), UnnestResult::SimpleJoin { output_index }, )) } @@ -757,11 +743,7 @@ impl SubqueryDecorrelatorOptimizer { marker_index: Some(marker_index), ..Join::default() }; - let s_expr = SExpr::create_binary( - Arc::new(mark_join.into()), - Arc::new(outer), - Arc::new(*subquery.subquery.clone()), - ); + let s_expr = SExpr::create_binary(mark_join, outer, *subquery.subquery.clone()); Ok((s_expr, UnnestResult::MarkJoin { marker_index })) } _ => unreachable!(), diff --git a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs index be109fb9f5d71..5e750af70d066 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/operator/filter/pull_up_filter.rs @@ -65,10 +65,7 @@ impl PullUpFilterOptimizer { let predicates = InferFilterOptimizer::new(None).optimize(self.predicates.clone())?; let predicates = NormalizeDisjunctiveFilterOptimizer::new().optimize(predicates)?; let filter = Filter { predicates }; - Ok(SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(s_expr), - )) + Ok(SExpr::create_unary(filter, s_expr)) } } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs index 46bec9fdfe8f2..977d7e97dae4d 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_push_down_filter_aggregate.rs @@ -124,25 +124,25 @@ impl Rule for RulePushDownFilterAggregate { let mut result = if remaining_predicates.is_empty() { SExpr::create_unary( - Arc::new(aggregate.into()), - Arc::new(SExpr::create_unary( - Arc::new(pushed_down_filter.into()), - Arc::new(aggregate_expr.child(0)?.clone()), - )), + aggregate.into(), + SExpr::create_unary( + pushed_down_filter.into(), + aggregate_expr.child(0)?.clone(), + ), ) } else { let remaining_filter = Filter { predicates: remaining_predicates, }; SExpr::create_unary( - Arc::new(remaining_filter.into()), - Arc::new(SExpr::create_unary( - Arc::new(aggregate.into()), - Arc::new(SExpr::create_unary( - Arc::new(pushed_down_filter.into()), - Arc::new(aggregate_expr.child(0)?.clone()), - )), - )), + remaining_filter.into(), + SExpr::create_unary( + aggregate.into(), + SExpr::create_unary( + pushed_down_filter.into(), + aggregate_expr.child(0)?.clone(), + ), + ), ) }; result.set_applied_rule(&self.id); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs index f1f9ef9535840..2435d909633b9 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/agg_rules/rule_split_aggregate.rs @@ -60,13 +60,8 @@ impl Rule for RuleSplitAggregate { agg.mode = AggregateMode::Final; let mut partial = agg.clone(); partial.mode = AggregateMode::Partial; - let result = SExpr::create_unary( - Arc::new(agg.into()), - Arc::new(SExpr::create_unary( - Arc::new(partial.into()), - Arc::new(s_expr.child(0)?.clone()), - )), - ); + let result = + SExpr::create_unary(agg, SExpr::create_unary(partial, s_expr.child(0)?.clone())); state.add_result(result); Ok(()) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs index afde523cae737..3c2d739a8a072 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_eliminate_filter.rs @@ -123,10 +123,7 @@ impl Rule for RuleEliminateFilter { state.add_result(s_expr.child(0)?.clone()); } else if origin_predicates.len() != predicates.len() { let filter = Filter { predicates }; - state.add_result(SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(s_expr.child(0)?.clone()), - )); + state.add_result(SExpr::create_unary(filter, s_expr.child(0)?.clone())); } Ok(()) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs index b52056f5178ae..51b4c4e9e0ed7 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_merge_filter.rs @@ -71,10 +71,7 @@ impl Rule for RuleMergeFilter { .collect(); let merged = Filter { predicates }; - let new_expr = SExpr::create_unary( - Arc::new(merged.into()), - Arc::new(s_expr.child(0)?.child(0)?.clone()), - ); + let new_expr = SExpr::create_unary(merged, s_expr.child(0)?.child(0)?.clone()); state.add_result(new_expr); Ok(()) } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs index f25db4f167e70..0fd2eae3ccd73 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_join.rs @@ -286,25 +286,19 @@ pub fn try_push_down_filter_join(s_expr: &SExpr, metadata: MetadataRef) -> Resul if !left_push_down.is_empty() { left_child = SExpr::create_unary( - Arc::new( - Filter { - predicates: left_push_down, - } - .into(), - ), - Arc::new(left_child), + Filter { + predicates: left_push_down, + }, + left_child, ); } if !right_push_down.is_empty() { right_child = SExpr::create_unary( - Arc::new( - Filter { - predicates: right_push_down, - } - .into(), - ), - Arc::new(right_child), + Filter { + predicates: right_push_down, + }, + right_child, ); } @@ -312,13 +306,10 @@ pub fn try_push_down_filter_join(s_expr: &SExpr, metadata: MetadataRef) -> Resul if !original_predicates.is_empty() { result = SExpr::create_unary( - Arc::new( - Filter { - predicates: original_predicates, - } - .into(), - ), - Arc::new(result), + Filter { + predicates: original_predicates, + }, + result, ); } diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs index 0f98694f96844..ac2d5a4c33e6b 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_project_set.rs @@ -98,25 +98,22 @@ impl Rule for RulePushDownFilterProjectSet { }; let mut result = if remaining_predicates.is_empty() { SExpr::create_unary( - Arc::new(project_set.into()), - Arc::new(SExpr::create_unary( - Arc::new(pushed_down_filter.into()), - Arc::new(project_set_expr.child(0)?.clone()), - )), + project_set, + SExpr::create_unary( + pushed_down_filter.into(), + project_set_expr.child(0)?.clone(), + ), ) } else { let remaining_filter = Filter { predicates: remaining_predicates, }; SExpr::create_unary( - Arc::new(remaining_filter.into()), - Arc::new(SExpr::create_unary( - Arc::new(project_set.into()), - Arc::new(SExpr::create_unary( - Arc::new(pushed_down_filter.into()), - Arc::new(project_set_expr.child(0)?.clone()), - )), - )), + remaining_filter, + SExpr::create_unary( + project_set, + SExpr::create_unary(pushed_down_filter, project_set_expr.child(0)?.clone()), + ), ) }; result.set_applied_rule(&self.id); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs index 8c4f5b155c759..96a5754df2560 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_sort.rs @@ -72,11 +72,8 @@ impl Rule for RulePushDownFilterSort { let sort_expr = s_expr.child(0)?; let mut result = SExpr::create_unary( - Arc::new(sort.into()), - Arc::new(SExpr::create_unary( - Arc::new(filter.into()), - Arc::new(sort_expr.child(0)?.clone()), - )), + sort, + SExpr::create_unary(filter, sort_expr.child(0)?.clone()), ); result.set_applied_rule(&self.id); state.add_result(result); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs index 444d61f969cb4..7254088e05f4d 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/filter_rules/rule_push_down_filter_window.rs @@ -77,7 +77,12 @@ impl Rule for RulePushDownFilterWindow { s_expr: &SExpr, state: &mut TransformResult, ) -> databend_common_exception::Result<()> { - let filter = s_expr.plan().as_any().downcast_ref::().unwrap(); + let filter = s_expr + .plan() + .as_any() + .downcast_ref::() + .unwrap() + .clone(); let window_expr = s_expr.child(0)?; let window = window_expr .plan() @@ -95,7 +100,7 @@ impl Rule for RulePushDownFilterWindow { ); let (pushed_down, remaining): (Vec<_>, Vec<_>) = - predicates.into_iter().partition(|predicate| { + filter.predicates.into_iter().partition(|predicate| { let used = predicate.used_columns(); used.is_subset(&allowed) && used.is_disjoint(&rejected) }); diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs index 68cd0f2d1c0a7..085532dfe151f 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_left_exchange_join.rs @@ -130,7 +130,7 @@ impl Rule for RuleLeftExchangeJoin { let t2_prop = RelExpr::with_s_expr(t2).derive_relational_prop()?; let t3_prop = RelExpr::with_s_expr(t3).derive_relational_prop()?; let join4_prop = RelExpr::with_s_expr(&SExpr::create_binary( - join_4.clone().into(), + join_4.clone(), t1.clone(), t3.clone(), )) @@ -220,8 +220,8 @@ impl Rule for RuleLeftExchangeJoin { let mut result = SExpr::create( join_3, vec![ - SExpr::create_binary(join_4, t1.clone(), t3.clone()), - t2.clone(), + Arc::new(SExpr::create_binary(join_4, t1.clone(), t3.clone())), + Arc::new(t2.clone()), ], None, None, diff --git a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs index 2e17b231502e6..9204dd4ce75c1 100644 --- a/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs +++ b/src/query/sql/src/planner/optimizer/optimizers/rule/join_rules/rule_semi_to_inner_join.rs @@ -155,7 +155,7 @@ fn find_group_by_keys( | RelOp::Join | RelOp::RecursiveCteScan | RelOp::MutationSource - | RelOp::MergeInto + | RelOp::Mutation | RelOp::CompactBlock => {} } Ok(()) diff --git a/src/query/sql/src/planner/plans/mutation.rs b/src/query/sql/src/planner/plans/mutation.rs index e270d05984932..5dc13ebaa0860 100644 --- a/src/query/sql/src/planner/plans/mutation.rs +++ b/src/query/sql/src/planner/plans/mutation.rs @@ -201,6 +201,6 @@ impl Operator for Mutation { self } fn rel_op(&self) -> RelOp { - RelOp::MergeInto + RelOp::Mutation } } diff --git a/src/query/sql/src/planner/plans/operator.rs b/src/query/sql/src/planner/plans/operator.rs index 30e20bd687078..62e8f1d1b5786 100644 --- a/src/query/sql/src/planner/plans/operator.rs +++ b/src/query/sql/src/planner/plans/operator.rs @@ -51,7 +51,7 @@ use crate::ScalarExpr; pub type OperatorRef = Arc; -pub trait Operator: Send + Sync + 'static { +pub trait Operator: std::hash::Hash + Sized + Clone + Send + Sync + 'static { /// Get relational operator kind fn rel_op(&self) -> RelOp; @@ -137,7 +137,7 @@ pub enum RelOp { Udf, AsyncFunction, RecursiveCteScan, - MergeInto, + Mutation, CompactBlock, MutationSource, // Pattern diff --git a/src/query/sql/src/planner/plans/recluster.rs b/src/query/sql/src/planner/plans/recluster.rs index 1ad8080f48538..70be2965914bc 100644 --- a/src/query/sql/src/planner/plans/recluster.rs +++ b/src/query/sql/src/planner/plans/recluster.rs @@ -136,7 +136,7 @@ pub fn replace_with_constant(expr: &SExpr, variables: &VecDeque, partiti for item in &mut expr.items { visit_expr_column(&mut item.scalar, variables); } - Arc::new(expr), + Arc::new(expr) } RelOp::Aggregate => { let aggr = s_expr.plan().as_any().downcast_ref::().unwrap(); @@ -148,7 +148,7 @@ pub fn replace_with_constant(expr: &SExpr, variables: &VecDeque, partiti } } } - Arc::new(aggr), + Arc::new(aggr) } _ => s_expr.plan.clone(), }; diff --git a/src/query/sql/src/planner/semantic/async_function_rewriter.rs b/src/query/sql/src/planner/semantic/async_function_rewriter.rs index 4f1236f85d1b3..f863aa8e277cb 100644 --- a/src/query/sql/src/planner/semantic/async_function_rewriter.rs +++ b/src/query/sql/src/planner/semantic/async_function_rewriter.rs @@ -129,10 +129,7 @@ impl AsyncFunctionRewriter { items: scalar_items, }; - child_expr = Arc::new(SExpr::create_unary( - Arc::new(eval_scalar.into()), - child_expr, - )); + child_expr = Arc::new(SExpr::create_unary(eval_scalar, child_expr)); } if !self.async_functions.is_empty() { @@ -141,10 +138,7 @@ impl AsyncFunctionRewriter { let async_func_plan = AsyncFunction { items: async_fun_items, }; - child_expr = Arc::new(SExpr::create_unary( - Arc::new(async_func_plan.into()), - child_expr, - )); + child_expr = Arc::new(SExpr::create_unary(async_func_plan, child_expr)); } child_expr } diff --git a/src/query/sql/src/planner/semantic/type_check.rs b/src/query/sql/src/planner/semantic/type_check.rs index 04b8cfe6f23a4..086f08b75cfde 100644 --- a/src/query/sql/src/planner/semantic/type_check.rs +++ b/src/query/sql/src/planner/semantic/type_check.rs @@ -5406,21 +5406,18 @@ impl<'a> TypeChecker<'a> { assert_eq!(ctx.columns.len(), 1); // Wrap group by on `const_scan` to deduplicate values let distinct_const_scan = SExpr::create_unary( - Arc::new( - Aggregate { - mode: AggregateMode::Initial, - group_items: vec![ScalarItem { - scalar: ScalarExpr::BoundColumnRef(BoundColumnRef { - span: None, - column: ctx.columns[0].clone(), - }), - index: self.metadata.read().columns().len() - 1, - }], - ..Default::default() - } - .into(), - ), - Arc::new(const_scan), + Aggregate { + mode: AggregateMode::Initial, + group_items: vec![ScalarItem { + scalar: ScalarExpr::BoundColumnRef(BoundColumnRef { + span: None, + column: ctx.columns[0].clone(), + }), + index: self.metadata.read().columns().len() - 1, + }], + ..Default::default() + }, + const_scan, ); let box mut data_type = ctx.columns[0].data_type.clone();