Skip to content

Commit 0a1e284

Browse files
committed
ExecReScan for MergeJoin.
Marked inner tuple now is copied into mergestate->mj_MarkedTupleSlot - no more tricks arround ttc_shouldfree.
1 parent b0571eb commit 0a1e284

File tree

2 files changed

+75
-88
lines changed

2 files changed

+75
-88
lines changed

src/backend/executor/execAmi.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.19 1998/02/26 04:31:08 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.20 1998/02/27 16:11:26 vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -44,6 +44,7 @@
4444
#include "executor/nodeAgg.h"
4545
#include "executor/nodeResult.h"
4646
#include "executor/nodeUnique.h"
47+
#include "executor/nodeMergejoin.h"
4748
#include "executor/nodeSubplan.h"
4849
#include "executor/execdebug.h"
4950
#include "optimizer/internal.h" /* for _TEMP_RELATION_ID_ */
@@ -366,6 +367,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
366367
ExecReScanSort((Sort *) node, exprCtxt, parent);
367368
break;
368369

370+
case T_MergeJoin:
371+
ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
372+
break;
373+
369374
/*
370375
* Tee is never used
371376
case T_Tee:

src/backend/executor/nodeMergejoin.c

Lines changed: 69 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.13 1998/02/26 04:31:30 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.14 1998/02/27 16:11:28 vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -77,6 +77,7 @@
7777
*/
7878
#include "postgres.h"
7979

80+
#include "access/heapam.h"
8081
#include "executor/executor.h"
8182
#include "executor/execdefs.h"
8283
#include "executor/nodeMergejoin.h"
@@ -86,46 +87,14 @@
8687

8788
static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext);
8889

89-
/* ----------------------------------------------------------------
90-
* MarkInnerTuple and RestoreInnerTuple macros
91-
*
92-
* when we "mark" a tuple, we place a pointer to it
93-
* in the marked tuple slot. now there are two pointers
94-
* to this tuple and we don't want it to be freed until
95-
* next time we mark a tuple, so we move the policy to
96-
* the marked tuple slot and set the inner tuple slot policy
97-
* to false.
98-
*
99-
* But, when we restore the inner tuple, the marked tuple
100-
* retains the policy. Basically once a tuple is marked, it
101-
* should only be freed when we mark another tuple. -cim 9/27/90
102-
*
103-
* Note: now that we store buffers in the tuple table,
104-
* we have to also increment buffer reference counts
105-
* correctly whenever we propagate an additional pointer
106-
* to a buffer item. Later, when ExecStoreTuple() is
107-
* called again on this slot, the refcnt is decremented
108-
* when the old tuple is replaced.
109-
* ----------------------------------------------------------------
110-
*/
11190
#define MarkInnerTuple(innerTupleSlot, mergestate) \
11291
{ \
113-
bool shouldFree; \
114-
shouldFree = ExecSetSlotPolicy(innerTupleSlot, false); \
115-
ExecStoreTuple(innerTupleSlot->val, \
92+
ExecStoreTuple(heap_copytuple(innerTupleSlot->val), \
11693
mergestate->mj_MarkedTupleSlot, \
117-
innerTupleSlot->ttc_buffer, \
118-
shouldFree); \
119-
ExecIncrSlotBufferRefcnt(innerTupleSlot); \
94+
InvalidBuffer, \
95+
true); \
12096
}
12197

122-
#define RestoreInnerTuple(innerTupleSlot, markedTupleSlot) \
123-
ExecStoreTuple(markedTupleSlot->val, \
124-
innerTupleSlot, \
125-
markedTupleSlot->ttc_buffer, \
126-
false); \
127-
ExecIncrSlotBufferRefcnt(innerTupleSlot)
128-
12998
/* ----------------------------------------------------------------
13099
* MJFormOSortopI
131100
*
@@ -467,8 +436,6 @@ ExecMergeJoin(MergeJoin *node)
467436
Plan *outerPlan;
468437
TupleTableSlot *outerTupleSlot;
469438

470-
TupleTableSlot *markedTupleSlot;
471-
472439
ExprContext *econtext;
473440

474441
/* ----------------
@@ -528,8 +495,8 @@ ExecMergeJoin(MergeJoin *node)
528495
* means that this is the first time ExecMergeJoin() has
529496
* been called and so we have to initialize the inner,
530497
* outer and marked tuples as well as various stuff in the
531-
* expression context. ********************************
532-
*
498+
* expression context.
499+
* ********************************
533500
*/
534501
case EXEC_MJ_INITIALIZE:
535502
MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
@@ -560,19 +527,9 @@ ExecMergeJoin(MergeJoin *node)
560527
econtext->ecxt_innertuple = innerTupleSlot;
561528
econtext->ecxt_outertuple = outerTupleSlot;
562529

