Skip to content

Commit 33dd91f

Browse files
authored
refactor(optimizer): s_expr.rs (#17767)
1 parent 876a3db commit 33dd91f

File tree

6 files changed

+88
-98
lines changed

6 files changed

+88
-98
lines changed

src/query/sql/src/planner/binder/bind_mutation/mutation_expression.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ impl Binder {
458458

459459
let row_id_index: usize = column_binding.index;
460460

461-
*expr = SExpr::add_internal_column_index(expr, table_index, row_id_index, &None);
461+
*expr = expr.add_column_index_to_scans(table_index, row_id_index, &None);
462462

463463
self.metadata
464464
.write()

src/query/sql/src/planner/binder/binder.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,12 +1108,7 @@ impl<'a> Binder {
11081108
i.has_score = has_score;
11091109
i
11101110
});
1111-
s_expr = SExpr::add_internal_column_index(
1112-
&s_expr,
1113-
*table_index,
1114-
*column_index,
1115-
&inverted_index,
1116-
);
1111+
s_expr = s_expr.add_column_index_to_scans(*table_index, *column_index, &inverted_index);
11171112
}
11181113
Ok(s_expr)
11191114
}

src/query/sql/src/planner/optimizer/ir/expr/s_expr.rs

Lines changed: 10 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,8 @@ use crate::plans::Exchange;
3030
use crate::plans::Operator;
3131
use crate::plans::RelOperator;
3232
use crate::plans::Scan;
33-
use crate::plans::SubqueryExpr;
34-
use crate::plans::Visitor;
3533
use crate::plans::WindowFuncType;
3634
use crate::IndexType;
37-
use crate::ScalarExpr;
3835

