Looks like I broke cases involving combinations of deferred update/delete

triggers ... oops ... but the regress tests should have covered this ...
This commit is contained in:
Tom Lane 2001-01-27 05:16:58 +00:00
parent 76beb79d27
commit a6f0adbe38
2 changed files with 54 additions and 38 deletions

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 void
ExecARInsertTriggers(EState *estate, Relation rel, HeapTuple trigtuple) 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 bool
@ -956,10 +962,16 @@ void
ExecARDeleteTriggers(EState *estate, ItemPointer tupleid) ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
{ {
Relation rel = estate->es_result_relation_info->ri_RelationDesc; Relation rel = estate->es_result_relation_info->ri_RelationDesc;
HeapTuple trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_DELETE, trigtuple, NULL); /* Must save info if there are upd/del deferred triggers on this rel */
heap_freetuple(trigtuple); 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 HeapTuple
@ -1011,10 +1023,16 @@ void
ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple) ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
{ {
Relation rel = estate->es_result_relation_info->ri_RelationDesc; Relation rel = estate->es_result_relation_info->ri_RelationDesc;
HeapTuple trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_UPDATE, trigtuple, newtuple); /* Must save info if there are upd/del deferred triggers on this rel */
heap_freetuple(trigtuple); 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() * 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. * resulted from in the same transaction.
* ---------- * ----------
*/ */
static DeferredTriggerEvent static DeferredTriggerEvent
deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid) deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
{ {
DeferredTriggerEvent previous; DeferredTriggerEvent previous = NULL;
int n; 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; continue;
if (previous->dte_event & TRIGGER_DEFERRED_CANCELED) if (prev->dte_event & TRIGGER_DEFERRED_CANCELED)
continue; continue;
if (ItemPointerGetBlockNumber(ctid) == if (ItemPointerGetBlockNumber(ctid) ==
ItemPointerGetBlockNumber(&(previous->dte_newctid)) && ItemPointerGetBlockNumber(&(prev->dte_newctid)) &&
ItemPointerGetOffsetNumber(ctid) == ItemPointerGetOffsetNumber(ctid) ==
ItemPointerGetOffsetNumber(&(previous->dte_newctid))) ItemPointerGetOffsetNumber(&(prev->dte_newctid)))
return previous; previous = prev;
} }
elog(ERROR, if (previous == NULL)
"deferredTriggerGetPreviousEvent: event for tuple %s not found", elog(ERROR,
DatumGetCString(DirectFunctionCall1(tidout, PointerGetDatum(ctid)))); "deferredTriggerGetPreviousEvent: event for tuple %s not found",
return NULL; DatumGetCString(DirectFunctionCall1(tidout,
PointerGetDatum(ctid))));
return previous;
} }
@ -1874,6 +1895,11 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
* DeferredTriggerSaveEvent() * DeferredTriggerSaveEvent()
* *
* Called by ExecAR...Triggers() to add the event to the queue. * 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 static void
@ -1895,15 +1921,6 @@ DeferredTriggerSaveEvent(Relation rel, int event,
elog(ERROR, elog(ERROR,
"DeferredTriggerSaveEvent() called outside of transaction"); "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 * Get the CTID's of OLD and NEW
* ---------- * ----------
@ -1923,6 +1940,8 @@ DeferredTriggerSaveEvent(Relation rel, int event,
*/ */
oldcxt = MemoryContextSwitchTo(deftrig_cxt); oldcxt = MemoryContextSwitchTo(deftrig_cxt);
ntriggers = rel->trigdesc->n_after_row[event];
triggers = rel->trigdesc->tg_after_row[event];
new_size = sizeof(DeferredTriggerEventData) + new_size = sizeof(DeferredTriggerEventData) +
ntriggers * sizeof(DeferredTriggerEventItem); ntriggers * sizeof(DeferredTriggerEventItem);

View File

@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * 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); ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
/* AFTER ROW INSERT Triggers */ /* AFTER ROW INSERT Triggers */
if (resultRelationDesc->trigdesc && if (resultRelationDesc->trigdesc)
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
ExecARInsertTriggers(estate, resultRelationDesc, tuple); ExecARInsertTriggers(estate, resultRelationDesc, tuple);
} }
@ -1351,8 +1350,7 @@ ldelete:;
*/ */
/* AFTER ROW DELETE Triggers */ /* AFTER ROW DELETE Triggers */
if (resultRelationDesc->trigdesc && if (resultRelationDesc->trigdesc)
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
ExecARDeleteTriggers(estate, tupleid); ExecARDeleteTriggers(estate, tupleid);
} }
@ -1491,8 +1489,7 @@ lreplace:;
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true); ExecInsertIndexTuples(slot, &(tuple->t_self), estate, true);
/* AFTER ROW UPDATE Triggers */ /* AFTER ROW UPDATE Triggers */
if (resultRelationDesc->trigdesc && if (resultRelationDesc->trigdesc)
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
ExecARUpdateTriggers(estate, tupleid, tuple); ExecARUpdateTriggers(estate, tupleid, tuple);
} }