mirror of
https://github.com/postgres/postgres.git
synced 2026-04-21 22:28:15 -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
c5edc6c8ff
commit
8d9a97e0bb
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
|
* for each column, giving priority to user-specified ones, and setting
|
||||||
* inhcount according to how many parents cause each column to get a
|
* inhcount according to how many parents cause each column to get a
|
||||||
* not-null constraint. If a user-specified name clashes with another
|
* 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
|
* Returns a list of AttrNumber for columns that need to have the attnotnull
|
||||||
* flag set.
|
* flag set.
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
AddRelationNotNullConstraints(Relation rel, List *constraints,
|
AddRelationNotNullConstraints(Relation rel, List *constraints,
|
||||||
List *old_notnulls)
|
List *old_notnulls, List *existing_constraints)
|
||||||
{
|
{
|
||||||
List *givennames;
|
List *givennames;
|
||||||
List *nnnames;
|
List *nnnames;
|
||||||
|
|
@ -2905,7 +2907,7 @@ AddRelationNotNullConstraints(Relation rel, List *constraints,
|
||||||
* because we must raise error for user-generated name conflicts, but for
|
* because we must raise error for user-generated name conflicts, but for
|
||||||
* system-generated name conflicts we just generate another.
|
* system-generated name conflicts we just generate another.
|
||||||
*/
|
*/
|
||||||
nnnames = NIL;
|
nnnames = list_copy(existing_constraints); /* don't scribble on input */
|
||||||
givennames = NIL;
|
givennames = NIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -776,6 +776,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
|
||||||
List *rawDefaults;
|
List *rawDefaults;
|
||||||
List *cookedDefaults;
|
List *cookedDefaults;
|
||||||
List *nncols;
|
List *nncols;
|
||||||
|
List *connames = NIL;
|
||||||
Datum reloptions;
|
Datum reloptions;
|
||||||
ListCell *listptr;
|
ListCell *listptr;
|
||||||
AttrNumber attnum;
|
AttrNumber attnum;
|
||||||
|
|
@ -1329,11 +1330,20 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
|
||||||
/*
|
/*
|
||||||
* Now add any newly specified CHECK constraints to the new relation. Same
|
* 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
|
* 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)
|
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
|
* Finally, merge the not-null constraints that are declared directly with
|
||||||
|
|
@ -1342,7 +1352,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
|
||||||
* columns that don't yet have it.
|
* columns that don't yet have it.
|
||||||
*/
|
*/
|
||||||
nncols = AddRelationNotNullConstraints(rel, stmt->nnconstraints,
|
nncols = AddRelationNotNullConstraints(rel, stmt->nnconstraints,
|
||||||
old_notnulls);
|
old_notnulls, connames);
|
||||||
foreach_int(attrnum, nncols)
|
foreach_int(attrnum, nncols)
|
||||||
set_attnotnull(NULL, rel, attrnum, true, false);
|
set_attnotnull(NULL, rel, attrnum, true, false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ extern List *AddRelationNewConstraints(Relation rel,
|
||||||
const char *queryString);
|
const char *queryString);
|
||||||
extern List *AddRelationNotNullConstraints(Relation rel,
|
extern List *AddRelationNotNullConstraints(Relation rel,
|
||||||
List *constraints,
|
List *constraints,
|
||||||
List *old_notnulls);
|
List *old_notnulls,
|
||||||
|
List *existing_constraints);
|
||||||
|
|
||||||
extern void RelationClearMissing(Relation rel);
|
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;
|
SAVEPOINT q; DROP TABLE remember_node_subid; ROLLBACK TO q;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
DROP TABLE remember_node_subid;
|
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
|
-- Partitioned tables
|
||||||
--
|
--
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,13 @@ SAVEPOINT q; DROP TABLE remember_node_subid; ROLLBACK TO q;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
DROP TABLE remember_node_subid;
|
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
|
-- Partitioned tables
|
||||||
--
|
--
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue