OSDN Git Service

ExecReScan for MergeJoin.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Fri, 27 Feb 1998 16:11:28 +0000 (16:11 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Fri, 27 Feb 1998 16:11:28 +0000 (16:11 +0000)
Marked inner tuple now is copied into mergestate->mj_MarkedTupleSlot -
no more tricks arround ttc_shouldfree.

src/backend/executor/execAmi.c
src/backend/executor/nodeMergejoin.c

index b2851d8..0497c92 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.19 1998/02/26 04:31:08 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.20 1998/02/27 16:11:26 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,6 +44,7 @@
 #include "executor/nodeAgg.h"
 #include "executor/nodeResult.h"
 #include "executor/nodeUnique.h"
+#include "executor/nodeMergejoin.h"
 #include "executor/nodeSubplan.h"
 #include "executor/execdebug.h"
 #include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */
@@ -366,6 +367,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
                        ExecReScanSort((Sort *) node, exprCtxt, parent);
                        break;
 
+               case T_MergeJoin:
+                       ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
+                       break;
+
 /*
  * Tee is never used
                case T_Tee:
index 005047f..211160b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.13 1998/02/26 04:31:30 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.14 1998/02/27 16:11:28 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -77,6 +77,7 @@
  */
 #include "postgres.h"
 
+#include "access/heapam.h"
 #include "executor/executor.h"
 #include "executor/execdefs.h"
 #include "executor/nodeMergejoin.h"
 
 static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext);
 
-/* ----------------------------------------------------------------
- *             MarkInnerTuple and RestoreInnerTuple macros
- *
- *             when we "mark" a tuple, we place a pointer to it
- *             in the marked tuple slot.  now there are two pointers
- *             to this tuple and we don't want it to be freed until
- *             next time we mark a tuple, so we move the policy to
- *             the marked tuple slot and set the inner tuple slot policy
- *             to false.
- *
- *             But, when we restore the inner tuple, the marked tuple
- *             retains the policy.  Basically once a tuple is marked, it
- *             should only be freed when we mark another tuple.  -cim 9/27/90
- *
- *             Note:  now that we store buffers in the tuple table,
- *                        we have to also increment buffer reference counts
- *                        correctly whenever we propagate an additional pointer
- *                        to a buffer item.  Later, when ExecStoreTuple() is
- *                        called again on this slot, the refcnt is decremented
- *                        when the old tuple is replaced.
- * ----------------------------------------------------------------
- */
 #define MarkInnerTuple(innerTupleSlot, mergestate) \
 { \
-       bool               shouldFree; \
-       shouldFree = ExecSetSlotPolicy(innerTupleSlot, false); \
-       ExecStoreTuple(innerTupleSlot->val, \
+       ExecStoreTuple(heap_copytuple(innerTupleSlot->val), \
                                   mergestate->mj_MarkedTupleSlot, \
-                                  innerTupleSlot->ttc_buffer, \
-                                  shouldFree); \
-       ExecIncrSlotBufferRefcnt(innerTupleSlot); \
+                                  InvalidBuffer, \
+                                  true); \
 }
 
-#define RestoreInnerTuple(innerTupleSlot, markedTupleSlot) \
-       ExecStoreTuple(markedTupleSlot->val, \
-                                  innerTupleSlot, \
-                                  markedTupleSlot->ttc_buffer, \
-                                  false); \
-       ExecIncrSlotBufferRefcnt(innerTupleSlot)
-
 /* ----------------------------------------------------------------
  *             MJFormOSortopI
  *
@@ -467,8 +436,6 @@ ExecMergeJoin(MergeJoin *node)
        Plan       *outerPlan;
        TupleTableSlot *outerTupleSlot;
 
-       TupleTableSlot *markedTupleSlot;
-
        ExprContext *econtext;
 
        /* ----------------
@@ -528,8 +495,8 @@ ExecMergeJoin(MergeJoin *node)
                                 * means that this is the first time ExecMergeJoin() has
                                 * been called and so we have to initialize the inner,
                                 * outer and marked tuples as well as various stuff in the
-                                * expression context. ********************************
-                                *
+                                * expression context.
+                                * ********************************
                                 */
                        case EXEC_MJ_INITIALIZE:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
