Commit 72d06421 authored by Alvaro Herrera's avatar Alvaro Herrera

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: default avatarNitin Jadhav <nitinjadhavpostgres@gmail.com>
Reviewed-by: default avatarPavel Borisov <pashkin.elfe@gmail.com>

Discussion: https://postgr.es/m/OS3PR01MB5718DA1C4609A25186D1FBF194089%40OS3PR01MB5718.jpnprd01.prod.outlook.com
parent 5b353aaf
......@@ -17307,6 +17307,22 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd,
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(attachrel));
/*
* If the partition we just attached is partitioned itself, invalidate
* relcache for all descendent partitions too to ensure that their
* rd_partcheck expression trees are rebuilt; partitions already locked
* at the beginning of this function.
*/
if (attachrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
ListCell *l;
foreach(l, attachrel_children)
{
CacheInvalidateRelcacheByRelid(lfirst_oid(l));
}
}
/* keep our lock until commit */
table_close(attachrel, NoLock);
......@@ -17997,6 +18013,25 @@ DetachPartitionFinalize(Relation rel, Relation partRel, bool concurrent,
* included in its partition descriptor.
*/
CacheInvalidateRelcache(rel);
/*
* If the partition we just detached is partitioned itself, invalidate
* relcache for all descendent partitions too to ensure that their
* rd_partcheck expression trees are rebuilt; must lock partitions
* before doing so, using the same lockmode as what partRel has been
* locked with by the caller.
*/
if (partRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
List *children;
children = find_all_inheritors(RelationGetRelid(partRel),
AccessExclusiveLock, NULL);
foreach(cell, children)
{
CacheInvalidateRelcacheByRelid(lfirst_oid(cell));
}
}
}
/*
......
......@@ -4496,3 +4496,23 @@ select indexrelid::regclass, indisclustered from pg_index
(2 rows)
drop table alttype_cluster;
--
-- Check that attaching or detaching a partitioned partition correctly leads
-- to its partitions' constraint being updated to reflect the parent's
-- newly added/removed constraint
create table target_parted (a int, b int) partition by list (a);
create table attach_parted (a int, b int) partition by list (b);
create table attach_parted_part1 partition of attach_parted for values in (1);
-- insert a row directly into the leaf partition so that its partition
-- constraint is built and stored in the relcache
insert into attach_parted_part1 values (1, 1);
-- the following better invalidate the partition constraint of the leaf
-- partition too...
alter table target_parted attach partition attach_parted for values in (1);
-- ...such that the following insert fails
insert into attach_parted_part1 values (2, 1);
ERROR: new row for relation "attach_parted_part1" violates partition constraint
DETAIL: Failing row contains (2, 1).
-- ...and doesn't when the partition is detached along with its own partition
alter table target_parted detach partition attach_parted;
insert into attach_parted_part1 values (2, 1);
......@@ -2949,3 +2949,22 @@ select indexrelid::regclass, indisclustered from pg_index
where indrelid = 'alttype_cluster'::regclass
order by indexrelid::regclass::text;
drop table alttype_cluster;
--
-- Check that attaching or detaching a partitioned partition correctly leads
-- to its partitions' constraint being updated to reflect the parent's
-- newly added/removed constraint
create table target_parted (a int, b int) partition by list (a);
create table attach_parted (a int, b int) partition by list (b);
create table attach_parted_part1 partition of attach_parted for values in (1);
-- insert a row directly into the leaf partition so that its partition
-- constraint is built and stored in the relcache
insert into attach_parted_part1 values (1, 1);
-- the following better invalidate the partition constraint of the leaf
-- partition too...
alter table target_parted attach partition attach_parted for values in (1);
-- ...such that the following insert fails
insert into attach_parted_part1 values (2, 1);
-- ...and doesn't when the partition is detached along with its own partition
alter table target_parted detach partition attach_parted;
insert into attach_parted_part1 values (2, 1);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment