diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index b0402effb9facad67bfd81690437624402d1ede7..d01ba4ec919a3b990754a399d18a76b583092581 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -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);
 
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 2959234318f6a36d8a09287b3beca10ec081d722..77af5e7eccef33046361f1a04b5312561aa5e0b7 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -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);
 }