1use crate::{
41 Aggregate, Analyze, CreateMemoryTable, CreateView, DdlStatement, Distinct,
42 DistinctOn, DmlStatement, Execute, Explain, Expr, Extension, Filter, Join, Limit,
43 LogicalPlan, Partitioning, Prepare, Projection, RecursiveQuery, Repartition, Sort,
44 Statement, Subquery, SubqueryAlias, TableScan, Union, Unnest, UserDefinedLogicalNode,
45 Values, Window, dml::CopyTo,
46};
47use datafusion_common::tree_node::TreeNodeRefContainer;
48
49use crate::expr::{Exists, InSubquery, SetComparison};
50use datafusion_common::tree_node::{
51 Transformed, TreeNode, TreeNodeContainer, TreeNodeIterator, TreeNodeRecursion,
52 TreeNodeRewriter, TreeNodeVisitor,
53};
54use datafusion_common::{Result, internal_err};
55
56impl TreeNode for LogicalPlan {
57 fn apply_children<'n, F: FnMut(&'n Self) -> Result<TreeNodeRecursion>>(
58 &'n self,
59 f: F,
60 ) -> Result<TreeNodeRecursion> {
61 self.inputs().apply_ref_elements(f)
62 }
63
64 fn map_children<F: FnMut(Self) -> Result<Transformed<Self>>>(
73 self,
74 f: F,
75 ) -> Result<Transformed<Self>> {
76 Ok(match self {
77 LogicalPlan::Projection(Projection {
78 expr,
79 input,
80 schema,
81 }) => input.map_elements(f)?.update_data(|input| {
82 LogicalPlan::Projection(Projection {
83 expr,
84 input,
85 schema,
86 })
87 }),
88 LogicalPlan::Filter(Filter { predicate, input }) => input
89 .map_elements(f)?
90 .update_data(|input| LogicalPlan::Filter(Filter { predicate, input })),
91 LogicalPlan::Repartition(Repartition {
92 input,
93 partitioning_scheme,
94 }) => input.map_elements(f)?.update_data(|input| {
95 LogicalPlan::Repartition(Repartition {
96 input,
97 partitioning_scheme,
98 })
99 }),
100 LogicalPlan::Window(Window {
101 input,
102 window_expr,
103 schema,
104 }) => input.map_elements(f)?.update_data(|input| {
105 LogicalPlan::Window(Window {
106 input,
107 window_expr,
108 schema,
109 })
110 }),
111 LogicalPlan::Aggregate(Aggregate {
112 input,
113 group_expr,
114 aggr_expr,
115 schema,
116 }) => input.map_elements(f)?.update_data(|input| {
117 LogicalPlan::Aggregate(Aggregate {
118 input,
119 group_expr,
120 aggr_expr,
121 schema,
122 })
123 }),
124 LogicalPlan::Sort(Sort { expr, input, fetch }) => input
125 .map_elements(f)?
126 .update_data(|input| LogicalPlan::Sort(Sort { expr, input, fetch })),
127 LogicalPlan::Join(Join {
128 left,
129 right,
130 on,
131 filter,
132 join_type,
133 join_constraint,
134 schema,
135 null_equality,
136 null_aware,
137 }) => (left, right).map_elements(f)?.update_data(|(left, right)| {
138 LogicalPlan::Join(Join {
139 left,
140 right,
141 on,
142 filter,
143 join_type,
144 join_constraint,
145 schema,
146 null_equality,
147 null_aware,
148 })
149 }),
150 LogicalPlan::Limit(Limit { skip, fetch, input }) => input
151 .map_elements(f)?
152 .update_data(|input| LogicalPlan::Limit(Limit { skip, fetch, input })),
153 LogicalPlan::Subquery(Subquery {
154 subquery,
155 outer_ref_columns,
156 spans,
157 }) => subquery.map_elements(f)?.update_data(|subquery| {
158 LogicalPlan::Subquery(Subquery {
159 subquery,
160 outer_ref_columns,
161 spans,
162 })
163 }),
164 LogicalPlan::SubqueryAlias(SubqueryAlias {
165 input,
166 alias,
167 schema,
168 }) => input.map_elements(f)?.update_data(|input| {
169 LogicalPlan::SubqueryAlias(SubqueryAlias {
170 input,
171 alias,
172 schema,
173 })
174 }),
175 LogicalPlan::Extension(extension) => rewrite_extension_inputs(extension, f)?
176 .update_data(LogicalPlan::Extension),
177 LogicalPlan::Union(Union { inputs, schema }) => inputs
178 .map_elements(f)?
179 .update_data(|inputs| LogicalPlan::Union(Union { inputs, schema })),
180 LogicalPlan::Distinct(distinct) => match distinct {
181 Distinct::All(input) => input.map_elements(f)?.update_data(Distinct::All),
182 Distinct::On(DistinctOn {
183 on_expr,
184 select_expr,
185 sort_expr,
186 input,
187 schema,
188 }) => input.map_elements(f)?.update_data(|input| {
189 Distinct::On(DistinctOn {
190 on_expr,
191 select_expr,
192 sort_expr,
193 input,
194 schema,
195 })
196 }),
197 }
198 .update_data(LogicalPlan::Distinct),
199 LogicalPlan::Explain(Explain {
200 verbose,
201 explain_format: format,
202 plan,
203 stringified_plans,
204 schema,
205 logical_optimization_succeeded,
206 }) => plan.map_elements(f)?.update_data(|plan| {
207 LogicalPlan::Explain(Explain {
208 verbose,
209 explain_format: format,
210 plan,
211 stringified_plans,
212 schema,
213 logical_optimization_succeeded,
214 })
215 }),
216 LogicalPlan::Analyze(Analyze {
217 verbose,
218 input,
219 schema,
220 }) => input.map_elements(f)?.update_data(|input| {
221 LogicalPlan::Analyze(Analyze {
222 verbose,
223 input,
224 schema,
225 })
226 }),
227 LogicalPlan::Dml(DmlStatement {
228 table_name,
229 target,
230 op,
231 input,
232 output_schema,
233 }) => input.map_elements(f)?.update_data(|input| {
234 LogicalPlan::Dml(DmlStatement {
235 table_name,
236 target,
237 op,
238 input,
239 output_schema,
240 })
241 }),
242 LogicalPlan::Copy(CopyTo {
243 input,
244 output_url,
245 partition_by,
246 file_type,
247 options,
248 output_schema,
249 }) => input.map_elements(f)?.update_data(|input| {
250 LogicalPlan::Copy(CopyTo {
251 input,
252 output_url,
253 partition_by,
254 file_type,
255 options,
256 output_schema,
257 })
258 }),
259 LogicalPlan::Ddl(ddl) => {
260 match ddl {
261 DdlStatement::CreateMemoryTable(CreateMemoryTable {
262 name,
263 constraints,
264 input,
265 if_not_exists,
266 or_replace,
267 column_defaults,
268 temporary,
269 }) => input.map_elements(f)?.update_data(|input| {
270 DdlStatement::CreateMemoryTable(CreateMemoryTable {
271 name,
272 constraints,
273 input,
274 if_not_exists,
275 or_replace,
276 column_defaults,
277 temporary,
278 })
279 }),
280 DdlStatement::CreateView(CreateView {
281 name,
282 input,
283 or_replace,
284 definition,
285 temporary,
286 }) => input.map_elements(f)?.update_data(|input| {
287 DdlStatement::CreateView(CreateView {
288 name,
289 input,
290 or_replace,
291 definition,
292 temporary,
293 })
294 }),
295 DdlStatement::CreateExternalTable(_)
297 | DdlStatement::CreateCatalogSchema(_)
298 | DdlStatement::CreateCatalog(_)
299 | DdlStatement::CreateIndex(_)
300 | DdlStatement::DropTable(_)
301 | DdlStatement::DropView(_)
302 | DdlStatement::DropCatalogSchema(_)
303 | DdlStatement::CreateFunction(_)
304 | DdlStatement::DropFunction(_) => Transformed::no(ddl),
305 }
306 .update_data(LogicalPlan::Ddl)
307 }
308 LogicalPlan::Unnest(Unnest {
309 input,
310 exec_columns: input_columns,
311 list_type_columns,
312 struct_type_columns,
313 dependency_indices,
314 schema,
315 options,
316 }) => input.map_elements(f)?.update_data(|input| {
317 LogicalPlan::Unnest(Unnest {
318 input,
319 exec_columns: input_columns,
320 list_type_columns,
321 struct_type_columns,
322 dependency_indices,
323 schema,
324 options,
325 })
326 }),
327 LogicalPlan::RecursiveQuery(RecursiveQuery {
328 name,
329 static_term,
330 recursive_term,
331 is_distinct,
332 schema,
333 }) => (static_term, recursive_term).map_elements(f)?.update_data(
334 |(static_term, recursive_term)| {
335 LogicalPlan::RecursiveQuery(RecursiveQuery {
339 name,
340 static_term,
341 recursive_term,
342 is_distinct,
343 schema,
344 })
345 },
346 ),
347 LogicalPlan::Statement(stmt) => match stmt {
348 Statement::Prepare(p) => p
349 .input
350 .map_elements(f)?
351 .update_data(|input| Statement::Prepare(Prepare { input, ..p })),
352 _ => Transformed::no(stmt),
353 }
354 .update_data(LogicalPlan::Statement),
355 LogicalPlan::TableScan { .. }
357 | LogicalPlan::EmptyRelation { .. }
358 | LogicalPlan::Values { .. }
359 | LogicalPlan::DescribeTable(_) => Transformed::no(self),
360 })
361 }
362}
363
364fn rewrite_extension_inputs<F: FnMut(LogicalPlan) -> Result<Transformed<LogicalPlan>>>(
370 extension: Extension,
371 f: F,
372) -> Result<Transformed<Extension>> {
373 let Extension { node } = extension;
374
375 node.inputs()
376 .into_iter()
377 .cloned()
378 .map_until_stop_and_collect(f)?
379 .map_data(|new_inputs| {
380 let exprs = node.expressions();
381 Ok(Extension {
382 node: node.with_exprs_and_inputs(exprs, new_inputs)?,
383 })
384 })
385}
386
387macro_rules! handle_transform_recursion {
390 ($F_DOWN:expr, $F_CHILD:expr, $F_UP:expr) => {{
391 $F_DOWN?
392 .transform_children(|n| {
393 n.map_subqueries($F_CHILD)?
394 .transform_sibling(|n| n.map_children($F_CHILD))
395 })?
396 .transform_parent($F_UP)
397 }};
398}
399
400impl LogicalPlan {
401 pub fn apply_expressions<F: FnMut(&Expr) -> Result<TreeNodeRecursion>>(
408 &self,
409 mut f: F,
410 ) -> Result<TreeNodeRecursion> {
411 match self {
412 LogicalPlan::Projection(Projection { expr, .. }) => expr.apply_elements(f),
413 LogicalPlan::Values(Values { values, .. }) => values.apply_elements(f),
414 LogicalPlan::Filter(Filter { predicate, .. }) => f(predicate),
415 LogicalPlan::Repartition(Repartition {
416 partitioning_scheme,
417 ..
418 }) => match partitioning_scheme {
419 Partitioning::Hash(expr, _) | Partitioning::DistributeBy(expr) => {
420 expr.apply_elements(f)
421 }
422 Partitioning::RoundRobinBatch(_) => Ok(TreeNodeRecursion::Continue),
423 },
424 LogicalPlan::Window(Window { window_expr, .. }) => {
425 window_expr.apply_elements(f)
426 }
427 LogicalPlan::Aggregate(Aggregate {
428 group_expr,
429 aggr_expr,
430 ..
431 }) => (group_expr, aggr_expr).apply_ref_elements(f),
432 LogicalPlan::Join(Join { on, filter, .. }) => {
436 (on, filter).apply_ref_elements(f)
437 }
438 LogicalPlan::Sort(Sort { expr, .. }) => expr.apply_elements(f),
439 LogicalPlan::Extension(extension) => {
440 extension.node.expressions().apply_elements(f)
443 }
444 LogicalPlan::TableScan(TableScan { filters, .. }) => {
445 filters.apply_elements(f)
446 }
447 LogicalPlan::Unnest(unnest) => {
448 let exprs = unnest
449 .exec_columns
450 .iter()
451 .cloned()
452 .map(Expr::Column)
453 .collect::<Vec<_>>();
454 exprs.apply_elements(f)
455 }
456 LogicalPlan::Distinct(Distinct::On(DistinctOn {
457 on_expr,
458 select_expr,
459 sort_expr,
460 ..
461 })) => (on_expr, select_expr, sort_expr).apply_ref_elements(f),
462 LogicalPlan::Limit(Limit { skip, fetch, .. }) => {
463 (skip, fetch).apply_ref_elements(f)
464 }
465 LogicalPlan::Statement(stmt) => match stmt {
466 Statement::Execute(Execute { parameters, .. }) => {
467 parameters.apply_elements(f)
468 }
469 _ => Ok(TreeNodeRecursion::Continue),
470 },
471 LogicalPlan::EmptyRelation(_)
473 | LogicalPlan::RecursiveQuery(_)
474 | LogicalPlan::Subquery(_)
475 | LogicalPlan::SubqueryAlias(_)
476 | LogicalPlan::Analyze(_)
477 | LogicalPlan::Explain(_)
478 | LogicalPlan::Union(_)
479 | LogicalPlan::Distinct(Distinct::All(_))
480 | LogicalPlan::Dml(_)
481 | LogicalPlan::Ddl(_)
482 | LogicalPlan::Copy(_)
483 | LogicalPlan::DescribeTable(_) => Ok(TreeNodeRecursion::Continue),
484 }
485 }
486
487 pub fn map_expressions<F: FnMut(Expr) -> Result<Transformed<Expr>>>(
495 self,
496 mut f: F,
497 ) -> Result<Transformed<Self>> {
498 Ok(match self {
499 LogicalPlan::Projection(Projection {
500 expr,
501 input,
502 schema,
503 }) => expr.map_elements(f)?.update_data(|expr| {
504 LogicalPlan::Projection(Projection {
505 expr,
506 input,
507 schema,
508 })
509 }),
510 LogicalPlan::Values(Values { schema, values }) => values
511 .map_elements(f)?
512 .update_data(|values| LogicalPlan::Values(Values { schema, values })),
513 LogicalPlan::Filter(Filter { predicate, input }) => f(predicate)?
514 .update_data(|predicate| {
515 LogicalPlan::Filter(Filter { predicate, input })
516 }),
517 LogicalPlan::Repartition(Repartition {
518 input,
519 partitioning_scheme,
520 }) => match partitioning_scheme {
521 Partitioning::Hash(expr, usize) => expr
522 .map_elements(f)?
523 .update_data(|expr| Partitioning::Hash(expr, usize)),
524 Partitioning::DistributeBy(expr) => expr
525 .map_elements(f)?
526 .update_data(Partitioning::DistributeBy),
527 Partitioning::RoundRobinBatch(_) => Transformed::no(partitioning_scheme),
528 }
529 .update_data(|partitioning_scheme| {
530 LogicalPlan::Repartition(Repartition {
531 input,
532 partitioning_scheme,
533 })
534 }),
535 LogicalPlan::Window(Window {
536 input,
537 window_expr,
538 schema,
539 }) => window_expr.map_elements(f)?.update_data(|window_expr| {
540 LogicalPlan::Window(Window {
541 input,
542 window_expr,
543 schema,
544 })
545 }),
546 LogicalPlan::Aggregate(Aggregate {
547 input,
548 group_expr,
549 aggr_expr,
550 schema,
551 }) => (group_expr, aggr_expr).map_elements(f)?.update_data(
552 |(group_expr, aggr_expr)| {
553 LogicalPlan::Aggregate(Aggregate {
554 input,
555 group_expr,
556 aggr_expr,
557 schema,
558 })
559 },
560 ),
561
562 LogicalPlan::Join(Join {
566 left,
567 right,
568 on,
569 filter,
570 join_type,
571 join_constraint,
572 schema,
573 null_equality,
574 null_aware,
575 }) => (on, filter).map_elements(f)?.update_data(|(on, filter)| {
576 LogicalPlan::Join(Join {
577 left,
578 right,
579 on,
580 filter,
581 join_type,
582 join_constraint,
583 schema,
584 null_equality,
585 null_aware,
586 })
587 }),
588 LogicalPlan::Sort(Sort { expr, input, fetch }) => expr
589 .map_elements(f)?
590 .update_data(|expr| LogicalPlan::Sort(Sort { expr, input, fetch })),
591 LogicalPlan::Extension(Extension { node }) => {
592 let raw_exprs = node.expressions();
593 if raw_exprs.is_empty() {
594 Transformed::no(LogicalPlan::Extension(Extension { node }))
597 } else {
598 let exprs = raw_exprs.map_elements(f)?;
606 let plan = LogicalPlan::Extension(Extension {
607 node: UserDefinedLogicalNode::with_exprs_and_inputs(
608 node.as_ref(),
609 exprs.data,
610 node.inputs().into_iter().cloned().collect::<Vec<_>>(),
611 )?,
612 });
613 Transformed::new(plan, exprs.transformed, exprs.tnr)
614 }
615 }
616 LogicalPlan::TableScan(TableScan {
617 table_name,
618 source,
619 projection,
620 projected_schema,
621 filters,
622 fetch,
623 }) => filters.map_elements(f)?.update_data(|filters| {
624 LogicalPlan::TableScan(TableScan {
625 table_name,
626 source,
627 projection,
628 projected_schema,
629 filters,
630 fetch,
631 })
632 }),
633 LogicalPlan::Distinct(Distinct::On(DistinctOn {
634 on_expr,
635 select_expr,
636 sort_expr,
637 input,
638 schema,
639 })) => (on_expr, select_expr, sort_expr)
640 .map_elements(f)?
641 .update_data(|(on_expr, select_expr, sort_expr)| {
642 LogicalPlan::Distinct(Distinct::On(DistinctOn {
643 on_expr,
644 select_expr,
645 sort_expr,
646 input,
647 schema,
648 }))
649 }),
650 LogicalPlan::Limit(Limit { skip, fetch, input }) => {
651 (skip, fetch).map_elements(f)?.update_data(|(skip, fetch)| {
652 LogicalPlan::Limit(Limit { skip, fetch, input })
653 })
654 }
655 LogicalPlan::Statement(stmt) => match stmt {
656 Statement::Execute(e) => {
657 e.parameters.map_elements(f)?.update_data(|parameters| {
658 Statement::Execute(Execute { parameters, ..e })
659 })
660 }
661 _ => Transformed::no(stmt),
662 }
663 .update_data(LogicalPlan::Statement),
664 LogicalPlan::EmptyRelation(_)
666 | LogicalPlan::Unnest(_)
667 | LogicalPlan::RecursiveQuery(_)
668 | LogicalPlan::Subquery(_)
669 | LogicalPlan::SubqueryAlias(_)
670 | LogicalPlan::Analyze(_)
671 | LogicalPlan::Explain(_)
672 | LogicalPlan::Union(_)
673 | LogicalPlan::Distinct(Distinct::All(_))
674 | LogicalPlan::Dml(_)
675 | LogicalPlan::Ddl(_)
676 | LogicalPlan::Copy(_)
677 | LogicalPlan::DescribeTable(_) => Transformed::no(self),
678 })
679 }
680
681 #[cfg_attr(feature = "recursive_protection", recursive::recursive)]
684 pub fn visit_with_subqueries<V: for<'n> TreeNodeVisitor<'n, Node = Self>>(
685 &self,
686 visitor: &mut V,
687 ) -> Result<TreeNodeRecursion> {
688 visitor
689 .f_down(self)?
690 .visit_children(|| {
691 self.apply_subqueries(|c| c.visit_with_subqueries(visitor))?
692 .visit_sibling(|| {
693 self.apply_children(|c| c.visit_with_subqueries(visitor))
694 })
695 })?
696 .visit_parent(|| visitor.f_up(self))
697 }
698
699 #[cfg_attr(feature = "recursive_protection", recursive::recursive)]
703 pub fn rewrite_with_subqueries<R: TreeNodeRewriter<Node = Self>>(
704 self,
705 rewriter: &mut R,
706 ) -> Result<Transformed<Self>> {
707 handle_transform_recursion!(
708 rewriter.f_down(self),
709 |c| c.rewrite_with_subqueries(rewriter),
710 |n| rewriter.f_up(n)
711 )
712 }
713
714 pub fn apply_with_subqueries<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
718 &self,
719 mut f: F,
720 ) -> Result<TreeNodeRecursion> {
721 #[cfg_attr(feature = "recursive_protection", recursive::recursive)]
722 fn apply_with_subqueries_impl<
723 F: FnMut(&LogicalPlan) -> Result<TreeNodeRecursion>,
724 >(
725 node: &LogicalPlan,
726 f: &mut F,
727 ) -> Result<TreeNodeRecursion> {
728 f(node)?.visit_children(|| {
729 node.apply_subqueries(|c| apply_with_subqueries_impl(c, f))?
730 .visit_sibling(|| {
731 node.apply_children(|c| apply_with_subqueries_impl(c, f))
732 })
733 })
734 }
735
736 apply_with_subqueries_impl(self, &mut f)
737 }
738
739 pub fn transform_with_subqueries<F: FnMut(Self) -> Result<Transformed<Self>>>(
743 self,
744 f: F,
745 ) -> Result<Transformed<Self>> {
746 self.transform_up_with_subqueries(f)
747 }
748
749 pub fn transform_down_with_subqueries<F: FnMut(Self) -> Result<Transformed<Self>>>(
753 self,
754 mut f: F,
755 ) -> Result<Transformed<Self>> {
756 #[cfg_attr(feature = "recursive_protection", recursive::recursive)]
757 fn transform_down_with_subqueries_impl<
758 F: FnMut(LogicalPlan) -> Result<Transformed<LogicalPlan>>,
759 >(
760 node: LogicalPlan,
761 f: &mut F,
762 ) -> Result<Transformed<LogicalPlan>> {
763 f(node)?.transform_children(|n| {
764 n.map_subqueries(|c| transform_down_with_subqueries_impl(c, f))?
765 .transform_sibling(|n| {
766 n.map_children(|c| transform_down_with_subqueries_impl(c, f))
767 })
768 })
769 }
770
771 transform_down_with_subqueries_impl(self, &mut f)
772 }
773
774 pub fn transform_up_with_subqueries<F: FnMut(Self) -> Result<Transformed<Self>>>(
778 self,
779 mut f: F,
780 ) -> Result<Transformed<Self>> {
781 #[cfg_attr(feature = "recursive_protection", recursive::recursive)]
782 fn transform_up_with_subqueries_impl<
783 F: FnMut(LogicalPlan) -> Result<Transformed<LogicalPlan>>,
784 >(
785 node: LogicalPlan,
786 f: &mut F,
787 ) -> Result<Transformed<LogicalPlan>> {
788 node.map_subqueries(|c| transform_up_with_subqueries_impl(c, f))?
789 .transform_sibling(|n| {
790 n.map_children(|c| transform_up_with_subqueries_impl(c, f))
791 })?
792 .transform_parent(f)
793 }
794
795 transform_up_with_subqueries_impl(self, &mut f)
796 }
797
798 pub fn transform_down_up_with_subqueries<
802 FD: FnMut(Self) -> Result<Transformed<Self>>,
803 FU: FnMut(Self) -> Result<Transformed<Self>>,
804 >(
805 self,
806 mut f_down: FD,
807 mut f_up: FU,
808 ) -> Result<Transformed<Self>> {
809 #[cfg_attr(feature = "recursive_protection", recursive::recursive)]
810 fn transform_down_up_with_subqueries_impl<
811 FD: FnMut(LogicalPlan) -> Result<Transformed<LogicalPlan>>,
812 FU: FnMut(LogicalPlan) -> Result<Transformed<LogicalPlan>>,
813 >(
814 node: LogicalPlan,
815 f_down: &mut FD,
816 f_up: &mut FU,
817 ) -> Result<Transformed<LogicalPlan>> {
818 handle_transform_recursion!(
819 f_down(node),
820 |c| transform_down_up_with_subqueries_impl(c, f_down, f_up),
821 f_up
822 )
823 }
824
825 transform_down_up_with_subqueries_impl(self, &mut f_down, &mut f_up)
826 }
827
828 pub fn apply_subqueries<F: FnMut(&Self) -> Result<TreeNodeRecursion>>(
832 &self,
833 mut f: F,
834 ) -> Result<TreeNodeRecursion> {
835 self.apply_expressions(|expr| {
836 expr.apply(|expr| match expr {
837 Expr::Exists(Exists { subquery, .. })
838 | Expr::InSubquery(InSubquery { subquery, .. })
839 | Expr::SetComparison(SetComparison { subquery, .. })
840 | Expr::ScalarSubquery(subquery) => {
841 f(&LogicalPlan::Subquery(subquery.clone()))
843 }
844 _ => Ok(TreeNodeRecursion::Continue),
845 })
846 })
847 }
848
849 pub fn map_subqueries<F: FnMut(Self) -> Result<Transformed<Self>>>(
854 self,
855 mut f: F,
856 ) -> Result<Transformed<Self>> {
857 self.map_expressions(|expr| {
858 expr.transform_down(|expr| match expr {
859 Expr::Exists(Exists { subquery, negated }) => {
860 f(LogicalPlan::Subquery(subquery))?.map_data(|s| match s {
861 LogicalPlan::Subquery(subquery) => {
862 Ok(Expr::Exists(Exists { subquery, negated }))
863 }
864 _ => internal_err!("Transformation should return Subquery"),
865 })
866 }
867 Expr::InSubquery(InSubquery {
868 expr,
869 subquery,
870 negated,
871 }) => f(LogicalPlan::Subquery(subquery))?.map_data(|s| match s {
872 LogicalPlan::Subquery(subquery) => Ok(Expr::InSubquery(InSubquery {
873 expr,
874 subquery,
875 negated,
876 })),
877 _ => internal_err!("Transformation should return Subquery"),
878 }),
879 Expr::SetComparison(SetComparison {
880 expr,
881 subquery,
882 op,
883 quantifier,
884 }) => f(LogicalPlan::Subquery(subquery))?.map_data(|s| match s {
885 LogicalPlan::Subquery(subquery) => {
886 Ok(Expr::SetComparison(SetComparison {
887 expr,
888 subquery,
889 op,
890 quantifier,
891 }))
892 }
893 _ => internal_err!("Transformation should return Subquery"),
894 }),
895 Expr::ScalarSubquery(subquery) => f(LogicalPlan::Subquery(subquery))?
896 .map_data(|s| match s {
897 LogicalPlan::Subquery(subquery) => {
898 Ok(Expr::ScalarSubquery(subquery))
899 }
900 _ => internal_err!("Transformation should return Subquery"),
901 }),
902 _ => Ok(Transformed::no(expr)),
903 })
904 })
905 }
906
907 pub fn map_uncorrelated_subqueries<F: FnMut(Self) -> Result<Transformed<Self>>>(
910 self,
911 mut f: F,
912 ) -> Result<Transformed<Self>> {
913 self.map_subqueries(|subquery_plan| match &subquery_plan {
914 LogicalPlan::Subquery(sq) if sq.outer_ref_columns.is_empty() => {
915 f(subquery_plan)
916 }
917 _ => Ok(Transformed::no(subquery_plan)),
918 })
919 }
920}