Skip to content

Commit fe35528

Browse files
committed
Invalidate partitions of table being attached/detached
Failing to do that, any direct inserts/updates of those partitions would fail to enforce the correct constraint, that is, one that considers the new partition constraint of their parent table. Backpatch to 10. Reported by: Hou Zhijie <houzj.fnst@fujitsu.com> Author: Amit Langote <amitlangote09@gmail.com> Author: Álvaro Herrera <alvherre@alvh.no-ip.org> Reviewed-by: Nitin Jadhav <nitinjadhavpostgres@gmail.com> Reviewed-by: Pavel Borisov <pashkin.elfe@gmail.com> Discussion: https://postgr.es/m/OS3PR01MB5718DA1C4609A25186D1FBF194089%40OS3PR01MB5718.jpnprd01.prod.outlook.com
1 parent 8f4fe8d commit fe35528

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/backend/commands/tablecmds.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16795,6 +16795,22 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
1679516795

1679616796
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(attachrel));
1679716797

16798+
/*
16799+
* If the partition we just attached is partitioned itself, invalidate
16800+
* relcache for all descendent partitions too to ensure that their
16801+
* rd_partcheck expression trees are rebuilt; partitions already locked
16802+
* at the beginning of this function.
16803+
*/
16804+
if (attachrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
16805+
{
16806+
ListCell *l;
16807+
16808+
foreach(l, attachrel_children)
16809+
{
16810+
CacheInvalidateRelcacheByRelid(lfirst_oid(l));
16811+
}
16812+
}
16813+
1679816814
/* keep our lock until commit */
1679916815
table_close(attachrel, NoLock);
1680016816

@@ -17312,6 +17328,25 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
1731217328
*/
1731317329
CacheInvalidateRelcache(rel);
1731417330

17331+
/*
17332+
* If the partition we just detached is partitioned itself, invalidate
17333+
* relcache for all descendent partitions too to ensure that their
17334+
* rd_partcheck expression trees are rebuilt; must lock partitions
17335+
* before doing so, using the same lockmode as what partRel has been
17336+
* locked with by the caller.
17337+
*/
17338+
if (partRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
17339+
{
17340+
List *children;
17341+
17342+
children = find_all_inheritors(RelationGetRelid(partRel),
17343+
AccessExclusiveLock, NULL);
17344+
foreach(cell, children)
17345+
{
17346+
CacheInvalidateRelcacheByRelid(lfirst_oid(cell));
17347+
}
17348+
}
17349+
1731517350
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel));
1731617351

1731717352
/* keep our lock until commit */

src/test/regress/expected/alter_table.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4436,3 +4436,23 @@ select indexrelid::regclass, indisclustered from pg_index
44364436
(2 rows)
44374437

44384438
drop table alttype_cluster;
4439+
--
4440+
-- Check that attaching or detaching a partitioned partition correctly leads
4441+
-- to its partitions' constraint being updated to reflect the parent's
4442+
-- newly added/removed constraint
4443+
create table target_parted (a int, b int) partition by list (a);
4444+
create table attach_parted (a int, b int) partition by list (b);
4445+
create table attach_parted_part1 partition of attach_parted for values in (1);
4446+
-- insert a row directly into the leaf partition so that its partition
4447+
-- constraint is built and stored in the relcache
4448+
insert into attach_parted_part1 values (1, 1);
4449+
-- the following better invalidate the partition constraint of the leaf
4450+
-- partition too...
4451+
alter table target_parted attach partition attach_parted for values in (1);
4452+
-- ...such that the following insert fails
4453+
insert into attach_parted_part1 values (2, 1);
4454+
ERROR: new row for relation "attach_parted_part1" violates partition constraint
4455+
DETAIL: Failing row contains (2, 1).
4456+
-- ...and doesn't when the partition is detached along with its own partition
4457+
alter table target_parted detach partition attach_parted;
4458+
insert into attach_parted_part1 values (2, 1);

src/test/regress/sql/alter_table.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2923,3 +2923,22 @@ select indexrelid::regclass, indisclustered from pg_index
29232923
where indrelid = 'alttype_cluster'::regclass
29242924
order by indexrelid::regclass::text;
29252925
drop table alttype_cluster;
2926+
2927+
--
2928+
-- Check that attaching or detaching a partitioned partition correctly leads
2929+
-- to its partitions' constraint being updated to reflect the parent's
2930+
-- newly added/removed constraint
2931+
create table target_parted (a int, b int) partition by list (a);
2932+
create table attach_parted (a int, b int) partition by list (b);
2933+
create table attach_parted_part1 partition of attach_parted for values in (1);
2934+
-- insert a row directly into the leaf partition so that its partition
2935+
-- constraint is built and stored in the relcache
2936+
insert into attach_parted_part1 values (1, 1);
2937+
-- the following better invalidate the partition constraint of the leaf
2938+
-- partition too...
2939+
alter table target_parted attach partition attach_parted for values in (1);
2940+
-- ...such that the following insert fails
2941+
insert into attach_parted_part1 values (2, 1);
2942+
-- ...and doesn't when the partition is detached along with its own partition
2943+
alter table target_parted detach partition attach_parted;
2944+
insert into attach_parted_part1 values (2, 1);

0 commit comments

Comments
 (0)