ExecReScan for MergeJoin.

Marked inner tuple now is copied into mergestate->mj_MarkedTupleSlot -
no more tricks arround ttc_shouldfree.
This commit is contained in:
Vadim B. Mikheev 1998-02-27 16:11:28 +00:00
parent b0571ebf65
commit 0a1e28494e
2 changed files with 75 additions and 88 deletions

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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/nodeAgg.h"
#include "executor/nodeResult.h" #include "executor/nodeResult.h"
#include "executor/nodeUnique.h" #include "executor/nodeUnique.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeSubplan.h" #include "executor/nodeSubplan.h"
#include "executor/execdebug.h" #include "executor/execdebug.h"
#include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */ #include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */
@ -366,6 +367,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
ExecReScanSort((Sort *) node, exprCtxt, parent); ExecReScanSort((Sort *) node, exprCtxt, parent);
break; break;
case T_MergeJoin:
ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
break;
/* /*
* Tee is never used * Tee is never used
case T_Tee: case T_Tee:

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include "access/heapam.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "executor/execdefs.h" #include "executor/execdefs.h"
#include "executor/nodeMergejoin.h" #include "executor/nodeMergejoin.h"
@ -86,46 +87,14 @@
static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext); 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) \ #define MarkInnerTuple(innerTupleSlot, mergestate) \
{ \ { \
bool shouldFree; \ ExecStoreTuple(heap_copytuple(innerTupleSlot->val), \
shouldFree = ExecSetSlotPolicy(innerTupleSlot, false); \
ExecStoreTuple(innerTupleSlot->val, \
mergestate->mj_MarkedTupleSlot, \ mergestate->mj_MarkedTupleSlot, \
innerTupleSlot->ttc_buffer, \ InvalidBuffer, \
shouldFree); \ true); \
ExecIncrSlotBufferRefcnt(innerTupleSlot); \
} }
#define RestoreInnerTuple(innerTupleSlot, markedTupleSlot) \
ExecStoreTuple(markedTupleSlot->val, \
innerTupleSlot, \
markedTupleSlot->ttc_buffer, \
false); \
ExecIncrSlotBufferRefcnt(innerTupleSlot)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* MJFormOSortopI * MJFormOSortopI
* *
@ -467,8 +436,6 @@ ExecMergeJoin(MergeJoin *node)
Plan *outerPlan; Plan *outerPlan;
TupleTableSlot *outerTupleSlot; TupleTableSlot *outerTupleSlot;
TupleTableSlot *markedTupleSlot;
ExprContext *econtext; ExprContext *econtext;
/* ---------------- /* ----------------
@ -528,8 +495,8 @@ ExecMergeJoin(MergeJoin *node)
* means that this is the first time ExecMergeJoin() has * means that this is the first time ExecMergeJoin() has
* been called and so we have to initialize the inner, * been called and so we have to initialize the inner,
* outer and marked tuples as well as various stuff in the * outer and marked tuples as well as various stuff in the
* expression context. ******************************** * expression context.
* * ********************************
*/ */
case EXEC_MJ_INITIALIZE: case EXEC_MJ_INITIALIZE:
MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
@ -560,19 +527,9 @@ ExecMergeJoin(MergeJoin *node)
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; 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 = mergestate->mj_MarkedTupleSlot->ttc_tupleDescriptor =
innerTupleSlot->ttc_tupleDescriptor; innerTupleSlot->ttc_tupleDescriptor;
/*
mergestate->mj_MarkedTupleSlot->ttc_execTupDescriptor =
innerTupleSlot->ttc_execTupDescriptor;
*/
/* ---------------- /* ----------------
* initialize merge join state to skip inner tuples. * initialize merge join state to skip inner tuples.
* ---------------- * ----------------
@ -584,15 +541,14 @@ ExecMergeJoin(MergeJoin *node)
* ******************************** EXEC_MJ_JOINMARK means * ******************************** EXEC_MJ_JOINMARK means
* we have just found a new outer tuple and a possible * we have just found a new outer tuple and a possible
* matching inner tuple. This is the case after the * matching inner tuple. This is the case after the
* INITIALIZE, SKIPOUTER or SKIPINNER states. ******************************** * INITIALIZE, SKIPOUTER or SKIPINNER states.
* * ********************************
*/ */
case EXEC_MJ_JOINMARK: case EXEC_MJ_JOINMARK:
MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n");
ExecMarkPos(innerPlan); ExecMarkPos(innerPlan);
innerTupleSlot = econtext->ecxt_innertuple; MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
MarkInnerTuple(innerTupleSlot, mergestate);
mergestate->mj_JoinState = EXEC_MJ_JOINTEST; mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
break; break;
@ -724,8 +680,8 @@ ExecMergeJoin(MergeJoin *node)
break; break;
/* /*
* ******************************** EXEC_MJ_TESTOUTER If * ******************************** EXEC_MJ_TESTOUTER
* the new outer tuple and the marked tuple satisify the * If the new outer tuple and the marked tuple satisify the
* merge clause then we know we have duplicates in the * merge clause then we know we have duplicates in the
* outer scan so we have to restore the inner scan to the * outer scan so we have to restore the inner scan to the
* marked tuple and proceed to join the new outer tuples * marked tuple and proceed to join the new outer tuples
@ -749,12 +705,7 @@ ExecMergeJoin(MergeJoin *node)
* *
* new outer tuple > marked tuple * new outer tuple > marked tuple
* *
**************************** * ****************************
*
*
*
*
*
*/ */
case EXEC_MJ_TESTOUTER: case EXEC_MJ_TESTOUTER:
MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
@ -765,29 +716,32 @@ ExecMergeJoin(MergeJoin *node)
* ---------------- * ----------------
*/ */
innerTupleSlot = econtext->ecxt_innertuple; innerTupleSlot = econtext->ecxt_innertuple;
markedTupleSlot = mergestate->mj_MarkedTupleSlot; econtext->ecxt_innertuple = mergestate->mj_MarkedTupleSlot;
econtext->ecxt_innertuple = markedTupleSlot;
qualResult = ExecQual((List *) mergeclauses, econtext); qualResult = ExecQual((List *) mergeclauses, econtext);
MJ_DEBUG_QUAL(mergeclauses, qualResult); MJ_DEBUG_QUAL(mergeclauses, qualResult);
if (qualResult) if (qualResult)
{ {
/* ---------------- /*
* the merge clause matched so now we juggle the slots * the merge clause matched so now we juggle the slots
* back the way they were and proceed to JOINTEST. * 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); ExecRestrPos(innerPlan);
#if 0
mergestate->mj_JoinState = EXEC_MJ_JOINTEST; mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
#endif
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
} }
else else
{ {
econtext->ecxt_innertuple = innerTupleSlot;
/* ---------------- /* ----------------
* if the inner tuple was nil and the new outer * if the inner tuple was nil and the new outer
* tuple didn't match the marked outer tuple then * tuple didn't match the marked outer tuple then
@ -809,12 +763,7 @@ ExecMergeJoin(MergeJoin *node)
return NULL; return NULL;
} }
/* ---------------- /* continue on to skip outer tuples */
* restore the inner tuple and continue on to
* skip outer tuples.
* ----------------
*/
econtext->ecxt_innertuple = innerTupleSlot;
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER; mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
} }
break; break;
@ -853,9 +802,8 @@ ExecMergeJoin(MergeJoin *node)
if (qualResult) if (qualResult)
{ {
ExecMarkPos(innerPlan); ExecMarkPos(innerPlan);
innerTupleSlot = econtext->ecxt_innertuple;
MarkInnerTuple(innerTupleSlot, mergestate); MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
break; break;
@ -958,9 +906,8 @@ ExecMergeJoin(MergeJoin *node)
if (qualResult) if (qualResult)
{ {
ExecMarkPos(innerPlan); ExecMarkPos(innerPlan);
innerTupleSlot = econtext->ecxt_innertuple;
MarkInnerTuple(innerTupleSlot, mergestate); MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
break; break;
@ -1078,6 +1025,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
RegProcedure rightsortop; RegProcedure rightsortop;
RegProcedure leftsortop; RegProcedure leftsortop;
RegProcedure sortop; RegProcedure sortop;
TupleTableSlot *mjSlot;
List *OSortopI; List *OSortopI;
List *ISortopO; List *ISortopO;
@ -1120,7 +1068,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
* ---------------- * ----------------
*/ */
ExecInitResultTupleSlot(estate, &mergestate->jstate); 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. * get merge sort operators.
@ -1245,7 +1199,35 @@ ExecEndMergeJoin(MergeJoin *node)
*/ */
ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot); ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);
ExecClearTuple(mergestate->mj_MarkedTupleSlot); ExecClearTuple(mergestate->mj_MarkedTupleSlot);
pfree (mergestate->mj_MarkedTupleSlot);
mergestate->mj_MarkedTupleSlot = NULL;
MJ1_printf("ExecEndMergeJoin: %s\n", MJ1_printf("ExecEndMergeJoin: %s\n",
"node processing ended"); "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);
}