1#include "duckdb/main/relation/aggregate_relation.hpp"
2#include "duckdb/main/client_context.hpp"
3#include "duckdb/parser/query_node/select_node.hpp"
4#include "duckdb/parser/tableref/subqueryref.hpp"
5
6namespace duckdb {
7
8AggregateRelation::AggregateRelation(shared_ptr<Relation> child_p,
9 vector<unique_ptr<ParsedExpression>> parsed_expressions)
10 : Relation(child_p->context, RelationType::AGGREGATE_RELATION), expressions(std::move(parsed_expressions)),
11 child(std::move(child_p)) {
12 // bind the expressions
13 context.GetContext()->TryBindRelation(relation&: *this, result_columns&: this->columns);
14}
15
16AggregateRelation::AggregateRelation(shared_ptr<Relation> child_p,
17 vector<unique_ptr<ParsedExpression>> parsed_expressions,
18 vector<unique_ptr<ParsedExpression>> groups_p)
19 : Relation(child_p->context, RelationType::AGGREGATE_RELATION), expressions(std::move(parsed_expressions)),
20 groups(std::move(groups_p)), child(std::move(child_p)) {
21 // bind the expressions
22 context.GetContext()->TryBindRelation(relation&: *this, result_columns&: this->columns);
23}
24
25unique_ptr<QueryNode> AggregateRelation::GetQueryNode() {
26 auto child_ptr = child.get();
27 while (child_ptr->InheritsColumnBindings()) {
28 child_ptr = child_ptr->ChildRelation();
29 }
30 unique_ptr<QueryNode> result;
31 if (child_ptr->type == RelationType::JOIN_RELATION) {
32 // child node is a join: push projection into the child query node
33 result = child->GetQueryNode();
34 } else {
35 // child node is not a join: create a new select node and push the child as a table reference
36 auto select = make_uniq<SelectNode>();
37 select->from_table = child->GetTableRef();
38 result = std::move(select);
39 }
40 D_ASSERT(result->type == QueryNodeType::SELECT_NODE);
41 auto &select_node = result->Cast<SelectNode>();
42 if (!groups.empty()) {
43 // explicit groups provided: use standard handling
44 select_node.aggregate_handling = AggregateHandling::STANDARD_HANDLING;
45 select_node.groups.group_expressions.clear();
46 GroupingSet grouping_set;
47 for (idx_t i = 0; i < groups.size(); i++) {
48 select_node.groups.group_expressions.push_back(x: groups[i]->Copy());
49 grouping_set.insert(x: i);
50 }
51 select_node.groups.grouping_sets.push_back(x: std::move(grouping_set));
52 } else {
53 // no groups provided: automatically figure out groups (if any)
54 select_node.aggregate_handling = AggregateHandling::FORCE_AGGREGATES;
55 }
56 select_node.select_list.clear();
57 for (auto &expr : expressions) {
58 select_node.select_list.push_back(x: expr->Copy());
59 }
60 return result;
61}
62
63string AggregateRelation::GetAlias() {
64 return child->GetAlias();
65}
66
67const vector<ColumnDefinition> &AggregateRelation::Columns() {
68 return columns;
69}
70
71string AggregateRelation::ToString(idx_t depth) {
72 string str = RenderWhitespace(depth) + "Aggregate [";
73 for (idx_t i = 0; i < expressions.size(); i++) {
74 if (i != 0) {
75 str += ", ";
76 }
77 str += expressions[i]->ToString();
78 }
79 str += "]\n";
80 return str + child->ToString(depth: depth + 1);
81}
82
83} // namespace duckdb
84