MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / split_subquery_predicates

Function split_subquery_predicates

src/sql/src/plan/transform_hir.rs:60–148  ·  view source on GitHub ↗

Rewrites predicates that contain subqueries so that the subqueries appear in their own later predicate when possible. For example, this function rewrites this expression ```text Filter { predicates: [a = b AND EXISTS ( ) AND c = d AND ( ) = e] } ``` like so: ```text Filter { predicates: [ a = b AND c = d, EXISTS ( ), ( ) = e, ] } ``` The rewrite cause

(expr: &mut HirRelationExpr)

Source from the content-addressed store, hash-verified

58/// d AND EXISTS(<subquery>)`. This can vastly reduce the cost of the
59/// subquery, especially when the original conjunction contains join keys.
60pub fn split_subquery_predicates(expr: &mut HirRelationExpr) -> Result<(), RecursionLimitError> {
61 fn walk_relation(expr: &mut HirRelationExpr) -> Result<(), RecursionLimitError> {
62 #[allow(deprecated)]
63 expr.visit_mut_fallible(0, &mut |expr, _| {
64 match expr {
65 HirRelationExpr::Map { scalars, .. } => {
66 for scalar in scalars {
67 walk_scalar(scalar)?;
68 }
69 }
70 HirRelationExpr::CallTable { exprs, .. } => {
71 for expr in exprs {
72 walk_scalar(expr)?;
73 }
74 }
75 HirRelationExpr::Filter { predicates, .. } => {
76 let mut subqueries = vec![];
77 for predicate in &mut *predicates {
78 walk_scalar(predicate)?;
79 extract_conjuncted_subqueries(predicate, &mut subqueries)?;
80 }
81 // TODO(benesch): we could be smarter about the order in which
82 // we emit subqueries. At the moment we just emit in the order
83 // we discovered them, but ideally we'd emit them in an order
84 // that accounted for their cost/selectivity. E.g., low-cost,
85 // high-selectivity subqueries should go first.
86 for subquery in subqueries {
87 predicates.push(subquery);
88 }
89 }
90 _ => (),
91 }
92 Ok(())
93 })
94 }
95
96 fn walk_scalar(expr: &mut HirScalarExpr) -> Result<(), RecursionLimitError> {
97 expr.try_visit_direct_subqueries_mut(&mut walk_relation)
98 }
99
100 fn contains_subquery(expr: &HirScalarExpr) -> Result<bool, RecursionLimitError> {
101 let mut found = false;
102 expr.try_visit_direct_subqueries(|_| {
103 found = true;
104 Ok(())
105 })?;
106 Ok(found)
107 }
108
109 /// Extracts subqueries from a conjunction into `out`.
110 ///
111 /// For example, given an expression like
112 ///
113 /// ```text
114 /// a = b AND EXISTS (<subquery 1>) AND c = d AND (<subquery 2>) = e
115 /// ```
116 ///
117 /// this function rewrites the expression to

Callers 1

lowerMethod · 0.85

Calls 1

walk_relationFunction · 0.85

Tested by

no test coverage detected