@@ -560,19 +527,9 @@ ExecMergeJoin(MergeJoin *node)
                                econtext->ecxt_innertuple = innerTupleSlot;
                                econtext->ecxt_outertuple = outerTupleSlot;
 
-                               /* ----------------
-                                *       set the marked tuple to nil
-                                *       and initialize its tuple descriptor atttributes.
-                                *              -jeff 10 july 1991
-                                * ----------------
-                                */
-                               ExecClearTuple(mergestate->mj_MarkedTupleSlot);
                                mergestate->mj_MarkedTupleSlot->ttc_tupleDescriptor =
                                        innerTupleSlot->ttc_tupleDescriptor;
-/*
-                       mergestate->mj_MarkedTupleSlot->ttc_execTupDescriptor =
-                         innerTupleSlot->ttc_execTupDescriptor;
-*/
+                               
                                /* ----------------
                                 *      initialize merge join state to skip inner tuples.
                                 * ----------------
@@ -584,15 +541,14 @@ ExecMergeJoin(MergeJoin *node)
                                 * ******************************** EXEC_MJ_JOINMARK means
                                 * we have just found a new outer tuple and a possible
                                 * matching inner tuple. This is the case after the
-                                * INITIALIZE, SKIPOUTER or SKIPINNER states. ********************************
-                                *
+                                * INITIALIZE, SKIPOUTER or SKIPINNER states. 
+                                * ********************************
                                 */
                        case EXEC_MJ_JOINMARK:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n");
                                ExecMarkPos(innerPlan);
 
-                               innerTupleSlot = econtext->ecxt_innertuple;
-                               MarkInnerTuple(innerTupleSlot, mergestate);
+                               MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
 
                                mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
                                break;
@@ -724,8 +680,8 @@ ExecMergeJoin(MergeJoin *node)
                                break;
 
                                /*
-                                * ******************************** EXEC_MJ_TESTOUTER If
-                                * the new outer tuple and the marked tuple satisify the
+                                * ******************************** EXEC_MJ_TESTOUTER 
+                                * If the new outer tuple and the marked tuple satisify the
                                 * merge clause then we know we have duplicates in the
                                 * outer scan so we have to restore the inner scan to the
                                 * marked tuple and proceed to join the new outer tuples
@@ -749,12 +705,7 @@ ExecMergeJoin(MergeJoin *node)
                                 *
                                 * new outer tuple > marked tuple
                                 *
-                               ****************************
-                                *
-                                *
-                                *
-                                *
-                                *
+                                * ****************************
                                 */
                        case EXEC_MJ_TESTOUTER:
                                MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
@@ -765,29 +716,32 @@ ExecMergeJoin(MergeJoin *node)
                                 * ----------------
                                 */
                                innerTupleSlot = econtext->ecxt_innertuple;
-                               markedTupleSlot = mergestate->mj_MarkedTupleSlot;
-                               econtext->ecxt_innertuple = markedTupleSlot;
+                               econtext->ecxt_innertuple = mergestate->mj_MarkedTupleSlot;
 
                                qualResult = ExecQual((List *) mergeclauses, econtext);
                                MJ_DEBUG_QUAL(mergeclauses, qualResult);
 
                                if (qualResult)
                                {
-                                       /* ----------------
+                                       /* 
                                         *      the merge clause matched so now we juggle the slots
                                         *      back the way they were and proceed to JOINTEST.
-                                        * ----------------
+                                        *
+                                        *  I can't understand why we have to go to JOINTEST
+                                        *  and compare outer tuple with the same inner one
+                                        *  again -> go to JOINTUPLES...        - vadim 02/27/98
                                         */
-                                       econtext->ecxt_innertuple = innerTupleSlot;
-
-                                       RestoreInnerTuple(innerTupleSlot, markedTupleSlot);
 
                                        ExecRestrPos(innerPlan);
+#if 0
                                        mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+#endif
+                                       mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
 
                                }
                                else
                                {
+                                       econtext->ecxt_innertuple = innerTupleSlot;
                                        /* ----------------
                                         *      if the inner tuple was nil and the new outer
                                         *      tuple didn't match the marked outer tuple then
@@ -809,12 +763,7 @@ ExecMergeJoin(MergeJoin *node)
                                                return NULL;
                                        }
 
-                                       /* ----------------
-                                        *      restore the inner tuple and continue on to
-                                        *      skip outer tuples.
-                                        * ----------------
-                                        */
-                                       econtext->ecxt_innertuple = innerTupleSlot;
+                                       /*      continue on to skip outer tuples */
                                        mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
                                }
                                break;
