aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorVadim B. Mikheev <vadim4o@yahoo.com>1999-01-29 11:56:01 +0000
committerVadim B. Mikheev <vadim4o@yahoo.com>1999-01-29 11:56:01 +0000
commitaaef7beb79dd397a6c7ab004909a1beebe5843b8 (patch)
tree24957b5ada8f7045c92ffed1bc6ebc8921081721 /src/backend/commands/trigger.c
parent1d41e88568782213a52fa88b9f732b730bc29005 (diff)
downloadpostgresql-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.c29
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;
}
}