1use crate::plan::{ProjectionPlan, QueryBlockPlan};
10use crate::{FunctionTypeResolver, RowSchema, ScalarExpr, ScalarFrameBound};
11use crate::{SQLError, SQLParam};
12use uqa_core::Value;
13
14use super::validation::{
15 expression_may_return_set, function_may_return_set, resolve_set_function_binding,
16};
17use super::{
18 AggregateOutputProjectionPlan, GroupSetProjectionPlan, ProjectionTarget, SetFunctionCall,
19 SetFunctionCatalog,
20};
21use crate::semantics::aggregates::{exprs_match, is_aggregate};
22use crate::semantics::projection_columns;
23
24#[expect(
25 clippy::too_many_lines,
26 reason = "preserves SELECT schema and row identity"
27)]
28pub fn rewrite_set_calls(
29 engine: &dyn SetFunctionCatalog,
30 resolver: &dyn FunctionTypeResolver,
31 mut expression: ScalarExpr,
32 calls: &mut Vec<SetFunctionCall>,
33 call_relation: crate::ast::InternalRelationId,
34 schema: &RowSchema,
35 params: &[SQLParam],
36) -> Result<ScalarExpr, SQLError> {
37 let descendant_start = calls.len();
38 match &mut expression {
39 ScalarExpr::Func {
40 args,
41 order_by,
42 filter,
43 ..
44 } => {
45 for argument in args {
46 *argument = rewrite_set_calls(
47 engine,
48 resolver,
49 argument.clone(),
50 calls,
51 call_relation,
52 schema,
53 params,
54 )?;
55 }
56 for order in order_by {
57 order.expr = rewrite_set_calls(
58 engine,
59 resolver,
60 order.expr.clone(),
61 calls,
62 call_relation,
63 schema,
64 params,
65 )?;
66 }
67 if let Some(filter) = filter {
68 **filter = rewrite_set_calls(
69 engine,
70 resolver,
71 (**filter).clone(),
72 calls,
73 call_relation,
74 schema,
75 params,
76 )?;
77 }
78 }
79 ScalarExpr::Array(items)
80 | ScalarExpr::Row(items)
81 | ScalarExpr::CompositeRow { items, .. }
82 | ScalarExpr::And(items)
83 | ScalarExpr::Or(items) => {
84 for item in items {
85 *item = rewrite_set_calls(
86 engine,
87 resolver,
88 item.clone(),
89 calls,
90 call_relation,
91 schema,
92 params,
93 )?;
94 }
95 }
96 ScalarExpr::Binary { lhs, rhs, .. } => {
97 **lhs = rewrite_set_calls(
98 engine,
99 resolver,
100 (**lhs).clone(),
101 calls,
102 call_relation,
103 schema,
104 params,
105 )?;
106 **rhs = rewrite_set_calls(
107 engine,
108 resolver,
109 (**rhs).clone(),
110 calls,
111 call_relation,
112 schema,
113 params,
114 )?;
115 }
116 ScalarExpr::Not(inner)
117 | ScalarExpr::UnaryMinus(inner)
118 | ScalarExpr::IsNull { expr: inner, .. }
119 | ScalarExpr::Cast { expr: inner, .. } => {
120 **inner = rewrite_set_calls(
121 engine,
122 resolver,
123 (**inner).clone(),
124 calls,
125 call_relation,
126 schema,
127 params,
128 )?;
129 }
130 ScalarExpr::Between { expr, low, high } => {
131 **expr = rewrite_set_calls(
132 engine,
133 resolver,
134 (**expr).clone(),
135 calls,
136 call_relation,
137 schema,
138 params,
139 )?;
140 **low = rewrite_set_calls(
141 engine,
142 resolver,
143 (**low).clone(),
144 calls,
145 call_relation,
146 schema,
147 params,
148 )?;
149 **high = rewrite_set_calls(
150 engine,
151 resolver,
152 (**high).clone(),
153 calls,
154 call_relation,
155 schema,
156 params,
157 )?;
158 }
159 ScalarExpr::InList { expr, list, .. } => {
160 **expr = rewrite_set_calls(
161 engine,
162 resolver,
163 (**expr).clone(),
164 calls,
165 call_relation,
166 schema,
167 params,
168 )?;
169 for item in list {
170 *item = rewrite_set_calls(
171 engine,
172 resolver,
173 item.clone(),
174 calls,
175 call_relation,
176 schema,
177 params,
178 )?;
179 }
180 }
181 ScalarExpr::WindowCall {
182 args, spec, filter, ..
183 } => {
184 for argument in args {
185 *argument = rewrite_set_calls(
186 engine,
187 resolver,
188 argument.clone(),
189 calls,
190 call_relation,
191 schema,
192 params,
193 )?;
194 }
195 if let Some(filter) = filter {
196 **filter = rewrite_set_calls(
197 engine,
198 resolver,
199 (**filter).clone(),
200 calls,
201 call_relation,
202 schema,
203 params,
204 )?;
205 }
206 for item in &mut spec.partition_by {
207 *item = rewrite_set_calls(
208 engine,
209 resolver,
210 item.clone(),
211 calls,
212 call_relation,
213 schema,
214 params,
215 )?;
216 }
217 for order in &mut spec.order_by {
218 order.expr = rewrite_set_calls(
219 engine,
220 resolver,
221 order.expr.clone(),
222 calls,
223 call_relation,
224 schema,
225 params,
226 )?;
227 }
228 if let Some(frame) = &mut spec.frame {
229 rewrite_set_frame_bound(
230 engine,
231 resolver,
232 &mut frame.start,
233 calls,
234 call_relation,
235 schema,
236 params,
237 )?;
238 rewrite_set_frame_bound(
239 engine,
240 resolver,
241 &mut frame.end,
242 calls,
243 call_relation,
244 schema,
245 params,
246 )?;
247 }
248 }
249 ScalarExpr::Case {
250 base,
251 when,
252 else_branch,
253 } => {
254 if let Some(base) = base {
255 **base = rewrite_set_calls(
256 engine,
257 resolver,
258 (**base).clone(),
259 calls,
260 call_relation,
261 schema,
262 params,
263 )?;
264 }
265 for (condition, result) in when {
266 *condition = rewrite_set_calls(
267 engine,
268 resolver,
269 condition.clone(),
270 calls,
271 call_relation,
272 schema,
273 params,
274 )?;
275 *result = rewrite_set_calls(
276 engine,
277 resolver,
278 result.clone(),
279 calls,
280 call_relation,
281 schema,
282 params,
283 )?;
284 }
285 if let Some(branch) = else_branch {
286 **branch = rewrite_set_calls(
287 engine,
288 resolver,
289 (**branch).clone(),
290 calls,
291 call_relation,
292 schema,
293 params,
294 )?;
295 }
296 }
297 ScalarExpr::InSubquery { expr, .. } => {
298 **expr = rewrite_set_calls(
299 engine,
300 resolver,
301 (**expr).clone(),
302 calls,
303 call_relation,
304 schema,
305 params,
306 )?;
307 }
308 ScalarExpr::Default
309 | ScalarExpr::Star
310 | ScalarExpr::QualifiedStar(_)
311 | ScalarExpr::Column(_)
312 | ScalarExpr::Position(_)
313 | ScalarExpr::InternalColumn(_)
314 | ScalarExpr::QualifiedColumn { .. }
315 | ScalarExpr::Literal(_)
316 | ScalarExpr::TypedLiteral { .. }
317 | ScalarExpr::Param(_)
318 | ScalarExpr::ScalarSubquery(_)
319 | ScalarExpr::Exists { .. } => {}
320 }
321 if let ScalarExpr::Func {
322 name,
323 binding,
324 args,
325 ..
326 } = &expression
327 {
328 if function_may_return_set(
329 engine,
330 resolver,
331 name,
332 binding.as_ref(),
333 args,
334 schema,
335 params,
336 )? {
337 let binding = resolve_set_function_binding(
338 engine,
339 resolver,
340 name,
341 binding.as_ref(),
342 args,
343 schema,
344 params,
345 )?
346 .or_else(|| binding.clone());
347 let level = calls[descendant_start..]
348 .iter()
349 .map(|call| call.level + 1)
350 .max()
351 .unwrap_or(0);
352 let placeholder = call_relation.column(calls.len());
353 calls.push(SetFunctionCall {
354 placeholder,
355 name: name.clone(),
356 binding,
357 args: args.clone(),
358 level,
359 });
360 return Ok(ScalarExpr::InternalColumn(placeholder));
361 }
362 }
363 Ok(expression)
364}
365
366fn rewrite_set_frame_bound(
367 engine: &dyn SetFunctionCatalog,
368 resolver: &dyn FunctionTypeResolver,
369 bound: &mut ScalarFrameBound,
370 calls: &mut Vec<SetFunctionCall>,
371 call_relation: crate::ast::InternalRelationId,
372 schema: &RowSchema,
373 params: &[SQLParam],
374) -> Result<(), SQLError> {
375 match bound {
376 ScalarFrameBound::Preceding(expression) | ScalarFrameBound::Following(expression) => {
377 **expression = rewrite_set_calls(
378 engine,
379 resolver,
380 (**expression).clone(),
381 calls,
382 call_relation,
383 schema,
384 params,
385 )?;
386 }
387 ScalarFrameBound::UnboundedPreceding
388 | ScalarFrameBound::UnboundedFollowing
389 | ScalarFrameBound::CurrentRow => {}
390 }
391 Ok(())
392}
393
394fn replace_group_set_expression(
395 expression: &mut ScalarExpr,
396 mappings: &[(ScalarExpr, crate::ast::InternalColumnRef)],
397) {
398 if let Some((_, column)) = mappings
399 .iter()
400 .find(|(group, _)| exprs_match(expression, group))
401 {
402 *expression = ScalarExpr::InternalColumn(*column);
403 return;
404 }
405 match expression {
406 ScalarExpr::Func {
407 args,
408 order_by,
409 filter,
410 ..
411 } => {
412 for expression in args
413 .iter_mut()
414 .chain(order_by.iter_mut().map(|order| &mut order.expr))
415 .chain(filter.as_deref_mut())
416 {
417 replace_group_set_expression(expression, mappings);
418 }
419 }
420 ScalarExpr::Array(items)
421 | ScalarExpr::Row(items)
422 | ScalarExpr::CompositeRow { items, .. }
423 | ScalarExpr::And(items)
424 | ScalarExpr::Or(items) => {
425 for item in items {
426 replace_group_set_expression(item, mappings);
427 }
428 }
429 ScalarExpr::Binary { lhs, rhs, .. } => {
430 replace_group_set_expression(lhs, mappings);
431 replace_group_set_expression(rhs, mappings);
432 }
433 ScalarExpr::Not(inner)
434 | ScalarExpr::UnaryMinus(inner)
435 | ScalarExpr::IsNull { expr: inner, .. }
436 | ScalarExpr::Cast { expr: inner, .. } => {
437 replace_group_set_expression(inner, mappings);
438 }
439 ScalarExpr::Between { expr, low, high } => {
440 replace_group_set_expression(expr, mappings);
441 replace_group_set_expression(low, mappings);
442 replace_group_set_expression(high, mappings);
443 }
444 ScalarExpr::InList { expr, list, .. } => {
445 replace_group_set_expression(expr, mappings);
446 for item in list {
447 replace_group_set_expression(item, mappings);
448 }
449 }
450 ScalarExpr::WindowCall {
451 args, spec, filter, ..
452 } => {
453 for expression in args
454 .iter_mut()
455 .chain(filter.as_deref_mut())
456 .chain(&mut spec.partition_by)
457 .chain(spec.order_by.iter_mut().map(|order| &mut order.expr))
458 {
459 replace_group_set_expression(expression, mappings);
460 }
461 if let Some(frame) = &mut spec.frame {
462 replace_group_set_frame_bound(&mut frame.start, mappings);
463 replace_group_set_frame_bound(&mut frame.end, mappings);
464 }
465 }
466 ScalarExpr::Case {
467 base,
468 when,
469 else_branch,
470 } => {
471 if let Some(base) = base {
472 replace_group_set_expression(base, mappings);
473 }
474 for (condition, result) in when {
475 replace_group_set_expression(condition, mappings);
476 replace_group_set_expression(result, mappings);
477 }
478 if let Some(branch) = else_branch {
479 replace_group_set_expression(branch, mappings);
480 }
481 }
482 ScalarExpr::InSubquery { expr, .. } => {
483 replace_group_set_expression(expr, mappings);
484 }
485 ScalarExpr::Default
486 | ScalarExpr::Star
487 | ScalarExpr::QualifiedStar(_)
488 | ScalarExpr::Column(_)
489 | ScalarExpr::Position(_)
490 | ScalarExpr::InternalColumn(_)
491 | ScalarExpr::QualifiedColumn { .. }
492 | ScalarExpr::Literal(_)
493 | ScalarExpr::TypedLiteral { .. }
494 | ScalarExpr::Param(_)
495 | ScalarExpr::ScalarSubquery(_)
496 | ScalarExpr::Exists { .. } => {}
497 }
498}
499
500fn replace_group_set_frame_bound(
501 bound: &mut ScalarFrameBound,
502 mappings: &[(ScalarExpr, crate::ast::InternalColumnRef)],
503) {
504 match bound {
505 ScalarFrameBound::Preceding(expression) | ScalarFrameBound::Following(expression) => {
506 replace_group_set_expression(expression, mappings);
507 }
508 ScalarFrameBound::UnboundedPreceding
509 | ScalarFrameBound::UnboundedFollowing
510 | ScalarFrameBound::CurrentRow => {}
511 }
512}
513
514pub fn prepare_group_set_projection(
515 engine: &dyn SetFunctionCatalog,
516 resolver: &dyn FunctionTypeResolver,
517 statement: &QueryBlockPlan,
518 schema: &RowSchema,
519 params: &[SQLParam],
520) -> Result<Option<GroupSetProjectionPlan>, SQLError> {
521 let mut groups = Vec::new();
522 for expression in statement
523 .group_by
524 .iter()
525 .chain(statement.grouping_sets.iter().flatten())
526 {
527 if expression_may_return_set(engine, resolver, expression, schema, params)?
528 && !groups
529 .iter()
530 .any(|existing| exprs_match(existing, expression))
531 {
532 groups.push(expression.clone());
533 }
534 }
535 if groups.is_empty() {
536 return Ok(None);
537 }
538
539 let relation = crate::ast::InternalRelationId::allocate();
540 let mappings = groups
541 .iter()
542 .enumerate()
543 .map(|(index, expression)| (expression.clone(), relation.column(index)))
544 .collect::<Vec<_>>();
545 let projections = mappings
546 .iter()
547 .map(|(expression, column)| (ProjectionTarget::Internal(*column), expression.clone()))
548 .collect();
549 let mut rewritten = statement.clone();
550 let projection_labels = projection_columns(&rewritten.projections);
551 for expression in &mut rewritten.group_by {
552 replace_group_set_expression(expression, &mappings);
553 }
554 for set in &mut rewritten.grouping_sets {
555 for expression in set {
556 replace_group_set_expression(expression, &mappings);
557 }
558 }
559 for (projection, label) in rewritten.projections.iter_mut().zip(projection_labels) {
560 if projection.alias.is_none() {
561 projection.alias = Some(label);
562 }
563 replace_group_set_expression(&mut projection.expr, &mappings);
564 }
565 if let Some(having) = &mut rewritten.having {
566 replace_group_set_expression(having, &mappings);
567 }
568 for order in &mut rewritten.order_by {
569 replace_group_set_expression(&mut order.expr, &mappings);
570 }
571 for expression in &mut rewritten.distinct_on {
572 replace_group_set_expression(expression, &mappings);
573 }
574 Ok(Some(GroupSetProjectionPlan {
575 statement: rewritten,
576 projections,
577 }))
578}
579
580fn capture_aggregate_dependency(
581 expression: &ScalarExpr,
582 dependencies: &mut Vec<ProjectionPlan>,
583) -> ScalarExpr {
584 let position = dependencies.len();
585 dependencies.push(ProjectionPlan {
586 expr: expression.clone(),
587 alias: None,
588 });
589 ScalarExpr::Position(position)
590}
591
592#[expect(
593 clippy::too_many_lines,
594 reason = "preserves SELECT schema and row identity"
595)]
596fn rewrite_aggregate_dependencies(
597 engine: &dyn SetFunctionCatalog,
598 group_by: &[&ScalarExpr],
599 expression: &ScalarExpr,
600 dependencies: &mut Vec<ProjectionPlan>,
601) -> ScalarExpr {
602 if is_aggregate(engine, expression)
603 || group_by.iter().any(|group| exprs_match(expression, group))
604 {
605 return capture_aggregate_dependency(expression, dependencies);
606 }
607 match expression {
608 ScalarExpr::Column(_)
609 | ScalarExpr::Position(_)
610 | ScalarExpr::InternalColumn(_)
611 | ScalarExpr::QualifiedColumn { .. } => {
612 capture_aggregate_dependency(expression, dependencies)
613 }
614 ScalarExpr::Func {
615 order_syntax,
616 name,
617 binding,
618 args,
619 distinct,
620 order_by,
621 filter,
622 } => ScalarExpr::Func {
623 order_syntax: *order_syntax,
624 name: name.clone(),
625 binding: binding.clone(),
626 args: args
627 .iter()
628 .map(|argument| {
629 rewrite_aggregate_dependencies(engine, group_by, argument, dependencies)
630 })
631 .collect(),
632 distinct: *distinct,
633 order_by: order_by
634 .iter()
635 .map(|order| {
636 let mut order = order.clone();
637 order.expr =
638 rewrite_aggregate_dependencies(engine, group_by, &order.expr, dependencies);
639 order
640 })
641 .collect(),
642 filter: filter.as_deref().map(|filter| {
643 Box::new(rewrite_aggregate_dependencies(
644 engine,
645 group_by,
646 filter,
647 dependencies,
648 ))
649 }),
650 },
651 ScalarExpr::Array(items) => ScalarExpr::Array(
652 items
653 .iter()
654 .map(|item| rewrite_aggregate_dependencies(engine, group_by, item, dependencies))
655 .collect(),
656 ),
657 ScalarExpr::Row(items) => ScalarExpr::Row(
658 items
659 .iter()
660 .map(|item| rewrite_aggregate_dependencies(engine, group_by, item, dependencies))
661 .collect(),
662 ),
663 ScalarExpr::CompositeRow {
664 items,
665 binding,
666 bound_type,
667 } => ScalarExpr::CompositeRow {
668 items: items
669 .iter()
670 .map(|item| rewrite_aggregate_dependencies(engine, group_by, item, dependencies))
671 .collect(),
672 binding: binding.clone(),
673 bound_type: bound_type.clone(),
674 },
675 ScalarExpr::Binary { op, lhs, rhs } => ScalarExpr::Binary {
676 op: *op,
677 lhs: Box::new(rewrite_aggregate_dependencies(
678 engine,
679 group_by,
680 lhs,
681 dependencies,
682 )),
683 rhs: Box::new(rewrite_aggregate_dependencies(
684 engine,
685 group_by,
686 rhs,
687 dependencies,
688 )),
689 },
690 ScalarExpr::Not(inner) => ScalarExpr::Not(Box::new(rewrite_aggregate_dependencies(
691 engine,
692 group_by,
693 inner,
694 dependencies,
695 ))),
696 ScalarExpr::UnaryMinus(inner) => ScalarExpr::UnaryMinus(Box::new(
697 rewrite_aggregate_dependencies(engine, group_by, inner, dependencies),
698 )),
699 ScalarExpr::And(items) => ScalarExpr::And(
700 items
701 .iter()
702 .map(|item| rewrite_aggregate_dependencies(engine, group_by, item, dependencies))
703 .collect(),
704 ),
705 ScalarExpr::Or(items) => ScalarExpr::Or(
706 items
707 .iter()
708 .map(|item| rewrite_aggregate_dependencies(engine, group_by, item, dependencies))
709 .collect(),
710 ),
711 ScalarExpr::IsNull { expr, negated } => ScalarExpr::IsNull {
712 expr: Box::new(rewrite_aggregate_dependencies(
713 engine,
714 group_by,
715 expr,
716 dependencies,
717 )),
718 negated: *negated,
719 },
720 ScalarExpr::Between { expr, low, high } => ScalarExpr::Between {
721 expr: Box::new(rewrite_aggregate_dependencies(
722 engine,
723 group_by,
724 expr,
725 dependencies,
726 )),
727 low: Box::new(rewrite_aggregate_dependencies(
728 engine,
729 group_by,
730 low,
731 dependencies,
732 )),
733 high: Box::new(rewrite_aggregate_dependencies(
734 engine,
735 group_by,
736 high,
737 dependencies,
738 )),
739 },
740 ScalarExpr::InList {
741 expr,
742 list,
743 negated,
744 } => ScalarExpr::InList {
745 expr: Box::new(rewrite_aggregate_dependencies(
746 engine,
747 group_by,
748 expr,
749 dependencies,
750 )),
751 list: list
752 .iter()
753 .map(|item| rewrite_aggregate_dependencies(engine, group_by, item, dependencies))
754 .collect(),
755 negated: *negated,
756 },
757 ScalarExpr::WindowCall {
758 name,
759 args,
760 spec,
761 filter,
762 modifiers,
763 } => {
764 let mut spec = spec.clone();
765 spec.partition_by = spec
766 .partition_by
767 .iter()
768 .map(|item| rewrite_aggregate_dependencies(engine, group_by, item, dependencies))
769 .collect();
770 for order in &mut spec.order_by {
771 order.expr =
772 rewrite_aggregate_dependencies(engine, group_by, &order.expr, dependencies);
773 }
774 if let Some(frame) = &mut spec.frame {
775 rewrite_aggregate_frame_bound(engine, group_by, &mut frame.start, dependencies);
776 rewrite_aggregate_frame_bound(engine, group_by, &mut frame.end, dependencies);
777 }
778 ScalarExpr::WindowCall {
779 modifiers: *modifiers,
780 name: name.clone(),
781 args: args
782 .iter()
783 .map(|argument| {
784 rewrite_aggregate_dependencies(engine, group_by, argument, dependencies)
785 })
786 .collect(),
787 spec,
788 filter: filter.as_deref().map(|filter| {
789 Box::new(rewrite_aggregate_dependencies(
790 engine,
791 group_by,
792 filter,
793 dependencies,
794 ))
795 }),
796 }
797 }
798 ScalarExpr::Case {
799 base,
800 when,
801 else_branch,
802 } => ScalarExpr::Case {
803 base: base.as_deref().map(|base| {
804 Box::new(rewrite_aggregate_dependencies(
805 engine,
806 group_by,
807 base,
808 dependencies,
809 ))
810 }),
811 when: when
812 .iter()
813 .map(|(condition, result)| {
814 (
815 rewrite_aggregate_dependencies(engine, group_by, condition, dependencies),
816 rewrite_aggregate_dependencies(engine, group_by, result, dependencies),
817 )
818 })
819 .collect(),
820 else_branch: else_branch.as_deref().map(|branch| {
821 Box::new(rewrite_aggregate_dependencies(
822 engine,
823 group_by,
824 branch,
825 dependencies,
826 ))
827 }),
828 },
829 ScalarExpr::Cast { expr, ty, implicit } => ScalarExpr::Cast {
830 implicit: *implicit,
831 expr: Box::new(rewrite_aggregate_dependencies(
832 engine,
833 group_by,
834 expr,
835 dependencies,
836 )),
837 ty: ty.clone(),
838 },
839 ScalarExpr::InSubquery {
840 expr,
841 subquery,
842 negated,
843 } => ScalarExpr::InSubquery {
844 expr: Box::new(rewrite_aggregate_dependencies(
845 engine,
846 group_by,
847 expr,
848 dependencies,
849 )),
850 subquery: *subquery,
851 negated: *negated,
852 },
853 ScalarExpr::Default
854 | ScalarExpr::Star
855 | ScalarExpr::QualifiedStar(_)
856 | ScalarExpr::Literal(_)
857 | ScalarExpr::TypedLiteral { .. }
858 | ScalarExpr::Param(_)
859 | ScalarExpr::ScalarSubquery(_)
860 | ScalarExpr::Exists { .. } => expression.clone(),
861 }
862}
863
864fn rewrite_aggregate_frame_bound(
865 engine: &dyn SetFunctionCatalog,
866 group_by: &[&ScalarExpr],
867 bound: &mut ScalarFrameBound,
868 dependencies: &mut Vec<ProjectionPlan>,
869) {
870 match bound {
871 ScalarFrameBound::Preceding(expression) | ScalarFrameBound::Following(expression) => {
872 **expression =
873 rewrite_aggregate_dependencies(engine, group_by, expression, dependencies);
874 }
875 ScalarFrameBound::UnboundedPreceding
876 | ScalarFrameBound::UnboundedFollowing
877 | ScalarFrameBound::CurrentRow => {}
878 }
879}
880
881pub fn prepare_aggregate_output_projection(
882 engine: &dyn SetFunctionCatalog,
883 statement: &QueryBlockPlan,
884 internal_targets: &[(usize, crate::ast::InternalColumnRef)],
885) -> AggregateOutputProjectionPlan {
886 let labels = projection_columns(&statement.projections);
887 let group_by = statement
889 .group_by
890 .iter()
891 .chain(statement.grouping_sets.iter().flatten())
892 .collect::<Vec<_>>();
893 let mut dependencies = Vec::new();
894 let projections = statement
895 .projections
896 .iter()
897 .enumerate()
898 .zip(labels)
899 .map(|((position, projection), label)| {
900 let target = internal_targets
901 .iter()
902 .find(|(target_position, _)| *target_position == position)
903 .map_or_else(
904 || ProjectionTarget::Column(label),
905 |(_, column)| ProjectionTarget::Internal(*column),
906 );
907 (
908 target,
909 rewrite_aggregate_dependencies(
910 engine,
911 &group_by,
912 &projection.expr,
913 &mut dependencies,
914 ),
915 )
916 })
917 .collect();
918 if dependencies.is_empty() {
919 dependencies.push(ProjectionPlan {
920 expr: ScalarExpr::Literal(Value::Int(1)),
921 alias: None,
922 });
923 }
924 let mut aggregate_statement = statement.clone();
925 aggregate_statement.projections = dependencies;
926 AggregateOutputProjectionPlan {
927 statement: aggregate_statement,
928 projections,
929 }
930}