| 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 | |
| 11 | namespace duckdb { |
| 12 | |
| 13 | CommonTableExpressionMap::CommonTableExpressionMap() { |
| 14 | } |
| 15 | |
| 16 | CommonTableExpressionMap 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 | |
| 29 | string 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 | |
| 70 | void CommonTableExpressionMap::FormatSerialize(FormatSerializer &serializer) const { |
| 71 | serializer.WriteProperty(tag: "map" , value: map); |
| 72 | } |
| 73 | |
| 74 | CommonTableExpressionMap CommonTableExpressionMap::FormatDeserialize(FormatDeserializer &deserializer) { |
| 75 | auto result = CommonTableExpressionMap(); |
| 76 | deserializer.ReadProperty(tag: "map" , ret&: result.map); |
| 77 | return result; |
| 78 | } |
| 79 | |
| 80 | string 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 | |
| 114 | bool 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 | |
| 152 | void 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 | |
| 166 | void 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. |
| 185 | void 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 | |
| 191 | unique_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 | |
| 220 | unique_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 | |
| 256 | void 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 | |