1#include "duckdb/parser/column_definition.hpp"
2#include "duckdb/common/field_writer.hpp"
3#include "duckdb/parser/parsed_expression_iterator.hpp"
4#include "duckdb/parser/expression/columnref_expression.hpp"
5#include "duckdb/parser/parsed_data/alter_table_info.hpp"
6#include "duckdb/parser/expression/cast_expression.hpp"
7
8namespace duckdb {
9
10ColumnDefinition::ColumnDefinition(string name_p, LogicalType type_p)
11 : name(std::move(name_p)), type(std::move(type_p)) {
12}
13
14ColumnDefinition::ColumnDefinition(string name_p, LogicalType type_p, unique_ptr<ParsedExpression> expression,
15 TableColumnType category)
16 : name(std::move(name_p)), type(std::move(type_p)), category(category) {
17 switch (category) {
18 case TableColumnType::STANDARD: {
19 default_value = std::move(expression);
20 break;
21 }
22 case TableColumnType::GENERATED: {
23 generated_expression = std::move(expression);
24 break;
25 }
26 default: {
27 throw InternalException("Type not implemented for TableColumnType");
28 }
29 }
30}
31
32ColumnDefinition ColumnDefinition::Copy() const {
33 ColumnDefinition copy(name, type);
34 copy.oid = oid;
35 copy.storage_oid = storage_oid;
36 copy.SetDefaultValue(default_value ? default_value->Copy() : nullptr);
37 copy.generated_expression = generated_expression ? generated_expression->Copy() : nullptr;
38 copy.compression_type = compression_type;
39 copy.category = category;
40 return copy;
41}
42
43void ColumnDefinition::Serialize(Serializer &serializer) const {
44 FieldWriter writer(serializer);
45 writer.WriteString(val: name);
46 writer.WriteSerializable(element: type);
47 if (Generated()) {
48 writer.WriteOptional(element: generated_expression);
49 } else {
50 writer.WriteOptional(element: default_value);
51 }
52 writer.WriteField<TableColumnType>(element: category);
53 writer.WriteField<duckdb::CompressionType>(element: compression_type);
54 writer.Finalize();
55}
56
57ColumnDefinition ColumnDefinition::Deserialize(Deserializer &source) {
58 FieldReader reader(source);
59 auto column_name = reader.ReadRequired<string>();
60 auto column_type = reader.ReadRequiredSerializable<LogicalType, LogicalType>();
61 auto expression = reader.ReadOptional<ParsedExpression>(default_value: nullptr);
62 auto category = reader.ReadField<TableColumnType>(default_value: TableColumnType::STANDARD);
63 auto compression_type = reader.ReadField<duckdb::CompressionType>(default_value: duckdb::CompressionType::COMPRESSION_AUTO);
64 reader.Finalize();
65
66 ColumnDefinition result(column_name, column_type, std::move(expression), category);
67 result.compression_type = compression_type;
68 return result;
69}
70
71const unique_ptr<ParsedExpression> &ColumnDefinition::DefaultValue() const {
72 return default_value;
73}
74
75void ColumnDefinition::SetDefaultValue(unique_ptr<ParsedExpression> default_value) {
76 this->default_value = std::move(default_value);
77}
78
79const LogicalType &ColumnDefinition::Type() const {
80 return type;
81}
82
83LogicalType &ColumnDefinition::TypeMutable() {
84 return type;
85}
86
87void ColumnDefinition::SetType(const LogicalType &type) {
88 this->type = type;
89}
90
91const string &ColumnDefinition::Name() const {
92 return name;
93}
94
95void ColumnDefinition::SetName(const string &name) {
96 this->name = name;
97}
98
99const duckdb::CompressionType &ColumnDefinition::CompressionType() const {
100 return compression_type;
101}
102
103void ColumnDefinition::SetCompressionType(duckdb::CompressionType compression_type) {
104 this->compression_type = compression_type;
105}
106
107const storage_t &ColumnDefinition::StorageOid() const {
108 return storage_oid;
109}
110
111LogicalIndex ColumnDefinition::Logical() const {
112 return LogicalIndex(oid);
113}
114
115PhysicalIndex ColumnDefinition::Physical() const {
116 return PhysicalIndex(storage_oid);
117}
118
119void ColumnDefinition::SetStorageOid(storage_t storage_oid) {
120 this->storage_oid = storage_oid;
121}
122
123const column_t &ColumnDefinition::Oid() const {
124 return oid;
125}
126
127void ColumnDefinition::SetOid(column_t oid) {
128 this->oid = oid;
129}
130
131const TableColumnType &ColumnDefinition::Category() const {
132 return category;
133}
134
135bool ColumnDefinition::Generated() const {
136 return category == TableColumnType::GENERATED;
137}
138
139//===--------------------------------------------------------------------===//
140// Generated Columns (VIRTUAL)
141//===--------------------------------------------------------------------===//
142
143static void VerifyColumnRefs(ParsedExpression &expr) {
144 if (expr.type == ExpressionType::COLUMN_REF) {
145 auto &column_ref = expr.Cast<ColumnRefExpression>();
146 if (column_ref.IsQualified()) {
147 throw ParserException(
148 "Qualified (tbl.name) column references are not allowed inside of generated column expressions");
149 }
150 }
151 ParsedExpressionIterator::EnumerateChildren(
152 expr, callback: [&](const ParsedExpression &child) { VerifyColumnRefs(expr&: (ParsedExpression &)child); });
153}
154
155static void InnerGetListOfDependencies(ParsedExpression &expr, vector<string> &dependencies) {
156 if (expr.type == ExpressionType::COLUMN_REF) {
157 auto columnref = expr.Cast<ColumnRefExpression>();
158 auto &name = columnref.GetColumnName();
159 dependencies.push_back(x: name);
160 }
161 ParsedExpressionIterator::EnumerateChildren(expr, callback: [&](const ParsedExpression &child) {
162 if (expr.type == ExpressionType::LAMBDA) {
163 throw NotImplementedException("Lambda functions are currently not supported in generated columns.");
164 }
165 InnerGetListOfDependencies(expr&: (ParsedExpression &)child, dependencies);
166 });
167}
168
169void ColumnDefinition::GetListOfDependencies(vector<string> &dependencies) const {
170 D_ASSERT(Generated());
171 InnerGetListOfDependencies(expr&: *generated_expression, dependencies);
172}
173
174string ColumnDefinition::GetName() const {
175 return name;
176}
177
178LogicalType ColumnDefinition::GetType() const {
179 return type;
180}
181
182void ColumnDefinition::SetGeneratedExpression(unique_ptr<ParsedExpression> expression) {
183 category = TableColumnType::GENERATED;
184
185 if (expression->HasSubquery()) {
186 throw ParserException("Expression of generated column \"%s\" contains a subquery, which isn't allowed", name);
187 }
188
189 VerifyColumnRefs(expr&: *expression);
190 if (type.id() == LogicalTypeId::ANY) {
191 generated_expression = std::move(expression);
192 return;
193 }
194 // Always wrap the expression in a cast, that way we can always update the cast when we change the type
195 // Except if the type is LogicalType::ANY (no type specified)
196 generated_expression = make_uniq_base<ParsedExpression, CastExpression>(args&: type, args: std::move(expression));
197}
198
199void ColumnDefinition::ChangeGeneratedExpressionType(const LogicalType &type) {
200 D_ASSERT(Generated());
201 // First time the type is set, add a cast around the expression
202 D_ASSERT(this->type.id() == LogicalTypeId::ANY);
203 generated_expression = make_uniq_base<ParsedExpression, CastExpression>(args: type, args: std::move(generated_expression));
204 // Every generated expression should be wrapped in a cast on creation
205 // D_ASSERT(generated_expression->type == ExpressionType::OPERATOR_CAST);
206 // auto &cast_expr = generated_expression->Cast<CastExpression>();
207 // auto base_expr = std::move(cast_expr.child);
208 // generated_expression = make_uniq_base<ParsedExpression, CastExpression>(type, std::move(base_expr));
209}
210
211const ParsedExpression &ColumnDefinition::GeneratedExpression() const {
212 D_ASSERT(Generated());
213 return *generated_expression;
214}
215
216ParsedExpression &ColumnDefinition::GeneratedExpressionMutable() {
217 D_ASSERT(Generated());
218 return *generated_expression;
219}
220
221} // namespace duckdb
222