Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2ee02c9

Browse files
committed
Refuse ATTACH of a table referenced by a foreign key
Trying to attach a table as a partition which is already on thereferenced side of a foreign key on the partitioned table that it isbeing attached to, leads to strange behavior: we try to clone theforeign key from the parent to the partition, but this new FK points tothe partition itself, and the mix of pg_constraint rows and triggersdoesn't behave well.Rather than trying to untangle the mess (which might be possible givensufficient time), I opted to forbid the ATTACH. This doesn't seem aproblematic restriction, given that we already fail to create theforeign key if you do it the other way around, that is, having thepartition first and the FK second.Backpatch to all supported branches.Reported-by: Alexander Lakhin <exclusion@gmail.com>Reviewed-by: Tender Wang <tndrwang@gmail.com>Discussion:https://postgr.es/m/18541-628a61bc267cd2d3@postgresql.org
1 parentc943e2a commit2ee02c9

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9640,6 +9640,23 @@ CloneFkReferencing(List **wqueue, Relation parentRel, Relation partRel)
96409640
{
96419641
ForeignKeyCacheInfo *fk = lfirst(cell);
96429642

9643+
/*
9644+
* Refuse to attach a table as partition that this partitioned table
9645+
* already has a foreign key to. This isn't useful schema, which is
9646+
* proven by the fact that there have been no user complaints that
9647+
* it's already impossible to achieve this in the opposite direction,
9648+
* i.e., creating a foreign key that references a partition. This
9649+
* restriction allows us to dodge some complexities around
9650+
* pg_constraint and pg_trigger row creations that would be needed
9651+
* during ATTACH/DETACH for this kind of relationship.
9652+
*/
9653+
if (fk->confrelid == RelationGetRelid(partRel))
9654+
ereport(ERROR,
9655+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
9656+
errmsg("can't attach table \"%s\" as a partition which is referenced by foreign key \"%s\"",
9657+
RelationGetRelationName(partRel),
9658+
get_constraint_name(fk->conoid))));
9659+
96439660
clone = lappend_oid(clone, fk->conoid);
96449661
}
96459662

‎src/test/regress/expected/foreign_key.out

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,23 @@ INSERT INTO fk_notpartitioned_pk VALUES (1600, 601), (1600, 1601);
18961896
ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2
18971897
FOR VALUES IN (1600);
18981898
-- leave these tables around intentionally
1899+
-- Verify that attaching a table that's referenced by an existing FK
1900+
-- in the parent throws an error
1901+
CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY);
1902+
CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_6) PARTITION BY LIST (a);
1903+
ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1);
1904+
ERROR: can't attach table "fk_partitioned_pk_6" as a partition which is referenced by foreign key "fk_partitioned_fk_6_a_fkey"
1905+
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
1906+
-- This case is similar to above, but the referenced relation is one level
1907+
-- lower in the hierarchy. This one fails in a different way as the above,
1908+
-- because we don't bother to protect against this case explicitly. If the
1909+
-- current error stops happening, we'll need to add a better protection.
1910+
CREATE TABLE fk_partitioned_pk_6 (a int PRIMARY KEY) PARTITION BY list (a);
1911+
CREATE TABLE fk_partitioned_pk_61 PARTITION OF fk_partitioned_pk_6 FOR VALUES IN (1);
1912+
CREATE TABLE fk_partitioned_fk_6 (a int REFERENCES fk_partitioned_pk_61) PARTITION BY LIST (a);
1913+
ALTER TABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FOR VALUES IN (1);
1914+
ERROR: cannot ALTER TABLE "fk_partitioned_pk_61" because it is being used by active queries in this session
1915+
DROP TABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
18991916
-- test the case when the referenced table is owned by a different user
19001917
create role regress_other_partitioned_fk_owner;
19011918
grant references on fk_notpartitioned_pk to regress_other_partitioned_fk_owner;

‎src/test/regress/sql/foreign_key.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,23 @@ ALTER TABLE fk_partitioned_fk ATTACH PARTITION fk_partitioned_fk_2
13661366

13671367
-- leave these tables around intentionally
13681368

1369+
-- Verify that attaching a table that's referenced by an existing FK
1370+
-- in the parent throws an error
1371+
CREATETABLEfk_partitioned_pk_6 (aintPRIMARY KEY);
1372+
CREATETABLEfk_partitioned_fk_6 (aintREFERENCES fk_partitioned_pk_6) PARTITION BY LIST (a);
1373+
ALTERTABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FORVALUESIN (1);
1374+
DROPTABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
1375+
1376+
-- This case is similar to above, but the referenced relation is one level
1377+
-- lower in the hierarchy. This one fails in a different way as the above,
1378+
-- because we don't bother to protect against this case explicitly. If the
1379+
-- current error stops happening, we'll need to add a better protection.
1380+
CREATETABLEfk_partitioned_pk_6 (aintPRIMARY KEY) PARTITION BY list (a);
1381+
CREATETABLEfk_partitioned_pk_61 PARTITION OF fk_partitioned_pk_6 FORVALUESIN (1);
1382+
CREATETABLEfk_partitioned_fk_6 (aintREFERENCES fk_partitioned_pk_61) PARTITION BY LIST (a);
1383+
ALTERTABLE fk_partitioned_fk_6 ATTACH PARTITION fk_partitioned_pk_6 FORVALUESIN (1);
1384+
DROPTABLE fk_partitioned_pk_6, fk_partitioned_fk_6;
1385+
13691386
-- test the case when the referenced table is owned by a different user
13701387
create role regress_other_partitioned_fk_owner;
13711388
grantreferenceson fk_notpartitioned_pk to regress_other_partitioned_fk_owner;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp