diff options
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r-- | src/backend/commands/trigger.c | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index d9d9201ac38..7326ece5565 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -84,8 +84,9 @@ static bool GetTupleForTrigger(EState *estate, ItemPointer tid, LockTupleMode lockmode, TupleTableSlot *oldslot, - TupleTableSlot **newSlot, - TM_FailureData *tmfpd); + TupleTableSlot **epqslot, + TM_Result *tmresultp, + TM_FailureData *tmfdp); static bool TriggerEnabled(EState *estate, ResultRelInfo *relinfo, Trigger *trigger, TriggerEvent event, Bitmapset *modifiedCols, @@ -2753,11 +2754,13 @@ ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo, * back the concurrently updated tuple if any. */ bool -ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, - ResultRelInfo *relinfo, - ItemPointer tupleid, - HeapTuple fdw_trigtuple, - TupleTableSlot **epqslot) +ExecBRDeleteTriggersNew(EState *estate, EPQState *epqstate, + ResultRelInfo *relinfo, + ItemPointer tupleid, + HeapTuple fdw_trigtuple, + TupleTableSlot **epqslot, + TM_Result *tmresult, + TM_FailureData *tmfd) { TupleTableSlot *slot = ExecGetTriggerOldSlot(estate, relinfo); TriggerDesc *trigdesc = relinfo->ri_TrigDesc; @@ -2774,7 +2777,7 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid, LockTupleExclusive, slot, &epqslot_candidate, - NULL)) + tmresult, tmfd)) return false; /* @@ -2838,6 +2841,21 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, } /* + * ABI-compatible wrapper to emulate old version of the above function. + * Do not call this version in new code. + */ +bool +ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, + ResultRelInfo *relinfo, + ItemPointer tupleid, + HeapTuple fdw_trigtuple, + TupleTableSlot **epqslot) +{ + return ExecBRDeleteTriggersNew(estate, epqstate, relinfo, tupleid, + fdw_trigtuple, epqslot, NULL, NULL); +} + +/* * Note: is_crosspart_update must be true if the DELETE is being performed * as part of a cross-partition update. */ @@ -2865,6 +2883,7 @@ ExecARDeleteTriggers(EState *estate, LockTupleExclusive, slot, NULL, + NULL, NULL); else ExecForceStoreHeapTuple(fdw_trigtuple, slot, false); @@ -3001,12 +3020,13 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo, } bool -ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, - ResultRelInfo *relinfo, - ItemPointer tupleid, - HeapTuple fdw_trigtuple, - TupleTableSlot *newslot, - TM_FailureData *tmfd) +ExecBRUpdateTriggersNew(EState *estate, EPQState *epqstate, + ResultRelInfo *relinfo, + ItemPointer tupleid, + HeapTuple fdw_trigtuple, + TupleTableSlot *newslot, + TM_Result *tmresult, + TM_FailureData *tmfd) { TriggerDesc *trigdesc = relinfo->ri_TrigDesc; TupleTableSlot *oldslot = ExecGetTriggerOldSlot(estate, relinfo); @@ -3030,7 +3050,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, /* get a copy of the on-disk tuple we are planning to update */ if (!GetTupleForTrigger(estate, epqstate, relinfo, tupleid, lockmode, oldslot, &epqslot_candidate, - tmfd)) + tmresult, tmfd)) return false; /* cancel the update action */ /* @@ -3135,6 +3155,22 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, } /* + * ABI-compatible wrapper to emulate old version of the above function. + * Do not call this version in new code. + */ +bool +ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, + ResultRelInfo *relinfo, + ItemPointer tupleid, + HeapTuple fdw_trigtuple, + TupleTableSlot *newslot, + TM_FailureData *tmfd) +{ + return ExecBRUpdateTriggersNew(estate, epqstate, relinfo, tupleid, + fdw_trigtuple, newslot, NULL, tmfd); +} + +/* * Note: 'src_partinfo' and 'dst_partinfo', when non-NULL, refer to the source * and destination partitions, respectively, of a cross-partition update of * the root partitioned table mentioned in the query, given by 'relinfo'. @@ -3185,6 +3221,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo, LockTupleExclusive, oldslot, NULL, + NULL, NULL); else if (fdw_trigtuple != NULL) ExecForceStoreHeapTuple(fdw_trigtuple, oldslot, false); @@ -3340,6 +3377,7 @@ GetTupleForTrigger(EState *estate, LockTupleMode lockmode, TupleTableSlot *oldslot, TupleTableSlot **epqslot, + TM_Result *tmresultp, TM_FailureData *tmfdp) { Relation relation = relinfo->ri_RelationDesc; @@ -3367,6 +3405,8 @@ GetTupleForTrigger(EState *estate, &tmfd); /* Let the caller know about the status of this operation */ + if (tmresultp) + *tmresultp = test; if (tmfdp) *tmfdp = tmfd; @@ -3394,6 +3434,18 @@ GetTupleForTrigger(EState *estate, case TM_Ok: if (tmfd.traversed) { + /* + * Recheck the tuple using EPQ. For MERGE, we leave this + * to the caller (it must do additional rechecking, and + * might end up executing a different action entirely). + */ + if (estate->es_plannedstmt->commandType == CMD_MERGE) + { + if (tmresultp) + *tmresultp = TM_Updated; + return false; + } + *epqslot = EvalPlanQual(epqstate, relation, relinfo->ri_RangeTableIndex, |