1#include "duckdb/parser/query_node.hpp"
2
3#include "duckdb/parser/query_node/select_node.hpp"
4#include "duckdb/parser/query_node/set_operation_node.hpp"
5#include "duckdb/parser/query_node/recursive_cte_node.hpp"
6#include "duckdb/common/limits.hpp"
7#include "duckdb/common/field_writer.hpp"
8#include "duckdb/common/serializer/format_serializer.hpp"
9#include "duckdb/common/serializer/format_deserializer.hpp"
10
11namespace duckdb {
12
13CommonTableExpressionMap::CommonTableExpressionMap() {
14}
15
16CommonTableExpressionMap CommonTableExpressionMap::Copy() const {
17 CommonTableExpressionMap res;
18 for (auto &kv : this->map) {
19 auto kv_info = make_uniq<CommonTableExpressionInfo>();
20 for (auto &al : kv.second->aliases) {
21 kv_info->aliases.push_back(x: al);
22 }
23 kv_info->query = unique_ptr_cast<SQLStatement, SelectStatement>(src: kv.second->query->Copy());
24 res.map[kv.first] = std::move(kv_info);
25 }
26 return res;
27}
28
29string CommonTableExpressionMap::ToString() const {
30 if (map.empty()) {
31 return string();
32 }
33 // check if there are any recursive CTEs
34 bool has_recursive = false;
35 for (auto &kv : map) {
36 if (kv.second->query->node->type == QueryNodeType::RECURSIVE_CTE_NODE) {
37 has_recursive = true;
38 break;
39 }
40 }
41 string result = "WITH ";
42 if (has_recursive) {
43 result += "RECURSIVE ";
44 }
45 bool first_cte = true;
46 for (auto &kv : map) {
47 if (!first_cte) {
48 result += ", ";
49 }
50 auto &cte = *kv.second;
51 result += KeywordHelper::WriteOptionallyQuoted(text: kv.first);
52 if (!cte.aliases.empty()) {
53 result += " (";
54 for (idx_t k = 0; k < cte.aliases.size(); k++) {
55 if (k > 0) {
56 result += ", ";
57 }
58 result += KeywordHelper::WriteOptionallyQuoted(text: cte.aliases[k]);
59 }
60 result += ")";
61 }
62 result += " AS (";
63 result += cte.query->ToString();
64 result += ")";
65 first_cte = false;
66 }
67 return result;
68}
69
70void CommonTableExpressionMap::FormatSerialize(FormatSerializer &serializer) const {
71 serializer.WriteProperty(tag: "map", value: map);
72}
73
74CommonTableExpressionMap CommonTableExpressionMap::FormatDeserialize(FormatDeserializer &deserializer) {
75 auto result = CommonTableExpressionMap();
76 deserializer.ReadProperty(tag: "map", ret&: result.map);
77 return result;
78}
79
80string QueryNode::ResultModifiersToString() const {
81 string result;
82 for (idx_t modifier_idx = 0; modifier_idx < modifiers.size(); modifier_idx++) {
83 auto &modifier = *modifiers[modifier_idx];
84 if (modifier.type == ResultModifierType::ORDER_MODIFIER) {
85 auto &order_modifier = modifier.Cast<OrderModifier>();
86 result += " ORDER BY ";
87 for (idx_t k = 0; k < order_modifier.orders.size(); k++) {
88 if (k > 0) {
89 result += ", ";
90 }
91 result += order_modifier.orders[k].ToString();
92 }
93 } else if (modifier.type == ResultModifierType::LIMIT_MODIFIER) {
94 auto &limit_modifier = modifier.Cast<LimitModifier>();
95 if (limit_modifier.limit) {
96 result += " LIMIT " + limit_modifier.limit->ToString();
97 }
98 if (limit_modifier.offset) {
99 result += " OFFSET " + limit_modifier.offset->ToString();
100 }
101 } else if (modifier.type == ResultModifierType::LIMIT_PERCENT_MODIFIER) {
102 auto &limit_p_modifier = modifier.Cast<LimitPercentModifier>();
103 if (limit_p_modifier.limit) {
104 result += " LIMIT (" + limit_p_modifier.limit->ToString() + ") %";
105 }
106 if (limit_p_modifier.offset) {
107 result += " OFFSET " + limit_p_modifier.offset->ToString();
108 }
109 }
110 }
111 return result;
112}
113
114bool QueryNode::Equals(const QueryNode *other) const {
115 if (!other) {
116 return false;
117 }
118 if (this == other) {
119 return true;
120 }
121 if (other->type != this->type) {
122 return false;
123 }
124
125 if (modifiers.size() != other->modifiers.size()) {
126 return false;
127 }
128 for (idx_t i = 0; i < modifiers.size(); i++) {
129 if (!modifiers[i]->Equals(other: *other->modifiers[i])) {
130 return false;
131 }
132 }
133 // WITH clauses (CTEs)
134 if (cte_map.map.size() != other->cte_map.map.size()) {
135 return false;
136 }
137 for (auto &entry : cte_map.map) {
138 auto other_entry = other->cte_map.map.find(x: entry.first);
139 if (other_entry == other->cte_map.map.end()) {
140 return false;
141 }
142 if (entry.second->aliases != other_entry->second->aliases) {
143 return false;
144 }
145 if (!entry.second->query->Equals(other: *other_entry->second->query)) {
146 return false;
147 }
148 }
149 return other->type == type;
150}
151
152void QueryNode::CopyProperties(QueryNode &other) const {
153 for (auto &modifier : modifiers) {
154 other.modifiers.push_back(x: modifier->Copy());
155 }
156 for (auto &kv : cte_map.map) {
157 auto kv_info = make_uniq<CommonTableExpressionInfo>();
158 for (auto &al : kv.second->aliases) {
159 kv_info->aliases.push_back(x: al);
160 }
161 kv_info->query = unique_ptr_cast<SQLStatement, SelectStatement>(src: kv.second->query->Copy());
162 other.cte_map.map[kv.first] = std::move(kv_info);
163 }
164}
165
166void QueryNode::Serialize(Serializer &main_serializer) const {
167 FieldWriter writer(main_serializer);
168 writer.WriteField<QueryNodeType>(element: type);
169 writer.WriteSerializableList(elements: modifiers);
170 // cte_map
171
172 writer.WriteField<uint32_t>(element: (uint32_t)cte_map.map.size());
173 auto &serializer = writer.GetSerializer();
174 for (auto &cte : cte_map.map) {
175 serializer.WriteString(val: cte.first);
176 serializer.WriteStringVector(list: cte.second->aliases);
177 cte.second->query->Serialize(serializer);
178 }
179 Serialize(writer);
180
181 writer.Finalize();
182}
183
184// Children should call the base method before their own.
185void QueryNode::FormatSerialize(FormatSerializer &serializer) const {
186 serializer.WriteProperty(tag: "type", value: type);
187 serializer.WriteProperty(tag: "modifiers", value: modifiers);
188 serializer.WriteProperty(tag: "cte_map", value: cte_map);
189}
190
191unique_ptr<QueryNode> QueryNode::FormatDeserialize(FormatDeserializer &deserializer) {
192
193 auto type = deserializer.ReadProperty<QueryNodeType>(tag: "type");
194
195 auto modifiers = deserializer.ReadProperty<vector<unique_ptr<ResultModifier>>>(tag: "modifiers");
196 auto cte_map = deserializer.ReadProperty<CommonTableExpressionMap>(tag: "cte_map");
197
198 unique_ptr<QueryNode> result;
199
200 switch (type) {
201 case QueryNodeType::SELECT_NODE:
202 result = SelectNode::FormatDeserialize(deserializer);
203 break;
204 case QueryNodeType::SET_OPERATION_NODE:
205 result = SetOperationNode::FormatDeserialize(source&: deserializer);
206 break;
207 case QueryNodeType::RECURSIVE_CTE_NODE:
208 result = RecursiveCTENode::FormatDeserialize(source&: deserializer);
209 break;
210 default:
211 throw SerializationException("Could not deserialize Query Node: unknown type!");
212 }
213
214 result->type = type;
215 result->modifiers = std::move(modifiers);
216 result->cte_map = std::move(cte_map);
217 return result;
218}
219
220unique_ptr<QueryNode> QueryNode::Deserialize(Deserializer &main_source) {
221 FieldReader reader(main_source);
222
223 auto type = reader.ReadRequired<QueryNodeType>();
224 auto modifiers = reader.ReadRequiredSerializableList<ResultModifier>();
225 // cte_map
226 auto cte_count = reader.ReadRequired<uint32_t>();
227 auto &source = reader.GetSource();
228 case_insensitive_map_t<unique_ptr<CommonTableExpressionInfo>> new_map;
229 for (idx_t i = 0; i < cte_count; i++) {
230 auto name = source.Read<string>();
231 auto info = make_uniq<CommonTableExpressionInfo>();
232 source.ReadStringVector(list&: info->aliases);
233 info->query = SelectStatement::Deserialize(source);
234 new_map[name] = std::move(info);
235 }
236 unique_ptr<QueryNode> result;
237 switch (type) {
238 case QueryNodeType::SELECT_NODE:
239 result = SelectNode::Deserialize(reader);
240 break;
241 case QueryNodeType::SET_OPERATION_NODE:
242 result = SetOperationNode::Deserialize(reader);
243 break;
244 case QueryNodeType::RECURSIVE_CTE_NODE:
245 result = RecursiveCTENode::Deserialize(reader);
246 break;
247 default:
248 throw SerializationException("Could not deserialize Query Node: unknown type!");
249 }
250 result->modifiers = std::move(modifiers);
251 result->cte_map.map = std::move(new_map);
252 reader.Finalize();
253 return result;
254}
255
256void QueryNode::AddDistinct() {
257 // check if we already have a DISTINCT modifier
258 for (idx_t modifier_idx = modifiers.size(); modifier_idx > 0; modifier_idx--) {
259 auto &modifier = *modifiers[modifier_idx - 1];
260 if (modifier.type == ResultModifierType::DISTINCT_MODIFIER) {
261 auto &distinct_modifier = modifier.Cast<DistinctModifier>();
262 if (distinct_modifier.distinct_on_targets.empty()) {
263 // we have a DISTINCT without an ON clause - this distinct does not need to be added
264 return;
265 }
266 } else if (modifier.type == ResultModifierType::LIMIT_MODIFIER ||
267 modifier.type == ResultModifierType::LIMIT_PERCENT_MODIFIER) {
268 // we encountered a LIMIT or LIMIT PERCENT - these change the result of DISTINCT, so we do need to push a
269 // DISTINCT relation
270 break;
271 }
272 }
273 modifiers.push_back(x: make_uniq<DistinctModifier>());
274}
275
276} // namespace duckdb
277