Skip to content

Commit d6f1e16

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 fc0f3b4 commit d6f1e16

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
@@ -17460,6 +17460,22 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd,
1746017460

1746117461
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(attachrel));
1746217462

17463+
/*
17464+
* If the partition we just attached is partitioned itself, invalidate
17465+
* relcache for all descendent partitions too to ensure that their
17466+
* rd_partcheck expression trees are rebuilt; partitions already locked
17467+
* at the beginning of this function.
17468+
*/
17469+
if (attachrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
17470+
{
17471+
ListCell *l;
17472+
17473+
foreach(l, attachrel_children)
17474+
{
17475+
CacheInvalidateRelcacheByRelid(lfirst_oid(l));
17476+
}
17477+
}
17478+
1746317479
/* keep our lock until commit */
1746417480
table_close(attachrel, NoLock);
1746517481

@@ -18150,6 +18166,25 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
1815018166
* included in its partition descriptor.
1815118167
*/
1815218168
CacheInvalidateRelcache(rel);
18169+
18170+
/*
18171+
* If the partition we just detached is partitioned itself, invalidate
18172+
* relcache for all descendent partitions too to ensure that their
18173+
* rd_partcheck expression trees are rebuilt; must lock partitions
18174+
* before doing so, using the same lockmode as what partRel has been
18175+
* locked with by the caller.
18176+
*/
18177+
if (partRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
18178+
{
18179+
List *children;
18180+
18181+
children = find_all_inheritors(RelationGetRelid(partRel),
18182+
AccessExclusiveLock, NULL);
18183+
foreach(cell, children)
18184+
{
18185+
CacheInvalidateRelcacheByRelid(lfirst_oid(cell));
18186+
}
18187+
}
1815318188
}
1815418189

1815518190
/*

src/test/regress/expected/alter_table.out

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

44914491
drop table alttype_cluster;
4492+
--
4493+
-- Check that attaching or detaching a partitioned partition correctly leads
4494+
-- to its partitions' constraint being updated to reflect the parent's
4495+
-- newly added/removed constraint
4496+
create table target_parted (a int, b int) partition by list (a);
4497+
create table attach_parted (a int, b int) partition by list (b);
4498+
create table attach_parted_part1 partition of attach_parted for values in (1);
4499+
-- insert a row directly into the leaf partition so that its partition
4500+
-- constraint is built and stored in the relcache
4501+
insert into attach_parted_part1 values (1, 1);
4502+
-- the following better invalidate the partition constraint of the leaf
4503+
-- partition too...
4504+
alter table target_parted attach partition attach_parted for values in (1);
4505+
-- ...such that the following insert fails
4506+
insert into attach_parted_part1 values (2, 1);
4507+
ERROR: new row for relation "attach_parted_part1" violates partition constraint
4508+
DETAIL: Failing row contains (2, 1).
4509+
-- ...and doesn't when the partition is detached along with its own partition
4510+
alter table target_parted detach partition attach_parted;
4511+
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
@@ -2940,3 +2940,22 @@ select indexrelid::regclass, indisclustered from pg_index
29402940
where indrelid = 'alttype_cluster'::regclass
29412941
order by indexrelid::regclass::text;
29422942
drop table alttype_cluster;
2943+
2944+
--
2945+
-- Check that attaching or detaching a partitioned partition correctly leads
2946+
-- to its partitions' constraint being updated to reflect the parent's
2947+
-- newly added/removed constraint
2948+
create table target_parted (a int, b int) partition by list (a);
2949+
create table attach_parted (a int, b int) partition by list (b);
2950+
create table attach_parted_part1 partition of attach_parted for values in (1);
2951+
-- insert a row directly into the leaf partition so that its partition
2952+
-- constraint is built and stored in the relcache
2953+
insert into attach_parted_part1 values (1, 1);
2954+
-- the following better invalidate the partition constraint of the leaf
2955+
-- partition too...
2956+
alter table target_parted attach partition attach_parted for values in (1);
2957+
-- ...such that the following insert fails
2958+
insert into attach_parted_part1 values (2, 1);
2959+
-- ...and doesn't when the partition is detached along with its own partition
2960+
alter table target_parted detach partition attach_parted;
2961+
insert into attach_parted_part1 values (2, 1);

0 commit comments

Comments
 (0)