563-
/* ----------------
564-
* set the marked tuple to nil
565-
* and initialize its tuple descriptor atttributes.
566-
* -jeff 10 july 1991
567-
* ----------------
568-
*/
569-
ExecClearTuple(mergestate->mj_MarkedTupleSlot);
570530
mergestate->mj_MarkedTupleSlot->ttc_tupleDescriptor =
571531
innerTupleSlot->ttc_tupleDescriptor;
572-
/*
573-
mergestate->mj_MarkedTupleSlot->ttc_execTupDescriptor =
574-
innerTupleSlot->ttc_execTupDescriptor;
575-
*/
532+
576533
/* ----------------
577534
* initialize merge join state to skip inner tuples.
578535
* ----------------
@@ -584,15 +541,14 @@ ExecMergeJoin(MergeJoin *node)
584541
* ******************************** EXEC_MJ_JOINMARK means
585542
* we have just found a new outer tuple and a possible
586543
* matching inner tuple. This is the case after the
587-
* INITIALIZE, SKIPOUTER or SKIPINNER states. ********************************
588-
*
544+
* INITIALIZE, SKIPOUTER or SKIPINNER states.
545+
* ********************************
589546
*/
590547
case EXEC_MJ_JOINMARK:
591548
MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n");
592549
ExecMarkPos(innerPlan);
593550

594-
innerTupleSlot = econtext->ecxt_innertuple;
595-
MarkInnerTuple(innerTupleSlot, mergestate);
551+
MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
596552

597553
mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
598554
break;
@@ -724,8 +680,8 @@ ExecMergeJoin(MergeJoin *node)
724680
break;
725681

726682
/*
727-
* ******************************** EXEC_MJ_TESTOUTER If
728-
* the new outer tuple and the marked tuple satisify the
683+
* ******************************** EXEC_MJ_TESTOUTER
684+
* If the new outer tuple and the marked tuple satisify the
729685
* merge clause then we know we have duplicates in the
730686
* outer scan so we have to restore the inner scan to the
731687
* marked tuple and proceed to join the new outer tuples
@@ -749,12 +705,7 @@ ExecMergeJoin(MergeJoin *node)
749705
*
750706
* new outer tuple > marked tuple
751707
*
752-
****************************
753-
*
754-
*
755-
*
756-
*
757-
*
708+
* ****************************
758709
*/
759710
case EXEC_MJ_TESTOUTER:
760711
MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
@@ -765,29 +716,32 @@ ExecMergeJoin(MergeJoin *node)
765716
* ----------------
766717
*/
767718
innerTupleSlot = econtext->ecxt_innertuple;
768-
markedTupleSlot = mergestate->mj_MarkedTupleSlot;
769-
econtext->ecxt_innertuple = markedTupleSlot;
719+
econtext->ecxt_innertuple = mergestate->mj_MarkedTupleSlot;
770720

771721
qualResult = ExecQual((List *) mergeclauses, econtext);
772722
MJ_DEBUG_QUAL(mergeclauses, qualResult);
773723