3936
/// `SExpr` is abbreviation of single expression, which is a tree of relational operators.
4037
#[derive(Educe)]
@@ -177,13 +174,14 @@ impl SExpr {
177174

178175
/// Check if contain subquery
179176
#[recursive::recursive]
180-
pub(crate) fn contain_subquery(&self) -> bool {
181-
if !find_subquery(&self.plan) {
182-
return self.children.iter().any(|child| child.contain_subquery());
177+
pub(crate) fn has_subquery(&self) -> bool {
178+
if !self.plan.has_subquery() {
179+
return self.children.iter().any(|child| child.has_subquery());
183180
}
184181
true
185182
}
186183

184+
//
187185
#[recursive::recursive]
188186
pub fn get_udfs(&self) -> Result<HashSet<&String>> {
189187
let mut udfs = HashSet::new();
@@ -374,15 +372,15 @@ impl SExpr {
374372
Ok(udfs)
375373
}
376374

377-
// Add (table_index, column_index) into `Scan` node recursively.
378-
pub fn add_internal_column_index(
379-
expr: &SExpr,
375+
// Add column index to Scan nodes that match the given table index
376+
pub fn add_column_index_to_scans(
377+
&self,
380378
table_index: IndexType,
381379
column_index: IndexType,
382380
inverted_index: &Option<InvertedIndexInfo>,
383381
) -> SExpr {
384382
#[recursive::recursive]
385-
fn add_internal_column_index_into_child(
383+
fn add_column_index_to_scans_recursive(
386384
s_expr: &SExpr,
387385
column_index: IndexType,
388386
table_index: IndexType,
@@ -406,7 +404,7 @@ impl SExpr {
406404
} else {
407405
let mut children = Vec::with_capacity(s_expr.children.len());
408406
for child in s_expr.children.iter() {
409-
children.push(Arc::new(add_internal_column_index_into_child(
407+
children.push(Arc::new(add_column_index_to_scans_recursive(
410408
child,
411409
column_index,
412410
table_index,
@@ -420,7 +418,7 @@ impl SExpr {
420418
}
421419
}
422420

423-
add_internal_column_index_into_child(expr, column_index, table_index, inverted_index)
421+
add_column_index_to_scans_recursive(self, column_index, table_index, inverted_index)
424422
}
425423

426424
// The method will clear the applied rules of current SExpr and its children.
@@ -457,81 +455,3 @@ impl SExpr {
457455
Ok(rel_prop)
458456
}
459457
}
460-
461-
fn find_subquery(rel_op: &RelOperator) -> bool {
462-
match rel_op {
463-
RelOperator::Scan(_)
464-
| RelOperator::Limit(_)
465-
| RelOperator::Exchange(_)
466-
| RelOperator::UnionAll(_)
467-
| RelOperator::Sort(_)
468-
| RelOperator::DummyTableScan(_)
469-
| RelOperator::ConstantTableScan(_)
470-
| RelOperator::ExpressionScan(_)
471-
| RelOperator::CacheScan(_)
472-
| RelOperator::AsyncFunction(_)
473-
| RelOperator::RecursiveCteScan(_)
474-
| RelOperator::Mutation(_)
475-
| RelOperator::CompactBlock(_) => false,
476-
RelOperator::Join(op) => {
477-
op.equi_conditions.iter().any(|condition| {
478-
find_subquery_in_expr(&condition.left) || find_subquery_in_expr(&condition.right)
479-
}) || op.non_equi_conditions.iter().any(find_subquery_in_expr)
480-
}
481-
RelOperator::EvalScalar(op) => op
482-
.items
483-
.iter()
484-
.any(|expr| find_subquery_in_expr(&expr.scalar)),
485-
RelOperator::Filter(op) => op.predicates.iter().any(find_subquery_in_expr),
486-
RelOperator::Aggregate(op) => {
487-
op.group_items
488-
.iter()
489-
.any(|expr| find_subquery_in_expr(&expr.scalar))
490-
|| op
491-
.aggregate_functions
492-
.iter()
493-
.any(|expr| find_subquery_in_expr(&expr.scalar))
494-
}
495-
RelOperator::Window(op) => {
496-
op.order_by
497-
.iter()
498-
.any(|o| find_subquery_in_expr(&o.order_by_item.scalar))
499-
|| op
500-
.partition_by
501-
.iter()
502-
.any(|expr| find_subquery_in_expr(&expr.scalar))
503-
|| match &op.function {
504-
WindowFuncType::Aggregate(agg) => agg.exprs().any(find_subquery_in_expr),
505-
_ => false,
506-
}
507-
}
508-
RelOperator::ProjectSet(op) => op
509-
.srfs
510-
.iter()
511-
.any(|expr| find_subquery_in_expr(&expr.scalar)),
512-
RelOperator::Udf(op) => op
513-
.items
514-
.iter()
515-
.any(|expr| find_subquery_in_expr(&expr.scalar)),
516-
RelOperator::MutationSource(_) => false,
517-
}
518-
}
519-
520-
fn find_subquery_in_expr(expr: &ScalarExpr) -> bool {
521-
struct HasSubqueryVisitor {
522-
has_subquery: bool,
523-
}
524-
525-
impl<'a> Visitor<'a> for HasSubqueryVisitor {
526-
fn visit_subquery(&mut self, _: &'a SubqueryExpr) -> Result<()> {
527-
self.has_subquery = true;
528-
Ok(())
529-
}
530-
}
531-
532-
let mut has_subquery = HasSubqueryVisitor {
533-
has_subquery: false,
534-
};
535-
has_subquery.visit(expr).unwrap();
536-
has_subquery.has_subquery
537-
}

src/query/sql/src/planner/optimizer/optimizers/operator/decorrelate/subquery_decorrelator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ impl SubqueryDecorrelatorOptimizer {
171171
#[recursive::recursive]
172172
pub fn optimize_sync(&mut self, s_expr: &SExpr) -> Result<SExpr> {
173173
// If there is no subquery, return directly
174-
if !s_expr.contain_subquery() {
174+
if !s_expr.has_subquery() {
175175
return Ok(s_expr.clone());
176176
}
177177

src/query/sql/src/planner/plans/operator.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use crate::plans::Sort;
4545
use crate::plans::Udf;
4646
use crate::plans::UnionAll;
4747
use crate::plans::Window;
48+
use crate::plans::WindowFuncType;
4849

4950
pub trait Operator {
5051
/// Get relational operator kind
@@ -155,6 +156,61 @@ pub enum RelOperator {
155156
MutationSource(MutationSource),
156157
}
157158

159+
impl RelOperator {
160+
pub fn has_subquery(&self) -> bool {
161+
match self {
162+
RelOperator::Scan(_)
163+
| RelOperator::Limit(_)
164+
| RelOperator::Exchange(_)
165+
| RelOperator::UnionAll(_)
166+
| RelOperator::Sort(_)
167+
| RelOperator::DummyTableScan(_)
168+
| RelOperator::ConstantTableScan(_)
169+
| RelOperator::ExpressionScan(_)
170+
| RelOperator::CacheScan(_)
171+
| RelOperator::AsyncFunction(_)
172+
| RelOperator::RecursiveCteScan(_)
173+
| RelOperator::Mutation(_)
174+
| RelOperator::CompactBlock(_) => false,
175+
RelOperator::Join(op) => {
176+
op.equi_conditions.iter().any(|condition| {
177+
condition.left.has_subquery() || condition.right.has_subquery()
178+
}) || op
179+
.non_equi_conditions
180+
.iter()
181+
.any(|expr| expr.has_subquery())
182+
}
183+
RelOperator::EvalScalar(op) => op.items.iter().any(|expr| expr.scalar.has_subquery()),
184+
RelOperator::Filter(op) => op.predicates.iter().any(|expr| expr.has_subquery()),
185+
RelOperator::Aggregate(op) => {
186+
op.group_items.iter().any(|expr| expr.scalar.has_subquery())
187+
|| op
188+
.aggregate_functions
189+
.iter()
190+
.any(|expr| expr.scalar.has_subquery())
191+
}
192+
RelOperator::Window(op) => {
193+
op.order_by
194+
.iter()
195+
.any(|o| o.order_by_item.scalar.has_subquery())
196+
|| op
197+
.partition_by
198+
.iter()
199+
.any(|expr| expr.scalar.has_subquery())
200+
|| match &op.function {
201+
WindowFuncType::Aggregate(agg) => {
202+
agg.exprs().any(|expr| expr.has_subquery())
203+
}
204+
_ => false,
205+
}
206+
}
207+
RelOperator::ProjectSet(op) => op.srfs.iter().any(|expr| expr.scalar.has_subquery()),
208+
RelOperator::Udf(op) => op.items.iter().any(|expr| expr.scalar.has_subquery()),
209+
RelOperator::MutationSource(_) => false,
210+
}
211+
}
212+
}
213+
158214
impl Operator for RelOperator {
159215
fn rel_op(&self) -> RelOp {
160216
match self {

src/query/sql/src/planner/plans/scalar_expr.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,25 @@ impl ScalarExpr {
401401
find_udfs.visit(self)?;
402402
Ok(find_udfs.udfs)
403403
}
404+
405+
pub fn has_subquery(&self) -> bool {
406+
struct HasSubqueryVisitor {
407+
has_subquery: bool,
408+
}
409+
410+
impl<'a> Visitor<'a> for HasSubqueryVisitor {
411+
fn visit_subquery(&mut self, _: &'a SubqueryExpr) -> Result<()> {
412+
self.has_subquery = true;
413+
Ok(())
414+
}
415+
}
416+
417+
let mut has_subquery = HasSubqueryVisitor {
418+
has_subquery: false,
419+
};
420+
has_subquery.visit(self).unwrap();
421+
has_subquery.has_subquery
422+
}
404423
}
405424

406425
impl From<BoundColumnRef> for ScalarExpr {

0 commit comments

Comments
 (0)