7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
77
77
*/
78
78
#include "postgres.h"
79
79
80
+ #include "access/heapam.h"
80
81
#include "executor/executor.h"
81
82
#include "executor/execdefs.h"
82
83
#include "executor/nodeMergejoin.h"
86
87
87
88
static bool MergeCompare (List * eqQual ,List * compareQual ,ExprContext * econtext );
88
89
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
- */
111
90
#define MarkInnerTuple (innerTupleSlot ,mergestate ) \
112
91
{ \
113
- bool shouldFree; \
114
- shouldFree = ExecSetSlotPolicy(innerTupleSlot, false); \
115
- ExecStoreTuple(innerTupleSlot->val, \
92
+ ExecStoreTuple(heap_copytuple(innerTupleSlot->val), \
116
93
mergestate->mj_MarkedTupleSlot, \
117
- innerTupleSlot->ttc_buffer, \
118
- shouldFree); \
119
- ExecIncrSlotBufferRefcnt(innerTupleSlot); \
94
+ InvalidBuffer, \
95
+ true); \
120
96
}
121
97
122
- #define RestoreInnerTuple (innerTupleSlot ,markedTupleSlot ) \
123
- ExecStoreTuple(markedTupleSlot->val, \
124
- innerTupleSlot, \
125
- markedTupleSlot->ttc_buffer, \
126
- false); \
127
- ExecIncrSlotBufferRefcnt(innerTupleSlot)
128
-
129
98
/* ----------------------------------------------------------------
130
99
*MJFormOSortopI
131
100
*
@@ -467,8 +436,6 @@ ExecMergeJoin(MergeJoin *node)
467
436
Plan * outerPlan ;
468
437
TupleTableSlot * outerTupleSlot ;
469
438
470
- TupleTableSlot * markedTupleSlot ;
471
-
472
439
ExprContext * econtext ;
473
440
474
441
/* ----------------
@@ -528,8 +495,8 @@ ExecMergeJoin(MergeJoin *node)
528
495
* means that this is the first time ExecMergeJoin() has
529
496
* been called and so we have to initialize the inner,
530
497
* outer and marked tuples as well as various stuff in the
531
- * expression context. ********************************
532
- *
498
+ * expression context.
499
+ * ********************************
533
500
*/
534
501
case EXEC_MJ_INITIALIZE :
535
502
MJ_printf ("ExecMergeJoin: EXEC_MJ_INITIALIZE\n" );
@@ -560,19 +527,9 @@ ExecMergeJoin(MergeJoin *node)
560
527
econtext -> ecxt_innertuple = innerTupleSlot ;
561
528
econtext -> ecxt_outertuple = outerTupleSlot ;
562
529
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 );
570
530
mergestate -> mj_MarkedTupleSlot -> ttc_tupleDescriptor =
571
531
innerTupleSlot -> ttc_tupleDescriptor ;
572
- /*
573
- mergestate->mj_MarkedTupleSlot->ttc_execTupDescriptor =
574
- innerTupleSlot->ttc_execTupDescriptor;
575
- */
532
+
576
533
/* ----------------
577
534
*initialize merge join state to skip inner tuples.
578
535
* ----------------
@@ -584,15 +541,14 @@ ExecMergeJoin(MergeJoin *node)
584
541
* ******************************** EXEC_MJ_JOINMARK means
585
542
* we have just found a new outer tuple and a possible
586
543
* matching inner tuple. This is the case after the
587
- * INITIALIZE, SKIPOUTER or SKIPINNER states.********************************
588
- *
544
+ * INITIALIZE, SKIPOUTER or SKIPINNER states.
545
+ * ********************************
589
546
*/
590
547
case EXEC_MJ_JOINMARK :
591
548
MJ_printf ("ExecMergeJoin: EXEC_MJ_JOINMARK\n" );
592
549
ExecMarkPos (innerPlan );
593
550
594
- innerTupleSlot = econtext -> ecxt_innertuple ;
595
- MarkInnerTuple (innerTupleSlot ,mergestate );
551
+ MarkInnerTuple (econtext -> ecxt_innertuple ,mergestate );
596
552
597
553
mergestate -> mj_JoinState = EXEC_MJ_JOINTEST ;
598
554
break ;
@@ -724,8 +680,8 @@ ExecMergeJoin(MergeJoin *node)
724
680
break ;
725
681
726
682
/*
727
- * ******************************** EXEC_MJ_TESTOUTERIf
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
729
685
* merge clause then we know we have duplicates in the
730
686
* outer scan so we have to restore the inner scan to the
731
687
* marked tuple and proceed to join the new outer tuples
@@ -749,12 +705,7 @@ ExecMergeJoin(MergeJoin *node)
749
705
*
750
706
* new outer tuple > marked tuple
751
707
*
752
- ****************************
753
- *
754
- *
755
- *
756
- *
757
- *
708
+ * ****************************
758
709
*/
759
710
case EXEC_MJ_TESTOUTER :
760
711
MJ_printf ("ExecMergeJoin: EXEC_MJ_TESTOUTER\n" );
@@ -765,29 +716,32 @@ ExecMergeJoin(MergeJoin *node)
765
716
* ----------------
766
717
*/
767
718
innerTupleSlot = econtext -> ecxt_innertuple ;
768
- markedTupleSlot = mergestate -> mj_MarkedTupleSlot ;
769
- econtext -> ecxt_innertuple = markedTupleSlot ;
719
+ econtext -> ecxt_innertuple = mergestate -> mj_MarkedTupleSlot ;
770
720
771
721
qualResult = ExecQual ((List * )mergeclauses ,econtext );
772
722
MJ_DEBUG_QUAL (mergeclauses ,qualResult );
773
723
774
724
if (qualResult )
775
725
{
776
- /*----------------
726
+ /*
777
727
*the merge clause matched so now we juggle the slots
778
728
*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
780
733
*/
781
- econtext -> ecxt_innertuple = innerTupleSlot ;
782
-
783
- RestoreInnerTuple (innerTupleSlot ,markedTupleSlot );
784
734
785
735
ExecRestrPos (innerPlan );
736
+ #if 0
786
737
mergestate -> mj_JoinState = EXEC_MJ_JOINTEST ;
738
+ #endif
739
+ mergestate -> mj_JoinState = EXEC_MJ_JOINTUPLES ;
787
740
788
741
}
789
742
else
790
743
{
744
+ econtext -> ecxt_innertuple = innerTupleSlot ;
791
745
/* ----------------
792
746
*if the inner tuple was nil and the new outer
793
747
*tuple didn't match the marked outer tuple then
@@ -809,12 +763,7 @@ ExecMergeJoin(MergeJoin *node)
809
763
return NULL ;
810
764
}
811
765
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 */
818
767
mergestate -> mj_JoinState = EXEC_MJ_SKIPOUTER ;
819
768
}
820
769
break ;
@@ -853,9 +802,8 @@ ExecMergeJoin(MergeJoin *node)
853
802
if (qualResult )
854
803
{
855
804
ExecMarkPos (innerPlan );
856
- innerTupleSlot = econtext -> ecxt_innertuple ;
857
805
858
- MarkInnerTuple (innerTupleSlot ,mergestate );
806
+ MarkInnerTuple (econtext -> ecxt_innertuple ,mergestate );
859
807
860
808
mergestate -> mj_JoinState = EXEC_MJ_JOINTUPLES ;
861
809
break ;
@@ -958,9 +906,8 @@ ExecMergeJoin(MergeJoin *node)
958
906
if (qualResult )
959
907
{
960
908
ExecMarkPos (innerPlan );
961
- innerTupleSlot = econtext -> ecxt_innertuple ;
962
909
963
- MarkInnerTuple (innerTupleSlot ,mergestate );
910
+ MarkInnerTuple (econtext -> ecxt_innertuple ,mergestate );
964
911
965
912
mergestate -> mj_JoinState = EXEC_MJ_JOINTUPLES ;
966
913
break ;
@@ -1074,10 +1021,11 @@ bool
1074
1021
ExecInitMergeJoin (MergeJoin * node ,EState * estate ,Plan * parent )
1075
1022
{
1076
1023
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 ;
1081
1029
1082
1030
List * OSortopI ;
1083
1031
List * ISortopO ;
@@ -1120,8 +1068,14 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
1120
1068
* ----------------
1121
1069
*/
1122
1070
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
+
1125
1079
/* ----------------
1126
1080
*get merge sort operators.
1127
1081
*
@@ -1245,7 +1199,35 @@ ExecEndMergeJoin(MergeJoin *node)
1245
1199
*/
1246
1200
ExecClearTuple (mergestate -> jstate .cs_ResultTupleSlot );
1247
1201
ExecClearTuple (mergestate -> mj_MarkedTupleSlot );
1248
-
1202
+ pfree (mergestate -> mj_MarkedTupleSlot );
1203
+ mergestate -> mj_MarkedTupleSlot = NULL ;
1204
+
1249
1205
MJ1_printf ("ExecEndMergeJoin: %s\n" ,
1250
1206
"node processing ended" );
1251
1207
}
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
+ }