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
This commit is contained in:
parent
506aa1f71a
commit
b703b7d312
@ -15330,6 +15330,22 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
|
|||||||
|
|
||||||
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(attachrel));
|
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 */
|
/* keep our lock until commit */
|
||||||
heap_close(attachrel, NoLock);
|
heap_close(attachrel, NoLock);
|
||||||
|
|
||||||
@ -15879,6 +15895,25 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
|
|||||||
*/
|
*/
|
||||||
CacheInvalidateRelcache(rel);
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel));
|
ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partRel));
|
||||||
|
|
||||||
/* keep our lock until commit */
|
/* keep our lock until commit */
|
||||||
|
@ -4305,3 +4305,23 @@ select indexrelid::regclass, indisclustered from pg_index
|
|||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
drop table alttype_cluster;
|
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);
|
||||||
|
@ -2860,3 +2860,22 @@ select indexrelid::regclass, indisclustered from pg_index
|
|||||||
where indrelid = 'alttype_cluster'::regclass
|
where indrelid = 'alttype_cluster'::regclass
|
||||||
order by indexrelid::regclass::text;
|
order by indexrelid::regclass::text;
|
||||||
drop table alttype_cluster;
|
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user