diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f1725c9da8c..8fa09afdc59 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -21503,9 +21503,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 @@ -21527,8 +21524,28 @@ 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 the existing partition with a temporary name, leaving it + * free for the new partition. We don't need to care about this + * in the future because we're going to eventually drop the + * existing partition anyway. + */ + 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, @@ -21548,15 +21565,7 @@ 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(get_namespace_name(RelationGetNamespace(rel)), - tmpRelName, -1); - } - createPartitionTable(mergePartName, + createPartitionTable(cmd->name, makeRangeVar(get_namespace_name(RelationGetNamespace(rel)), RelationGetRelationName(rel), -1), context); @@ -21567,18 +21576,12 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel, * excessive, but this is the way we make sure nobody is planning queries * involving merging partitions. */ - newPartRel = table_openrv(mergePartName, AccessExclusiveLock); + newPartRel = table_openrv(cmd->name, AccessExclusiveLock); /* Copy data from merged partitions to new partition. */ moveMergedTablesRows(rel, mergingPartitionsList, newPartRel); - /* - * Attach a new partition to the partitioned table. wqueue = NULL: - * verification for each cloned constraint is not need. - */ - attachPartitionTable(NULL, rel, newPartRel, cmd->bound); - - /* Unlock and drop merged partitions. */ + /* Drop the current partitions before attaching the new one. */ foreach(listptr, mergingPartitionsList) { ObjectAddress object; @@ -21596,18 +21599,12 @@ 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); - } + /* + * Attach a new partition to the partitioned table. wqueue = NULL: + * verification for each cloned constraint is not needed. + */ + attachPartitionTable(NULL, rel, newPartRel, cmd->bound); + /* Keep the lock until commit. */ table_close(newPartRel, NoLock); } diff --git a/src/test/regress/expected/partition_merge.out b/src/test/regress/expected/partition_merge.out index 373d32948ca..2e0bfdc705d 100644 --- a/src/test/regress/expected/partition_merge.out +++ b/src/test/regress/expected/partition_merge.out @@ -746,4 +746,29 @@ DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; -- +-- Check the partition index name if the partition name is the same as one +-- of the merged partitions. +-- +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 values should be 'tp_1_2_pkey' and 'tp_1_2_i_idx'. +-- Not-null constraint name should be 'tp_1_2_i_not_null'. +\d+ tp_1_2 + Table "partitions_merge_schema.tp_1_2" + Column | Type | Collation | Nullable | Default | Storage | Stats target | Description +--------+---------+-----------+----------+---------+---------+--------------+------------- + i | integer | | not null | | plain | | +Partition of: t FOR VALUES FROM (0) TO (2) +Partition constraint: ((i IS NOT NULL) AND (i >= 0) AND (i < 2)) +Indexes: + "tp_1_2_pkey" PRIMARY KEY, btree (i) + "tp_1_2_i_idx" btree (i) +Not-null constraints: + "tp_1_2_i_not_null" NOT NULL "i" + +DROP TABLE t; +-- DROP SCHEMA partitions_merge_schema; diff --git a/src/test/regress/sql/partition_merge.sql b/src/test/regress/sql/partition_merge.sql index 6a0b35b1799..72b1cb0b35e 100644 --- a/src/test/regress/sql/partition_merge.sql +++ b/src/test/regress/sql/partition_merge.sql @@ -444,5 +444,23 @@ DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; +-- +-- Check the partition index name if the partition name is the same as one +-- of the merged partitions. +-- +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 values should be 'tp_1_2_pkey' and 'tp_1_2_i_idx'. +-- Not-null constraint name should be 'tp_1_2_i_not_null'. +\d+ tp_1_2 + +DROP TABLE t; + -- DROP SCHEMA partitions_merge_schema;