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:
parent
76beb79d27
commit
a6f0adbe38
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user