aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c82
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,