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
* $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:

View 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"
@ -86,46 +87,14 @@
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);
}