Hi!
18.04.2024 19:00, Alexander Lakhin wrote:
leaves a strange constraint:
\d+ t*
Table "public.tp_0"
...
Not-null constraints:
"merge-16385-26BCB0-tmp_i_not_null" NOT NULL "i"
Thanks!
Attached fix (with test) for this case.
The patch should be applied after patches
v6-0001- ... .patch ... v6-0004- ... .patch
--
With best regards,
Dmitry Koval
Postgres Professional: http://postgrespro.com
From 58e4b7fb1d3b15cdf1c742c28690392dda34915d Mon Sep 17 00:00:00 2001
From: Koval Dmitry <d.ko...@postgrespro.ru>
Date: Fri, 19 Apr 2024 01:57:49 +0300
Subject: [PATCH v6] Fix
---
src/backend/commands/tablecmds.c | 49 ++++++-------------
src/test/regress/expected/partition_merge.out | 13 ++++-
src/test/regress/sql/partition_merge.sql | 8 ++-
3 files changed, 33 insertions(+), 37 deletions(-)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 72874295cb..8985747180 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -21508,9 +21508,6 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo
*tab, Relation rel,
ListCell *listptr;
List *mergingPartitionsList = NIL;
Oid defaultPartOid;
- char tmpRelName[NAMEDATALEN];
- RangeVar *mergePartName = cmd->name;
- bool isSameName = false;
/*
* Lock all merged partitions, check them and create list with
partitions
@@ -21532,8 +21529,22 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo
*tab, Relation rel,
* function transformPartitionCmdForMerge().
*/
if (equal(name, cmd->name))
+ {
/* One new partition can have the same name as merged
partition. */
- isSameName = true;
+ char tmpRelName[NAMEDATALEN];
+
+ /* Generate temporary name. */
+ sprintf(tmpRelName, "merge-%u-%X-tmp",
RelationGetRelid(rel), MyProcPid);
+
+ /* Rename partition. */
+
RenameRelationInternal(RelationGetRelid(mergingPartition),
+ tmpRelName,
false, false);
+ /*
+ * We must bump the command counter to make the new
partition tuple
+ * visible for rename.
+ */
+ CommandCounterIncrement();
+ }
/* Store a next merging partition into the list. */
mergingPartitionsList = lappend(mergingPartitionsList,
@@ -21553,16 +21564,8 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo
*tab, Relation rel,
DetachPartitionFinalize(rel, mergingPartition, false,
defaultPartOid);
}
- /* Create table for new partition, use partitioned table as model. */
- if (isSameName)
- {
- /* Create partition table with generated temporary name. */
- sprintf(tmpRelName, "merge-%u-%X-tmp", RelationGetRelid(rel),
MyProcPid);
- mergePartName = makeRangeVar(cmd->name->schemaname, tmpRelName,
-1);
- }
-
newPartRel = createPartitionTable(rel,
-
mergePartName,
+
cmd->name,
makeRangeVar(get_namespace_name(RelationGetNamespace(rel)),
RelationGetRelationName(rel), -1),
context);
@@ -21588,26 +21591,6 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo
*tab, Relation rel,
}
list_free(mergingPartitionsList);
- /* Rename new partition if it is needed. */
- if (isSameName)
- {
- /*
- * We must bump the command counter to make the new partition
tuple
- * visible for rename.
- */
- CommandCounterIncrement();
-
- /* Rename partition. */
- RenameRelationInternal(RelationGetRelid(newPartRel),
- cmd->name->relname,
false, false);
-
- /*
- * Bump the command counter to make the tuple of renamed
partition
- * visible for attach partition operation.
- */
- CommandCounterIncrement();
- }
-
/*
* Attach a new partition to the partitioned table. wqueue = NULL:
* verification for each cloned constraint is not needed.
diff --git a/src/test/regress/expected/partition_merge.out
b/src/test/regress/expected/partition_merge.out
index b5744ed498..2499a314fb 100644
--- a/src/test/regress/expected/partition_merge.out
+++ b/src/test/regress/expected/partition_merge.out
@@ -779,17 +779,26 @@ DROP TABLE t;
-- Check the partition index name if the partition name is the same as one
-- of the merged partitions.
--
-CREATE TABLE t (i int) PARTITION BY RANGE (i);
+CREATE TABLE t (i int, PRIMARY KEY(i)) PARTITION BY RANGE (i);
CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1);
CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2);
CREATE INDEX tidx ON t(i);
ALTER TABLE t MERGE PARTITIONS (tp_1_2, tp_0_1) INTO tp_1_2;
--- Indexname value should be 'tp_1_2_i_idx'.
+-- Indexname values should be 'tp_1_2_pkey' and 'tp_1_2_i_idx'.
SELECT indexname FROM pg_indexes
WHERE tablename = 'tp_1_2' AND schemaname = 'partitions_merge_schema';
indexname
--------------
+ tp_1_2_pkey
tp_1_2_i_idx
+(2 rows)
+
+-- Conname value should be 'tp_1_2_i_not_null'.
+SELECT conname FROM pg_constraint
+WHERE conrelid='tp_1_2'::regclass AND contype='n';
+ conname
+-------------------
+ tp_1_2_i_not_null
(1 row)
DROP TABLE t;
diff --git a/src/test/regress/sql/partition_merge.sql
b/src/test/regress/sql/partition_merge.sql
index df737e214e..6614512f69 100644
--- a/src/test/regress/sql/partition_merge.sql
+++ b/src/test/regress/sql/partition_merge.sql
@@ -470,7 +470,7 @@ DROP TABLE t;
-- Check the partition index name if the partition name is the same as one
-- of the merged partitions.
--
-CREATE TABLE t (i int) PARTITION BY RANGE (i);
+CREATE TABLE t (i int, PRIMARY KEY(i)) PARTITION BY RANGE (i);
CREATE TABLE tp_0_1 PARTITION OF t FOR VALUES FROM (0) TO (1);
CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO (2);
@@ -478,10 +478,14 @@ CREATE TABLE tp_1_2 PARTITION OF t FOR VALUES FROM (1) TO
(2);
CREATE INDEX tidx ON t(i);
ALTER TABLE t MERGE PARTITIONS (tp_1_2, tp_0_1) INTO tp_1_2;
--- Indexname value should be 'tp_1_2_i_idx'.
+-- Indexname values should be 'tp_1_2_pkey' and 'tp_1_2_i_idx'.
SELECT indexname FROM pg_indexes
WHERE tablename = 'tp_1_2' AND schemaname = 'partitions_merge_schema';
+-- Conname value should be 'tp_1_2_i_not_null'.
+SELECT conname FROM pg_constraint
+WHERE conrelid='tp_1_2'::regclass AND contype='n';
+
DROP TABLE t;
--
--
2.40.1.windows.1