aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2022-09-08 13:17:02 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2022-09-08 13:17:02 +0200
commit640c20d6266ddc89e7969c697681d3f869f92dfb (patch)
tree3a36897d5deb9bf7b526701837640ff4a66a0798
parenta254545a54a2e14ec6f41b8190d6c6713a85a18a (diff)
downloadpostgresql-640c20d6266ddc89e7969c697681d3f869f92dfb.tar.gz
postgresql-640c20d6266ddc89e7969c697681d3f869f92dfb.zip
Choose FK name correctly during partition attachment
During ALTER TABLE ATTACH PARTITION, if the name of a parent's foreign key constraint is already used on the partition, the code tries to choose another one before the FK attributes list has been populated, so the resulting constraint name was "<relname>__fkey" instead of "<relname>_<attrs>_fkey". Repair, and add a test case. Backpatch to 12. In 11, the code to attach a partition was not smart enough to cope with conflicting constraint names, so the problem doesn't exist there. Author: Jehan-Guillaume de Rorthais <jgdr@dalibo.com> Discussion: https://postgr.es/m/20220901184156.738ebee5@karst
-rw-r--r--src/backend/commands/tablecmds.c20
-rw-r--r--src/test/regress/input/constraints.source19
-rw-r--r--src/test/regress/output/constraints.source23
3 files changed, 52 insertions, 10 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 103c53c72a6..f19969fb10e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -10024,16 +10024,6 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
/* No dice. Set up to create our own constraint */
fkconstraint = makeNode(Constraint);
- if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
- RelationGetRelid(partRel),
- NameStr(constrForm->conname)))
- fkconstraint->conname =
- ChooseConstraintName(RelationGetRelationName(partRel),
- ChooseForeignKeyConstraintNameAddition(fkconstraint->fk_attrs),
- "fkey",
- RelationGetNamespace(partRel), NIL);
- else
- fkconstraint->conname = pstrdup(NameStr(constrForm->conname));
fkconstraint->fk_upd_action = constrForm->confupdtype;
fkconstraint->fk_del_action = constrForm->confdeltype;
fkconstraint->deferrable = constrForm->condeferrable;
@@ -10048,6 +10038,16 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
fkconstraint->fk_attrs = lappend(fkconstraint->fk_attrs,
makeString(NameStr(att->attname)));
}
+ if (ConstraintNameIsUsed(CONSTRAINT_RELATION,
+ RelationGetRelid(partRel),
+ NameStr(constrForm->conname)))
+ fkconstraint->conname =
+ ChooseConstraintName(RelationGetRelationName(partRel),
+ ChooseForeignKeyConstraintNameAddition(fkconstraint->fk_attrs),
+ "fkey",
+ RelationGetNamespace(partRel), NIL);
+ else
+ fkconstraint->conname = pstrdup(NameStr(constrForm->conname));
indexOid = constrForm->conindid;
constrOid =
diff --git a/src/test/regress/input/constraints.source b/src/test/regress/input/constraints.source
index 6bb76483218..8fe9754904c 100644
--- a/src/test/regress/input/constraints.source
+++ b/src/test/regress/input/constraints.source
@@ -410,6 +410,25 @@ INSERT INTO parted_uniq_tbl VALUES (1); -- OK now, fail at commit
COMMIT;
DROP TABLE parted_uniq_tbl;
+-- test naming a constraint in a partition when a conflict exists
+CREATE TABLE parted_fk_naming (
+ id bigint NOT NULL default 1,
+ id_abc bigint,
+ CONSTRAINT dummy_constr FOREIGN KEY (id_abc)
+ REFERENCES parted_fk_naming (id),
+ PRIMARY KEY (id)
+)
+PARTITION BY LIST (id);
+CREATE TABLE parted_fk_naming_1 (
+ id bigint NOT NULL default 1,
+ id_abc bigint,
+ PRIMARY KEY (id),
+ CONSTRAINT dummy_constr CHECK (true)
+);
+ALTER TABLE parted_fk_naming ATTACH PARTITION parted_fk_naming_1 FOR VALUES IN ('1');
+SELECT conname FROM pg_constraint WHERE conrelid = 'parted_fk_naming_1'::regclass AND contype = 'f';
+DROP TABLE parted_fk_naming;
+
-- test a HOT update that invalidates the conflicting tuple.
-- the trigger should still fire and catch the violation
diff --git a/src/test/regress/output/constraints.source b/src/test/regress/output/constraints.source
index eff793cc3d3..28e3f2c717b 100644
--- a/src/test/regress/output/constraints.source
+++ b/src/test/regress/output/constraints.source
@@ -575,6 +575,29 @@ COMMIT;
ERROR: duplicate key value violates unique constraint "parted_uniq_tbl_1_i_key"
DETAIL: Key (i)=(1) already exists.
DROP TABLE parted_uniq_tbl;
+-- test naming a constraint in a partition when a conflict exists
+CREATE TABLE parted_fk_naming (
+ id bigint NOT NULL default 1,
+ id_abc bigint,
+ CONSTRAINT dummy_constr FOREIGN KEY (id_abc)
+ REFERENCES parted_fk_naming (id),
+ PRIMARY KEY (id)
+)
+PARTITION BY LIST (id);
+CREATE TABLE parted_fk_naming_1 (
+ id bigint NOT NULL default 1,
+ id_abc bigint,
+ PRIMARY KEY (id),
+ CONSTRAINT dummy_constr CHECK (true)
+);
+ALTER TABLE parted_fk_naming ATTACH PARTITION parted_fk_naming_1 FOR VALUES IN ('1');
+SELECT conname FROM pg_constraint WHERE conrelid = 'parted_fk_naming_1'::regclass AND contype = 'f';
+ conname
+--------------------------------
+ parted_fk_naming_1_id_abc_fkey
+(1 row)
+
+DROP TABLE parted_fk_naming;
-- test a HOT update that invalidates the conflicting tuple.
-- the trigger should still fire and catch the violation
BEGIN;