Apply aggregation to the plan
(
mut self,
group_by: Vec<Expression>,
project_expressions: Vec<ProjectExpression>,
)
| 569 | |
| 570 | /// Apply aggregation to the plan |
| 571 | pub fn apply_aggregation( |
| 572 | mut self, |
| 573 | group_by: Vec<Expression>, |
| 574 | project_expressions: Vec<ProjectExpression>, |
| 575 | ) -> Self { |
| 576 | // Convert project expressions to aggregate expressions, preserving order |
| 577 | let mut aggregates = Vec::new(); |
| 578 | for expr in &project_expressions { |
| 579 | if let Expression::FunctionCall(func_call) = &expr.expression { |
| 580 | // Map function names to aggregate functions |
| 581 | let aggregate_function = match func_call.name.to_uppercase().as_str() { |
| 582 | "COUNT" => AggregateFunction::Count, |
| 583 | "SUM" => AggregateFunction::Sum, |
| 584 | "AVG" | "AVERAGE" => AggregateFunction::Avg, |
| 585 | "MIN" => AggregateFunction::Min, |
| 586 | "MAX" => AggregateFunction::Max, |
| 587 | "COLLECT" => AggregateFunction::Collect, |
| 588 | _ => continue, // Skip non-aggregate functions |
| 589 | }; |
| 590 | |
| 591 | // Get the argument expression (if any) |
| 592 | let arg_expr = if func_call.arguments.is_empty() { |
| 593 | Expression::Literal(crate::ast::Literal::Integer(1)) // COUNT(*) case |
| 594 | } else { |
| 595 | func_call.arguments[0].clone() |
| 596 | }; |
| 597 | |
| 598 | aggregates.push(AggregateExpression { |
| 599 | function: aggregate_function, |
| 600 | expression: arg_expr, |
| 601 | alias: expr.alias.clone(), |
| 602 | }); |
| 603 | } |
| 604 | // For non-aggregate expressions in group context, they should be in GROUP BY |
| 605 | } |
| 606 | |
| 607 | // Create aggregate node |
| 608 | self.root = LogicalNode::Aggregate { |
| 609 | group_by, |
| 610 | aggregates, |
| 611 | input: Box::new(self.root), |
| 612 | }; |
| 613 | |
| 614 | self |
| 615 | } |
| 616 | |
| 617 | /// Apply DISTINCT to remove duplicates |
| 618 | pub fn apply_distinct(mut self) -> Self { |
no test coverage detected