@@ -853,9 +802,8 @@ ExecMergeJoin(MergeJoin *node)
                                if (qualResult)
                                {
                                        ExecMarkPos(innerPlan);
-                                       innerTupleSlot = econtext->ecxt_innertuple;
 
-                                       MarkInnerTuple(innerTupleSlot, mergestate);
+                                       MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
 
                                        mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
                                        break;
@@ -958,9 +906,8 @@ ExecMergeJoin(MergeJoin *node)
                                if (qualResult)
                                {
                                        ExecMarkPos(innerPlan);
-                                       innerTupleSlot = econtext->ecxt_innertuple;
 
-                                       MarkInnerTuple(innerTupleSlot, mergestate);
+                                       MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
 
                                        mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
                                        break;
@@ -1074,10 +1021,11 @@ bool
 ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
 {
        MergeJoinState *mergestate;
-       List       *joinclauses;
-       RegProcedure rightsortop;
-       RegProcedure leftsortop;
-       RegProcedure sortop;
+       List               *joinclauses;
+       RegProcedure    rightsortop;
+       RegProcedure    leftsortop;
+       RegProcedure    sortop;
+       TupleTableSlot *mjSlot;
 
        List       *OSortopI;
        List       *ISortopO;
@@ -1120,8 +1068,14 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
         * ----------------
         */
        ExecInitResultTupleSlot(estate, &mergestate->jstate);
-       ExecInitMarkedTupleSlot(estate, mergestate);
-
+       mjSlot = (TupleTableSlot *) palloc(sizeof(TupleTableSlot));
+       mjSlot->val = NULL;
+       mjSlot->ttc_shouldFree = true;
+       mjSlot->ttc_tupleDescriptor = NULL;
+       mjSlot->ttc_whichplan = -1;
+       mjSlot->ttc_descIsNew = true;
+       mergestate->mj_MarkedTupleSlot = mjSlot;
+       
        /* ----------------
         *      get merge sort operators.
         *
@@ -1245,7 +1199,35 @@ ExecEndMergeJoin(MergeJoin *node)
         */
        ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);
        ExecClearTuple(mergestate->mj_MarkedTupleSlot);
-
+       pfree (mergestate->mj_MarkedTupleSlot);
+       mergestate->mj_MarkedTupleSlot = NULL;
+       
        MJ1_printf("ExecEndMergeJoin: %s\n",
                           "node processing ended");
 }
+
+void
+ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent)
+{
+       MergeJoinState *mergestate = node->mergestate;
+       TupleTableSlot *mjSlot = mergestate->mj_MarkedTupleSlot;
+
+       ExecClearTuple(mjSlot);
+       mjSlot->val = NULL;
+       mjSlot->ttc_shouldFree = true;
+       mjSlot->ttc_tupleDescriptor = NULL;
+       mjSlot->ttc_whichplan = -1;
+       mjSlot->ttc_descIsNew = true;
+       
+       mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
+
+       /*
+        * if chgParam of subnodes is not null then plans will be re-scanned by
+        * first ExecProcNode.
+        */
+       if (((Plan *) node)->lefttree->chgParam == NULL)
+               ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+       if (((Plan *) node)->righttree->chgParam == NULL)
+               ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node);
+
+}