1 | #include "duckdb/parser/constraints/list.hpp" |
2 | #include "duckdb/parser/expression/cast_expression.hpp" |
3 | #include "duckdb/planner/binder.hpp" |
4 | #include "duckdb/planner/constraints/list.hpp" |
5 | #include "duckdb/planner/expression/bound_constant_expression.hpp" |
6 | #include "duckdb/planner/expression/bound_function_expression.hpp" |
7 | #include "duckdb/planner/expression_binder/check_binder.hpp" |
8 | #include "duckdb/planner/expression_binder/constant_binder.hpp" |
9 | #include "duckdb/planner/parsed_data/bound_create_table_info.hpp" |
10 | #include "duckdb/catalog/catalog_entry/type_catalog_entry.hpp" |
11 | #include "duckdb/catalog/dependency_manager.hpp" |
12 | #include "duckdb/function/table/table_scan.hpp" |
13 | #include "duckdb/planner/operator/logical_get.hpp" |
14 | #include "duckdb/parser/parsed_expression_iterator.hpp" |
15 | #include "duckdb/common/string.hpp" |
16 | #include "duckdb/common/queue.hpp" |
17 | #include "duckdb/parser/expression/list.hpp" |
18 | #include "duckdb/common/index_map.hpp" |
19 | #include "duckdb/planner/expression_iterator.hpp" |
20 | #include "duckdb/planner/expression_binder/index_binder.hpp" |
21 | #include "duckdb/parser/parsed_data/create_index_info.hpp" |
22 | |
23 | #include <algorithm> |
24 | |
25 | namespace duckdb { |
26 | |
27 | static void CreateColumnDependencyManager(BoundCreateTableInfo &info) { |
28 | auto &base = info.base->Cast<CreateTableInfo>(); |
29 | for (auto &col : base.columns.Logical()) { |
30 | if (!col.Generated()) { |
31 | continue; |
32 | } |
33 | info.column_dependency_manager.AddGeneratedColumn(column: col, list: base.columns); |
34 | } |
35 | } |
36 | |
37 | static void BindCheckConstraint(Binder &binder, BoundCreateTableInfo &info, const unique_ptr<Constraint> &cond) { |
38 | auto &base = info.base->Cast<CreateTableInfo>(); |
39 | |
40 | auto bound_constraint = make_uniq<BoundCheckConstraint>(); |
41 | // check constraint: bind the expression |
42 | CheckBinder check_binder(binder, binder.context, base.table, base.columns, bound_constraint->bound_columns); |
43 | auto &check = cond->Cast<CheckConstraint>(); |
44 | // create a copy of the unbound expression because the binding destroys the constraint |
45 | auto unbound_expression = check.expression->Copy(); |
46 | // now bind the constraint and create a new BoundCheckConstraint |
47 | bound_constraint->expression = check_binder.Bind(expr&: check.expression); |
48 | info.bound_constraints.push_back(x: std::move(bound_constraint)); |
49 | // move the unbound constraint back into the original check expression |
50 | check.expression = std::move(unbound_expression); |
51 | } |
52 | |
53 | static void BindConstraints(Binder &binder, BoundCreateTableInfo &info) { |
54 | auto &base = info.base->Cast<CreateTableInfo>(); |
55 | |
56 | bool has_primary_key = false; |
57 | logical_index_set_t not_null_columns; |
58 | vector<LogicalIndex> primary_keys; |
59 | for (idx_t i = 0; i < base.constraints.size(); i++) { |
60 | auto &cond = base.constraints[i]; |
61 | switch (cond->type) { |
62 | case ConstraintType::CHECK: { |
63 | BindCheckConstraint(binder, info, cond); |
64 | break; |
65 | } |
66 | case ConstraintType::NOT_NULL: { |
67 | auto ¬_null = cond->Cast<NotNullConstraint>(); |
68 | auto &col = base.columns.GetColumn(index: LogicalIndex(not_null.index)); |
69 | info.bound_constraints.push_back(x: make_uniq<BoundNotNullConstraint>(args: PhysicalIndex(col.StorageOid()))); |
70 | not_null_columns.insert(x: not_null.index); |
71 | break; |
72 | } |
73 | case ConstraintType::UNIQUE: { |
74 | auto &unique = cond->Cast<UniqueConstraint>(); |
75 | // have to resolve columns of the unique constraint |
76 | vector<LogicalIndex> keys; |
77 | logical_index_set_t key_set; |
78 | if (unique.index.index != DConstants::INVALID_INDEX) { |
79 | D_ASSERT(unique.index.index < base.columns.LogicalColumnCount()); |
80 | // unique constraint is given by single index |
81 | unique.columns.push_back(x: base.columns.GetColumn(index: unique.index).Name()); |
82 | keys.push_back(x: unique.index); |
83 | key_set.insert(x: unique.index); |
84 | } else { |
85 | // unique constraint is given by list of names |
86 | // have to resolve names |
87 | D_ASSERT(!unique.columns.empty()); |
88 | for (auto &keyname : unique.columns) { |
89 | if (!base.columns.ColumnExists(name: keyname)) { |
90 | throw ParserException("column \"%s\" named in key does not exist" , keyname); |
91 | } |
92 | auto &column = base.columns.GetColumn(name: keyname); |
93 | auto column_index = column.Logical(); |
94 | if (key_set.find(x: column_index) != key_set.end()) { |
95 | throw ParserException("column \"%s\" appears twice in " |
96 | "primary key constraint" , |
97 | keyname); |
98 | } |
99 | keys.push_back(x: column_index); |
100 | key_set.insert(x: column_index); |
101 | } |
102 | } |
103 | |
104 | if (unique.is_primary_key) { |
105 | // we can only have one primary key per table |
106 | if (has_primary_key) { |
107 | throw ParserException("table \"%s\" has more than one primary key" , base.table); |
108 | } |
109 | has_primary_key = true; |
110 | primary_keys = keys; |
111 | } |
112 | info.bound_constraints.push_back( |
113 | x: make_uniq<BoundUniqueConstraint>(args: std::move(keys), args: std::move(key_set), args&: unique.is_primary_key)); |
114 | break; |
115 | } |
116 | case ConstraintType::FOREIGN_KEY: { |
117 | auto &fk = cond->Cast<ForeignKeyConstraint>(); |
118 | D_ASSERT((fk.info.type == ForeignKeyType::FK_TYPE_FOREIGN_KEY_TABLE && !fk.info.pk_keys.empty()) || |
119 | (fk.info.type == ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE && !fk.info.pk_keys.empty()) || |
120 | fk.info.type == ForeignKeyType::FK_TYPE_SELF_REFERENCE_TABLE); |
121 | physical_index_set_t fk_key_set, pk_key_set; |
122 | for (idx_t i = 0; i < fk.info.pk_keys.size(); i++) { |
123 | if (pk_key_set.find(x: fk.info.pk_keys[i]) != pk_key_set.end()) { |
124 | throw BinderException("Duplicate primary key referenced in FOREIGN KEY constraint" ); |
125 | } |
126 | pk_key_set.insert(x: fk.info.pk_keys[i]); |
127 | } |
128 | for (idx_t i = 0; i < fk.info.fk_keys.size(); i++) { |
129 | if (fk_key_set.find(x: fk.info.fk_keys[i]) != fk_key_set.end()) { |
130 | throw BinderException("Duplicate key specified in FOREIGN KEY constraint" ); |
131 | } |
132 | fk_key_set.insert(x: fk.info.fk_keys[i]); |
133 | } |
134 | info.bound_constraints.push_back( |
135 | x: make_uniq<BoundForeignKeyConstraint>(args&: fk.info, args: std::move(pk_key_set), args: std::move(fk_key_set))); |
136 | break; |
137 | } |
138 | default: |
139 | throw NotImplementedException("unrecognized constraint type in bind" ); |
140 | } |
141 | } |
142 | if (has_primary_key) { |
143 | // if there is a primary key index, also create a NOT NULL constraint for each of the columns |
144 | for (auto &column_index : primary_keys) { |
145 | if (not_null_columns.count(x: column_index)) { |
146 | //! No need to create a NotNullConstraint, it's already present |
147 | continue; |
148 | } |
149 | auto physical_index = base.columns.LogicalToPhysical(index: column_index); |
150 | base.constraints.push_back(x: make_uniq<NotNullConstraint>(args&: column_index)); |
151 | info.bound_constraints.push_back(x: make_uniq<BoundNotNullConstraint>(args&: physical_index)); |
152 | } |
153 | } |
154 | } |
155 | |
156 | void Binder::BindGeneratedColumns(BoundCreateTableInfo &info) { |
157 | auto &base = info.base->Cast<CreateTableInfo>(); |
158 | |
159 | vector<string> names; |
160 | vector<LogicalType> types; |
161 | |
162 | D_ASSERT(base.type == CatalogType::TABLE_ENTRY); |
163 | for (auto &col : base.columns.Logical()) { |
164 | names.push_back(x: col.Name()); |
165 | types.push_back(x: col.Type()); |
166 | } |
167 | auto table_index = GenerateTableIndex(); |
168 | |
169 | // Create a new binder because we dont need (or want) these bindings in this scope |
170 | auto binder = Binder::CreateBinder(context); |
171 | binder->bind_context.AddGenericBinding(index: table_index, alias: base.table, names, types); |
172 | auto expr_binder = ExpressionBinder(*binder, context); |
173 | string ignore; |
174 | auto table_binding = binder->bind_context.GetBinding(name: base.table, out_error&: ignore); |
175 | D_ASSERT(table_binding && ignore.empty()); |
176 | |
177 | auto bind_order = info.column_dependency_manager.GetBindOrder(columns: base.columns); |
178 | logical_index_set_t bound_indices; |
179 | |
180 | while (!bind_order.empty()) { |
181 | auto i = bind_order.top(); |
182 | bind_order.pop(); |
183 | auto &col = base.columns.GetColumnMutable(index: i); |
184 | |
185 | //! Already bound this previously |
186 | //! This can not be optimized out of the GetBindOrder function |
187 | //! These occurrences happen because we need to make sure that ALL dependencies of a column are resolved before |
188 | //! it gets resolved |
189 | if (bound_indices.count(x: i)) { |
190 | continue; |
191 | } |
192 | D_ASSERT(col.Generated()); |
193 | auto expression = col.GeneratedExpression().Copy(); |
194 | |
195 | auto bound_expression = expr_binder.Bind(expr&: expression); |
196 | D_ASSERT(bound_expression); |
197 | D_ASSERT(!bound_expression->HasSubquery()); |
198 | if (col.Type().id() == LogicalTypeId::ANY) { |
199 | // Do this before changing the type, so we know it's the first time the type is set |
200 | col.ChangeGeneratedExpressionType(type: bound_expression->return_type); |
201 | col.SetType(bound_expression->return_type); |
202 | |
203 | // Update the type in the binding, for future expansions |
204 | string ignore; |
205 | table_binding->types[i.index] = col.Type(); |
206 | } |
207 | bound_indices.insert(x: i); |
208 | } |
209 | } |
210 | |
211 | void Binder::BindDefaultValues(const ColumnList &columns, vector<unique_ptr<Expression>> &bound_defaults) { |
212 | for (auto &column : columns.Physical()) { |
213 | unique_ptr<Expression> bound_default; |
214 | if (column.DefaultValue()) { |
215 | // we bind a copy of the DEFAULT value because binding is destructive |
216 | // and we want to keep the original expression around for serialization |
217 | auto default_copy = column.DefaultValue()->Copy(); |
218 | ConstantBinder default_binder(*this, context, "DEFAULT value" ); |
219 | default_binder.target_type = column.Type(); |
220 | bound_default = default_binder.Bind(expr&: default_copy); |
221 | } else { |
222 | // no default value specified: push a default value of constant null |
223 | bound_default = make_uniq<BoundConstantExpression>(args: Value(column.Type())); |
224 | } |
225 | bound_defaults.push_back(x: std::move(bound_default)); |
226 | } |
227 | } |
228 | |
229 | static void (Expression &expr, DependencyList &dependencies) { |
230 | if (expr.type == ExpressionType::BOUND_FUNCTION) { |
231 | auto &function = expr.Cast<BoundFunctionExpression>(); |
232 | if (function.function.dependency) { |
233 | function.function.dependency(function, dependencies); |
234 | } |
235 | } |
236 | ExpressionIterator::EnumerateChildren( |
237 | expression&: expr, callback: [&](Expression &child) { ExtractExpressionDependencies(expr&: child, dependencies); }); |
238 | } |
239 | |
240 | static void (BoundCreateTableInfo &info) { |
241 | for (auto &default_value : info.bound_defaults) { |
242 | if (default_value) { |
243 | ExtractExpressionDependencies(expr&: *default_value, dependencies&: info.dependencies); |
244 | } |
245 | } |
246 | for (auto &constraint : info.bound_constraints) { |
247 | if (constraint->type == ConstraintType::CHECK) { |
248 | auto &bound_check = constraint->Cast<BoundCheckConstraint>(); |
249 | ExtractExpressionDependencies(expr&: *bound_check.expression, dependencies&: info.dependencies); |
250 | } |
251 | } |
252 | } |
253 | unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateInfo> info, SchemaCatalogEntry &schema) { |
254 | auto &base = info->Cast<CreateTableInfo>(); |
255 | auto result = make_uniq<BoundCreateTableInfo>(args&: schema, args: std::move(info)); |
256 | if (base.query) { |
257 | // construct the result object |
258 | auto query_obj = Bind(stmt&: *base.query); |
259 | base.query.reset(); |
260 | result->query = std::move(query_obj.plan); |
261 | |
262 | // construct the set of columns based on the names and types of the query |
263 | auto &names = query_obj.names; |
264 | auto &sql_types = query_obj.types; |
265 | D_ASSERT(names.size() == sql_types.size()); |
266 | base.columns.SetAllowDuplicates(true); |
267 | for (idx_t i = 0; i < names.size(); i++) { |
268 | base.columns.AddColumn(column: ColumnDefinition(names[i], sql_types[i])); |
269 | } |
270 | CreateColumnDependencyManager(info&: *result); |
271 | // bind the generated column expressions |
272 | BindGeneratedColumns(info&: *result); |
273 | } else { |
274 | CreateColumnDependencyManager(info&: *result); |
275 | // bind the generated column expressions |
276 | BindGeneratedColumns(info&: *result); |
277 | // bind any constraints |
278 | BindConstraints(binder&: *this, info&: *result); |
279 | // bind the default values |
280 | BindDefaultValues(columns: base.columns, bound_defaults&: result->bound_defaults); |
281 | } |
282 | // extract dependencies from any default values or CHECK constraints |
283 | ExtractDependencies(info&: *result); |
284 | |
285 | if (base.columns.PhysicalColumnCount() == 0) { |
286 | throw BinderException("Creating a table without physical (non-generated) columns is not supported" ); |
287 | } |
288 | // bind collations to detect any unsupported collation errors |
289 | for (idx_t i = 0; i < base.columns.PhysicalColumnCount(); i++) { |
290 | auto &column = base.columns.GetColumnMutable(index: PhysicalIndex(i)); |
291 | if (column.Type().id() == LogicalTypeId::VARCHAR) { |
292 | ExpressionBinder::TestCollation(context, collation: StringType::GetCollation(type: column.Type())); |
293 | } |
294 | BindLogicalType(context, type&: column.TypeMutable(), catalog: &result->schema.catalog); |
295 | // We add a catalog dependency |
296 | auto type_dependency = EnumType::GetCatalog(type: column.Type()); |
297 | |
298 | if (type_dependency) { |
299 | // Only if the USER comes from a create type |
300 | if (!schema.catalog.IsTemporaryCatalog()) { |
301 | // If it is not a TEMP table we add a dependency |
302 | result->dependencies.AddDependency(entry&: *type_dependency); |
303 | } else { |
304 | auto enum_type = type_dependency->user_type; |
305 | auto &enum_entries = EnumType::GetValuesInsertOrder(type: enum_type); |
306 | auto enum_size = EnumType::GetSize(type: enum_type); |
307 | Vector copy_enum_entries_vec(LogicalType::VARCHAR, enum_size); |
308 | auto copy_enum_entries_ptr = FlatVector::GetData<string_t>(vector&: copy_enum_entries_vec); |
309 | auto enum_entries_ptr = FlatVector::GetData<string_t>(vector: enum_entries); |
310 | for (idx_t enum_idx = 0; enum_idx < enum_size; enum_idx++) { |
311 | copy_enum_entries_ptr[enum_idx] = |
312 | StringVector::AddStringOrBlob(vector&: copy_enum_entries_vec, data: enum_entries_ptr[enum_idx]); |
313 | } |
314 | auto copy_type = LogicalType::ENUM(enum_name: EnumType::GetTypeName(type: enum_type), ordered_data&: copy_enum_entries_vec, size: enum_size); |
315 | column.SetType(copy_type); |
316 | } |
317 | } |
318 | } |
319 | result->dependencies.VerifyDependencies(catalog&: schema.catalog, name: result->Base().table); |
320 | properties.allow_stream_result = false; |
321 | return result; |
322 | } |
323 | |
324 | unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateInfo> info) { |
325 | auto &base = info->Cast<CreateTableInfo>(); |
326 | auto &schema = BindCreateSchema(info&: base); |
327 | return BindCreateTableInfo(info: std::move(info), schema); |
328 | } |
329 | |
330 | vector<unique_ptr<Expression>> Binder::BindCreateIndexExpressions(TableCatalogEntry &table, CreateIndexInfo &info) { |
331 | auto index_binder = IndexBinder(*this, this->context, &table, &info); |
332 | vector<unique_ptr<Expression>> expressions; |
333 | expressions.reserve(n: info.expressions.size()); |
334 | for (auto &expr : info.expressions) { |
335 | expressions.push_back(x: index_binder.Bind(expr)); |
336 | } |
337 | |
338 | return expressions; |
339 | } |
340 | |
341 | } // namespace duckdb |
342 | |