Skip to content

Commit 0a16c83

Browse files
committed
Add missing CommandCounterIncrement
For commit b663b94 I thought this was useless, but turns out not to be for the case where a partitioned table has two identical foreign key constraints which can both be matched by the same constraint in a partition during attach. This CCI makes the match search for the second constraint in the parent ignore the constraint in the child that has already been matched by the first constraint in the parent. Reported-by: Alexander Lakhin <exclusion@gmail.com> Discussion: https://postgr.es/m/c599253c-1ccd-4161-80fc-c9065e037a09@gmail.com
1 parent d28cd3e commit 0a16c83

File tree

3 files changed

+31
-10
lines changed

3 files changed

+31
-10
lines changed

src/backend/commands/tablecmds.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11564,22 +11564,22 @@ tryAttachPartitionForeignKey(List **wqueue,
1156411564
table_close(pg_constraint, RowShareLock);
1156511565
}
1156611566

11567+
/*
11568+
* We updated this pg_constraint row above to set its parent; validating
11569+
* it will cause its convalidated flag to change, so we need CCI here. In
11570+
* addition, we need it unconditionally for the rare case where the parent
11571+
* table has *two* identical constraints; when reaching this function for
11572+
* the second one, we must have made our changes visible, otherwise we
11573+
* would try to attach both to this one.
11574+
*/
11575+
CommandCounterIncrement();
11576+
1156711577
/* If validation is needed, put it in the queue now. */
1156811578
if (queueValidation)
1156911579
{
1157011580
Relation conrel;
1157111581

11572-
/*
11573-
* We updated this pg_constraint row above to set its parent;
11574-
* validating it will cause its convalidated flag to change, so we
11575-
* need CCI here. XXX it might work better to effect the convalidated
11576-
* changes for all constraints together during phase 3, but that
11577-
* requires more invasive code surgery.
11578-
*/
11579-
CommandCounterIncrement();
11580-
1158111582
conrel = table_open(ConstraintRelationId, RowExclusiveLock);
11582-
1158311583
partcontup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(fk->conoid));
1158411584
if (!HeapTupleIsValid(partcontup))
1158511585
elog(ERROR, "cache lookup failed for constraint %u", fk->conoid);

src/test/regress/expected/foreign_key.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,16 @@ CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_6) PARTITIO
20622062
ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1);
20632063
ERROR: cannot attach table "fk_partitioned_pk_6" as a partition because it is referenced by foreign key "fk_partitioned_fk_6_a_fkey"
20642064
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
2065+
-- Verify that attaching to a parent with two identical constraints work
2066+
CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY);
2067+
CREATE TABLE fk_partitioned_fk_6 (a int,
2068+
FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6,
2069+
FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6
2070+
) PARTITION BY LIST (a);
2071+
CREATE TABLE fk_partitioned_fk_6_1 PARTITION OF fk_partitioned_fk_6 FOR VALUES IN (1);
2072+
ALTER TABLE fk_partitioned_fk_6 DETACH PARTITION fk_partitioned_fk_6_1;
2073+
ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_fk_6_1 FOR VALUES IN (1);
2074+
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
20652075
-- This case is similar to above, but the referenced relation is one level
20662076
-- lower in the hierarchy. This one fails in a different way as the above,
20672077
-- because we don't bother to protect against this case explicitly. If the

src/test/regress/sql/foreign_key.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,6 +1491,17 @@ CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_6) PARTITIO
14911491
ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1);
14921492
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
14931493

1494+
-- Verify that attaching to a parent with two identical constraints work
1495+
CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY);
1496+
CREATE TABLE fk_partitioned_fk_6 (a int,
1497+
FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6,
1498+
FOREIGN KEY (a) REFERENCES fk_partitioned_pk_6
1499+
) PARTITION BY LIST (a);
1500+
CREATE TABLE fk_partitioned_fk_6_1 PARTITION OF fk_partitioned_fk_6 FOR VALUES IN (1);
1501+
ALTER TABLE fk_partitioned_fk_6 DETACH PARTITION fk_partitioned_fk_6_1;
1502+
ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_fk_6_1 FOR VALUES IN (1);
1503+
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
1504+
14941505
-- This case is similar to above, but the referenced relation is one level
14951506
-- lower in the hierarchy. This one fails in a different way as the above,
14961507
-- because we don't bother to protect against this case explicitly. If the

0 commit comments

Comments
 (0)