diff --git a/src/common/backend/catalog/index.cpp b/src/common/backend/catalog/index.cpp index 1613448a6..86fbacc1b 100644 --- a/src/common/backend/catalog/index.cpp +++ b/src/common/backend/catalog/index.cpp @@ -5862,7 +5862,7 @@ void AddGPIForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid) * @@GaussDB@@ * Target : This routine is used to scan partition tuples and delete them from all global partition indexes. */ -void ScanPartitionDeleteGPITuples(Relation partTableRel, Relation partRel, const List* indexRelList, +void ScanPartitionDeleteGPITuples(Relation partTableRel, Relation partRel, const List* indexRelList, const List* indexInfoList) { TableScanDesc scan = NULL; @@ -5893,9 +5893,8 @@ void ScanPartitionDeleteGPITuples(Relation partTableRel, Relation partRel, const Relation indexRel = (Relation)lfirst(cell); IndexInfo* indexInfo = static_cast(lfirst(cell1)); - if (!RelationIsUstoreIndex(indexRel)) { - continue; /* only ubtree have index_delete routine */ - } + /* only ubtree have index_delete routine */ + Assert(RelationIsUstoreIndex(indexRel)); Datum values[tupleDesc->natts]; bool isNull[tupleDesc->natts]; @@ -5988,7 +5987,7 @@ bool DeleteGPITuplesForPartition(Oid partTableOid, Oid partOid) * Description : * Notes : */ -void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid) +bool DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid) { Relation partTableRel = NULL; Relation partRel = NULL; @@ -5999,6 +5998,7 @@ void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOi List* indexRelList = NIL; List* indexInfoList = NIL; ListCell* cell = NULL; + bool all_ubtree = true; partTableRel = heap_open(partTableOid, AccessShareLock); part = partitionOpen(partTableRel, partOid, AccessShareLock); @@ -6012,6 +6012,12 @@ void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOi Relation indexRel = relation_open(indexOid, RowExclusiveLock); IndexInfo* indexInfo = BuildIndexInfo(indexRel); + if (!RelationIsUstoreIndex(indexRel)) { + all_ubtree = false; + relation_close(indexRel, RowExclusiveLock); + continue; + } + indexRelList = lappend(indexRelList, indexRel); indexInfoList = lappend(indexInfoList, indexInfo); } @@ -6033,6 +6039,8 @@ void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOi releaseDummyRelation(&partRel); partitionClose(partTableRel, part, NoLock); heap_close(partTableRel, NoLock); + + return all_ubtree; } void mergeBTreeIndexes(List* mergingBtreeIndexes, List* srcPartMergeOffset, int2 bktId) diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index a52496dc7..a02ee3424 100644 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -20816,29 +20816,36 @@ static void renamePartitionIndexes(Oid partitionedTableOid, Oid partitionOid, ch * Description : * Notes : */ -static void heap_truncate_one_part_new(const AlterTableCmd* cmd, Relation rel, Oid srcPartOid) { +static void heap_truncate_one_part_new(const AlterTableCmd* cmd, Relation partRel, Oid srcPartOid, + Relation rel = InvalidRelation) +{ Partition srcPart = NULL; bool renameTargetPart = false; char* destPartitionName = NULL; - Oid destPartOid = AddTemporaryPartitionForAlterPartitions(cmd, rel, srcPartOid, &renameTargetPart); + Oid destPartOid = AddTemporaryPartitionForAlterPartitions(cmd, partRel, srcPartOid, &renameTargetPart); - List* indexList = RelationGetSpecificKindIndexList(rel, false); + List* indexList = NULL; + if (RelationIsPartitionOfSubPartitionTable(partRel) && RelationIsValid(rel)) { + indexList = RelationGetSpecificKindIndexList(rel, false); + } else { + indexList = RelationGetSpecificKindIndexList(partRel, false); + } char** partitionIndexNames = getPartitionIndexesName(srcPartOid, indexList); - srcPart = partitionOpen(rel, srcPartOid, AccessExclusiveLock); + srcPart = partitionOpen(partRel, srcPartOid, AccessExclusiveLock); destPartitionName = pstrdup(PartitionGetPartitionName(srcPart)); - partitionClose(rel, srcPart, NoLock); + partitionClose(partRel, srcPart, NoLock); CommandCounterIncrement(); - fastDropPartition(rel, srcPartOid, "TRUNCATE PARTITION"); + fastDropPartition(partRel, srcPartOid, "TRUNCATE PARTITION"); CommandCounterIncrement(); - renamePartitionIndexes(rel->rd_id, destPartOid, partitionIndexNames, indexList); + renamePartitionIndexes(partRel->rd_id, destPartOid, partitionIndexNames, indexList); if (renameTargetPart) { CommandCounterIncrement(); - renamePartitionInternal(rel->rd_id, destPartOid, destPartitionName); + renamePartitionInternal(partRel->rd_id, destPartOid, destPartitionName); } list_free_ext(indexList); @@ -20861,13 +20868,20 @@ static void ATExecTruncatePartitionForSubpartitionTable(Relation rel, Oid partOi } foreach (subPartOidCell, subPartOidList) { Oid subPartOid = lfirst_oid(subPartOidCell); + bool all_ubtree = true; - AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid); if (cmd->alterGPI) { /* Delete subpartition tuples in GPI and add parent to pending vacuum list */ - DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid); + all_ubtree = DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid); + AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid); + } + + if (all_ubtree) { + /* If no nbtree global index exists */ + heap_truncate_one_part(partRel, subPartOid); + } else { + heap_truncate_one_part_new(cmd, partRel, subPartOid, rel); } - heap_truncate_one_part(partRel, subPartOid); pgstat_report_truncate(subPartOid, partRel->rd_id, partRel->rd_rel->relisshared); } @@ -21029,6 +21043,7 @@ static void ATExecTruncateSubPartition(Relation rel, AlterTableCmd* cmd) List* oidList = NULL; List* relid = lappend_oid(NULL, rel->rd_id); Oid subPartOid = InvalidOid; + bool all_ubtree = true; oidList = heap_truncate_find_FKs(relid); if (PointerIsValid(oidList)) { @@ -21066,17 +21081,21 @@ static void ATExecTruncateSubPartition(Relation rel, AlterTableCmd* cmd) Partition part = partitionOpen(rel, partOid, AccessExclusiveLock); Relation partRel = partitionGetRelation(rel, part); - AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid); - if (!cmd->alterGPI) { // Unusable Global Index ATUnusableGlobalIndex(rel); } else { /* Delete subpartition tuples in GPI and add parent to pending vacuum list */ - DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid); + all_ubtree = DeleteGPITuplesForSubPartition(RelationGetRelid(rel), partOid, subPartOid); + AlterSubPartitionedSetWaitCleanGPI(cmd->alterGPI, rel, partOid, subPartOid); } - heap_truncate_one_part(partRel, subPartOid); + if (all_ubtree) { + /* If no nbtree global index exists */ + heap_truncate_one_part(partRel, subPartOid); + } else { + heap_truncate_one_part_new(cmd, partRel, subPartOid, rel); + } pgstat_report_truncate(subPartOid, partRel->rd_id, partRel->rd_rel->relisshared); releaseDummyRelation(&partRel); @@ -24406,11 +24425,11 @@ static char* GenTemporaryPartitionName(Relation partTableRel, int sequence) #ifndef ENABLE_MULTIPLE_NODES static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *partDef, Oid bucketOid, - bool *isTimestamptz, StorageType stype, Datum new_reloptions) + bool *isTimestamptz, StorageType stype, Datum new_reloptions, bool isSubpartition) { #else static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *partDef, - Oid bucketOid, bool *isTimestamptz, StorageType stype) + Oid bucketOid, bool *isTimestamptz, StorageType stype, bool isSubpartition) { Datum new_reloptions = (Datum)0; #endif @@ -24426,7 +24445,9 @@ static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *p (Datum)new_reloptions, isTimestamptz, stype, - AccessExclusiveLock); + AccessExclusiveLock, + NULL, + isSubpartition); break; case T_ListPartitionDefState: newPartOid = HeapAddListPartition(pgPartRel, @@ -24437,7 +24458,9 @@ static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *p partTableRel->rd_rel->relowner, (Datum)new_reloptions, isTimestamptz, - stype); + stype, + NULL, + isSubpartition); break; case T_HashPartitionDefState: newPartOid = HeapAddHashPartition(pgPartRel, @@ -24448,7 +24471,9 @@ static Oid GetNewPartitionOid(Relation pgPartRel, Relation partTableRel, Node *p partTableRel->rd_rel->relowner, (Datum)new_reloptions, isTimestamptz, - stype); + stype, + NULL, + isSubpartition); break; default: ereport(ERROR, @@ -24480,17 +24505,20 @@ static Oid AddTemporaryPartition(Relation partTableRel, Node* partDef) Datum rel_reloptions; Datum new_reloptions; List* old_reloptions = NIL; + bool isPartitionOfSubPartition = RelationIsPartitionOfSubPartitionTable(partTableRel); bool* isTimestamptz = CheckPartkeyHasTimestampwithzone(partTableRel); bucketOid = RelationGetBucketOid(partTableRel); pgPartRel = relation_open(PartitionRelationId, RowExclusiveLock); /* add new partition entry in pg_partition */ - tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(partTableRel->rd_id)); + Oid relOid = isPartitionOfSubPartition ? + ObjectIdGetDatum(partTableRel->parentId) : ObjectIdGetDatum(partTableRel->rd_id); + tuple = SearchSysCache1(RELOID, relOid); if (!HeapTupleIsValid(tuple)) { ereport(ERROR, (errcode(ERRCODE_CACHE_LOOKUP_FAILED), - (errmsg("cache lookup failed"), errdetail("cache lookup failed for relation %u", partTableRel->rd_id), + (errmsg("cache lookup failed"), errdetail("cache lookup failed for relation %u", relOid), errcause("The oid of the target relation is invalid."), erraction("Check whether the target relation is correct.")))); } @@ -24508,18 +24536,25 @@ static Oid AddTemporaryPartition(Relation partTableRel, Node* partDef) /* Temporary tables do not use segment-page */ #ifndef ENABLE_MULTIPLE_NODES newPartOid = GetNewPartitionOid(pgPartRel, partTableRel, partDef, bucketOid, - isTimestamptz, RelationGetStorageType(partTableRel), new_reloptions); + isTimestamptz, RelationGetStorageType(partTableRel), new_reloptions, isPartitionOfSubPartition); #else - newPartOid = GetNewPartitionOid( - pgPartRel, partTableRel, partDef, bucketOid, isTimestamptz, RelationGetStorageType(partTableRel)); + newPartOid = GetNewPartitionOid(pgPartRel, partTableRel, partDef, bucketOid, isTimestamptz, + RelationGetStorageType(partTableRel), isPartitionOfSubPartition); + #endif // We must bump the command counter to make the newly-created // partition tuple visible for opening. CommandCounterIncrement(); - addIndexForPartition(partTableRel, newPartOid); + if (isPartitionOfSubPartition) { + Relation rel = heap_open(partTableRel->parentId, AccessShareLock); + addIndexForPartition(rel, newPartOid); + heap_close(rel, NoLock); + } else { + addIndexForPartition(partTableRel, newPartOid); + } - addToastTableForNewPartition(partTableRel, newPartOid); + addToastTableForNewPartition(partTableRel, newPartOid, isPartitionOfSubPartition); // invalidate relation CacheInvalidateRelcache(partTableRel); diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 78f7b5e4d..9977af63b 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -240,7 +240,7 @@ extern void AddGPIForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid) void AddCBIForPartition(Relation partTableRel, Relation tempTableRel, const List* indexRelList, const List* indexDestOidList); extern bool DeleteGPITuplesForPartition(Oid partTableOid, Oid partOid); -extern void DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid); +extern bool DeleteGPITuplesForSubPartition(Oid partTableOid, Oid partOid, Oid subPartOid); extern void mergeBTreeIndexes(List* mergingBtreeIndexes, List* srcPartMergeOffset, int2 bktId); extern bool RecheckIndexTuple(IndexScanDesc scan, TupleTableSlot *slot); extern void SetIndexCreateExtraArgs(IndexCreateExtraArgs* extra, Oid psortOid, bool isPartition, bool isGlobal,