diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index a6ed9849e77..5748aa9a1a9 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -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; /* diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 2f5b7007ff9..df1ba112b35 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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); diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 624c415dadb..6c9ac812aa0 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -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); diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out index 029beb20aae..90639ea0d89 100644 --- a/src/test/regress/expected/create_table.out +++ b/src/test/regress/expected/create_table.out @@ -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 -- diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql index 9b3e93b4164..80e424e6bda 100644 --- a/src/test/regress/sql/create_table.sql +++ b/src/test/regress/sql/create_table.sql @@ -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 --