| 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 | |
| 8 | namespace duckdb { |
| 9 | |
| 10 | ColumnDefinition::ColumnDefinition(string name_p, LogicalType type_p) |
| 11 | : name(std::move(name_p)), type(std::move(type_p)) { |
| 12 | } |
| 13 | |
| 14 | ColumnDefinition::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 | |
| 32 | ColumnDefinition 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 | |
| 43 | void 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 | |
| 57 | ColumnDefinition 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 | |
| 71 | const unique_ptr<ParsedExpression> &ColumnDefinition::DefaultValue() const { |
| 72 | return default_value; |
| 73 | } |
| 74 | |
| 75 | void ColumnDefinition::SetDefaultValue(unique_ptr<ParsedExpression> default_value) { |
| 76 | this->default_value = std::move(default_value); |
| 77 | } |
| 78 | |
| 79 | const LogicalType &ColumnDefinition::Type() const { |
| 80 | return type; |
| 81 | } |
| 82 | |
| 83 | LogicalType &ColumnDefinition::TypeMutable() { |
| 84 | return type; |
| 85 | } |
| 86 | |
| 87 | void ColumnDefinition::SetType(const LogicalType &type) { |
| 88 | this->type = type; |
| 89 | } |
| 90 | |
| 91 | const string &ColumnDefinition::Name() const { |
| 92 | return name; |
| 93 | } |
| 94 | |
| 95 | void ColumnDefinition::SetName(const string &name) { |
| 96 | this->name = name; |
| 97 | } |
| 98 | |
| 99 | const duckdb::CompressionType &ColumnDefinition::CompressionType() const { |
| 100 | return compression_type; |
| 101 | } |
| 102 | |
| 103 | void ColumnDefinition::SetCompressionType(duckdb::CompressionType compression_type) { |
| 104 | this->compression_type = compression_type; |
| 105 | } |
| 106 | |
| 107 | const storage_t &ColumnDefinition::StorageOid() const { |
| 108 | return storage_oid; |
| 109 | } |
| 110 | |
| 111 | LogicalIndex ColumnDefinition::Logical() const { |
| 112 | return LogicalIndex(oid); |
| 113 | } |
| 114 | |
| 115 | PhysicalIndex ColumnDefinition::Physical() const { |
| 116 | return PhysicalIndex(storage_oid); |
| 117 | } |
| 118 | |
| 119 | void ColumnDefinition::SetStorageOid(storage_t storage_oid) { |
| 120 | this->storage_oid = storage_oid; |
| 121 | } |
| 122 | |
| 123 | const column_t &ColumnDefinition::Oid() const { |
| 124 | return oid; |
| 125 | } |
| 126 | |
| 127 | void ColumnDefinition::SetOid(column_t oid) { |
| 128 | this->oid = oid; |
| 129 | } |
| 130 | |
| 131 | const TableColumnType &ColumnDefinition::Category() const { |
| 132 | return category; |
| 133 | } |
| 134 | |
| 135 | bool ColumnDefinition::Generated() const { |
| 136 | return category == TableColumnType::GENERATED; |
| 137 | } |
| 138 | |
| 139 | //===--------------------------------------------------------------------===// |
| 140 | // Generated Columns (VIRTUAL) |
| 141 | //===--------------------------------------------------------------------===// |
| 142 | |
| 143 | static 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 | |
| 155 | static 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 | |
| 169 | void ColumnDefinition::GetListOfDependencies(vector<string> &dependencies) const { |
| 170 | D_ASSERT(Generated()); |
| 171 | InnerGetListOfDependencies(expr&: *generated_expression, dependencies); |
| 172 | } |
| 173 | |
| 174 | string ColumnDefinition::GetName() const { |
| 175 | return name; |
| 176 | } |
| 177 | |
| 178 | LogicalType ColumnDefinition::GetType() const { |
| 179 | return type; |
| 180 | } |
| 181 | |
| 182 | void 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 | |
| 199 | void 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 | |
| 211 | const ParsedExpression &ColumnDefinition::GeneratedExpression() const { |
| 212 | D_ASSERT(Generated()); |
| 213 | return *generated_expression; |
| 214 | } |
| 215 | |
| 216 | ParsedExpression &ColumnDefinition::GeneratedExpressionMutable() { |
| 217 | D_ASSERT(Generated()); |
| 218 | return *generated_expression; |
| 219 | } |
| 220 | |
| 221 | } // namespace duckdb |
| 222 | |