Skip to content

Commit e6f98d8

Browse files
author
Álvaro Herrera
committed
Avoid bogus scans of partitions when marking FKs enforced
Similar to commit cc733ed: when an unenforced foreign key that references a partitioned table is altered to be enforced, we scan the constrained table based on each partition on the referenced partitioned table. This is bogus and likely to cause the ALTER TABLE to fail: we must only scan the constrained table as pointing to the top-level partitioned table. Oversight in commit eec0040. Fix by eliding those scans. Author: Amul Sul <sulamul@gmail.com> Reported-by: jian he <jian.universality@gmail.com> Discussion: https://postgr.es/m/CACJufxF1e_gPOLtsDoaE4VCgQPC8KZW_kPAjPR5Rvv4Ew=fb2A@mail.gmail.com
1 parent 04acad8 commit e6f98d8

File tree

3 files changed

+37
-22
lines changed

3 files changed

+37
-22
lines changed

src/backend/commands/tablecmds.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12466,9 +12466,12 @@ ATExecAlterConstrEnforceability(List **wqueue, ATAlterConstraint *cmdcon,
1246612466

1246712467
/*
1246812468
* Tell Phase 3 to check that the constraint is satisfied by existing
12469-
* rows.
12469+
* rows. Only applies to leaf partitions, and (for constraints that
12470+
* reference a partitioned table) only if this is not one of the
12471+
* pg_constraint rows that exist solely to support action triggers.
1247012472
*/
12471-
if (rel->rd_rel->relkind == RELKIND_RELATION)
12473+
if (rel->rd_rel->relkind == RELKIND_RELATION &&
12474+
currcon->confrelid == pkrelid)
1247212475
{
1247312476
AlteredTableInfo *tab;
1247412477
NewConstraint *newcon;

src/test/regress/expected/foreign_key.out

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,8 +1895,8 @@ WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass:
18951895
(5 rows)
18961896

18971897
DROP TABLE fk_partitioned_fk, fk_notpartitioned_pk;
1898-
-- NOT VALID foreign key on a non-partitioned table referencing a partitioned
1899-
-- table
1898+
-- NOT VALID and NOT ENFORCED foreign key on a non-partitioned table
1899+
-- referencing a partitioned table
19001900
CREATE TABLE fk_partitioned_pk (a int, b int, PRIMARY KEY (a, b)) PARTITION BY RANGE (a, b);
19011901
CREATE TABLE fk_partitioned_pk_1 PARTITION OF fk_partitioned_pk FOR VALUES FROM (0,0) TO (1000,1000);
19021902
CREATE TABLE fk_partitioned_pk_2 PARTITION OF fk_partitioned_pk FOR VALUES FROM (1000,1000) TO (2000,2000);
@@ -1905,26 +1905,35 @@ INSERT INTO fk_partitioned_pk VALUES(100,100), (1000,1000);
19051905
INSERT INTO fk_notpartitioned_fk VALUES(100,100), (1000,1000);
19061906
ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey
19071907
FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT VALID;
1908-
-- All constraints will be invalid.
1908+
ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey2
1909+
FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT ENFORCED;
1910+
-- All constraints will be invalid, and _fkey2 constraints will not be enforced.
19091911
SELECT conname, conenforced, convalidated FROM pg_constraint
19101912
WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text;
1911-
conname | conenforced | convalidated
1912-
---------------------------------+-------------+--------------
1913-
fk_notpartitioned_fk_a_b_fkey | t | f
1914-
fk_notpartitioned_fk_a_b_fkey_1 | t | f
1915-
fk_notpartitioned_fk_a_b_fkey_2 | t | f
1916-
(3 rows)
1913+
conname | conenforced | convalidated
1914+
----------------------------------+-------------+--------------
1915+
fk_notpartitioned_fk_a_b_fkey | t | f
1916+
fk_notpartitioned_fk_a_b_fkey_1 | t | f
1917+
fk_notpartitioned_fk_a_b_fkey_2 | t | f
1918+
fk_notpartitioned_fk_a_b_fkey2 | f | f
1919+
fk_notpartitioned_fk_a_b_fkey2_1 | f | f
1920+
fk_notpartitioned_fk_a_b_fkey2_2 | f | f
1921+
(6 rows)
19171922

19181923
ALTER TABLE fk_notpartitioned_fk VALIDATE CONSTRAINT fk_notpartitioned_fk_a_b_fkey;
1919-
-- All constraints are now valid.
1924+
ALTER TABLE fk_notpartitioned_fk ALTER CONSTRAINT fk_notpartitioned_fk_a_b_fkey2 ENFORCED;
1925+
-- All constraints are now valid and enforced.
19201926
SELECT conname, conenforced, convalidated FROM pg_constraint
19211927
WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text;
1922-
conname | conenforced | convalidated
1923-
---------------------------------+-------------+--------------
1924-
fk_notpartitioned_fk_a_b_fkey | t | t
1925-
fk_notpartitioned_fk_a_b_fkey_1 | t | t
1926-
fk_notpartitioned_fk_a_b_fkey_2 | t | t
1927-
(3 rows)
1928+
conname | conenforced | convalidated
1929+
----------------------------------+-------------+--------------
1930+
fk_notpartitioned_fk_a_b_fkey | t | t
1931+
fk_notpartitioned_fk_a_b_fkey_1 | t | t
1932+
fk_notpartitioned_fk_a_b_fkey_2 | t | t
1933+
fk_notpartitioned_fk_a_b_fkey2 | t | t
1934+
fk_notpartitioned_fk_a_b_fkey2_1 | t | t
1935+
fk_notpartitioned_fk_a_b_fkey2_2 | t | t
1936+
(6 rows)
19281937

19291938
-- test a self-referential FK
19301939
ALTER TABLE fk_partitioned_pk ADD CONSTRAINT selffk FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT VALID;

src/test/regress/sql/foreign_key.sql

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,8 +1389,8 @@ WHERE conrelid::regclass::text like 'fk_partitioned_fk%' ORDER BY oid::regclass:
13891389

13901390
DROP TABLE fk_partitioned_fk, fk_notpartitioned_pk;
13911391

1392-
-- NOT VALID foreign key on a non-partitioned table referencing a partitioned
1393-
-- table
1392+
-- NOT VALID and NOT ENFORCED foreign key on a non-partitioned table
1393+
-- referencing a partitioned table
13941394
CREATE TABLE fk_partitioned_pk (a int, b int, PRIMARY KEY (a, b)) PARTITION BY RANGE (a, b);
13951395
CREATE TABLE fk_partitioned_pk_1 PARTITION OF fk_partitioned_pk FOR VALUES FROM (0,0) TO (1000,1000);
13961396
CREATE TABLE fk_partitioned_pk_2 PARTITION OF fk_partitioned_pk FOR VALUES FROM (1000,1000) TO (2000,2000);
@@ -1399,14 +1399,17 @@ INSERT INTO fk_partitioned_pk VALUES(100,100), (1000,1000);
13991399
INSERT INTO fk_notpartitioned_fk VALUES(100,100), (1000,1000);
14001400
ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey
14011401
FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT VALID;
1402+
ALTER TABLE fk_notpartitioned_fk ADD CONSTRAINT fk_notpartitioned_fk_a_b_fkey2
1403+
FOREIGN KEY (a, b) REFERENCES fk_partitioned_pk NOT ENFORCED;
14021404

1403-
-- All constraints will be invalid.
1405+
-- All constraints will be invalid, and _fkey2 constraints will not be enforced.
14041406
SELECT conname, conenforced, convalidated FROM pg_constraint
14051407
WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text;
14061408

14071409
ALTER TABLE fk_notpartitioned_fk VALIDATE CONSTRAINT fk_notpartitioned_fk_a_b_fkey;
1410+
ALTER TABLE fk_notpartitioned_fk ALTER CONSTRAINT fk_notpartitioned_fk_a_b_fkey2 ENFORCED;
14081411

1409-
-- All constraints are now valid.
1412+
-- All constraints are now valid and enforced.
14101413
SELECT conname, conenforced, convalidated FROM pg_constraint
14111414
WHERE conrelid = 'fk_notpartitioned_fk'::regclass ORDER BY oid::regclass::text;
14121415

0 commit comments

Comments
 (0)