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
9namespace duckdb {
10
11StarExpression::StarExpression(string relation_name_p)
12 : ParsedExpression(ExpressionType::STAR, ExpressionClass::STAR), relation_name(std::move(relation_name_p)) {
13}
14
15string 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
57bool 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
82void 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
102unique_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
122unique_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
134void 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
143unique_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