Skip to content

Commit 749fb12

Browse files
alvherrereshke
authored andcommitted
Create FKs properly when attaching table as partition
Commit f56f8f8 added some code in CloneFkReferencing that's way too lax about a Constraint node it manufactures, not initializing enough struct members -- initially_valid in particular was forgotten. This causes some FKs in partitions added by ALTER TABLE ATTACH PARTITION to be marked as not validated. Set initially_valid true, which fixes the bug. While at it, make the struct initialization more complete. Very similar code was added in two other places by the same commit; make them all follow the same pattern for consistency, though no bugs are apparent there. This bug has never been reported: I only happened to notice while working on commit 614a406. The test case that was added there with the improper result is repaired. Backpatch to 12. Discussion: https://postgr.es/m/20221005105523.bhuhkdx4olajboof@alvherre.pgsql
1 parent b90e568 commit 749fb12

2 files changed

Lines changed: 37 additions & 10 deletions

File tree

src/backend/commands/tablecmds.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11951,14 +11951,21 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel)
1195111951
mapped_confkey[i] = attmap->attnums[confkey[i] - 1];
1195211952

1195311953
fkconstraint = makeNode(Constraint);
11954-
/* for now this is all we need */
11954+
fkconstraint->contype = CONSTRAINT_FOREIGN;
1195511955
fkconstraint->conname = NameStr(constrForm->conname);
11956-
fkconstraint->fk_upd_action = constrForm->confupdtype;
11957-
fkconstraint->fk_del_action = constrForm->confdeltype;
1195811956
fkconstraint->deferrable = constrForm->condeferrable;
1195911957
fkconstraint->initdeferred = constrForm->condeferred;
11960-
fkconstraint->initially_valid = true;
11958+
fkconstraint->location = -1;
11959+
fkconstraint->pktable = NULL;
11960+
/* ->fk_attrs determined below */
11961+
fkconstraint->pk_attrs = NIL;
1196111962
fkconstraint->fk_matchtype = constrForm->confmatchtype;
11963+
fkconstraint->fk_upd_action = constrForm->confupdtype;
11964+
fkconstraint->fk_del_action = constrForm->confdeltype;
11965+
fkconstraint->old_conpfeqop = NIL;
11966+
fkconstraint->old_pktable_oid = InvalidOid;
11967+
fkconstraint->skip_validation = false;
11968+
fkconstraint->initially_valid = true;
1196211969

1196311970
/* set up colnames that are used to generate the constraint name */
1196411971
for (int i = 0; i < numfks; i++)
@@ -12130,11 +12137,21 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
1213012137

1213112138
/* No dice. Set up to create our own constraint */
1213212139
fkconstraint = makeNode(Constraint);
12133-
fkconstraint->fk_upd_action = constrForm->confupdtype;
12134-
fkconstraint->fk_del_action = constrForm->confdeltype;
12140+
fkconstraint->contype = CONSTRAINT_FOREIGN;
12141+
/* ->conname determined below */
1213512142
fkconstraint->deferrable = constrForm->condeferrable;
1213612143
fkconstraint->initdeferred = constrForm->condeferred;
12144+
fkconstraint->location = -1;
12145+
fkconstraint->pktable = NULL;
12146+
/* ->fk_attrs determined below */
12147+
fkconstraint->pk_attrs = NIL;
1213712148
fkconstraint->fk_matchtype = constrForm->confmatchtype;
12149+
fkconstraint->fk_upd_action = constrForm->confupdtype;
12150+
fkconstraint->fk_del_action = constrForm->confdeltype;
12151+
fkconstraint->old_conpfeqop = NIL;
12152+
fkconstraint->old_pktable_oid = InvalidOid;
12153+
fkconstraint->skip_validation = false;
12154+
fkconstraint->initially_valid = true;
1213812155
for (int i = 0; i < numfks; i++)
1213912156
{
1214012157
Form_pg_attribute att;
@@ -22433,11 +22450,21 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
2243322450
* still do), but now we need separate ones of our own.
2243422451
*/
2243522452
fkconstraint = makeNode(Constraint);
22453+
fkconstraint->contype = CONSTRAINT_FOREIGN;
2243622454
fkconstraint->conname = pstrdup(NameStr(conform->conname));
22437-
fkconstraint->fk_upd_action = conform->confupdtype;
22438-
fkconstraint->fk_del_action = conform->confdeltype;
2243922455
fkconstraint->deferrable = conform->condeferrable;
2244022456
fkconstraint->initdeferred = conform->condeferred;
22457+
fkconstraint->location = -1;
22458+
fkconstraint->pktable = NULL;
22459+
fkconstraint->fk_attrs = NIL;
22460+
fkconstraint->pk_attrs = NIL;
22461+
fkconstraint->fk_matchtype = conform->confmatchtype;
22462+
fkconstraint->fk_upd_action = conform->confupdtype;
22463+
fkconstraint->fk_del_action = conform->confdeltype;
22464+
fkconstraint->old_conpfeqop = NIL;
22465+
fkconstraint->old_pktable_oid = InvalidOid;
22466+
fkconstraint->skip_validation = false;
22467+
fkconstraint->initially_valid = true;
2244122468

2244222469
createForeignKeyActionTriggers(partRel, conform->confrelid,
2244322470
fkconstraint, fk->conoid,

src/test/regress/expected/foreign_key.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,7 +1966,7 @@ ORDER BY co.contype, cr.relname, co.conname, p.conname;
19661966
----------------+----------------------------+---------+--------------+----------------------------+--------------+----------------
19671967
part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
19681968
part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
1969-
part32_self_fk | parted_self_fk_id_abc_fkey | f | f | parted_self_fk_id_abc_fkey | t | parted_self_fk
1969+
part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
19701970
part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
19711971
part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
19721972
parted_self_fk | parted_self_fk_id_abc_fkey | f | t | | | parted_self_fk
@@ -1995,7 +1995,7 @@ ORDER BY co.contype, cr.relname, co.conname, p.conname;
19951995
----------------+----------------------------+---------+--------------+----------------------------+--------------+----------------
19961996
part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
19971997
part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
1998-
part32_self_fk | parted_self_fk_id_abc_fkey | f | f | parted_self_fk_id_abc_fkey | t | parted_self_fk
1998+
part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
19991999
part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20002000
part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20012001
parted_self_fk | parted_self_fk_id_abc_fkey | f | t | | | parted_self_fk

0 commit comments

Comments
 (0)