Skip to content

Commit b0284bf

Browse files
committed
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 2fe4c73 commit b0284bf

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

src/backend/commands/tablecmds.c

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10092,14 +10092,22 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel)
1009210092
mapped_confkey[i] = attmap->attnums[confkey[i] - 1];
1009310093

1009410094
fkconstraint = makeNode(Constraint);
10095-
/* for now this is all we need */
10095+
fkconstraint->contype = CONSTRAINT_FOREIGN;
1009610096
fkconstraint->conname = NameStr(constrForm->conname);
10097-
fkconstraint->fk_upd_action = constrForm->confupdtype;
10098-
fkconstraint->fk_del_action = constrForm->confdeltype;
1009910097
fkconstraint->deferrable = constrForm->condeferrable;
1010010098
fkconstraint->initdeferred = constrForm->condeferred;
10101-
fkconstraint->initially_valid = true;
10099+
fkconstraint->location = -1;
10100+
fkconstraint->pktable = NULL;
10101+
/* ->fk_attrs determined below */
10102+
fkconstraint->pk_attrs = NIL;
1010210103
fkconstraint->fk_matchtype = constrForm->confmatchtype;
10104+
fkconstraint->fk_upd_action = constrForm->confupdtype;
10105+
fkconstraint->fk_del_action = constrForm->confdeltype;
10106+
fkconstraint->fk_del_set_cols = NIL;
10107+
fkconstraint->old_conpfeqop = NIL;
10108+
fkconstraint->old_pktable_oid = InvalidOid;
10109+
fkconstraint->skip_validation = false;
10110+
fkconstraint->initially_valid = true;
1010310111

1010410112
/* set up colnames that are used to generate the constraint name */
1010510113
for (int i = 0; i < numfks; i++)
@@ -10317,11 +10325,22 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
1031710325

1031810326
/* No dice. Set up to create our own constraint */
1031910327
fkconstraint = makeNode(Constraint);
10320-
fkconstraint->fk_upd_action = constrForm->confupdtype;
10321-
fkconstraint->fk_del_action = constrForm->confdeltype;
10328+
fkconstraint->contype = CONSTRAINT_FOREIGN;
10329+
/* ->conname determined below */
1032210330
fkconstraint->deferrable = constrForm->condeferrable;
1032310331
fkconstraint->initdeferred = constrForm->condeferred;
10332+
fkconstraint->location = -1;
10333+
fkconstraint->pktable = NULL;
10334+
/* ->fk_attrs determined below */
10335+
fkconstraint->pk_attrs = NIL;
1032410336
fkconstraint->fk_matchtype = constrForm->confmatchtype;
10337+
fkconstraint->fk_upd_action = constrForm->confupdtype;
10338+
fkconstraint->fk_del_action = constrForm->confdeltype;
10339+
fkconstraint->fk_del_set_cols = NIL;
10340+
fkconstraint->old_conpfeqop = NIL;
10341+
fkconstraint->old_pktable_oid = InvalidOid;
10342+
fkconstraint->skip_validation = false;
10343+
fkconstraint->initially_valid = true;
1032510344
for (int i = 0; i < numfks; i++)
1032610345
{
1032710346
Form_pg_attribute att;
@@ -18517,11 +18536,22 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
1851718536
* still do), but now we need separate ones of our own.
1851818537
*/
1851918538
fkconstraint = makeNode(Constraint);
18539+
fkconstraint->contype = CONSTRAINT_FOREIGN;
1852018540
fkconstraint->conname = pstrdup(NameStr(conform->conname));
18521-
fkconstraint->fk_upd_action = conform->confupdtype;
18522-
fkconstraint->fk_del_action = conform->confdeltype;
1852318541
fkconstraint->deferrable = conform->condeferrable;
1852418542
fkconstraint->initdeferred = conform->condeferred;
18543+
fkconstraint->location = -1;
18544+
fkconstraint->pktable = NULL;
18545+
fkconstraint->fk_attrs = NIL;
18546+
fkconstraint->pk_attrs = NIL;
18547+
fkconstraint->fk_matchtype = conform->confmatchtype;
18548+
fkconstraint->fk_upd_action = conform->confupdtype;
18549+
fkconstraint->fk_del_action = conform->confdeltype;
18550+
fkconstraint->fk_del_set_cols = NIL;
18551+
fkconstraint->old_conpfeqop = NIL;
18552+
fkconstraint->old_pktable_oid = InvalidOid;
18553+
fkconstraint->skip_validation = false;
18554+
fkconstraint->initially_valid = true;
1852518555

1852618556
createForeignKeyActionTriggers(partRel, conform->confrelid,
1852718557
fkconstraint, fk->conoid,

src/test/regress/expected/foreign_key.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,7 +2031,7 @@ ORDER BY co.contype, cr.relname, co.conname, p.conname;
20312031
----------------+----------------------------+---------+--------------+----------------------------+--------------+----------------
20322032
part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20332033
part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
2034-
part32_self_fk | parted_self_fk_id_abc_fkey | f | f | parted_self_fk_id_abc_fkey | t | parted_self_fk
2034+
part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20352035
part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20362036
part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20372037
parted_self_fk | parted_self_fk_id_abc_fkey | f | t | | | parted_self_fk
@@ -2060,7 +2060,7 @@ ORDER BY co.contype, cr.relname, co.conname, p.conname;
20602060
----------------+----------------------------+---------+--------------+----------------------------+--------------+----------------
20612061
part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20622062
part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
2063-
part32_self_fk | parted_self_fk_id_abc_fkey | f | f | parted_self_fk_id_abc_fkey | t | parted_self_fk
2063+
part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20642064
part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20652065
part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk
20662066
parted_self_fk | parted_self_fk_id_abc_fkey | f | t | | | parted_self_fk

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy