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
This commit is contained in:
parent
adb466150b
commit
e7936f8b3e
@ -10304,16 +10304,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;
|
||||
@ -10328,6 +10318,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 =
|
||||
|
@ -603,6 +603,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;
|
||||
|
@ -430,6 +430,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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user