77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.85 2001/01/24 19:42:53 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.86 2001/01/27 05:16:58 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -911,7 +911,13 @@ ExecBRInsertTriggers(EState *estate, Relation rel, HeapTuple trigtuple)
911911void
912912ExecARInsertTriggers (EState * estate ,Relation rel ,HeapTuple trigtuple )
913913{
914- DeferredTriggerSaveEvent (rel ,TRIGGER_EVENT_INSERT ,NULL ,trigtuple );
914+ /* Must save info if there are any deferred triggers on this rel */
915+ if (rel -> trigdesc -> n_after_row [TRIGGER_EVENT_INSERT ]> 0 ||
916+ rel -> trigdesc -> n_after_row [TRIGGER_EVENT_UPDATE ]> 0 ||
917+ rel -> trigdesc -> n_after_row [TRIGGER_EVENT_DELETE ]> 0 )
918+ {
919+ DeferredTriggerSaveEvent (rel ,TRIGGER_EVENT_INSERT ,NULL ,trigtuple );
920+ }
915921}
916922
917923bool
@@ -956,10 +962,16 @@ void
956962ExecARDeleteTriggers (EState * estate ,ItemPointer tupleid )
957963{
958964Relation rel = estate -> es_result_relation_info -> ri_RelationDesc ;
959- HeapTuple trigtuple = GetTupleForTrigger (estate ,tupleid ,NULL );
960965
961- DeferredTriggerSaveEvent (rel ,TRIGGER_EVENT_DELETE ,trigtuple ,NULL );
962- heap_freetuple (trigtuple );
966+ /* Must save info if there are upd/del deferred triggers on this rel */
967+ if (rel -> trigdesc -> n_after_row [TRIGGER_EVENT_UPDATE ]> 0 ||
968+ rel -> trigdesc -> n_after_row [TRIGGER_EVENT_DELETE ]> 0 )
969+ {
970+ HeapTuple trigtuple = GetTupleForTrigger (estate ,tupleid ,NULL );
971+
972+ DeferredTriggerSaveEvent (rel ,TRIGGER_EVENT_DELETE ,trigtuple ,NULL );
973+ heap_freetuple (trigtuple );
974+ }
963975}
964976
965977HeapTuple
@@ -1011,10 +1023,16 @@ void
10111023ExecARUpdateTriggers (EState * estate ,ItemPointer tupleid ,HeapTuple newtuple )
10121024{
10131025Relation rel = estate -> es_result_relation_info -> ri_RelationDesc ;
1014- HeapTuple trigtuple = GetTupleForTrigger (estate ,tupleid ,NULL );
10151026
1016- DeferredTriggerSaveEvent (rel ,TRIGGER_EVENT_UPDATE ,trigtuple ,newtuple );
1017- heap_freetuple (trigtuple );
1027+ /* Must save info if there are upd/del deferred triggers on this rel */
1028+ if (rel -> trigdesc -> n_after_row [TRIGGER_EVENT_UPDATE ]> 0 ||
1029+ rel -> trigdesc -> n_after_row [TRIGGER_EVENT_DELETE ]> 0 )
1030+ {
1031+ HeapTuple trigtuple = GetTupleForTrigger (estate ,tupleid ,NULL );
1032+
1033+ DeferredTriggerSaveEvent (rel ,TRIGGER_EVENT_UPDATE ,trigtuple ,newtuple );
1034+ heap_freetuple (trigtuple );
1035+ }
10181036}
10191037
10201038
@@ -1225,36 +1243,39 @@ deferredTriggerAddEvent(DeferredTriggerEvent event)
12251243/* ----------
12261244 * deferredTriggerGetPreviousEvent()
12271245 *
1228- *Backward scan the eventlist to find the event a given OLD tuple
1246+ *Scan the eventlist to find the event a given OLD tuple
12291247 *resulted from in the same transaction.
12301248 * ----------
12311249 */
12321250static DeferredTriggerEvent
12331251deferredTriggerGetPreviousEvent (Oid relid ,ItemPointer ctid )
12341252{
1235- DeferredTriggerEvent previous ;
1236- int n ;
1253+ DeferredTriggerEvent previous = NULL ;
1254+ List * dtev ;
12371255
1238- for (n = deftrig_n_events - 1 ;n >=0 ;n -- )
1256+ /* Search the list to find the last event affecting this tuple */
1257+ foreach (dtev ,deftrig_events )
12391258{
1240- previous = (DeferredTriggerEvent )nth ( n , deftrig_events );
1259+ DeferredTriggerEvent prev = (DeferredTriggerEvent )lfirst ( dtev );
12411260
1242- if (previous -> dte_relid != relid )
1261+ if (prev -> dte_relid != relid )
12431262continue ;
1244- if (previous -> dte_event & TRIGGER_DEFERRED_CANCELED )
1263+ if (prev -> dte_event & TRIGGER_DEFERRED_CANCELED )
12451264continue ;
12461265
12471266if (ItemPointerGetBlockNumber (ctid )==
1248- ItemPointerGetBlockNumber (& (previous -> dte_newctid ))&&
1267+ ItemPointerGetBlockNumber (& (prev -> dte_newctid ))&&
12491268ItemPointerGetOffsetNumber (ctid )==
1250- ItemPointerGetOffsetNumber (& (previous -> dte_newctid )))
1251- return previous ;
1269+ ItemPointerGetOffsetNumber (& (prev -> dte_newctid )))
1270+ previous = prev ;
12521271}
12531272
1254- elog (ERROR ,
1255- "deferredTriggerGetPreviousEvent: event for tuple %s not found" ,
1256- DatumGetCString (DirectFunctionCall1 (tidout ,PointerGetDatum (ctid ))));
1257- return NULL ;
1273+ if (previous == NULL )
1274+ elog (ERROR ,
1275+ "deferredTriggerGetPreviousEvent: event for tuple %s not found" ,
1276+ DatumGetCString (DirectFunctionCall1 (tidout ,
1277+ PointerGetDatum (ctid ))));
1278+ return previous ;
12581279}
12591280
12601281
@@ -1874,6 +1895,11 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
18741895 * DeferredTriggerSaveEvent()
18751896 *
18761897 *Called by ExecAR...Triggers() to add the event to the queue.
1898+ *
1899+ *NOTE: should be called only if we've determined that an event must
1900+ *be added to the queue. We must save *all* events if there is either
1901+ *an UPDATE or a DELETE deferred trigger; see uses of
1902+ *deferredTriggerGetPreviousEvent.
18771903 * ----------
18781904 */
18791905static void
@@ -1895,15 +1921,6 @@ DeferredTriggerSaveEvent(Relation rel, int event,
18951921elog (ERROR ,
18961922"DeferredTriggerSaveEvent() called outside of transaction" );
18971923
1898- /* ----------
1899- * Check if we're interested in this row at all
1900- * ----------
1901- */
1902- ntriggers = rel -> trigdesc -> n_after_row [event ];
1903- if (ntriggers <=0 )
1904- return ;
1905- triggers = rel -> trigdesc -> tg_after_row [event ];
1906-
19071924/* ----------
19081925 * Get the CTID's of OLD and NEW
19091926 * ----------
@@ -1923,6 +1940,8 @@ DeferredTriggerSaveEvent(Relation rel, int event,
19231940 */
19241941oldcxt = MemoryContextSwitchTo (deftrig_cxt );
19251942
1943+ ntriggers = rel -> trigdesc -> n_after_row [event ];
1944+ triggers = rel -> trigdesc -> tg_after_row [event ];
19261945new_size = sizeof (DeferredTriggerEventData )+
19271946ntriggers * sizeof (DeferredTriggerEventItem );
19281947