Commit aaef7beb authored by Vadim B. Mikheev's avatar Vadim B. Mikheev

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.
parent 1d41e885
...@@ -42,7 +42,7 @@ void FreeTriggerDesc(Relation relation); ...@@ -42,7 +42,7 @@ void FreeTriggerDesc(Relation relation);
static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger); static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid, static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
bool before); TupleTableSlot **newSlot);
extern GlobalMemory CacheCxt; extern GlobalMemory CacheCxt;
...@@ -664,9 +664,10 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid) ...@@ -664,9 +664,10 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE]; Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
HeapTuple trigtuple; HeapTuple trigtuple;
HeapTuple newtuple = NULL; HeapTuple newtuple = NULL;
TupleTableSlot *newSlot;
int i; int i;
trigtuple = GetTupleForTrigger(estate, tupleid, true); trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot);
if (trigtuple == NULL) if (trigtuple == NULL)
return false; return false;
...@@ -701,7 +702,7 @@ ExecARDeleteTriggers(EState *estate, ItemPointer tupleid) ...@@ -701,7 +702,7 @@ ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
HeapTuple trigtuple; HeapTuple trigtuple;
int i; int i;
trigtuple = GetTupleForTrigger(estate, tupleid, false); trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
Assert(trigtuple != NULL); Assert(trigtuple != NULL);
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
...@@ -732,12 +733,20 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple) ...@@ -732,12 +733,20 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
HeapTuple trigtuple; HeapTuple trigtuple;
HeapTuple oldtuple; HeapTuple oldtuple;
HeapTuple intuple = newtuple; HeapTuple intuple = newtuple;
TupleTableSlot *newSlot;
int i; int i;
trigtuple = GetTupleForTrigger(estate, tupleid, true); trigtuple = GetTupleForTrigger(estate, tupleid, &newSlot);
if (trigtuple == NULL) if (trigtuple == NULL)
return 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 = (TriggerData *) palloc(sizeof(TriggerData));
SaveTriggerData->tg_event = SaveTriggerData->tg_event =
TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE; TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
...@@ -770,7 +779,7 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple) ...@@ -770,7 +779,7 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
HeapTuple trigtuple; HeapTuple trigtuple;
int i; int i;
trigtuple = GetTupleForTrigger(estate, tupleid, false); trigtuple = GetTupleForTrigger(estate, tupleid, NULL);
Assert(trigtuple != NULL); Assert(trigtuple != NULL);
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData)); SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
...@@ -794,20 +803,21 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple) ...@@ -794,20 +803,21 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid); extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
static HeapTuple 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; Relation relation = estate->es_result_relation_info->ri_RelationDesc;
HeapTupleData tuple; HeapTupleData tuple;
HeapTuple result; HeapTuple result;
Buffer buffer; Buffer buffer;
if (before) if (newSlot != NULL)
{ {
int test; int test;
/* /*
* mark tuple for update * mark tuple for update
*/ */
*newSlot = NULL;
tuple.t_self = *tid; tuple.t_self = *tid;
ltrmark:; ltrmark:;
test = heap_mark4update(relation, &tuple, &buffer); test = heap_mark4update(relation, &tuple, &buffer);
...@@ -826,13 +836,14 @@ ltrmark:; ...@@ -826,13 +836,14 @@ ltrmark:;
elog(ERROR, "Can't serialize access due to concurrent update"); elog(ERROR, "Can't serialize access due to concurrent update");
else if (!(ItemPointerEquals(&(tuple.t_self), tid))) else if (!(ItemPointerEquals(&(tuple.t_self), tid)))
{ {
TupleTableSlot *slot = EvalPlanQual(estate, TupleTableSlot *epqslot = EvalPlanQual(estate,
estate->es_result_relation_info->ri_RangeTableIndex, estate->es_result_relation_info->ri_RangeTableIndex,
&(tuple.t_self)); &(tuple.t_self));
if (!(TupIsNull(slot))) if (!(TupIsNull(epqslot)))
{ {
*tid = tuple.t_self; *tid = tuple.t_self;
*newSlot = epqslot;
goto ltrmark; goto ltrmark;
} }
} }
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -174,7 +174,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) ...@@ -174,7 +174,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
Plan *plan; Plan *plan;
TupleTableSlot *result; TupleTableSlot *result;
CommandDest dest; CommandDest dest;
void (*destination) (); DestReceiver *destfunc;
/****************** /******************
* sanity checks * sanity checks
...@@ -190,10 +190,19 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) ...@@ -190,10 +190,19 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
operation = queryDesc->operation; operation = queryDesc->operation;
plan = queryDesc->plantree; plan = queryDesc->plantree;
dest = queryDesc->dest; dest = queryDesc->dest;
destination = (void (*) ()) DestToFunction(dest); destfunc = DestToFunction(dest);
estate->es_processed = 0; estate->es_processed = 0;
estate->es_lastoid = InvalidOid; 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) switch (feature)
{ {
...@@ -203,7 +212,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) ...@@ -203,7 +212,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
operation, operation,
ALL_TUPLES, ALL_TUPLES,
ForwardScanDirection, ForwardScanDirection,
destination); destfunc);
break; break;
case EXEC_FOR: case EXEC_FOR:
result = ExecutePlan(estate, result = ExecutePlan(estate,
...@@ -211,7 +220,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) ...@@ -211,7 +220,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
operation, operation,
count, count,
ForwardScanDirection, ForwardScanDirection,
destination); destfunc);
break; break;
/****************** /******************
...@@ -224,7 +233,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) ...@@ -224,7 +233,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
operation, operation,
count, count,
BackwardScanDirection, BackwardScanDirection,
destination); destfunc);
break; break;
/****************** /******************
...@@ -238,7 +247,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) ...@@ -238,7 +247,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
operation, operation,
ONE_TUPLE, ONE_TUPLE,
ForwardScanDirection, ForwardScanDirection,
destination); destfunc);
break; break;
default: default:
result = NULL; result = NULL;
...@@ -246,6 +255,8 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) ...@@ -246,6 +255,8 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
break; break;
} }
(*destfunc->cleanup) (destfunc);
return result; return result;
} }
...@@ -756,7 +767,7 @@ ExecutePlan(EState *estate, ...@@ -756,7 +767,7 @@ ExecutePlan(EState *estate,
CmdType operation, CmdType operation,
int numberTuples, int numberTuples,
ScanDirection direction, ScanDirection direction,
DestReceiver *destfunc) DestReceiver* destfunc)
{ {
JunkFilter *junkfilter; JunkFilter *junkfilter;
...@@ -941,7 +952,7 @@ lmark:; ...@@ -941,7 +952,7 @@ lmark:;
{ {
case CMD_SELECT: case CMD_SELECT:
ExecRetrieve(slot, /* slot containing tuple */ ExecRetrieve(slot, /* slot containing tuple */
destfunc, /* print function */ destfunc, /* destination's tuple-receiver obj */
estate); /* */ estate); /* */
result = slot; result = slot;
break; break;
...@@ -1024,7 +1035,7 @@ ExecRetrieve(TupleTableSlot *slot, ...@@ -1024,7 +1035,7 @@ ExecRetrieve(TupleTableSlot *slot,
* send the tuple to the front end (or the screen) * send the tuple to the front end (or the screen)
****************** ******************
*/ */
(*printfunc) (tuple, attrtype); (*destfunc->receiveTuple) (tuple, attrtype, destfunc);
IncrRetrieved(); IncrRetrieved();
(estate->es_processed)++; (estate->es_processed)++;
} }
......
...@@ -65,7 +65,7 @@ ...@@ -65,7 +65,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/gram.c,v 1.3 1999/01/28 11:50:41 wieck Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/gram.c,v 1.4 1999/01/29 11:56:01 vadim Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -414,7 +414,7 @@ static const short yycheck[] = { 21, ...@@ -414,7 +414,7 @@ static const short yycheck[] = { 21,
152, 62 152, 62
}; };
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
#line 3 "/usr/share/bison.simple" #line 3 "/usr/share/misc/bison.simple"
/* Skeleton output parser for bison, /* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
...@@ -467,16 +467,6 @@ void *alloca (); ...@@ -467,16 +467,6 @@ void *alloca ();
#endif /* not GNU C. */ #endif /* not GNU C. */
#endif /* alloca not defined. */ #endif /* alloca not defined. */
#ifdef __cplusplus
extern "C" {
void yyerror(char *);
int yylex();
};
#else
extern void yyerror(char *);
extern int yylex();
#endif
/* This is the parser code that is written into each bison parser /* This is the parser code that is written into each bison parser
when the %semantic_parser declaration is not specified in the grammar. when the %semantic_parser declaration is not specified in the grammar.
It was written by Richard Stallman by simplifying the hairy parser It was written by Richard Stallman by simplifying the hairy parser
...@@ -573,13 +563,9 @@ int yydebug; /* nonzero means print parse trace */ ...@@ -573,13 +563,9 @@ int yydebug; /* nonzero means print parse trace */
#define YYMAXDEPTH 10000 #define YYMAXDEPTH 10000
#endif #endif
#ifndef YYPARSE_RETURN_TYPE
#define YYPARSE_RETURN_TYPE int
#endif
/* Prevent warning if -Wstrict-prototypes. */ /* Prevent warning if -Wstrict-prototypes. */
#ifdef __GNUC__ #ifdef __GNUC__
YYPARSE_RETURN_TYPE yyparse (void); int yyparse (void);
#endif #endif
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
...@@ -621,7 +607,7 @@ __yy_memcpy (char *to, char *from, int count) ...@@ -621,7 +607,7 @@ __yy_memcpy (char *to, char *from, int count)
#endif #endif
#endif #endif
#line 196 "/usr/share/bison.simple" #line 196 "/usr/share/misc/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed /* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *. into yyparse. The argument should have type void *.
...@@ -642,7 +628,7 @@ __yy_memcpy (char *to, char *from, int count) ...@@ -642,7 +628,7 @@ __yy_memcpy (char *to, char *from, int count)
#define YYPARSE_PARAM_DECL #define YYPARSE_PARAM_DECL
#endif /* not YYPARSE_PARAM */ #endif /* not YYPARSE_PARAM */
YYPARSE_RETURN_TYPE int
yyparse(YYPARSE_PARAM_ARG) yyparse(YYPARSE_PARAM_ARG)
YYPARSE_PARAM_DECL YYPARSE_PARAM_DECL
{ {
...@@ -1905,7 +1891,7 @@ case 105: ...@@ -1905,7 +1891,7 @@ case 105:
break;} break;}
} }
/* the action file gets copied in in place of this dollarsign */ /* the action file gets copied in in place of this dollarsign */
#line 498 "/usr/share/bison.simple" #line 498 "/usr/share/misc/bison.simple"
yyvsp -= yylen; yyvsp -= yylen;
yyssp -= yylen; yyssp -= yylen;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment