diff options
author | Vadim B. Mikheev <vadim4o@yahoo.com> | 1999-01-29 11:56:01 +0000 |
---|---|---|
committer | Vadim B. Mikheev <vadim4o@yahoo.com> | 1999-01-29 11:56:01 +0000 |
commit | aaef7beb79dd397a6c7ab004909a1beebe5843b8 (patch) | |
tree | 24957b5ada8f7045c92ffed1bc6ebc8921081721 /src/backend/commands/trigger.c | |
parent | 1d41e88568782213a52fa88b9f732b730bc29005 (diff) | |
download | postgresql-aaef7beb79dd397a6c7ab004909a1beebe5843b8.tar.gz postgresql-aaef7beb79dd397a6c7ab004909a1beebe5843b8.zip |
Hope that execMain.c good merged.
Fix for BEFORE ROW UPDATE triggers: result tuple may be different
(due to concurrent update) from one initially produced by top level plan.
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r-- | src/backend/commands/trigger.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index a5e27227cf2..aac9f2599f5 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -42,7 +42,7 @@ void FreeTriggerDesc(Relation relation); static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger); static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid, - bool before); + TupleTableSlot **newSlot); extern GlobalMemory CacheCxt; @@ -664,9 +664,10 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid) Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE]; HeapTuple trigtuple; HeapTuple newtuple = NULL; + TupleTableSlot *newSlot; int i; - trigtuple = GetTupleForTrigger(estate, tupleid, true); + trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot); if (trigtuple == NULL) return false; @@ -701,7 +702,7 @@ ExecARDeleteTriggers(EState *estate, ItemPointer tupleid) HeapTuple trigtuple; int i; - trigtuple = GetTupleForTrigger(estate, tupleid, false); + trigtuple = GetTupleForTrigger(estate, tupleid, NULL); Assert(trigtuple != NULL); SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); @@ -732,12 +733,20 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple) HeapTuple trigtuple; HeapTuple oldtuple; HeapTuple intuple = newtuple; + TupleTableSlot *newSlot; int i; - trigtuple = GetTupleForTrigger(estate, tupleid, true); + trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot); if (trigtuple == NULL) return NULL; + /* + * In READ COMMITTED isolevel it's possible that newtuple + * was changed due to concurrent update. + */ + if (newSlot != NULL) + intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot); + SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData->tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE; @@ -770,7 +779,7 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple) HeapTuple trigtuple; int i; - trigtuple = GetTupleForTrigger(estate, tupleid, false); + trigtuple = GetTupleForTrigger(estate, tupleid, NULL); Assert(trigtuple != NULL); SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); @@ -794,20 +803,21 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple) extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid); static HeapTuple -GetTupleForTrigger(EState *estate, ItemPointer tid, bool before) +GetTupleForTrigger(EState *estate, ItemPointer tid, TupleTableSlot **newSlot) { Relation relation = estate->es_result_relation_info->ri_RelationDesc; HeapTupleData tuple; HeapTuple result; Buffer buffer; - if (before) + if (newSlot != NULL) { int test; /* * mark tuple for update */ + *newSlot = NULL; tuple.t_self = *tid; ltrmark:; test = heap_mark4update(relation, &tuple, &buffer); @@ -826,13 +836,14 @@ ltrmark:; elog(ERROR, "Can't serialize access due to concurrent update"); else if (!(ItemPointerEquals(&(tuple.t_self), tid))) { - TupleTableSlot *slot = EvalPlanQual(estate, + TupleTableSlot *epqslot = EvalPlanQual(estate, estate->es_result_relation_info->ri_RangeTableIndex, &(tuple.t_self)); - if (!(TupIsNull(slot))) + if (!(TupIsNull(epqslot))) { *tid = tuple.t_self; + *newSlot = epqslot; goto ltrmark; } } |