1#include "duckdb/planner/operator/logical_aggregate.hpp"
2
3#include "duckdb/common/field_writer.hpp"
4#include "duckdb/common/string_util.hpp"
5#include "duckdb/main/config.hpp"
6
7namespace duckdb {
8
9LogicalAggregate::LogicalAggregate(idx_t group_index, idx_t aggregate_index, vector<unique_ptr<Expression>> select_list)
10 : LogicalOperator(LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY, std::move(select_list)),
11 group_index(group_index), aggregate_index(aggregate_index), groupings_index(DConstants::INVALID_INDEX) {
12}
13
14void LogicalAggregate::ResolveTypes() {
15 D_ASSERT(groupings_index != DConstants::INVALID_INDEX || grouping_functions.empty());
16 for (auto &expr : groups) {
17 types.push_back(x: expr->return_type);
18 }
19 // get the chunk types from the projection list
20 for (auto &expr : expressions) {
21 types.push_back(x: expr->return_type);
22 }
23 for (idx_t i = 0; i < grouping_functions.size(); i++) {
24 types.emplace_back(args: LogicalType::BIGINT);
25 }
26}
27
28vector<ColumnBinding> LogicalAggregate::GetColumnBindings() {
29 D_ASSERT(groupings_index != DConstants::INVALID_INDEX || grouping_functions.empty());
30 vector<ColumnBinding> result;
31 result.reserve(n: groups.size() + expressions.size() + grouping_functions.size());
32 for (idx_t i = 0; i < groups.size(); i++) {
33 result.emplace_back(args&: group_index, args&: i);
34 }
35 for (idx_t i = 0; i < expressions.size(); i++) {
36 result.emplace_back(args&: aggregate_index, args&: i);
37 }
38 for (idx_t i = 0; i < grouping_functions.size(); i++) {
39 result.emplace_back(args&: groupings_index, args&: i);
40 }
41 return result;
42}
43
44string LogicalAggregate::ParamsToString() const {
45 string result;
46 for (idx_t i = 0; i < groups.size(); i++) {
47 if (i > 0) {
48 result += "\n";
49 }
50 result += groups[i]->GetName();
51 }
52 for (idx_t i = 0; i < expressions.size(); i++) {
53 if (i > 0 || !groups.empty()) {
54 result += "\n";
55 }
56 result += expressions[i]->GetName();
57 }
58 return result;
59}
60
61void LogicalAggregate::Serialize(FieldWriter &writer) const {
62 writer.WriteSerializableList(elements: expressions);
63
64 writer.WriteField(element: group_index);
65 writer.WriteField(element: aggregate_index);
66 writer.WriteField(element: groupings_index);
67 writer.WriteSerializableList(elements: groups);
68 writer.WriteField<idx_t>(element: grouping_sets.size());
69 for (auto &entry : grouping_sets) {
70 writer.WriteList<idx_t>(elements: entry);
71 }
72 writer.WriteField<idx_t>(element: grouping_functions.size());
73 for (auto &entry : grouping_functions) {
74 writer.WriteList<idx_t>(elements: entry);
75 }
76
77 // TODO statistics
78}
79
80unique_ptr<LogicalOperator> LogicalAggregate::Deserialize(LogicalDeserializationState &state, FieldReader &reader) {
81 auto expressions = reader.ReadRequiredSerializableList<Expression>(args&: state.gstate);
82
83 auto group_index = reader.ReadRequired<idx_t>();
84 auto aggregate_index = reader.ReadRequired<idx_t>();
85 auto groupings_index = reader.ReadRequired<idx_t>();
86 auto groups = reader.ReadRequiredSerializableList<Expression>(args&: state.gstate);
87 auto grouping_sets_size = reader.ReadRequired<idx_t>();
88 vector<GroupingSet> grouping_sets;
89 for (idx_t i = 0; i < grouping_sets_size; i++) {
90 grouping_sets.push_back(x: reader.ReadRequiredSet<idx_t>());
91 }
92 vector<unsafe_vector<idx_t>> grouping_functions;
93 auto grouping_functions_size = reader.ReadRequired<idx_t>();
94 for (idx_t i = 0; i < grouping_functions_size; i++) {
95 grouping_functions.push_back(x: reader.ReadRequiredList<idx_t>());
96 }
97 auto result = make_uniq<LogicalAggregate>(args&: group_index, args&: aggregate_index, args: std::move(expressions));
98 result->groupings_index = groupings_index;
99 result->groups = std::move(groups);
100 result->grouping_functions = std::move(grouping_functions);
101 result->grouping_sets = std::move(grouping_sets);
102
103 return std::move(result);
104}
105
106idx_t LogicalAggregate::EstimateCardinality(ClientContext &context) {
107 if (groups.empty()) {
108 // ungrouped aggregate
109 return 1;
110 }
111 return LogicalOperator::EstimateCardinality(context);
112}
113
114vector<idx_t> LogicalAggregate::GetTableIndex() const {
115 vector<idx_t> result {group_index, aggregate_index};
116 if (groupings_index != DConstants::INVALID_INDEX) {
117 result.push_back(x: groupings_index);
118 }
119 return result;
120}
121
122string LogicalAggregate::GetName() const {
123#ifdef DEBUG
124 if (DBConfigOptions::debug_print_bindings) {
125 return LogicalOperator::GetName() +
126 StringUtil::Format(" #%llu, #%llu, #%llu", group_index, aggregate_index, groupings_index);
127 }
128#endif
129 return LogicalOperator::GetName();
130}
131
132} // namespace duckdb
133