diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2022-11-03 20:40:21 +0100 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2022-11-03 20:40:21 +0100 |
commit | c301e1c0c09cfedce9eb469744384a6d15e50745 (patch) | |
tree | a8db61d1d1a2d4ec16efb32b77f964deb2c0d7fd /src | |
parent | f2dc7f9e35a288d21dfdd74e56f8809862d02dd6 (diff) | |
download | postgresql-c301e1c0c09cfedce9eb469744384a6d15e50745.tar.gz postgresql-c301e1c0c09cfedce9eb469744384a6d15e50745.zip |
Create FKs properly when attaching table as partition
Commit f56f8f8da6af 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 614a406b4ff1. 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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/tablecmds.c | 46 | ||||
-rw-r--r-- | src/test/regress/expected/foreign_key.out | 4 |
2 files changed, 40 insertions, 10 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 793c4d7988d..eb7ff76d493 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -10126,14 +10126,22 @@ CloneFkReferenced(Relation parentRel, Relation partitionRel) mapped_confkey[i] = attmap->attnums[confkey[i] - 1]; fkconstraint = makeNode(Constraint); - /* for now this is all we need */ + fkconstraint->contype = CONSTRAINT_FOREIGN; fkconstraint->conname = NameStr(constrForm->conname); - fkconstraint->fk_upd_action = constrForm->confupdtype; - fkconstraint->fk_del_action = constrForm->confdeltype; fkconstraint->deferrable = constrForm->condeferrable; fkconstraint->initdeferred = constrForm->condeferred; - fkconstraint->initially_valid = true; + fkconstraint->location = -1; + fkconstraint->pktable = NULL; + /* ->fk_attrs determined below */ + fkconstraint->pk_attrs = NIL; fkconstraint->fk_matchtype = constrForm->confmatchtype; + fkconstraint->fk_upd_action = constrForm->confupdtype; + fkconstraint->fk_del_action = constrForm->confdeltype; + fkconstraint->fk_del_set_cols = NIL; + fkconstraint->old_conpfeqop = NIL; + fkconstraint->old_pktable_oid = InvalidOid; + fkconstraint->skip_validation = false; + fkconstraint->initially_valid = true; /* set up colnames that are used to generate the constraint name */ for (int i = 0; i < numfks; i++) @@ -10351,11 +10359,22 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel) /* No dice. Set up to create our own constraint */ fkconstraint = makeNode(Constraint); - fkconstraint->fk_upd_action = constrForm->confupdtype; - fkconstraint->fk_del_action = constrForm->confdeltype; + fkconstraint->contype = CONSTRAINT_FOREIGN; + /* ->conname determined below */ fkconstraint->deferrable = constrForm->condeferrable; fkconstraint->initdeferred = constrForm->condeferred; + fkconstraint->location = -1; + fkconstraint->pktable = NULL; + /* ->fk_attrs determined below */ + fkconstraint->pk_attrs = NIL; fkconstraint->fk_matchtype = constrForm->confmatchtype; + fkconstraint->fk_upd_action = constrForm->confupdtype; + fkconstraint->fk_del_action = constrForm->confdeltype; + fkconstraint->fk_del_set_cols = NIL; + fkconstraint->old_conpfeqop = NIL; + fkconstraint->old_pktable_oid = InvalidOid; + fkconstraint->skip_validation = false; + fkconstraint->initially_valid = true; for (int i = 0; i < numfks; i++) { Form_pg_attribute att; @@ -18571,11 +18590,22 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent, * still do), but now we need separate ones of our own. */ fkconstraint = makeNode(Constraint); + fkconstraint->contype = CONSTRAINT_FOREIGN; fkconstraint->conname = pstrdup(NameStr(conform->conname)); - fkconstraint->fk_upd_action = conform->confupdtype; - fkconstraint->fk_del_action = conform->confdeltype; fkconstraint->deferrable = conform->condeferrable; fkconstraint->initdeferred = conform->condeferred; + fkconstraint->location = -1; + fkconstraint->pktable = NULL; + fkconstraint->fk_attrs = NIL; + fkconstraint->pk_attrs = NIL; + fkconstraint->fk_matchtype = conform->confmatchtype; + fkconstraint->fk_upd_action = conform->confupdtype; + fkconstraint->fk_del_action = conform->confdeltype; + fkconstraint->fk_del_set_cols = NIL; + fkconstraint->old_conpfeqop = NIL; + fkconstraint->old_pktable_oid = InvalidOid; + fkconstraint->skip_validation = false; + fkconstraint->initially_valid = true; createForeignKeyActionTriggers(partRel, conform->confrelid, fkconstraint, fk->conoid, diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 91437198cf9..7beea18c7df 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -2031,7 +2031,7 @@ ORDER BY co.contype, cr.relname, co.conname, p.conname; ----------------+----------------------------+---------+--------------+----------------------------+--------------+---------------- part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part32_self_fk | parted_self_fk_id_abc_fkey | f | f | parted_self_fk_id_abc_fkey | t | parted_self_fk + part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk 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; ----------------+----------------------------+---------+--------------+----------------------------+--------------+---------------- part1_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk part2_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk - part32_self_fk | parted_self_fk_id_abc_fkey | f | f | parted_self_fk_id_abc_fkey | t | parted_self_fk + part32_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk part33_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk part3_self_fk | parted_self_fk_id_abc_fkey | f | t | parted_self_fk_id_abc_fkey | t | parted_self_fk parted_self_fk | parted_self_fk_id_abc_fkey | f | t | | | parted_self_fk |