mirror of
https://github.com/postgres/postgres.git
synced 2026-03-22 18:33:19 -04:00
Avoid name collision with NOT NULL constraints
If a CREATE TABLE statement defined a constraint whose name is identical to the name generated for a NOT NULL constraint, we'd throw an (unnecessary) unique key violation error on pg_constraint_conrelid_contypid_conname_index: this can easily be avoided by choosing a different name for the NOT NULL constraint. Fix by passing the constraint names already created by AddRelationNewConstraints() to AddRelationNotNullConstraints(), so that the latter can avoid name collisions with them. Bug: #19393 Author: Laurenz Albe <laurenz.albe@cybertec.at> Reported-by: Hüseyin Demir <huseyin.d3r@gmail.com> Backpatch-through: 18 Discussion: https://postgr.es/m/19393-6a82427485a744cf@postgresql.org
This commit is contained in:
parent
36bbcd5be3
commit
0eeffd31bf
5 changed files with 34 additions and 8 deletions
|
|
@ -2886,14 +2886,16 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
|
|||
* for each column, giving priority to user-specified ones, and setting
|
||||
* inhcount according to how many parents cause each column to get a
|
||||
* not-null constraint. If a user-specified name clashes with another
|
||||
* user-specified name, an error is raised.
|
||||
* user-specified name, an error is raised. 'existing_constraints'
|
||||
* is a list of already defined constraint names, which should be avoided
|
||||
* when generating further ones.
|
||||
*
|
||||
* Returns a list of AttrNumber for columns that need to have the attnotnull
|
||||
* flag set.
|
||||
*/
|
||||
List *
|
||||
AddRelationNotNullConstraints(Relation rel, List *constraints,
|
||||
List *old_notnulls)
|
||||
List *old_notnulls, List *existing_constraints)
|
||||
{
|
||||
List *givennames;
|
||||
List *nnnames;
|
||||
|
|
@ -2905,7 +2907,7 @@ AddRelationNotNullConstraints(Relation rel, List *constraints,
|
|||
* because we must raise error for user-generated name conflicts, but for
|
||||
* system-generated name conflicts we just generate another.
|
||||
*/
|
||||
nnnames = NIL;
|
||||
nnnames = list_copy(existing_constraints); /* don't scribble on input */
|
||||
givennames = NIL;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -781,6 +781,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
|
|||
List *rawDefaults;
|
||||
List *cookedDefaults;
|
||||
List *nncols;
|
||||
List *connames = NIL;
|
||||
Datum reloptions;
|
||||
ListCell *listptr;
|
||||
AttrNumber attnum;
|
||||
|
|
@ -1335,11 +1336,20 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
|
|||
/*
|
||||
* Now add any newly specified CHECK constraints to the new relation. Same
|
||||
* as for defaults above, but these need to come after partitioning is set
|
||||
* up.
|
||||
* up. We save the constraint names that were used, to avoid dupes below.
|
||||
*/
|
||||
if (stmt->constraints)
|
||||
AddRelationNewConstraints(rel, NIL, stmt->constraints,
|
||||
true, true, false, queryString);
|
||||
{
|
||||
List *conlist;
|
||||
|
||||
conlist = AddRelationNewConstraints(rel, NIL, stmt->constraints,
|
||||
true, true, false, queryString);
|
||||
foreach_ptr(CookedConstraint, cons, conlist)
|
||||
{
|
||||
if (cons->name != NULL)
|
||||
connames = lappend(connames, cons->name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, merge the not-null constraints that are declared directly with
|
||||
|
|
@ -1348,7 +1358,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
|
|||
* columns that don't yet have it.
|
||||
*/
|
||||
nncols = AddRelationNotNullConstraints(rel, stmt->nnconstraints,
|
||||
old_notnulls);
|
||||
old_notnulls, connames);
|
||||
foreach_int(attrnum, nncols)
|
||||
set_attnotnull(NULL, rel, attrnum, true, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ extern List *AddRelationNewConstraints(Relation rel,
|
|||
const char *queryString);
|
||||
extern List *AddRelationNotNullConstraints(Relation rel,
|
||||
List *constraints,
|
||||
List *old_notnulls);
|
||||
List *old_notnulls,
|
||||
List *existing_constraints);
|
||||
|
||||
extern void RelationClearMissing(Relation rel);
|
||||
|
||||
|
|
|
|||
|
|
@ -161,6 +161,12 @@ ALTER TABLE remember_node_subid ALTER c TYPE bigint;
|
|||
SAVEPOINT q; DROP TABLE remember_node_subid; ROLLBACK TO q;
|
||||
COMMIT;
|
||||
DROP TABLE remember_node_subid;
|
||||
-- generated NOT NULL constraint names must not collide with explicitly named constraints
|
||||
CREATE TABLE two_not_null_constraints (
|
||||
col integer NOT NULL,
|
||||
CONSTRAINT two_not_null_constraints_col_not_null CHECK (col IS NOT NULL)
|
||||
);
|
||||
DROP TABLE two_not_null_constraints;
|
||||
--
|
||||
-- Partitioned tables
|
||||
--
|
||||
|
|
|
|||
|
|
@ -105,6 +105,13 @@ SAVEPOINT q; DROP TABLE remember_node_subid; ROLLBACK TO q;
|
|||
COMMIT;
|
||||
DROP TABLE remember_node_subid;
|
||||
|
||||
-- generated NOT NULL constraint names must not collide with explicitly named constraints
|
||||
CREATE TABLE two_not_null_constraints (
|
||||
col integer NOT NULL,
|
||||
CONSTRAINT two_not_null_constraints_col_not_null CHECK (col IS NOT NULL)
|
||||
);
|
||||
DROP TABLE two_not_null_constraints;
|
||||
|
||||
--
|
||||
-- Partitioned tables
|
||||
--
|
||||
|
|
|
|||
Loading…
Reference in a new issue