Looks like I broke cases involving combinations of deferred update/delete
authorTom Lane
Sat, 27 Jan 2001 05:16:58 +0000 (05:16 +0000)
committerTom Lane
Sat, 27 Jan 2001 05:16:58 +0000 (05:16 +0000)
triggers ... oops ... but the regress tests should have covered this ...

src/backend/commands/trigger.c
src/backend/executor/execMain.c

index b0402effb9facad67bfd81690437624402d1ede7..d01ba4ec919a3b990754a399d18a76b583092581 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.85 2001/01/24 19:42:53 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.86 2001/01/27 05:16:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -911,7 +911,13 @@ ExecBRInsertTriggers(EState *estate, Relation rel, HeapTuple trigtuple)
 void
 ExecARInsertTriggers(EState *estate, Relation rel, HeapTuple trigtuple)
 {
-   DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_INSERT, NULL, trigtuple);
+   /* Must save info if there are any deferred triggers on this rel */
+   if (rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0 ||
+       rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0 ||
+       rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
+   {
+       DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_INSERT, NULL, trigtuple);
+   }
 }
 
 bool
@@ -956,10 +962,16 @@ void
 ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
 {
    Relation    rel = estate->es_result_relation_info->ri_RelationDesc;
-   HeapTuple   trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
 
-   DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_DELETE, trigtuple, NULL);
-   heap_freetuple(trigtuple);
+   /* Must save info if there are upd/del deferred triggers on this rel */
+   if (rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0 ||
+       rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
+   {
+       HeapTuple   trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
+
+       DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_DELETE, trigtuple, NULL);
+       heap_freetuple(trigtuple);
+   }
 }
 
 HeapTuple
@@ -1011,10 +1023,16 @@ void
 ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
 {
    Relation    rel = estate->es_result_relation_info->ri_RelationDesc;
-   HeapTuple   trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
 
-   DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_UPDATE, trigtuple, newtuple);
-   heap_freetuple(trigtuple);
+   /* Must save info if there are upd/del deferred triggers on this rel */
+   if (rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0 ||
+       rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
+   {
+       HeapTuple   trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
+
+       DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_UPDATE, trigtuple, newtuple);
+       heap_freetuple(trigtuple);
+   }
 }
 
 
@@ -1225,36 +1243,39 @@ deferredTriggerAddEvent(DeferredTriggerEvent event)
 /* ----------
  * deferredTriggerGetPreviousEvent()
  *
- * Backward scan the eventlist to find the event a given OLD tuple
+ * Scan the eventlist to find the event a given OLD tuple
  * resulted from in the same transaction.
  * ----------
  */
 static DeferredTriggerEvent
 deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
 {
-   DeferredTriggerEvent previous;
-   int         n;
+   DeferredTriggerEvent previous = NULL;
+   List   *dtev;
 
-   for (n = deftrig_n_events - 1; n >= 0; n--)
+   /* Search the list to find the last event affecting this tuple */
+   foreach(dtev, deftrig_events)
    {
-       previous = (DeferredTriggerEvent) nth(n, deftrig_events);
+       DeferredTriggerEvent prev = (DeferredTriggerEvent) lfirst(dtev);
 
-       if (previous->dte_relid != relid)
+       if (prev->dte_relid != relid)
            continue;
-       if (previous->dte_event & TRIGGER_DEFERRED_CANCELED)
+       if (prev->dte_event & TRIGGER_DEFERRED_CANCELED)
            continue;
 
        if (ItemPointerGetBlockNumber(ctid) ==
-           ItemPointerGetBlockNumber(&(previous->dte_newctid)) &&
+           ItemPointerGetBlockNumber(&(prev->dte_newctid)) &&
            ItemPointerGetOffsetNumber(ctid) ==
-           ItemPointerGetOffsetNumber(&(previous->dte_newctid)))
-           return previous;
+           ItemPointerGetOffsetNumber(&(prev->dte_newctid)))
+           previous = prev;
    }
 
-   elog(ERROR,
-        "deferredTriggerGetPreviousEvent: event for tuple %s not found",
-        DatumGetCString(DirectFunctionCall1(tidout, PointerGetDatum(ctid))));
-   return NULL;
+   if (previous == NULL)
+       elog(ERROR,
+            "deferredTriggerGetPreviousEvent: event for tuple %s not found",
+            DatumGetCString(DirectFunctionCall1(tidout,
+                                                PointerGetDatum(ctid))));
+   return previous;
 }
 
 
@@ -1874,6 +1895,11 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
  * DeferredTriggerSaveEvent()
  *
  * Called by ExecAR...Triggers() to add the event to the queue.
+ *
+ * NOTE: should be called only if we've determined that an event must
+ * be added to the queue.  We must save *all* events if there is either
+ * an UPDATE or a DELETE deferred trigger; see uses of
+ * deferredTriggerGetPreviousEvent.
  * ----------
  */
 static void
@@ -1895,15 +1921,6 @@ DeferredTriggerSaveEvent(Relation rel, int event,
        elog(ERROR,
             "DeferredTriggerSaveEvent() called outside of transaction");
 
-   /* ----------
-    * Check if we're interested in this row at all
-    * ----------
-    */
-   ntriggers = rel->trigdesc->n_after_row[event];
-   if (ntriggers <= 0)
-       return;
-   triggers = rel->trigdesc->tg_after_row[event];
-
    /* ----------
     * Get the CTID's of OLD and NEW
     * ----------
@@ -1923,6 +1940,8 @@ DeferredTriggerSaveEvent(Relation rel, int event,
     */
    oldcxt = MemoryContextSwitchTo(deftrig_cxt);
 
+   ntriggers = rel->trigdesc->n_after_row[event];
+   triggers = rel->trigdesc->tg_after_row[event];
    new_size = sizeof(DeferredTriggerEventData) +
        ntriggers * sizeof(DeferredTriggerEventItem);
 
index 2959234318f6a36d8a09287b3beca10ec081d722..77af5e7eccef33046361f1a04b5312561aa5e0b7 100644 (file)
@@ -27,7 +27,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.136 2001/01/24 19:42:53 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.137 2001/01/27 05:16:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1264,8 +1264,7 @@ ExecAppend(TupleTableSlot *slot,
        ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
 
    /* AFTER ROW INSERT Triggers */
-   if (resultRelationDesc->trigdesc &&
-       resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
+   if (resultRelationDesc->trigdesc)
        ExecARInsertTriggers(estate, resultRelationDesc, tuple);
 }
 
@@ -1351,8 +1350,7 @@ ldelete:;
     */
 
    /* AFTER ROW DELETE Triggers */
-   if (resultRelationDesc->trigdesc &&
-       resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
+   if (resultRelationDesc->trigdesc)
        ExecARDeleteTriggers(estate, tupleid);
 }
 
@@ -1491,8 +1489,7 @@ lreplace:;
        ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
 
    /* AFTER ROW UPDATE Triggers */
-   if (resultRelationDesc->trigdesc &&
-       resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
+   if (resultRelationDesc->trigdesc)
        ExecARUpdateTriggers(estate, tupleid, tuple);
 }