From 8b26be8a32c31d45d3e11bcdab39526969201c88 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 18 Oct 2021 19:08:25 -0300 Subject: Invalidate partitions of table being attached/detached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Author: Amit Langote Author: Álvaro Herrera Reviewed-by: Nitin Jadhav Reviewed-by: Pavel Borisov Discussion: https://postgr.es/m/OS3PR01MB5718DA1C4609A25186D1FBF194089%40OS3PR01MB5718.jpnprd01.prod.outlook.com --- src/backend/commands/tablecmds.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/backend/commands/tablecmds.c') diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 40a56839166..d61f8d526f8 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -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 */ -- cgit v1.2.3