mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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:
		@@ -16341,6 +16341,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);
 | 
			
		||||
 | 
			
		||||
@@ -16917,6 +16933,25 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
 | 
			
		||||
	 */
 | 
			
		||||
	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));
 | 
			
		||||
 | 
			
		||||
	/* keep our lock until commit */
 | 
			
		||||
 
 | 
			
		||||
@@ -4279,3 +4279,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);
 | 
			
		||||
 
 | 
			
		||||
@@ -2872,3 +2872,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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user