774724
if (qualResult)
775725
{
776-
/* ----------------
726+
/*
777727
* the merge clause matched so now we juggle the slots
778728
* back the way they were and proceed to JOINTEST.
779-
* ----------------
729+
*
730+
* I can't understand why we have to go to JOINTEST
731+
* and compare outer tuple with the same inner one
732+
* again -> go to JOINTUPLES... - vadim 02/27/98
780733
*/
781-
econtext->ecxt_innertuple = innerTupleSlot;
782-
783-
RestoreInnerTuple(innerTupleSlot, markedTupleSlot);
784734

785735
ExecRestrPos(innerPlan);
736+
#if 0
786737
mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
738+
#endif
739+
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
787740

788741
}
789742
else
790743
{
744+
econtext->ecxt_innertuple = innerTupleSlot;
791745
/* ----------------
792746
* if the inner tuple was nil and the new outer
793747
* tuple didn't match the marked outer tuple then
@@ -809,12 +763,7 @@ ExecMergeJoin(MergeJoin *node)
809763
return NULL;
810764
}
811765

812-
/* ----------------
813-
* restore the inner tuple and continue on to
814-
* skip outer tuples.
815-
* ----------------
816-
*/
817-
econtext->ecxt_innertuple = innerTupleSlot;
766+
/* continue on to skip outer tuples */
818767
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
819768
}
820769
break;
@@ -853,9 +802,8 @@ ExecMergeJoin(MergeJoin *node)
853802
if (qualResult)
854803
{
855804
ExecMarkPos(innerPlan);
856-
innerTupleSlot = econtext->ecxt_innertuple;
857805

858-
MarkInnerTuple(innerTupleSlot, mergestate);
806+
MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
859807

860808
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
861809
break;
@@ -958,9 +906,8 @@ ExecMergeJoin(MergeJoin *node)
958906
if (qualResult)
959907
{
960908
ExecMarkPos(innerPlan);
961-
innerTupleSlot = econtext->ecxt_innertuple;
962909

963-
MarkInnerTuple(innerTupleSlot, mergestate);
910+
MarkInnerTuple(econtext->ecxt_innertuple, mergestate);
964911

965912
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
966913
break;
@@ -1074,10 +1021,11 @@ bool
10741021
ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
10751022
{
10761023
MergeJoinState *mergestate;
1077-
List *joinclauses;
1078-
RegProcedure rightsortop;
1079-
RegProcedure leftsortop;
1080-
RegProcedure sortop;
1024+
List *joinclauses;
1025+
RegProcedure rightsortop;
1026+
RegProcedure leftsortop;
1027+
RegProcedure sortop;
1028+
TupleTableSlot *mjSlot;
10811029

10821030
List *OSortopI;
10831031
List *ISortopO;
@@ -1120,8 +1068,14 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
11201068
* ----------------
11211069
*/
11221070
ExecInitResultTupleSlot(estate, &mergestate->jstate);
1123-
ExecInitMarkedTupleSlot(estate, mergestate);
1124-
1071+
mjSlot = (TupleTableSlot *) palloc(sizeof(TupleTableSlot));
1072+
mjSlot->val = NULL;
1073+
mjSlot->ttc_shouldFree = true;
1074+
mjSlot->ttc_tupleDescriptor = NULL;
1075+
mjSlot->ttc_whichplan = -1;
1076+
mjSlot->ttc_descIsNew = true;
1077+
mergestate->mj_MarkedTupleSlot = mjSlot;
1078+
11251079
/* ----------------
11261080
* get merge sort operators.
11271081
*
@@ -1245,7 +1199,35 @@ ExecEndMergeJoin(MergeJoin *node)
12451199
*/
12461200
ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);
12471201
ExecClearTuple(mergestate->mj_MarkedTupleSlot);
1248-
1202+
pfree (mergestate->mj_MarkedTupleSlot);
1203+
mergestate->mj_MarkedTupleSlot = NULL;
1204+
12491205
MJ1_printf("ExecEndMergeJoin: %s\n",
12501206
"node processing ended");
12511207
}
1208+
1209+
void
1210+
ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent)
1211+
{
1212+
MergeJoinState *mergestate = node->mergestate;
1213+
TupleTableSlot *mjSlot = mergestate->mj_MarkedTupleSlot;
1214+
1215+
ExecClearTuple(mjSlot);
1216+
mjSlot->val = NULL;
1217+
mjSlot->ttc_shouldFree = true;
1218+
mjSlot->ttc_tupleDescriptor = NULL;
1219+
mjSlot->ttc_whichplan = -1;
1220+
mjSlot->ttc_descIsNew = true;
1221+
1222+
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
1223+
1224+
/*
1225+
* if chgParam of subnodes is not null then plans will be re-scanned by
1226+
* first ExecProcNode.
1227+
*/
1228+
if (((Plan *) node)->lefttree->chgParam == NULL)
1229+
ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
1230+
if (((Plan *) node)->righttree->chgParam == NULL)
1231+
ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node);
1232+
1233+
}

0 commit comments

Comments
 (0)