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 | ScalarExpr::Collated { expr: inner, .. } => {
121 **inner = rewrite_set_calls(
122 engine,
123 resolver,
124 (**inner).clone(),
125 calls,
126 call_relation,
127 schema,
128 params,
129 )?;
130 }
131 ScalarExpr::Between { expr, low, high } => {
132 **expr = rewrite_set_calls(
133 engine,
134 resolver,
135 (**expr).clone(),
136 calls,
137 call_relation,
138 schema,
139 params,
140 )?;
141 **low = rewrite_set_calls(
142 engine,
143 resolver,
144 (**low).clone(),
145 calls,
146 call_relation,
147 schema,
148 params,
149 )?;
150 **high = rewrite_set_calls(
151 engine,
152 resolver,
153 (**high).clone(),
154 calls,
155 call_relation,
156 schema,
157 params,
158 )?;
159 }
160 ScalarExpr::InList { expr, list, .. } => {
161 **expr = rewrite_set_calls(
162 engine,
163 resolver,
164 (**expr).clone(),
165 calls,
166 call_relation,
167 schema,
168 params,
169 )?;
170 for item in list {
171 *item = rewrite_set_calls(
172 engine,
173 resolver,
174 item.clone(),
175 calls,
176 call_relation,
177 schema,
178 params,
179 )?;
180 }
181 }
182 ScalarExpr::WindowCall {
183 args, spec, filter, ..
184 } => {
185 for argument in args {
186 *argument = rewrite_set_calls(
187 engine,
188 resolver,
189 argument.clone(),
190 calls,
191 call_relation,
192 schema,
193 params,
194 )?;
195 }
196 if let Some(filter) = filter {
197 **filter = rewrite_set_calls(
198 engine,
199 resolver,
200 (**filter).clone(),
201 calls,
202 call_relation,
203 schema,
204 params,
205 )?;
206 }
207 for item in &mut spec.partition_by {
208 *item = rewrite_set_calls(
209 engine,
210 resolver,
211 item.clone(),
212 calls,
213 call_relation,
214 schema,
215 params,
216 )?;
217 }
218 for order in &mut spec.order_by {
219 order.expr = rewrite_set_calls(
220 engine,
221 resolver,
222 order.expr.clone(),
223 calls,
224 call_relation,
225 schema,
226 params,
227 )?;
228 }
229 if let Some(frame) = &mut spec.frame {
230 rewrite_set_frame_bound(
231 engine,
232 resolver,
233 &mut frame.start,
234 calls,
235 call_relation,
236 schema,
237 params,
238 )?;
239 rewrite_set_frame_bound(
240 engine,
241 resolver,
242 &mut frame.end,
243 calls,
244 call_relation,
245 schema,
246 params,
247 )?;
248 }
249 }
250 ScalarExpr::Case {
251 base,
252 when,
253 else_branch,
254 } => {
255 if let Some(base) = base {
256 **base = rewrite_set_calls(
257 engine,
258 resolver,
259 (**base).clone(),
260 calls,
261 call_relation,
262 schema,
263 params,
264 )?;
265 }
266 for (condition, result) in when {
267 *condition = rewrite_set_calls(
268 engine,
269 resolver,
270 condition.clone(),
271 calls,
272 call_relation,
273 schema,
274 params,
275 )?;
276 *result = rewrite_set_calls(
277 engine,
278 resolver,
279 result.clone(),
280 calls,
281 call_relation,
282 schema,
283 params,
284 )?;
285 }
286 if let Some(branch) = else_branch {
287 **branch = rewrite_set_calls(
288 engine,
289 resolver,
290 (**branch).clone(),
291 calls,
292 call_relation,
293 schema,
294 params,
295 )?;
296 }
297 }
298 ScalarExpr::InSubquery { expr, .. } => {
299 **expr = rewrite_set_calls(
300 engine,
301 resolver,
302 (**expr).clone(),
303 calls,
304 call_relation,
305 schema,
306 params,
307 )?;
308 }
309 ScalarExpr::Default
310 | ScalarExpr::Star
311 | ScalarExpr::QualifiedStar(_)
312 | ScalarExpr::Column(_)
313 | ScalarExpr::Position(_)
314 | ScalarExpr::InternalColumn(_)
315 | ScalarExpr::QualifiedColumn { .. }
316 | ScalarExpr::Literal(_)
317 | ScalarExpr::TypedLiteral { .. }
318 | ScalarExpr::Param(_)
319 | ScalarExpr::ScalarSubquery(_)
320 | ScalarExpr::Exists { .. } => {}
321 }
322 if let ScalarExpr::Func {
323 name,
324 binding,
325 args,
326 ..
327 } = &expression
328 {
329 if function_may_return_set(
330 engine,
331 resolver,
332 name,
333 binding.as_ref(),
334 args,
335 schema,
336 params,
337 )? {
338 let binding = resolve_set_function_binding(
339 engine,
340 resolver,
341 name,
342 binding.as_ref(),
343 args,
344 schema,
345 params,
346 )?
347 .or_else(|| binding.clone());
348 let level = calls[descendant_start..]
349 .iter()
350 .map(|call| call.level + 1)
351 .max()
352 .unwrap_or(0);
353 let placeholder = call_relation.column(calls.len());
354 calls.push(SetFunctionCall {
355 placeholder,
356 name: name.clone(),
357 binding,
358 args: args.clone(),
359 level,
360 });
361 return Ok(ScalarExpr::InternalColumn(placeholder));
362 }
363 }
364 Ok(expression)
365}
366
367fn rewrite_set_frame_bound(
368 engine: &dyn SetFunctionCatalog,
369 resolver: &dyn FunctionTypeResolver,
370 bound: &mut ScalarFrameBound,
371 calls: &mut Vec<SetFunctionCall>,
372 call_relation: crate::ast::InternalRelationId,
373 schema: &RowSchema,
374 params: &[SQLParam],
375) -> Result<(), SQLError> {
376 match bound {
377 ScalarFrameBound::Preceding(expression) | ScalarFrameBound::Following(expression) => {
378 **expression = rewrite_set_calls(
379 engine,
380 resolver,
381 (**expression).clone(),
382 calls,
383 call_relation,
384 schema,
385 params,
386 )?;
387 }
388 ScalarFrameBound::UnboundedPreceding
389 | ScalarFrameBound::UnboundedFollowing
390 | ScalarFrameBound::CurrentRow => {}
391 }
392 Ok(())
393}
394
395fn replace_group_set_expression(
396 expression: &mut ScalarExpr,
397 mappings: &[(ScalarExpr, crate::ast::InternalColumnRef)],
398) {
399 if let Some((_, column)) = mappings
400 .iter()
401 .find(|(group, _)| exprs_match(expression, group))
402 {
403 *expression = ScalarExpr::InternalColumn(*column);
404 return;
405 }
406 match expression {
407 ScalarExpr::Func {
408 args,
409 order_by,
410 filter,
411 ..
412 } => {
413 for expression in args
414 .iter_mut()
415 .chain(order_by.iter_mut().map(|order| &mut order.expr))
416 .chain(filter.as_deref_mut())
417 {
418 replace_group_set_expression(expression, mappings);
419 }
420 }
421 ScalarExpr::Array(items)
422 | ScalarExpr::Row(items)
423 | ScalarExpr::CompositeRow { items, .. }
424 | ScalarExpr::And(items)
425 | ScalarExpr::Or(items) => {
426 for item in items {
427 replace_group_set_expression(item, mappings);
428 }
429 }
430 ScalarExpr::Binary { lhs, rhs, .. } => {
431 replace_group_set_expression(lhs, mappings);
432 replace_group_set_expression(rhs, mappings);
433 }
434 ScalarExpr::Not(inner)
435 | ScalarExpr::UnaryMinus(inner)
436 | ScalarExpr::IsNull { expr: inner, .. }
437 | ScalarExpr::Cast { expr: inner, .. }
438 | ScalarExpr::Collated { expr: inner, .. }
439 | ScalarExpr::InSubquery { expr: inner, .. } => {
440 replace_group_set_expression(inner, mappings);
441 }
442 ScalarExpr::Between { expr, low, high } => {
443 replace_group_set_expression(expr, mappings);
444 replace_group_set_expression(low, mappings);
445 replace_group_set_expression(high, mappings);
446 }
447 ScalarExpr::InList { expr, list, .. } => {
448 replace_group_set_expression(expr, mappings);
449 for item in list {
450 replace_group_set_expression(item, mappings);
451 }
452 }
453 ScalarExpr::WindowCall {
454 args, spec, filter, ..
455 } => {
456 for expression in args
457 .iter_mut()
458 .chain(filter.as_deref_mut())
459 .chain(&mut spec.partition_by)
460 .chain(spec.order_by.iter_mut().map(|order| &mut order.expr))
461 {
462 replace_group_set_expression(expression, mappings);
463 }
464 if let Some(frame) = &mut spec.frame {
465 replace_group_set_frame_bound(&mut frame.start, mappings);
466 replace_group_set_frame_bound(&mut frame.end, mappings);
467 }
468 }
469 ScalarExpr::Case {
470 base,
471 when,
472 else_branch,
473 } => {
474 if let Some(base) = base {
475 replace_group_set_expression(base, mappings);
476 }
477 for (condition, result) in when {
478 replace_group_set_expression(condition, mappings);
479 replace_group_set_expression(result, mappings);
480 }
481 if let Some(branch) = else_branch {
482 replace_group_set_expression(branch, mappings);
483 }
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::Collated {
830 expr,
831 ty,
832 collation,
833 } => ScalarExpr::Collated {
834 expr: Box::new(rewrite_aggregate_dependencies(
835 engine,
836 group_by,
837 expr,
838 dependencies,
839 )),
840 ty: ty.clone(),
841 collation: *collation,
842 },
843 ScalarExpr::Cast { expr, ty, implicit } => ScalarExpr::Cast {
844 implicit: *implicit,
845 expr: Box::new(rewrite_aggregate_dependencies(
846 engine,
847 group_by,
848 expr,
849 dependencies,
850 )),
851 ty: ty.clone(),
852 },
853 ScalarExpr::InSubquery {
854 expr,
855 subquery,
856 negated,
857 } => ScalarExpr::InSubquery {
858 expr: Box::new(rewrite_aggregate_dependencies(
859 engine,
860 group_by,
861 expr,
862 dependencies,
863 )),
864 subquery: *subquery,
865 negated: *negated,
866 },
867 ScalarExpr::Default
868 | ScalarExpr::Star
869 | ScalarExpr::QualifiedStar(_)
870 | ScalarExpr::Literal(_)
871 | ScalarExpr::TypedLiteral { .. }
872 | ScalarExpr::Param(_)
873 | ScalarExpr::ScalarSubquery(_)
874 | ScalarExpr::Exists { .. } => expression.clone(),
875 }
876}
877
878fn rewrite_aggregate_frame_bound(
879 engine: &dyn SetFunctionCatalog,
880 group_by: &[&ScalarExpr],
881 bound: &mut ScalarFrameBound,
882 dependencies: &mut Vec<ProjectionPlan>,
883) {
884 match bound {
885 ScalarFrameBound::Preceding(expression) | ScalarFrameBound::Following(expression) => {
886 **expression =
887 rewrite_aggregate_dependencies(engine, group_by, expression, dependencies);
888 }
889 ScalarFrameBound::UnboundedPreceding
890 | ScalarFrameBound::UnboundedFollowing
891 | ScalarFrameBound::CurrentRow => {}
892 }
893}
894
895pub fn prepare_aggregate_output_projection(
896 engine: &dyn SetFunctionCatalog,
897 statement: &QueryBlockPlan,
898 internal_targets: &[(usize, crate::ast::InternalColumnRef)],
899) -> AggregateOutputProjectionPlan {
900 let labels = projection_columns(&statement.projections);
901 let group_by = statement
903 .group_by
904 .iter()
905 .chain(statement.grouping_sets.iter().flatten())
906 .collect::<Vec<_>>();
907 let mut dependencies = Vec::new();
908 let projections = statement
909 .projections
910 .iter()
911 .enumerate()
912 .zip(labels)
913 .map(|((position, projection), label)| {
914 let target = internal_targets
915 .iter()
916 .find(|(target_position, _)| *target_position == position)
917 .map_or_else(
918 || ProjectionTarget::Column(label),
919 |(_, column)| ProjectionTarget::Internal(*column),
920 );
921 (
922 target,
923 rewrite_aggregate_dependencies(
924 engine,
925 &group_by,
926 &projection.expr,
927 &mut dependencies,
928 ),
929 )
930 })
931 .collect();
932 if dependencies.is_empty() {
933 dependencies.push(ProjectionPlan {
934 expr: ScalarExpr::Literal(Value::Int(1)),
935 alias: None,
936 });
937 }
938 let mut aggregate_statement = statement.clone();
939 aggregate_statement.projections = dependencies;
940 AggregateOutputProjectionPlan {
941 statement: aggregate_statement,
942 projections,
943 }
944}