From f719422916547584a0b753880a85b074349ab72c Mon Sep 17 00:00:00 2001 From: TotaJ Date: Tue, 26 Apr 2022 09:35:24 +0800 Subject: [PATCH] Fix ustore bug in publication. --- .../runtime/executor/execReplication.cpp | 18 ++++++-- .../storage/access/ustore/knl_utuple.cpp | 44 +++++++++++++++++++ src/include/access/ustore/knl_utuple.h | 1 + 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/gausskernel/runtime/executor/execReplication.cpp b/src/gausskernel/runtime/executor/execReplication.cpp index 695266eae..b67583339 100644 --- a/src/gausskernel/runtime/executor/execReplication.cpp +++ b/src/gausskernel/runtime/executor/execReplication.cpp @@ -322,7 +322,6 @@ static bool RelationFindReplTupleByIndex(EState *estate, Relation rel, Relation } if (found) { /* Found tuple, try to lock it in the lockmode. */ - outslot->tts_tuple = ExecMaterializeSlot(outslot); xwait = TransactionIdIsValid(snap.xmin) ? snap.xmin : snap.xmax; /* * If the tuple is locked, wait for locking transaction to finish @@ -346,12 +345,16 @@ static bool RelationFindReplTupleByIndex(EState *estate, Relation rel, Relation ItemPointer tid = tableam_tops_get_t_self(targetRel, outslot->tts_tuple); if (RelationIsUstoreFormat(targetRel)) { + /* materialize the slot, so we can visit it after the scan is end */ + outslot->tts_tuple = UHeapMaterialize(outslot); ItemPointerCopy(tid, &UHeaplocktup.ctid); rc = memset_s(&tbuf, sizeof(tbuf), 0, sizeof(tbuf)); securec_check(rc, "\0", "\0"); UHeaplocktup.disk_tuple = &tbuf.hdr; locktup = &UHeaplocktup; } else { + /* materialize the slot, so we can visit it after the scan is end */ + outslot->tts_tuple = ExecMaterializeSlot(outslot); ItemPointerCopy(tid, &heaplocktup.t_self); locktup = &heaplocktup; } @@ -401,6 +404,10 @@ static bool tuple_equals_slot(TupleDesc desc, const Tuple tup, TupleTableSlot *s /* Check equality of the attributes. */ for (attrnum = 0; attrnum < desc->natts; attrnum++) { TypeCacheEntry *typentry; + /* skip generate column */ + if (GetGeneratedCol(desc, attrnum)) { + continue; + } /* * If one value is NULL and other is not, then they are certainly not * equal @@ -478,7 +485,6 @@ static bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, Tuple found = true; ExecStoreTuple(scantuple, outslot, InvalidBuffer, false); - outslot->tts_tuple = ExecMaterializeSlot(outslot); xwait = TransactionIdIsValid(snap.xmin) ? snap.xmin : snap.xmax; /* @@ -511,12 +517,16 @@ static bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, Tuple ItemPointer tid = tableam_tops_get_t_self(rel, outslot->tts_tuple); if (RelationIsUstoreFormat(targetRel)) { + /* materialize the slot, so we can visit it after the scan is end */ + outslot->tts_tuple = UHeapMaterialize(outslot); ItemPointerCopy(tid, &UHeaplocktup.ctid); rc = memset_s(&tbuf, sizeof(tbuf), 0, sizeof(tbuf)); securec_check(rc, "\0", "\0"); UHeaplocktup.disk_tuple = &tbuf.hdr; locktup = &UHeaplocktup; } else { + /* materialize the slot, so we can visit it after the scan is end */ + outslot->tts_tuple = ExecMaterializeSlot(outslot); ItemPointerCopy(tid, &heaplocktup.t_self); locktup = &heaplocktup; } @@ -653,7 +663,6 @@ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot /* Compute stored generated columns */ if (rel->rd_att->constr && rel->rd_att->constr->has_generated_stored) { ExecComputeStoredGenerated(resultRelInfo, estate, slot, tuple, CMD_UPDATE); - tuple = slot->tts_tuple; } /* Check the constraints of the tuple */ @@ -672,10 +681,11 @@ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot rowMovement = true; } + tuple = slot->tts_tuple; CommandId cid = GetCurrentCommandId(true); /* OK, update the tuple and index entries for it */ if (!rowMovement) { - res = tableam_tuple_update(targetRelation, parentRelation, searchSlotTid, slot->tts_tuple, cid, + res = tableam_tuple_update(targetRelation, parentRelation, searchSlotTid, tuple, cid, InvalidSnapshot, estate->es_snapshot, true, &oldslot, &tmfd, &updateIndexes, &modifiedIdxAttrs, false, allowInplaceUpdate); CheckTupleModifyRes(res); diff --git a/src/gausskernel/storage/access/ustore/knl_utuple.cpp b/src/gausskernel/storage/access/ustore/knl_utuple.cpp index f872b0e89..6ca60b535 100644 --- a/src/gausskernel/storage/access/ustore/knl_utuple.cpp +++ b/src/gausskernel/storage/access/ustore/knl_utuple.cpp @@ -1818,3 +1818,47 @@ void UHeapSlotStoreUHeapTuple(UHeapTuple utuple, TupleTableSlot *slot, bool shou /* Mark extracted state invalid */ slot->tts_nvalid = 0; } + +/* + * Make the contents of the uheap table's slot contents solely depend on the slot(make them a local copy), + * and not on underlying external resources like another memory context, buffers etc. + * + * @pram slot: slot to be materialized. + */ +Tuple UHeapMaterialize(TupleTableSlot *slot) +{ + Assert(!slot->tts_isempty); + Assert(slot->tts_tupslotTableAm == TAM_USTORE); + Assert(slot->tts_tupleDescriptor != NULL); + /* + * If we have a regular physical tuple, and it's locally palloc'd, we have + * nothing to do. + */ + if (slot->tts_tuple && slot->tts_shouldFree) { + return slot->tts_tuple; + } + + /* + * Otherwise, copy or build a physical tuple, and store it into the slot. + * + * We may be called in a context that is shorter-lived than the tuple + * slot, but we have to ensure that the materialized tuple will survive + * anyway. + */ + MemoryContext old_context = MemoryContextSwitchTo(slot->tts_mcxt); + if (slot->tts_tuple != NULL) { + slot->tts_tuple = UHeapCopyTuple((UHeapTuple)slot->tts_tuple); + } else { + slot->tts_tuple = UHeapFormTuple(slot->tts_tupleDescriptor, slot->tts_values, slot->tts_isnull); + } + slot->tts_shouldFree = true; + MemoryContextSwitchTo(old_context); + + /* + * Have to deform from scratch, otherwise tts_values[] entries could point + * into the non-materialized tuple (which might be gone when accessed). + */ + slot->tts_nvalid = 0; + return slot->tts_tuple; +} + diff --git a/src/include/access/ustore/knl_utuple.h b/src/include/access/ustore/knl_utuple.h index e40522a78..d8912ff3d 100644 --- a/src/include/access/ustore/knl_utuple.h +++ b/src/include/access/ustore/knl_utuple.h @@ -314,4 +314,5 @@ template void UHeapFillDiskTuple(TupleDesc tupleDesc, Datum *values, const bool *isnull, UHeapDiskTupleData *diskTuple, uint32 dataSize, bool enableReverseBitmap, bool enableReserve); void CheckTupleValidity(Relation rel, UHeapTuple utuple); +Tuple UHeapMaterialize(TupleTableSlot *slot); #endif