diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 313c782cae2..7a063ca8ae0 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -20409,6 +20409,7 @@ ATExecSplitPartition(List **wqueue, AlteredTableInfo *tab, Relation rel, * against concurrent drop, and mark stmt->relation as * RELPERSISTENCE_TEMP if a temporary namespace is selected. */ + sps->name->relpersistence = rel->rd_rel->relpersistence; namespaceId = RangeVarGetAndCheckCreationNamespace(sps->name, NoLock, NULL); @@ -20601,6 +20602,8 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel, ListCell *listptr; List *mergingPartitionsList = NIL; Oid defaultPartOid; + Oid namespaceId; + Oid existingRelid; /* * Lock all merged partitions, check them and create list with partitions @@ -20617,13 +20620,48 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel, */ mergingPartition = table_openrv(name, AccessExclusiveLock); - /* - * Checking that two partitions have the same name was before, in - * function transformPartitionCmdForMerge(). - */ - if (equal(name, cmd->name)) + /* Store a next merging partition into the list. */ + mergingPartitionsList = lappend(mergingPartitionsList, + mergingPartition); + } + + /* + * Look up the namespace in which we are supposed to create the partition, + * check we have permission to create there, lock it against concurrent + * drop, and mark stmt->relation as RELPERSISTENCE_TEMP if a temporary + * namespace is selected. + */ + cmd->name->relpersistence = rel->rd_rel->relpersistence; + namespaceId = + RangeVarGetAndCheckCreationNamespace(cmd->name, NoLock, NULL); + + /* + * Check if this name is already taken. This helps us to detect the + * situation when one of the merging partitions has the same name as the + * new partition. Otherwise, this would fail later on anyway but catching + * this here allows us to emit a nicer error message. + */ + existingRelid = get_relname_relid(cmd->name->relname, namespaceId); + + if (OidIsValid(existingRelid)) + { + Relation sameNamePartition = NULL; + + foreach_ptr(RelationData, mergingPartition, mergingPartitionsList) { - /* One new partition can have the same name as merged partition. */ + if (RelationGetRelid(mergingPartition) == existingRelid) + { + sameNamePartition = mergingPartition; + break; + } + } + + if (sameNamePartition) + { + /* + * The new partition has the same name as one of merging + * partitions. + */ char tmpRelName[NAMEDATALEN]; /* Generate temporary name. */ @@ -20635,7 +20673,7 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel, * in the future because we're going to eventually drop the * existing partition anyway. */ - RenameRelationInternal(RelationGetRelid(mergingPartition), + RenameRelationInternal(RelationGetRelid(sameNamePartition), tmpRelName, false, false); /* @@ -20644,10 +20682,12 @@ ATExecMergePartitions(List **wqueue, AlteredTableInfo *tab, Relation rel, */ CommandCounterIncrement(); } - - /* Store a next merging partition into the list. */ - mergingPartitionsList = lappend(mergingPartitionsList, - mergingPartition); + else + { + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_TABLE), + errmsg("relation \"%s\" already exists", cmd->name->relname))); + } } /* Detach all merged partitions. */ |