diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 851623c8ba..57c98912d5 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -2773,10 +2773,10 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid)); if (fdw_trigtuple == NULL) { - TupleTableSlot *newSlot; + TupleTableSlot *epqslot_candidate = NULL; if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid, - LockTupleExclusive, slot, &newSlot)) + LockTupleExclusive, slot, &epqslot_candidate)) return false; /* @@ -2784,9 +2784,9 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, * function requested for the updated tuple, skip the trigger * execution. */ - if (newSlot != NULL && epqslot != NULL) + if (epqslot_candidate != NULL && epqslot != NULL) { - *epqslot = newSlot; + *epqslot = epqslot_candidate; return false; } @@ -3026,11 +3026,11 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, Assert(HeapTupleIsValid(fdw_trigtuple) ^ ItemPointerIsValid(tupleid)); if (fdw_trigtuple == NULL) { - TupleTableSlot *newSlot = NULL; + TupleTableSlot *epqslot_candidate = NULL; /* get a copy of the on-disk tuple we are planning to update */ if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid, - lockmode, oldslot, &newSlot)) + lockmode, oldslot, &epqslot_candidate)) return false; /* cancel the update action */ /* @@ -3045,11 +3045,14 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, * nor our caller have any more interest in the prior contents of that * slot. */ - if (newSlot != NULL) + if (epqslot_candidate != NULL) { - TupleTableSlot *slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot); + TupleTableSlot *epqslot_clean; - ExecCopySlot(newslot, slot); + epqslot_clean = ExecFilterJunk(relinfo->ri_junkFilter, epqslot_candidate); + + if (newslot != epqslot_clean) + ExecCopySlot(newslot, epqslot_clean); } trigtuple = ExecFetchSlotHeapTuple(oldslot, true, &should_free_trig); @@ -3311,17 +3314,17 @@ GetTupleForTrigger(EState *estate, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot *oldslot, - TupleTableSlot **newSlot) + TupleTableSlot **epqslot) { Relation relation = relinfo->ri_RelationDesc; - if (newSlot != NULL) + if (epqslot != NULL) { TM_Result test; TM_FailureData tmfd; int lockflags = 0; - *newSlot = NULL; + *epqslot = NULL; /* caller must pass an epqstate if EvalPlanQual is possible */ Assert(epqstate != NULL); @@ -3361,21 +3364,20 @@ GetTupleForTrigger(EState *estate, case TM_Ok: if (tmfd.traversed) { - TupleTableSlot *epqslot; - - epqslot = EvalPlanQual(epqstate, - relation, - relinfo->ri_RangeTableIndex, - oldslot); + *epqslot = EvalPlanQual(epqstate, + relation, + relinfo->ri_RangeTableIndex, + oldslot); /* * If PlanQual failed for updated tuple - we must not * process this tuple! */ - if (TupIsNull(epqslot)) + if (TupIsNull(*epqslot)) + { + *epqslot = NULL; return false; - - *newSlot = epqslot; + } } break; diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index 203b1ab7dc..885b481d9a 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -476,6 +476,7 @@ static inline TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot) { Assert(!TTS_EMPTY(srcslot)); + AssertArg(srcslot != dstslot); dstslot->tts_ops->copyslot(dstslot, srcslot);