]> granicus.if.org Git - postgresql/blobdiff - src/backend/commands/trigger.c
Fix crash caused by EPQ happening with a before update trigger present.
[postgresql] / src / backend / commands / trigger.c
index cdb1105b4a7f5cd96cf182bb449e00c29142b0d0..7ba859d446d6c459bd7a551d8bb08dfbebc64006 100644 (file)
@@ -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;