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_binder/check_binder.hpp" |
7 | #include "duckdb/planner/expression_binder/constant_binder.hpp" |
8 | #include "duckdb/parser/parsed_data/create_table_info.hpp" |
9 | #include "duckdb/planner/parsed_data/bound_create_table_info.hpp" |
10 | |
11 | using namespace duckdb; |
12 | using namespace std; |
13 | |
14 | static void CreateColumnMap(BoundCreateTableInfo &info) { |
15 | auto &base = (CreateTableInfo &)*info.base; |
16 | |
17 | for (uint64_t oid = 0; oid < base.columns.size(); oid++) { |
18 | auto &col = base.columns[oid]; |
19 | if (info.name_map.find(col.name) != info.name_map.end()) { |
20 | throw CatalogException("Column with name %s already exists!" , col.name.c_str()); |
21 | } |
22 | |
23 | info.name_map[col.name] = oid; |
24 | col.oid = oid; |
25 | } |
26 | } |
27 | |
28 | static void BindConstraints(Binder &binder, BoundCreateTableInfo &info) { |
29 | auto &base = (CreateTableInfo &)*info.base; |
30 | |
31 | bool has_primary_key = false; |
32 | unordered_set<idx_t> primary_keys; |
33 | for (idx_t i = 0; i < base.constraints.size(); i++) { |
34 | auto &cond = base.constraints[i]; |
35 | switch (cond->type) { |
36 | case ConstraintType::CHECK: { |
37 | auto bound_constraint = make_unique<BoundCheckConstraint>(); |
38 | // check constraint: bind the expression |
39 | CheckBinder check_binder(binder, binder.context, base.table, base.columns, bound_constraint->bound_columns); |
40 | auto &check = (CheckConstraint &)*cond; |
41 | // create a copy of the unbound expression because the binding destroys the constraint |
42 | auto unbound_expression = check.expression->Copy(); |
43 | // now bind the constraint and create a new BoundCheckConstraint |
44 | bound_constraint->expression = check_binder.Bind(check.expression); |
45 | info.bound_constraints.push_back(move(bound_constraint)); |
46 | // move the unbound constraint back into the original check expression |
47 | check.expression = move(unbound_expression); |
48 | break; |
49 | } |
50 | case ConstraintType::NOT_NULL: { |
51 | auto ¬_null = (NotNullConstraint &)*cond; |
52 | info.bound_constraints.push_back(make_unique<BoundNotNullConstraint>(not_null.index)); |
53 | break; |
54 | } |
55 | case ConstraintType::UNIQUE: { |
56 | auto &unique = (UniqueConstraint &)*cond; |
57 | // have to resolve columns of the unique constraint |
58 | unordered_set<idx_t> keys; |
59 | if (unique.index != INVALID_INDEX) { |
60 | assert(unique.index < base.columns.size()); |
61 | // unique constraint is given by single index |
62 | keys.insert(unique.index); |
63 | } else { |
64 | // unique constraint is given by list of names |
65 | // have to resolve names |
66 | assert(unique.columns.size() > 0); |
67 | for (auto &keyname : unique.columns) { |
68 | auto entry = info.name_map.find(keyname); |
69 | if (entry == info.name_map.end()) { |
70 | throw ParserException("column \"%s\" named in key does not exist" , keyname.c_str()); |
71 | } |
72 | if (find(keys.begin(), keys.end(), entry->second) != keys.end()) { |
73 | throw ParserException("column \"%s\" appears twice in " |
74 | "primary key constraint" , |
75 | keyname.c_str()); |
76 | } |
77 | keys.insert(entry->second); |
78 | } |
79 | } |
80 | |
81 | if (unique.is_primary_key) { |
82 | // we can only have one primary key per table |
83 | if (has_primary_key) { |
84 | throw ParserException("table \"%s\" has more than one primary key" , base.table.c_str()); |
85 | } |
86 | has_primary_key = true; |
87 | primary_keys = keys; |
88 | } |
89 | info.bound_constraints.push_back(make_unique<BoundUniqueConstraint>(keys, unique.is_primary_key)); |
90 | break; |
91 | } |
92 | default: |
93 | throw NotImplementedException("unrecognized constraint type in bind" ); |
94 | } |
95 | } |
96 | if (has_primary_key) { |
97 | // if there is a primary key index, also create a NOT NULL constraint for each of the columns |
98 | for (auto &column_index : primary_keys) { |
99 | base.constraints.push_back(make_unique<NotNullConstraint>(column_index)); |
100 | info.bound_constraints.push_back(make_unique<BoundNotNullConstraint>(column_index)); |
101 | } |
102 | } |
103 | } |
104 | |
105 | void Binder::BindDefaultValues(vector<ColumnDefinition> &columns, vector<unique_ptr<Expression>> &bound_defaults) { |
106 | for (idx_t i = 0; i < columns.size(); i++) { |
107 | unique_ptr<Expression> bound_default; |
108 | if (columns[i].default_value) { |
109 | // we bind a copy of the DEFAULT value because binding is destructive |
110 | // and we want to keep the original expression around for serialization |
111 | auto default_copy = columns[i].default_value->Copy(); |
112 | ConstantBinder default_binder(*this, context, "DEFAULT value" ); |
113 | default_binder.target_type = columns[i].type; |
114 | bound_default = default_binder.Bind(default_copy); |
115 | } else { |
116 | // no default value specified: push a default value of constant null |
117 | bound_default = make_unique<BoundConstantExpression>(Value(GetInternalType(columns[i].type))); |
118 | } |
119 | bound_defaults.push_back(move(bound_default)); |
120 | } |
121 | } |
122 | |
123 | unique_ptr<BoundCreateTableInfo> Binder::BindCreateTableInfo(unique_ptr<CreateInfo> info) { |
124 | auto &base = (CreateTableInfo &)*info; |
125 | |
126 | auto result = make_unique<BoundCreateTableInfo>(move(info)); |
127 | result->schema = BindSchema(*result->base); |
128 | if (base.query) { |
129 | // construct the result object |
130 | auto query_obj = Bind(*base.query); |
131 | result->query = move(query_obj.plan); |
132 | |
133 | // construct the set of columns based on the names and types of the query |
134 | auto &names = query_obj.names; |
135 | auto &sql_types = query_obj.types; |
136 | assert(names.size() == sql_types.size()); |
137 | for (idx_t i = 0; i < names.size(); i++) { |
138 | base.columns.push_back(ColumnDefinition(names[i], sql_types[i])); |
139 | } |
140 | // create the name map for the statement |
141 | CreateColumnMap(*result); |
142 | } else { |
143 | // create the name map for the statement |
144 | CreateColumnMap(*result); |
145 | // bind any constraints |
146 | BindConstraints(*this, *result); |
147 | // bind the default values |
148 | BindDefaultValues(base.columns, result->bound_defaults); |
149 | } |
150 | // bind collations to detect any unsupported collation errors |
151 | for (auto &column : base.columns) { |
152 | ExpressionBinder::PushCollation(context, nullptr, column.type.collation); |
153 | } |
154 | return result; |
155 | } |
156 | |