]> granicus.if.org Git - postgresql/commitdiff
Hope that execMain.c good merged.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Fri, 29 Jan 1999 11:56:01 +0000 (11:56 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Fri, 29 Jan 1999 11:56:01 +0000 (11:56 +0000)
Fix for BEFORE ROW UPDATE triggers: result tuple may be different
(due to concurrent update) from one initially produced by top level plan.

src/backend/commands/trigger.c
src/backend/executor/execMain.c
src/pl/plpgsql/src/gram.c

index a5e27227cf2ca63321bd237f47ab5e98e256bd31..aac9f2599f52cecd69f71739af94bb848f0bcc9f 100644 (file)
@@ -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;
                                        }
                                }
index ba4d09eaa38ff5439e9c6e0a93090aa29c70cb70..f074ce951fd7cf4e65496529a9b0e840764737a2 100644 (file)
@@ -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)
+                       DestReceiverdestfunc)
 {
        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)++;
 }
index 2d4ef46a1b14382f66b533452f43a648f69b72e6..2ca9936c32e927c7522a72e484e16f90563b69f4 100644 (file)
@@ -65,7 +65,7 @@
  *                       procedural language
  *
  * 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.
  *
@@ -414,7 +414,7 @@ static const short yycheck[] = {    21,
    152,    62
 };
 /* -*-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,
    Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -467,16 +467,6 @@ void *alloca ();
 #endif /* not GNU C.  */
 #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
   when the %semantic_parser declaration is not specified in the grammar.
   It was written by Richard Stallman by simplifying the hairy parser
@@ -573,13 +563,9 @@ int yydebug;                       /*  nonzero means print parse trace     */
 #define YYMAXDEPTH 10000
 #endif
 
-#ifndef YYPARSE_RETURN_TYPE
-#define YYPARSE_RETURN_TYPE int
-#endif
-
 /* Prevent warning if -Wstrict-prototypes.  */
 #ifdef __GNUC__
-YYPARSE_RETURN_TYPE yyparse (void);
+int yyparse (void);
 #endif
 \f
 #if __GNUC__ > 1               /* GNU C and GNU C++ define this.  */
@@ -621,7 +607,7 @@ __yy_memcpy (char *to, char *from, int count)
 #endif
 #endif
 \f
-#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
    into yyparse.  The argument should have type void *.
@@ -642,7 +628,7 @@ __yy_memcpy (char *to, char *from, int count)
 #define YYPARSE_PARAM_DECL
 #endif /* not YYPARSE_PARAM */
 
-YYPARSE_RETURN_TYPE
+int
 yyparse(YYPARSE_PARAM_ARG)
      YYPARSE_PARAM_DECL
 {
@@ -1905,7 +1891,7 @@ case 105:
     break;}
 }
    /* the action file gets copied in in place of this dollarsign */
-#line 498 "/usr/share/bison.simple"
+#line 498 "/usr/share/misc/bison.simple"
 \f
   yyvsp -= yylen;
   yyssp -= yylen;