修复问题

Offering: openGaussDev

More detail: 修复TRUNCATE二级分区同时更新全局分区索引后索引损坏的问题

# Conflicts:
#	src/gausskernel/optimizer/commands/tablecmds.cpp

Match-id-5cca3b98dbd06df99074a23359704a58db4d5fc2
This commit is contained in:
openGaussDev
2022-03-08 19:02:23 +08:00
committed by yanghao
parent 1246208782
commit e353bc4d55
3 changed files with 76 additions and 33 deletions

View File

@ -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<IndexInfo*>(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)

View File

@ -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);

View File

@ -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,