Self FK oddity when attaching a partition
Jehan-Guillaume de Rorthais <jgdr@dalibo.com>
From: Jehan-Guillaume de Rorthais <jgdr@dalibo.com>
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2022-06-03T13:42:32Z
Lists: pgsql-hackers
Attachments
- self-fk-after-part-attach.sql (application/sql)
Hi all,
While studying the issue discussed in thread "Detaching a partition with a FK
on itself is not possible"[1], I stumbled across an oddity while attaching a
partition having the same multiple self-FK than the parent table.
Only one of the self-FK is found as a duplicate. Find in attachment some SQL to
reproduce the scenario. Below the result of this scenario (constant from v12 to
commit 7e367924e3). Why "child1_id_abc_no_part_fkey" is found duplicated but not
the three others? From pg_constraint, only "child1_id_abc_no_part_fkey" has a
"conparentid" set.
conname | conparentid | conrelid | confrelid
-----------------------------+-------------+----------+-----------
child1_id_abc_no_part_fkey | 16901 | 16921 | 16921
child1_id_def_no_part_fkey | 0 | 16921 | 16921
child1_id_ghi_no_part_fkey | 0 | 16921 | 16921
child1_id_jkl_no_part_fkey | 0 | 16921 | 16921
parent_id_abc_no_part_fkey | 16901 | 16921 | 16894
parent_id_abc_no_part_fkey | 0 | 16894 | 16894
parent_id_abc_no_part_fkey1 | 16901 | 16894 | 16921
parent_id_def_no_part_fkey | 16906 | 16921 | 16894
parent_id_def_no_part_fkey | 0 | 16894 | 16894
parent_id_def_no_part_fkey1 | 16906 | 16894 | 16921
parent_id_ghi_no_part_fkey | 0 | 16894 | 16894
parent_id_ghi_no_part_fkey | 16911 | 16921 | 16894
parent_id_ghi_no_part_fkey1 | 16911 | 16894 | 16921
parent_id_jkl_no_part_fkey | 0 | 16894 | 16894
parent_id_jkl_no_part_fkey | 16916 | 16921 | 16894
parent_id_jkl_no_part_fkey1 | 16916 | 16894 | 16921
(16 rows)
Table "public.child1"
[...]
Partition of: parent FOR VALUES IN ('1')
Partition constraint: ((no_part IS NOT NULL) AND (no_part = '1'::smallint))
Indexes:
"child1_pkey" PRIMARY KEY, btree (id, no_part)
Check constraints:
"child1" CHECK (no_part = 1)
Foreign-key constraints:
"child1_id_def_no_part_fkey"
FOREIGN KEY (id_def, no_part)
REFERENCES child1(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
"child1_id_ghi_no_part_fkey"
FOREIGN KEY (id_ghi, no_part)
REFERENCES child1(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
"child1_id_jkl_no_part_fkey"
FOREIGN KEY (id_jkl, no_part)
REFERENCES child1(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_abc_no_part_fkey"
FOREIGN KEY (id_abc, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_def_no_part_fkey"
FOREIGN KEY (id_def, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_ghi_no_part_fkey"
FOREIGN KEY (id_ghi, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_jkl_no_part_fkey"
FOREIGN KEY (id_jkl, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
Referenced by:
TABLE "child1" CONSTRAINT "child1_id_def_no_part_fkey"
FOREIGN KEY (id_def, no_part)
REFERENCES child1(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "child1" CONSTRAINT "child1_id_ghi_no_part_fkey"
FOREIGN KEY (id_ghi, no_part)
REFERENCES child1(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "child1" CONSTRAINT "child1_id_jkl_no_part_fkey"
FOREIGN KEY (id_jkl, no_part)
REFERENCES child1(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_abc_no_part_fkey"
FOREIGN KEY (id_abc, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_def_no_part_fkey"
FOREIGN KEY (id_def, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_ghi_no_part_fkey"
FOREIGN KEY (id_ghi, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
TABLE "parent" CONSTRAINT "parent_id_jkl_no_part_fkey"
FOREIGN KEY (id_jkl, no_part)
REFERENCES parent(id, no_part) ON UPDATE RESTRICT ON DELETE RESTRICT
Regards,
[1]
https://www.postgresql.org/message-id/flat/20220321113634.68c09d4b%40karst#83c0880a1b4921fcd00d836d4e6bceb3
Commits
-
Create FKs properly when attaching table as partition
- c301e1c0c09c 15.1 landed
- b0284bfb1db5 16.0 landed
- ab70b3a52fde 12.13 landed
- 41b6e7c9a32e 13.9 landed
- 18865f4df9ca 14.6 landed
-
Fix self-referencing foreign keys with partitioned tables
- 7d520e68ea1e 13.9 landed
- 669803af04e6 12.13 landed
- 614a406b4ff1 16.0 landed
- 6083132abdd4 15.0 landed
- 483d26930b4c 14.6 landed
-
Fix GetForeignKey*Triggers for self-referential FKs
- 8c848cd4b8e9 16.0 landed
- 68b0da67794e 15.0 landed
-
Choose FK name correctly during partition attachment
- e7936f8b3e57 16.0 landed
- ade2409b18e9 15.0 landed
- 80ef25b1adb1 13.9 landed
- 640c20d6266d 14.6 landed
- 562e100aeeaf 12.13 landed
-
Update SQL features
- 7e367924e33e 15.0 cited
-
Restore the previous semantics of get_constraint_index().
- 641f3dffcdf1 15.0 cited