1 | #include "duckdb/parser/expression/star_expression.hpp" |
2 | |
3 | #include "duckdb/common/exception.hpp" |
4 | #include "duckdb/common/field_writer.hpp" |
5 | |
6 | #include "duckdb/common/serializer/format_serializer.hpp" |
7 | #include "duckdb/common/serializer/format_deserializer.hpp" |
8 | |
9 | namespace duckdb { |
10 | |
11 | StarExpression::StarExpression(string relation_name_p) |
12 | : ParsedExpression(ExpressionType::STAR, ExpressionClass::STAR), relation_name(std::move(relation_name_p)) { |
13 | } |
14 | |
15 | string StarExpression::ToString() const { |
16 | if (expr) { |
17 | D_ASSERT(columns); |
18 | return "COLUMNS(" + expr->ToString() + ")" ; |
19 | } |
20 | string result; |
21 | if (columns) { |
22 | result += "COLUMNS(" ; |
23 | } |
24 | result += relation_name.empty() ? "*" : relation_name + ".*" ; |
25 | if (!exclude_list.empty()) { |
26 | result += " EXCLUDE (" ; |
27 | bool first_entry = true; |
28 | for (auto &entry : exclude_list) { |
29 | if (!first_entry) { |
30 | result += ", " ; |
31 | } |
32 | result += entry; |
33 | first_entry = false; |
34 | } |
35 | result += ")" ; |
36 | } |
37 | if (!replace_list.empty()) { |
38 | result += " REPLACE (" ; |
39 | bool first_entry = true; |
40 | for (auto &entry : replace_list) { |
41 | if (!first_entry) { |
42 | result += ", " ; |
43 | } |
44 | result += entry.second->ToString(); |
45 | result += " AS " ; |
46 | result += entry.first; |
47 | first_entry = false; |
48 | } |
49 | result += ")" ; |
50 | } |
51 | if (columns) { |
52 | result += ")" ; |
53 | } |
54 | return result; |
55 | } |
56 | |
57 | bool StarExpression::Equal(const StarExpression &a, const StarExpression &b) { |
58 | if (a.relation_name != b.relation_name || a.exclude_list != b.exclude_list) { |
59 | return false; |
60 | } |
61 | if (a.columns != b.columns) { |
62 | return false; |
63 | } |
64 | if (a.replace_list.size() != b.replace_list.size()) { |
65 | return false; |
66 | } |
67 | for (auto &entry : a.replace_list) { |
68 | auto other_entry = b.replace_list.find(x: entry.first); |
69 | if (other_entry == b.replace_list.end()) { |
70 | return false; |
71 | } |
72 | if (!entry.second->Equals(other: *other_entry->second)) { |
73 | return false; |
74 | } |
75 | } |
76 | if (!ParsedExpression::Equals(left: a.expr, right: b.expr)) { |
77 | return false; |
78 | } |
79 | return true; |
80 | } |
81 | |
82 | void StarExpression::Serialize(FieldWriter &writer) const { |
83 | auto &serializer = writer.GetSerializer(); |
84 | |
85 | writer.WriteString(val: relation_name); |
86 | |
87 | // in order to write the exclude_list/replace_list as single fields we directly use the field writers' internal |
88 | // serializer |
89 | writer.WriteField<uint32_t>(element: exclude_list.size()); |
90 | for (auto &exclusion : exclude_list) { |
91 | serializer.WriteString(val: exclusion); |
92 | } |
93 | writer.WriteField<uint32_t>(element: replace_list.size()); |
94 | for (auto &entry : replace_list) { |
95 | serializer.WriteString(val: entry.first); |
96 | entry.second->Serialize(serializer); |
97 | } |
98 | writer.WriteField<bool>(element: columns); |
99 | writer.WriteOptional(element: expr); |
100 | } |
101 | |
102 | unique_ptr<ParsedExpression> StarExpression::Deserialize(ExpressionType type, FieldReader &reader) { |
103 | auto &source = reader.GetSource(); |
104 | |
105 | auto result = make_uniq<StarExpression>(); |
106 | result->relation_name = reader.ReadRequired<string>(); |
107 | auto exclusion_count = reader.ReadRequired<uint32_t>(); |
108 | for (idx_t i = 0; i < exclusion_count; i++) { |
109 | result->exclude_list.insert(x: source.Read<string>()); |
110 | } |
111 | auto replace_count = reader.ReadRequired<uint32_t>(); |
112 | for (idx_t i = 0; i < replace_count; i++) { |
113 | auto name = source.Read<string>(); |
114 | auto expr = ParsedExpression::Deserialize(source); |
115 | result->replace_list.insert(x: make_pair(x&: name, y: std::move(expr))); |
116 | } |
117 | result->columns = reader.ReadField<bool>(default_value: false); |
118 | result->expr = reader.ReadOptional<ParsedExpression>(default_value: nullptr); |
119 | return std::move(result); |
120 | } |
121 | |
122 | unique_ptr<ParsedExpression> StarExpression::Copy() const { |
123 | auto copy = make_uniq<StarExpression>(args: relation_name); |
124 | copy->exclude_list = exclude_list; |
125 | for (auto &entry : replace_list) { |
126 | copy->replace_list[entry.first] = entry.second->Copy(); |
127 | } |
128 | copy->columns = columns; |
129 | copy->expr = expr ? expr->Copy() : nullptr; |
130 | copy->CopyProperties(other: *this); |
131 | return std::move(copy); |
132 | } |
133 | |
134 | void StarExpression::FormatSerialize(FormatSerializer &serializer) const { |
135 | ParsedExpression::FormatSerialize(serializer); |
136 | serializer.WriteProperty(tag: "relation_name" , value: relation_name); |
137 | serializer.WriteProperty(tag: "exclude_list" , value: exclude_list); |
138 | serializer.WriteProperty(tag: "replace_list" , value: replace_list); |
139 | serializer.WriteProperty(tag: "columns" , value: columns); |
140 | serializer.WriteOptionalProperty(tag: "expr" , ptr: expr); |
141 | } |
142 | |
143 | unique_ptr<ParsedExpression> StarExpression::FormatDeserialize(ExpressionType type, FormatDeserializer &deserializer) { |
144 | auto result = make_uniq<StarExpression>(); |
145 | deserializer.ReadProperty(tag: "relation_name" , ret&: result->relation_name); |
146 | deserializer.ReadProperty(tag: "exclude_list" , ret&: result->exclude_list); |
147 | deserializer.ReadProperty(tag: "replace_list" , ret&: result->replace_list); |
148 | deserializer.ReadProperty(tag: "columns" , ret&: result->columns); |
149 | deserializer.ReadOptionalProperty(tag: "expr" , ret&: result->expr); |
150 | return std::move(result); |
151 | } |
152 | |
153 | } // namespace duckdb |
154 | |