uqa_sql/plan/
subqueries.rs1use crate::ScalarExpr;
10use std::collections::BTreeMap;
11
12use super::{CommandPlan, QueryPlan, RelationalPlan, SourcePlan};
13
14mod transform;
15pub(crate) use transform::{
16 copy_occurrences, query_nodes as rewrite_query_with_arenas, rewrite_expression_with_arena,
17 rewrite_with_arenas,
18};
19
20pub fn prune_command(command: &mut CommandPlan) {
22 let Some(arena) = command_arena(command) else {
23 return;
24 };
25 let arena = std::mem::take(arena);
26 let arena = compact(arena, |visitor| {
27 for expression in command.expressions_mut() {
28 super::rewrite_scalar_expression(expression, visitor);
29 }
30 if let Some(source) = command.source_input_mut() {
31 visit_source(source, visitor);
32 }
33 });
34 if let Some(target) = command_arena(command) {
35 *target = arena;
36 }
37}
38
39fn command_arena(command: &mut CommandPlan) -> Option<&mut Vec<QueryPlan>> {
40 match command {
41 CommandPlan::Insert(plan) => Some(&mut plan.subqueries),
42 CommandPlan::Update(plan) => Some(&mut plan.subqueries),
43 CommandPlan::Delete(plan) => Some(&mut plan.subqueries),
44 CommandPlan::Merge(plan) => Some(&mut plan.subqueries),
45 _ => None,
46 }
47}
48
49pub fn prune_query(query: &mut QueryPlan) {
51 let arena = std::mem::take(query_arena(&mut query.root));
52 let arena = compact(arena, |visitor| visit_root(&mut query.root, visitor));
53 *query_arena(&mut query.root) = arena;
54}
55
56pub fn prune_expression(plan: &mut super::ExpressionPlan) {
58 let arena = std::mem::take(&mut plan.subqueries);
59 plan.subqueries = compact(arena, |visitor| {
60 super::rewrite_scalar_expression(&mut plan.scalar, visitor);
61 });
62}
63
64fn query_arena(root: &mut RelationalPlan) -> &mut Vec<QueryPlan> {
65 match root {
66 RelationalPlan::QueryBlock(block) => &mut block.subqueries,
67 RelationalPlan::Values { subqueries, .. } | RelationalPlan::SetOp { subqueries, .. } => {
68 subqueries
69 }
70 }
71}
72
73fn compact(
74 arena: Vec<QueryPlan>,
75 mut visit: impl FnMut(&mut dyn FnMut(&mut ScalarExpr)),
76) -> Vec<QueryPlan> {
77 if arena.is_empty() {
78 return arena;
79 }
80 let mut remap = BTreeMap::new();
81 visit(&mut |expression| {
82 if let Some(id) = subquery_id(expression) {
83 remap.insert(*id, 0);
84 }
85 });
86 if remap.keys().any(|id| *id >= arena.len()) || remap.len() == arena.len() {
89 return arena;
90 }
91 for (position, value) in remap.values_mut().enumerate() {
92 *value = position;
93 }
94 visit(&mut |expression| {
95 if let Some(id) = subquery_id(expression) {
96 *id = remap[id];
97 }
98 });
99 arena
100 .into_iter()
101 .enumerate()
102 .filter_map(|(id, query)| remap.contains_key(&id).then_some(query))
103 .collect()
104}
105
106fn subquery_id(expression: &mut ScalarExpr) -> Option<&mut usize> {
107 match expression {
108 ScalarExpr::ScalarSubquery(id)
109 | ScalarExpr::Exists { subquery: id, .. }
110 | ScalarExpr::InSubquery { subquery: id, .. } => Some(id),
111 _ => None,
112 }
113}
114
115fn visit_root(root: &mut RelationalPlan, visitor: &mut dyn FnMut(&mut ScalarExpr)) {
116 match root {
117 RelationalPlan::QueryBlock(block) => {
118 if let Some(source) = &mut block.from {
119 visit_source(source, visitor);
120 }
121 for expression in block
122 .projections
123 .iter_mut()
124 .map(|projection| &mut projection.expr)
125 .chain(block.r#where.iter_mut())
126 .chain(block.group_by.iter_mut())
127 .chain(block.grouping_sets.iter_mut().flatten())
128 .chain(block.having.iter_mut())
129 .chain(block.order_by.iter_mut().map(|order| &mut order.expr))
130 .chain(block.limit.iter_mut())
131 .chain(block.offset.iter_mut())
132 .chain(block.distinct_on.iter_mut())
133 .chain(
134 block
135 .windows
136 .iter_mut()
137 .flat_map(|window| window.spec.expressions_mut()),
138 )
139 {
140 super::rewrite_scalar_expression(expression, visitor);
141 }
142 }
143 RelationalPlan::Values { rows, .. } => {
144 for expression in rows.iter_mut().flatten() {
145 super::rewrite_scalar_expression(expression, visitor);
146 }
147 }
148 RelationalPlan::SetOp {
149 order_by,
150 limit,
151 offset,
152 ..
153 } => {
154 for expression in order_by
155 .iter_mut()
156 .map(|order| &mut order.expr)
157 .chain(limit.as_deref_mut())
158 .chain(offset.as_deref_mut())
159 {
160 super::rewrite_scalar_expression(expression, visitor);
161 }
162 }
163 }
164}
165
166fn visit_source(source: &mut SourcePlan, visitor: &mut dyn FnMut(&mut ScalarExpr)) {
167 match source {
168 SourcePlan::Join {
169 left, right, on, ..
170 } => {
171 visit_source(left, visitor);
172 visit_source(right, visitor);
173 if let Some(on) = on {
174 super::rewrite_scalar_expression(on, visitor);
175 }
176 }
177 SourcePlan::Values { rows, .. } => {
178 for expression in rows.iter_mut().flatten() {
179 super::rewrite_scalar_expression(expression, visitor);
180 }
181 }
182 SourcePlan::Function { args, .. } => {
183 for argument in args {
184 super::rewrite_scalar_expression(argument, visitor);
185 }
186 }
187 SourcePlan::FunctionGroup { functions, .. } => {
188 for argument in functions.iter_mut().flat_map(|function| &mut function.args) {
189 super::rewrite_scalar_expression(argument, visitor);
190 }
191 }
192 SourcePlan::Subquery { .. } | SourcePlan::Table { .. } => {}
194 }
195}