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 | |
| parent | 1d41e88568782213a52fa88b9f732b730bc29005 (diff) | |
| download | postgresql-aaef7beb79dd397a6c7ab004909a1beebe5843b8.tar.gz | |
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')
| -rw-r--r-- | src/backend/commands/trigger.c | 29 | ||||
| -rw-r--r-- | src/backend/executor/execMain.c | 39 |
2 files changed, 45 insertions, 23 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index a5e27227cf..aac9f2599f 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; } } diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index ba4d09eaa3..f074ce951f 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.67 1999/01/29 10:15:09 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.68 1999/01/29 11:56:00 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -66,7 +66,7 @@ static void EndPlan(Plan *plan, EState *estate); static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan, CmdType operation, int numberTuples, ScanDirection direction, DestReceiver *destfunc); -static void ExecRetrieve(TupleTableSlot *slot, +static void ExecRetrieve(TupleTableSlot *slot, DestReceiver *destfunc, EState *estate); static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid, @@ -170,11 +170,11 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate) TupleTableSlot * ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) { - CmdType operation; - Plan *plan; + CmdType operation; + Plan *plan; TupleTableSlot *result; - CommandDest dest; - void (*destination) (); + CommandDest dest; + DestReceiver *destfunc; /****************** * sanity checks @@ -190,10 +190,19 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) operation = queryDesc->operation; plan = queryDesc->plantree; dest = queryDesc->dest; - destination = (void (*) ()) DestToFunction(dest); + destfunc = DestToFunction(dest); estate->es_processed = 0; estate->es_lastoid = InvalidOid; + /****************** + * FIXME: the dest setup function ought to be handed the tuple desc + * for the tuples to be output, but I'm not quite sure how to get that + * info at this point. For now, passing NULL is OK because no existing + * dest setup function actually uses the pointer. + ****************** + */ + (*destfunc->setup) (destfunc, (TupleDesc) NULL); + switch (feature) { @@ -203,7 +212,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) operation, ALL_TUPLES, ForwardScanDirection, - destination); + destfunc); break; case EXEC_FOR: result = ExecutePlan(estate, @@ -211,7 +220,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) operation, count, ForwardScanDirection, - destination); + destfunc); break; /****************** @@ -224,7 +233,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) operation, count, BackwardScanDirection, - destination); + destfunc); break; /****************** @@ -238,7 +247,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) operation, ONE_TUPLE, ForwardScanDirection, - destination); + destfunc); break; default: result = NULL; @@ -246,6 +255,8 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) break; } + (*destfunc->cleanup) (destfunc); + return result; } @@ -756,7 +767,7 @@ ExecutePlan(EState *estate, CmdType operation, int numberTuples, ScanDirection direction, - DestReceiver *destfunc) + DestReceiver* destfunc) { JunkFilter *junkfilter; @@ -941,7 +952,7 @@ lmark:; { case CMD_SELECT: ExecRetrieve(slot, /* slot containing tuple */ - destfunc, /* print function */ + destfunc, /* destination's tuple-receiver obj */ estate); /* */ result = slot; break; @@ -1024,7 +1035,7 @@ ExecRetrieve(TupleTableSlot *slot, * send the tuple to the front end (or the screen) ****************** */ - (*printfunc) (tuple, attrtype); + (*destfunc->receiveTuple) (tuple, attrtype, destfunc); IncrRetrieved(); (estate->es_processed)++; } |
