mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-04 12:46:50 +02:00
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
|
* 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)
|
||||||
{
|
{
|
||||||
|
/* 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);
|
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;
|
||||||
|
|
||||||
|
/* 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);
|
HeapTuple trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
|
||||||
|
|
||||||
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_DELETE, trigtuple, NULL);
|
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_DELETE, trigtuple, NULL);
|
||||||
heap_freetuple(trigtuple);
|
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;
|
||||||
|
|
||||||
|
/* 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);
|
HeapTuple trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
|
||||||
|
|
||||||
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_UPDATE, trigtuple, newtuple);
|
DeferredTriggerSaveEvent(rel, TRIGGER_EVENT_UPDATE, trigtuple, newtuple);
|
||||||
heap_freetuple(trigtuple);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (previous == NULL)
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"deferredTriggerGetPreviousEvent: event for tuple %s not found",
|
"deferredTriggerGetPreviousEvent: event for tuple %s not found",
|
||||||
DatumGetCString(DirectFunctionCall1(tidout, PointerGetDatum(ctid))));
|
DatumGetCString(DirectFunctionCall1(tidout,
|
||||||
return NULL;
|
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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user