1 | #include "duckdb/parser/query_node/select_node.hpp" |
2 | #include "duckdb/parser/expression_util.hpp" |
3 | #include "duckdb/common/field_writer.hpp" |
4 | #include "duckdb/parser/keyword_helper.hpp" |
5 | #include "duckdb/common/serializer/format_serializer.hpp" |
6 | #include "duckdb/common/serializer/format_deserializer.hpp" |
7 | |
8 | namespace duckdb { |
9 | |
10 | SelectNode::SelectNode() |
11 | : QueryNode(QueryNodeType::SELECT_NODE), aggregate_handling(AggregateHandling::STANDARD_HANDLING) { |
12 | } |
13 | |
14 | string SelectNode::ToString() const { |
15 | string result; |
16 | result = cte_map.ToString(); |
17 | result += "SELECT " ; |
18 | |
19 | // search for a distinct modifier |
20 | for (idx_t modifier_idx = 0; modifier_idx < modifiers.size(); modifier_idx++) { |
21 | if (modifiers[modifier_idx]->type == ResultModifierType::DISTINCT_MODIFIER) { |
22 | auto &distinct_modifier = modifiers[modifier_idx]->Cast<DistinctModifier>(); |
23 | result += "DISTINCT " ; |
24 | if (!distinct_modifier.distinct_on_targets.empty()) { |
25 | result += "ON (" ; |
26 | for (idx_t k = 0; k < distinct_modifier.distinct_on_targets.size(); k++) { |
27 | if (k > 0) { |
28 | result += ", " ; |
29 | } |
30 | result += distinct_modifier.distinct_on_targets[k]->ToString(); |
31 | } |
32 | result += ") " ; |
33 | } |
34 | } |
35 | } |
36 | for (idx_t i = 0; i < select_list.size(); i++) { |
37 | if (i > 0) { |
38 | result += ", " ; |
39 | } |
40 | result += select_list[i]->ToString(); |
41 | if (!select_list[i]->alias.empty()) { |
42 | result += StringUtil::Format(fmt_str: " AS %s" , params: SQLIdentifier(select_list[i]->alias)); |
43 | } |
44 | } |
45 | if (from_table && from_table->type != TableReferenceType::EMPTY) { |
46 | result += " FROM " + from_table->ToString(); |
47 | } |
48 | if (where_clause) { |
49 | result += " WHERE " + where_clause->ToString(); |
50 | } |
51 | if (!groups.grouping_sets.empty()) { |
52 | result += " GROUP BY " ; |
53 | // if we are dealing with multiple grouping sets, we have to add a few additional brackets |
54 | bool grouping_sets = groups.grouping_sets.size() > 1; |
55 | if (grouping_sets) { |
56 | result += "GROUPING SETS (" ; |
57 | } |
58 | for (idx_t i = 0; i < groups.grouping_sets.size(); i++) { |
59 | auto &grouping_set = groups.grouping_sets[i]; |
60 | if (i > 0) { |
61 | result += "," ; |
62 | } |
63 | if (grouping_set.empty()) { |
64 | result += "()" ; |
65 | continue; |
66 | } |
67 | if (grouping_sets) { |
68 | result += "(" ; |
69 | } |
70 | bool first = true; |
71 | for (auto &grp : grouping_set) { |
72 | if (!first) { |
73 | result += ", " ; |
74 | } |
75 | result += groups.group_expressions[grp]->ToString(); |
76 | first = false; |
77 | } |
78 | if (grouping_sets) { |
79 | result += ")" ; |
80 | } |
81 | } |
82 | if (grouping_sets) { |
83 | result += ")" ; |
84 | } |
85 | } else if (aggregate_handling == AggregateHandling::FORCE_AGGREGATES) { |
86 | result += " GROUP BY ALL" ; |
87 | } |
88 | if (having) { |
89 | result += " HAVING " + having->ToString(); |
90 | } |
91 | if (qualify) { |
92 | result += " QUALIFY " + qualify->ToString(); |
93 | } |
94 | if (sample) { |
95 | result += " USING SAMPLE " ; |
96 | result += sample->sample_size.ToString(); |
97 | if (sample->is_percentage) { |
98 | result += "%" ; |
99 | } |
100 | result += " (" + EnumUtil::ToString(value: sample->method); |
101 | if (sample->seed >= 0) { |
102 | result += ", " + std::to_string(val: sample->seed); |
103 | } |
104 | result += ")" ; |
105 | } |
106 | return result + ResultModifiersToString(); |
107 | } |
108 | |
109 | bool SelectNode::Equals(const QueryNode *other_p) const { |
110 | if (!QueryNode::Equals(other: other_p)) { |
111 | return false; |
112 | } |
113 | if (this == other_p) { |
114 | return true; |
115 | } |
116 | auto &other = other_p->Cast<SelectNode>(); |
117 | |
118 | // SELECT |
119 | if (!ExpressionUtil::ListEquals(a: select_list, b: other.select_list)) { |
120 | return false; |
121 | } |
122 | // FROM |
123 | if (!TableRef::Equals(left: from_table, right: other.from_table)) { |
124 | return false; |
125 | } |
126 | // WHERE |
127 | if (!ParsedExpression::Equals(left: where_clause, right: other.where_clause)) { |
128 | return false; |
129 | } |
130 | // GROUP BY |
131 | if (!ParsedExpression::ListEquals(left: groups.group_expressions, right: other.groups.group_expressions)) { |
132 | return false; |
133 | } |
134 | if (groups.grouping_sets != other.groups.grouping_sets) { |
135 | return false; |
136 | } |
137 | if (!SampleOptions::Equals(a: sample.get(), b: other.sample.get())) { |
138 | return false; |
139 | } |
140 | // HAVING |
141 | if (!ParsedExpression::Equals(left: having, right: other.having)) { |
142 | return false; |
143 | } |
144 | // QUALIFY |
145 | if (!ParsedExpression::Equals(left: qualify, right: other.qualify)) { |
146 | return false; |
147 | } |
148 | return true; |
149 | } |
150 | |
151 | unique_ptr<QueryNode> SelectNode::Copy() const { |
152 | auto result = make_uniq<SelectNode>(); |
153 | for (auto &child : select_list) { |
154 | result->select_list.push_back(x: child->Copy()); |
155 | } |
156 | result->from_table = from_table ? from_table->Copy() : nullptr; |
157 | result->where_clause = where_clause ? where_clause->Copy() : nullptr; |
158 | // groups |
159 | for (auto &group : groups.group_expressions) { |
160 | result->groups.group_expressions.push_back(x: group->Copy()); |
161 | } |
162 | result->groups.grouping_sets = groups.grouping_sets; |
163 | result->aggregate_handling = aggregate_handling; |
164 | result->having = having ? having->Copy() : nullptr; |
165 | result->qualify = qualify ? qualify->Copy() : nullptr; |
166 | result->sample = sample ? sample->Copy() : nullptr; |
167 | this->CopyProperties(other&: *result); |
168 | return std::move(result); |
169 | } |
170 | |
171 | void SelectNode::Serialize(FieldWriter &writer) const { |
172 | writer.WriteSerializableList(elements: select_list); |
173 | writer.WriteOptional(element: from_table); |
174 | writer.WriteOptional(element: where_clause); |
175 | writer.WriteSerializableList(elements: groups.group_expressions); |
176 | writer.WriteField<uint32_t>(element: groups.grouping_sets.size()); |
177 | auto &serializer = writer.GetSerializer(); |
178 | for (auto &grouping_set : groups.grouping_sets) { |
179 | serializer.Write<idx_t>(element: grouping_set.size()); |
180 | for (auto &idx : grouping_set) { |
181 | serializer.Write<idx_t>(element: idx); |
182 | } |
183 | } |
184 | writer.WriteField<AggregateHandling>(element: aggregate_handling); |
185 | writer.WriteOptional(element: having); |
186 | writer.WriteOptional(element: sample); |
187 | writer.WriteOptional(element: qualify); |
188 | } |
189 | |
190 | void SelectNode::FormatSerialize(FormatSerializer &serializer) const { |
191 | QueryNode::FormatSerialize(serializer); |
192 | serializer.WriteProperty(tag: "select_list" , value: select_list); |
193 | serializer.WriteOptionalProperty(tag: "from_table" , ptr: from_table); |
194 | serializer.WriteOptionalProperty(tag: "where_clause" , ptr: where_clause); |
195 | serializer.WriteProperty(tag: "group_expressions" , value: groups.group_expressions); |
196 | serializer.WriteProperty(tag: "group_sets" , value: groups.grouping_sets); |
197 | serializer.WriteProperty(tag: "aggregate_handling" , value: aggregate_handling); |
198 | serializer.WriteOptionalProperty(tag: "having" , ptr: having); |
199 | serializer.WriteOptionalProperty(tag: "sample" , ptr: sample); |
200 | serializer.WriteOptionalProperty(tag: "qualify" , ptr: qualify); |
201 | } |
202 | |
203 | unique_ptr<QueryNode> SelectNode::FormatDeserialize(FormatDeserializer &deserializer) { |
204 | auto result = make_uniq<SelectNode>(); |
205 | |
206 | deserializer.ReadProperty(tag: "select_list" , ret&: result->select_list); |
207 | deserializer.ReadOptionalProperty(tag: "from_table" , ret&: result->from_table); |
208 | deserializer.ReadOptionalProperty(tag: "where_clause" , ret&: result->where_clause); |
209 | deserializer.ReadProperty(tag: "group_expressions" , ret&: result->groups.group_expressions); |
210 | deserializer.ReadProperty(tag: "group_sets" , ret&: result->groups.grouping_sets); |
211 | deserializer.ReadProperty(tag: "aggregate_handling" , ret&: result->aggregate_handling); |
212 | deserializer.ReadOptionalProperty(tag: "having" , ret&: result->having); |
213 | deserializer.ReadOptionalProperty(tag: "sample" , ret&: result->sample); |
214 | deserializer.ReadOptionalProperty(tag: "qualify" , ret&: result->qualify); |
215 | |
216 | return std::move(result); |
217 | } |
218 | |
219 | unique_ptr<QueryNode> SelectNode::Deserialize(FieldReader &reader) { |
220 | auto result = make_uniq<SelectNode>(); |
221 | result->select_list = reader.ReadRequiredSerializableList<ParsedExpression>(); |
222 | result->from_table = reader.ReadOptional<TableRef>(default_value: nullptr); |
223 | result->where_clause = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
224 | result->groups.group_expressions = reader.ReadRequiredSerializableList<ParsedExpression>(); |
225 | |
226 | auto grouping_set_count = reader.ReadRequired<uint32_t>(); |
227 | auto &source = reader.GetSource(); |
228 | for (idx_t set_idx = 0; set_idx < grouping_set_count; set_idx++) { |
229 | auto set_entries = source.Read<idx_t>(); |
230 | GroupingSet grouping_set; |
231 | for (idx_t i = 0; i < set_entries; i++) { |
232 | grouping_set.insert(x: source.Read<idx_t>()); |
233 | } |
234 | result->groups.grouping_sets.push_back(x: grouping_set); |
235 | } |
236 | |
237 | result->aggregate_handling = reader.ReadRequired<AggregateHandling>(); |
238 | result->having = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
239 | result->sample = reader.ReadOptional<SampleOptions>(default_value: nullptr); |
240 | result->qualify = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
241 | return std::move(result); |
242 | } |
243 | |
244 | } // namespace duckdb |
245 | |