| 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 | |