0001_stable_fix_detach_partition_concurrently_issue.patch

application/octet-stream

Filename: 0001_stable_fix_detach_partition_concurrently_issue.patch
Type: application/octet-stream
Part: 1
Message: Re:Re: BUG #19070: issue with DETACH PARTITION CONCURRENTLY on a hash partition table

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/commands/tablecmds.c 15 3
src/test/regress/expected/alter_table.out 24 0
src/test/regress/sql/alter_table.sql 13 0
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index b3ed69457fc..7612e9a3f86 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -20797,13 +20797,14 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	Relation	partRel;
 	ObjectAddress address;
 	Oid			defaultPartOid;
+	PartitionDesc partdesc;
 
 	/*
 	 * We must lock the default partition, because detaching this partition
 	 * will change its partition constraint.
 	 */
-	defaultPartOid =
-		get_default_oid_from_partdesc(RelationGetPartitionDesc(rel, true));
+	partdesc = RelationGetPartitionDesc(rel, true);
+	defaultPartOid = get_default_oid_from_partdesc(partdesc);
 	if (OidIsValid(defaultPartOid))
 	{
 		/*
@@ -20872,8 +20873,19 @@ ATExecDetachPartition(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		/*
 		 * Add a new constraint to the partition being detached, which
 		 * supplants the partition constraint (unless there is one already).
+		 * 
+		 * In stable branches, we currently skip adding this constraint
+ 		 * for hash partitions. The reason is to avoid leaving behind
+ 		 * OID-dependent check constraints referencing the parent table's OID,
+		 * which could lead to unexpected errors(e.g. Could not open relation
+		 * with OID xxxx).
+		 * 
+		 * For other partitioning strategies, we keep the previous behavior
+         * to prevent breaking existing workloads that might rely on the
+		 * absence of such constraints.
 		 */
-		DetachAddConstraintIfNeeded(wqueue, partRel);
+		if (partdesc->boundinfo->strategy != PARTITION_STRATEGY_HASH)
+			DetachAddConstraintIfNeeded(wqueue, partRel);
 
 		/*
 		 * We're almost done now; the only traces that remain are the
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 476266e3f4b..fd5b1b35bda 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -4487,6 +4487,30 @@ Check constraints:
     "part_rp100_a_check" CHECK (a >= 123 AND a < 133 AND a IS NOT NULL)
 
 DROP TABLE range_parted2;
+CREATE TABLE hash_parted2 (
+	a int
+) PARTITION BY HASH(a);
+CREATE TABLE part_hp PARTITION OF hash_parted2 FOR VALUES WITH (MODULUS 2, REMAINDER 0);
+ALTER TABLE hash_parted2 DETACH PARTITION part_hp CONCURRENTLY;
+\d+ hash_parted2
+                         Partitioned table "public.hash_parted2"
+ Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
+--------+---------+-----------+----------+---------+---------+--------------+-------------
+ a      | integer |           |          |         | plain   |              | 
+Partition key: HASH (a)
+Number of partitions: 0
+
+-- constraint should not be created
+\d part_hp
+              Table "public.part_hp"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+
+DROP TABLE hash_parted2;
+-- work fine
+INSERT INTO part_hp VALUES (1);
+DROP TABLE part_hp;
 -- Check ALTER TABLE commands for partitioned tables and partitions
 -- cannot add/drop column to/from *only* the parent
 ALTER TABLE ONLY list_parted2 ADD COLUMN c int;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 5ce9d1e429f..06d4a8be60f 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -2832,6 +2832,19 @@ ALTER TABLE range_parted2 DETACH PARTITION part_rp100 CONCURRENTLY;
 \d part_rp100
 DROP TABLE range_parted2;
 
+CREATE TABLE hash_parted2 (
+	a int
+) PARTITION BY HASH(a);
+CREATE TABLE part_hp PARTITION OF hash_parted2 FOR VALUES WITH (MODULUS 2, REMAINDER 0);
+ALTER TABLE hash_parted2 DETACH PARTITION part_hp CONCURRENTLY;
+\d+ hash_parted2
+-- constraint should not be created
+\d part_hp
+DROP TABLE hash_parted2;
+-- work fine
+INSERT INTO part_hp VALUES (1);
+DROP TABLE part_hp;
+
 -- Check ALTER TABLE commands for partitioned tables and partitions
 
 -- cannot add/drop column to/from *only* the parent