v4-0001-Fix-ATTACH-DETACH-PARTITION-to-invalidate-partiti.patch
application/octet-stream
Filename: v4-0001-Fix-ATTACH-DETACH-PARTITION-to-invalidate-partiti.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v4-0001
Subject: Fix ATTACH/DETACH PARTITION to invalidate partitions of table being attached/detached
| File | + | − |
|---|---|---|
| src/backend/commands/tablecmds.c | 34 | 0 |
| src/test/regress/expected/alter_table.out | 21 | 0 |
| src/test/regress/sql/alter_table.sql | 21 | 0 |
From 4c94ea50e46a06045e420711cf31e5d2efbdf999 Mon Sep 17 00:00:00 2001
From: Pavel Borisov <pashkin.elfe@gmail.com>
Date: Wed, 6 Oct 2021 17:05:32 +0400
Subject: [PATCH v4] Fix ATTACH/DETACH PARTITION to invalidate partitions of
table being attached/detached
---
src/backend/commands/tablecmds.c | 34 +++++++++++++++++++++++
src/test/regress/expected/alter_table.out | 21 ++++++++++++++
src/test/regress/sql/alter_table.sql | 21 ++++++++++++++
3 files changed, 76 insertions(+)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index ff97b618e6..795452679e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -17460,6 +17460,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);
@@ -18150,6 +18166,24 @@ 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.
+ */
+ if (partRel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+ {
+ List *partRel_children =
+ find_all_inheritors(RelationGetRelid(partRel),
+ AccessExclusiveLock, NULL);
+
+ foreach(cell, partRel_children)
+ {
+ CacheInvalidateRelcacheByRelid(lfirst_oid(cell));
+ }
+ }
}
/*
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 4bee0c1173..a4dd7b7410 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -4489,3 +4489,24 @@ 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
+-- Report: https://postgr.es/m/OS3PR01MB5718DA1C4609A25186D1FBF194089%40OS3PR01MB5718.jpnprd01.prod.outlook.com
+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 the following too, in the reverse direction
+alter table target_parted detach partition attach_parted;
+insert into attach_parted_part1 values (2, 1);
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index dc0200adcb..ac4ad7c00d 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -2940,3 +2940,24 @@ 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
+-- Report: https://postgr.es/m/OS3PR01MB5718DA1C4609A25186D1FBF194089%40OS3PR01MB5718.jpnprd01.prod.outlook.com
+
+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 the following too, in the reverse direction
+alter table target_parted detach partition attach_parted;
+insert into attach_parted_part1 values (2, 1);
--
2.24.3 (Apple Git-128)