]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeMergejoin.c
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / backend / executor / nodeMergejoin.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeMergejoin.c
4  *        routines supporting merge joins
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/executor/nodeMergejoin.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  * INTERFACE ROUTINES
17  *              ExecMergeJoin                   mergejoin outer and inner relations.
18  *              ExecInitMergeJoin               creates and initializes run time states
19  *              ExecEndMergeJoin                cleans up the node.
20  *
21  * NOTES
22  *
23  *              Merge-join is done by joining the inner and outer tuples satisfying
24  *              join clauses of the form ((= outerKey innerKey) ...).
25  *              The join clause list is provided by the query planner and may contain
26  *              more than one (= outerKey innerKey) clause (for composite sort key).
27  *
28  *              However, the query executor needs to know whether an outer
29  *              tuple is "greater/smaller" than an inner tuple so that it can
30  *              "synchronize" the two relations. For example, consider the following
31  *              relations:
32  *
33  *                              outer: (0 ^1 1 2 5 5 5 6 6 7)   current tuple: 1
34  *                              inner: (1 ^3 5 5 5 5 6)                 current tuple: 3
35  *
36  *              To continue the merge-join, the executor needs to scan both inner
37  *              and outer relations till the matching tuples 5. It needs to know
38  *              that currently inner tuple 3 is "greater" than outer tuple 1 and
39  *              therefore it should scan the outer relation first to find a
40  *              matching tuple and so on.
41  *
42  *              Therefore, rather than directly executing the merge join clauses,
43  *              we evaluate the left and right key expressions separately and then
44  *              compare the columns one at a time (see MJCompare).  The planner
45  *              passes us enough information about the sort ordering of the inputs
46  *              to allow us to determine how to make the comparison.  We may use the
47  *              appropriate btree comparison function, since Postgres' only notion
48  *              of ordering is specified by btree opfamilies.
49  *
50  *
51  *              Consider the above relations and suppose that the executor has
52  *              just joined the first outer "5" with the last inner "5". The
53  *              next step is of course to join the second outer "5" with all
54  *              the inner "5's". This requires repositioning the inner "cursor"
55  *              to point at the first inner "5". This is done by "marking" the
56  *              first inner 5 so we can restore the "cursor" to it before joining
57  *              with the second outer 5. The access method interface provides
58  *              routines to mark and restore to a tuple.
59  *
60  *
61  *              Essential operation of the merge join algorithm is as follows:
62  *
63  *              Join {
64  *                      get initial outer and inner tuples                              INITIALIZE
65  *                      do forever {
66  *                              while (outer != inner) {                                        SKIP_TEST
67  *                                      if (outer < inner)
68  *                                              advance outer                                           SKIPOUTER_ADVANCE
69  *                                      else
70  *                                              advance inner                                           SKIPINNER_ADVANCE
71  *                              }
72  *                              mark inner position                                                     SKIP_TEST
73  *                              do forever {
74  *                                      while (outer == inner) {
75  *                                              join tuples                                                     JOINTUPLES
76  *                                              advance inner position                          NEXTINNER
77  *                                      }
78  *                                      advance outer position                                  NEXTOUTER
79  *                                      if (outer == mark)                                              TESTOUTER
80  *                                              restore inner position to mark          TESTOUTER
81  *                                      else
82  *                                              break   // return to top of outer loop
83  *                              }
84  *                      }
85  *              }
86  *
87  *              The merge join operation is coded in the fashion
88  *              of a state machine.  At each state, we do something and then
89  *              proceed to another state.  This state is stored in the node's
90  *              execution state information and is preserved across calls to
91  *              ExecMergeJoin. -cim 10/31/89
92  */
93 #include "postgres.h"
94
95 #include "access/nbtree.h"
96 #include "executor/execdebug.h"
97 #include "executor/nodeMergejoin.h"
98 #include "miscadmin.h"
99 #include "utils/lsyscache.h"
100 #include "utils/memutils.h"
101
102
103 /*
104  * States of the ExecMergeJoin state machine
105  */
106 #define EXEC_MJ_INITIALIZE_OUTER                1
107 #define EXEC_MJ_INITIALIZE_INNER                2
108 #define EXEC_MJ_JOINTUPLES                              3
109 #define EXEC_MJ_NEXTOUTER                               4
110 #define EXEC_MJ_TESTOUTER                               5
111 #define EXEC_MJ_NEXTINNER                               6
112 #define EXEC_MJ_SKIP_TEST                               7
113 #define EXEC_MJ_SKIPOUTER_ADVANCE               8
114 #define EXEC_MJ_SKIPINNER_ADVANCE               9
115 #define EXEC_MJ_ENDOUTER                                10
116 #define EXEC_MJ_ENDINNER                                11
117
118 /*
119  * Runtime data for each mergejoin clause
120  */
121 typedef struct MergeJoinClauseData
122 {
123         /* Executable expression trees */
124         ExprState  *lexpr;                      /* left-hand (outer) input expression */
125         ExprState  *rexpr;                      /* right-hand (inner) input expression */
126
127         /*
128          * If we have a current left or right input tuple, the values of the
129          * expressions are loaded into these fields:
130          */
131         Datum           ldatum;                 /* current left-hand value */
132         Datum           rdatum;                 /* current right-hand value */
133         bool            lisnull;                /* and their isnull flags */
134         bool            risnull;
135
136         /*
137          * Everything we need to know to compare the left and right values is
138          * stored here.
139          */
140         SortSupportData ssup;
141 }                       MergeJoinClauseData;
142
143 /* Result type for MJEvalOuterValues and MJEvalInnerValues */
144 typedef enum
145 {
146         MJEVAL_MATCHABLE,                       /* normal, potentially matchable tuple */
147         MJEVAL_NONMATCHABLE,            /* tuple cannot join because it has a null */
148         MJEVAL_ENDOFJOIN                        /* end of input (physical or effective) */
149 } MJEvalResult;
150
151
152 #define MarkInnerTuple(innerTupleSlot, mergestate) \
153         ExecCopySlot((mergestate)->mj_MarkedTupleSlot, (innerTupleSlot))
154
155
156 /*
157  * MJExamineQuals
158  *
159  * This deconstructs the list of mergejoinable expressions, which is given
160  * to us by the planner in the form of a list of "leftexpr = rightexpr"
161  * expression trees in the order matching the sort columns of the inputs.
162  * We build an array of MergeJoinClause structs containing the information
163  * we will need at runtime.  Each struct essentially tells us how to compare
164  * the two expressions from the original clause.
165  *
166  * In addition to the expressions themselves, the planner passes the btree
167  * opfamily OID, collation OID, btree strategy number (BTLessStrategyNumber or
168  * BTGreaterStrategyNumber), and nulls-first flag that identify the intended
169  * sort ordering for each merge key.  The mergejoinable operator is an
170  * equality operator in the opfamily, and the two inputs are guaranteed to be
171  * ordered in either increasing or decreasing (respectively) order according
172  * to the opfamily and collation, with nulls at the indicated end of the range.
173  * This allows us to obtain the needed comparison function from the opfamily.
174  */
175 static MergeJoinClause
176 MJExamineQuals(List *mergeclauses,
177                            Oid *mergefamilies,
178                            Oid *mergecollations,
179                            int *mergestrategies,
180                            bool *mergenullsfirst,
181                            PlanState *parent)
182 {
183         MergeJoinClause clauses;
184         int                     nClauses = list_length(mergeclauses);
185         int                     iClause;
186         ListCell   *cl;
187
188         clauses = (MergeJoinClause) palloc0(nClauses * sizeof(MergeJoinClauseData));
189
190         iClause = 0;
191         foreach(cl, mergeclauses)
192         {
193                 OpExpr     *qual = (OpExpr *) lfirst(cl);
194                 MergeJoinClause clause = &clauses[iClause];
195                 Oid                     opfamily = mergefamilies[iClause];
196                 Oid                     collation = mergecollations[iClause];
197                 StrategyNumber opstrategy = mergestrategies[iClause];
198                 bool            nulls_first = mergenullsfirst[iClause];
199                 int                     op_strategy;
200                 Oid                     op_lefttype;
201                 Oid                     op_righttype;
202                 Oid                     sortfunc;
203
204                 if (!IsA(qual, OpExpr))
205                         elog(ERROR, "mergejoin clause is not an OpExpr");
206
207                 /*
208                  * Prepare the input expressions for execution.
209                  */
210                 clause->lexpr = ExecInitExpr((Expr *) linitial(qual->args), parent);
211                 clause->rexpr = ExecInitExpr((Expr *) lsecond(qual->args), parent);
212
213                 /* Set up sort support data */
214                 clause->ssup.ssup_cxt = CurrentMemoryContext;
215                 clause->ssup.ssup_collation = collation;
216                 if (opstrategy == BTLessStrategyNumber)
217                         clause->ssup.ssup_reverse = false;
218                 else if (opstrategy == BTGreaterStrategyNumber)
219                         clause->ssup.ssup_reverse = true;
220                 else                                    /* planner screwed up */
221                         elog(ERROR, "unsupported mergejoin strategy %d", opstrategy);
222                 clause->ssup.ssup_nulls_first = nulls_first;
223
224                 /* Extract the operator's declared left/right datatypes */
225                 get_op_opfamily_properties(qual->opno, opfamily, false,
226                                                                    &op_strategy,
227                                                                    &op_lefttype,
228                                                                    &op_righttype);
229                 if (op_strategy != BTEqualStrategyNumber)       /* should not happen */
230                         elog(ERROR, "cannot merge using non-equality operator %u",
231                                  qual->opno);
232
233                 /*
234                  * sortsupport routine must know if abbreviation optimization is
235                  * applicable in principle.  It is never applicable for merge joins
236                  * because there is no convenient opportunity to convert to
237                  * alternative representation.
238                  */
239                 clause->ssup.abbreviate = false;
240
241                 /* And get the matching support or comparison function */
242                 Assert(clause->ssup.comparator == NULL);
243                 sortfunc = get_opfamily_proc(opfamily,
244                                                                          op_lefttype,
245                                                                          op_righttype,
246                                                                          BTSORTSUPPORT_PROC);
247                 if (OidIsValid(sortfunc))
248                 {
249                         /* The sort support function can provide a comparator */
250                         OidFunctionCall1(sortfunc, PointerGetDatum(&clause->ssup));
251                 }
252                 if (clause->ssup.comparator == NULL)
253                 {
254                         /* support not available, get comparison func */
255                         sortfunc = get_opfamily_proc(opfamily,
256                                                                                  op_lefttype,
257                                                                                  op_righttype,
258                                                                                  BTORDER_PROC);
259                         if (!OidIsValid(sortfunc))      /* should not happen */
260                                 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
261                                          BTORDER_PROC, op_lefttype, op_righttype, opfamily);
262                         /* We'll use a shim to call the old-style btree comparator */
263                         PrepareSortSupportComparisonShim(sortfunc, &clause->ssup);
264                 }
265
266                 iClause++;
267         }
268
269         return clauses;
270 }
271
272 /*
273  * MJEvalOuterValues
274  *
275  * Compute the values of the mergejoined expressions for the current
276  * outer tuple.  We also detect whether it's impossible for the current
277  * outer tuple to match anything --- this is true if it yields a NULL
278  * input, since we assume mergejoin operators are strict.  If the NULL
279  * is in the first join column, and that column sorts nulls last, then
280  * we can further conclude that no following tuple can match anything
281  * either, since they must all have nulls in the first column.  However,
282  * that case is only interesting if we're not in FillOuter mode, else
283  * we have to visit all the tuples anyway.
284  *
285  * For the convenience of callers, we also make this routine responsible
286  * for testing for end-of-input (null outer tuple), and returning
287  * MJEVAL_ENDOFJOIN when that's seen.  This allows the same code to be used
288  * for both real end-of-input and the effective end-of-input represented by
289  * a first-column NULL.
290  *
291  * We evaluate the values in OuterEContext, which can be reset each
292  * time we move to a new tuple.
293  */
294 static MJEvalResult
295 MJEvalOuterValues(MergeJoinState *mergestate)
296 {
297         ExprContext *econtext = mergestate->mj_OuterEContext;
298         MJEvalResult result = MJEVAL_MATCHABLE;
299         int                     i;
300         MemoryContext oldContext;
301
302         /* Check for end of outer subplan */
303         if (TupIsNull(mergestate->mj_OuterTupleSlot))
304                 return MJEVAL_ENDOFJOIN;
305
306         ResetExprContext(econtext);
307
308         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
309
310         econtext->ecxt_outertuple = mergestate->mj_OuterTupleSlot;
311
312         for (i = 0; i < mergestate->mj_NumClauses; i++)
313         {
314                 MergeJoinClause clause = &mergestate->mj_Clauses[i];
315
316                 clause->ldatum = ExecEvalExpr(clause->lexpr, econtext,
317                                                                           &clause->lisnull);
318                 if (clause->lisnull)
319                 {
320                         /* match is impossible; can we end the join early? */
321                         if (i == 0 && !clause->ssup.ssup_nulls_first &&
322                                 !mergestate->mj_FillOuter)
323                                 result = MJEVAL_ENDOFJOIN;
324                         else if (result == MJEVAL_MATCHABLE)
325                                 result = MJEVAL_NONMATCHABLE;
326                 }
327         }
328
329         MemoryContextSwitchTo(oldContext);
330
331         return result;
332 }
333
334 /*
335  * MJEvalInnerValues
336  *
337  * Same as above, but for the inner tuple.  Here, we have to be prepared
338  * to load data from either the true current inner, or the marked inner,
339  * so caller must tell us which slot to load from.
340  */
341 static MJEvalResult
342 MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
343 {
344         ExprContext *econtext = mergestate->mj_InnerEContext;
345         MJEvalResult result = MJEVAL_MATCHABLE;
346         int                     i;
347         MemoryContext oldContext;
348
349         /* Check for end of inner subplan */
350         if (TupIsNull(innerslot))
351                 return MJEVAL_ENDOFJOIN;
352
353         ResetExprContext(econtext);
354
355         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
356
357         econtext->ecxt_innertuple = innerslot;
358
359         for (i = 0; i < mergestate->mj_NumClauses; i++)
360         {
361                 MergeJoinClause clause = &mergestate->mj_Clauses[i];
362
363                 clause->rdatum = ExecEvalExpr(clause->rexpr, econtext,
364                                                                           &clause->risnull);
365                 if (clause->risnull)
366                 {
367                         /* match is impossible; can we end the join early? */
368                         if (i == 0 && !clause->ssup.ssup_nulls_first &&
369                                 !mergestate->mj_FillInner)
370                                 result = MJEVAL_ENDOFJOIN;
371                         else if (result == MJEVAL_MATCHABLE)
372                                 result = MJEVAL_NONMATCHABLE;
373                 }
374         }
375
376         MemoryContextSwitchTo(oldContext);
377
378         return result;
379 }
380
381 /*
382  * MJCompare
383  *
384  * Compare the mergejoinable values of the current two input tuples
385  * and return 0 if they are equal (ie, the mergejoin equalities all
386  * succeed), >0 if outer > inner, <0 if outer < inner.
387  *
388  * MJEvalOuterValues and MJEvalInnerValues must already have been called
389  * for the current outer and inner tuples, respectively.
390  */
391 static int
392 MJCompare(MergeJoinState *mergestate)
393 {
394         int                     result = 0;
395         bool            nulleqnull = false;
396         ExprContext *econtext = mergestate->js.ps.ps_ExprContext;
397         int                     i;
398         MemoryContext oldContext;
399
400         /*
401          * Call the comparison functions in short-lived context, in case they leak
402          * memory.
403          */
404         ResetExprContext(econtext);
405
406         oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
407
408         for (i = 0; i < mergestate->mj_NumClauses; i++)
409         {
410                 MergeJoinClause clause = &mergestate->mj_Clauses[i];
411
412                 /*
413                  * Special case for NULL-vs-NULL, else use standard comparison.
414                  */
415                 if (clause->lisnull && clause->risnull)
416                 {
417                         nulleqnull = true;      /* NULL "=" NULL */
418                         continue;
419                 }
420
421                 result = ApplySortComparator(clause->ldatum, clause->lisnull,
422                                                                          clause->rdatum, clause->risnull,
423                                                                          &clause->ssup);
424
425                 if (result != 0)
426                         break;
427         }
428
429         /*
430          * If we had any NULL-vs-NULL inputs, we do not want to report that the
431          * tuples are equal.  Instead, if result is still 0, change it to +1. This
432          * will result in advancing the inner side of the join.
433          *
434          * Likewise, if there was a constant-false joinqual, do not report
435          * equality.  We have to check this as part of the mergequals, else the
436          * rescan logic will do the wrong thing.
437          */
438         if (result == 0 &&
439                 (nulleqnull || mergestate->mj_ConstFalseJoin))
440                 result = 1;
441
442         MemoryContextSwitchTo(oldContext);
443
444         return result;
445 }
446
447
448 /*
449  * Generate a fake join tuple with nulls for the inner tuple,
450  * and return it if it passes the non-join quals.
451  */
452 static TupleTableSlot *
453 MJFillOuter(MergeJoinState *node)
454 {
455         ExprContext *econtext = node->js.ps.ps_ExprContext;
456         ExprState  *otherqual = node->js.ps.qual;
457
458         ResetExprContext(econtext);
459
460         econtext->ecxt_outertuple = node->mj_OuterTupleSlot;
461         econtext->ecxt_innertuple = node->mj_NullInnerTupleSlot;
462
463         if (ExecQual(otherqual, econtext))
464         {
465                 /*
466                  * qualification succeeded.  now form the desired projection tuple and
467                  * return the slot containing it.
468                  */
469                 MJ_printf("ExecMergeJoin: returning outer fill tuple\n");
470
471                 return ExecProject(node->js.ps.ps_ProjInfo);
472         }
473         else
474                 InstrCountFiltered2(node, 1);
475
476         return NULL;
477 }
478
479 /*
480  * Generate a fake join tuple with nulls for the outer tuple,
481  * and return it if it passes the non-join quals.
482  */
483 static TupleTableSlot *
484 MJFillInner(MergeJoinState *node)
485 {
486         ExprContext *econtext = node->js.ps.ps_ExprContext;
487         ExprState  *otherqual = node->js.ps.qual;
488
489         ResetExprContext(econtext);
490
491         econtext->ecxt_outertuple = node->mj_NullOuterTupleSlot;
492         econtext->ecxt_innertuple = node->mj_InnerTupleSlot;
493
494         if (ExecQual(otherqual, econtext))
495         {
496                 /*
497                  * qualification succeeded.  now form the desired projection tuple and
498                  * return the slot containing it.
499                  */
500                 MJ_printf("ExecMergeJoin: returning inner fill tuple\n");
501
502                 return ExecProject(node->js.ps.ps_ProjInfo);
503         }
504         else
505                 InstrCountFiltered2(node, 1);
506
507         return NULL;
508 }
509
510
511 /*
512  * Check that a qual condition is constant true or constant false.
513  * If it is constant false (or null), set *is_const_false to true.
514  *
515  * Constant true would normally be represented by a NIL list, but we allow an
516  * actual bool Const as well.  We do expect that the planner will have thrown
517  * away any non-constant terms that have been ANDed with a constant false.
518  */
519 static bool
520 check_constant_qual(List *qual, bool *is_const_false)
521 {
522         ListCell   *lc;
523
524         foreach(lc, qual)
525         {
526                 Const      *con = (Const *) lfirst(lc);
527
528                 if (!con || !IsA(con, Const))
529                         return false;
530                 if (con->constisnull || !DatumGetBool(con->constvalue))
531                         *is_const_false = true;
532         }
533         return true;
534 }
535
536
537 /* ----------------------------------------------------------------
538  *              ExecMergeTupleDump
539  *
540  *              This function is called through the MJ_dump() macro
541  *              when EXEC_MERGEJOINDEBUG is defined
542  * ----------------------------------------------------------------
543  */
544 #ifdef EXEC_MERGEJOINDEBUG
545
546 static void
547 ExecMergeTupleDumpOuter(MergeJoinState *mergestate)
548 {
549         TupleTableSlot *outerSlot = mergestate->mj_OuterTupleSlot;
550
551         printf("==== outer tuple ====\n");
552         if (TupIsNull(outerSlot))
553                 printf("(nil)\n");
554         else
555                 MJ_debugtup(outerSlot);
556 }
557
558 static void
559 ExecMergeTupleDumpInner(MergeJoinState *mergestate)
560 {
561         TupleTableSlot *innerSlot = mergestate->mj_InnerTupleSlot;
562
563         printf("==== inner tuple ====\n");
564         if (TupIsNull(innerSlot))
565                 printf("(nil)\n");
566         else
567                 MJ_debugtup(innerSlot);
568 }
569
570 static void
571 ExecMergeTupleDumpMarked(MergeJoinState *mergestate)
572 {
573         TupleTableSlot *markedSlot = mergestate->mj_MarkedTupleSlot;
574
575         printf("==== marked tuple ====\n");
576         if (TupIsNull(markedSlot))
577                 printf("(nil)\n");
578         else
579                 MJ_debugtup(markedSlot);
580 }
581
582 static void
583 ExecMergeTupleDump(MergeJoinState *mergestate)
584 {
585         printf("******** ExecMergeTupleDump ********\n");
586
587         ExecMergeTupleDumpOuter(mergestate);
588         ExecMergeTupleDumpInner(mergestate);
589         ExecMergeTupleDumpMarked(mergestate);
590
591         printf("********\n");
592 }
593 #endif
594
595 /* ----------------------------------------------------------------
596  *              ExecMergeJoin
597  * ----------------------------------------------------------------
598  */
599 static TupleTableSlot *
600 ExecMergeJoin(PlanState *pstate)
601 {
602         MergeJoinState *node = castNode(MergeJoinState, pstate);
603         ExprState  *joinqual;
604         ExprState  *otherqual;
605         bool            qualResult;
606         int                     compareResult;
607         PlanState  *innerPlan;
608         TupleTableSlot *innerTupleSlot;
609         PlanState  *outerPlan;
610         TupleTableSlot *outerTupleSlot;
611         ExprContext *econtext;
612         bool            doFillOuter;
613         bool            doFillInner;
614
615         CHECK_FOR_INTERRUPTS();
616
617         /*
618          * get information from node
619          */
620         innerPlan = innerPlanState(node);
621         outerPlan = outerPlanState(node);
622         econtext = node->js.ps.ps_ExprContext;
623         joinqual = node->js.joinqual;
624         otherqual = node->js.ps.qual;
625         doFillOuter = node->mj_FillOuter;
626         doFillInner = node->mj_FillInner;
627
628         /*
629          * Reset per-tuple memory context to free any expression evaluation
630          * storage allocated in the previous tuple cycle.
631          */
632         ResetExprContext(econtext);
633
634         /*
635          * ok, everything is setup.. let's go to work
636          */
637         for (;;)
638         {
639                 MJ_dump(node);
640
641                 /*
642                  * get the current state of the join and do things accordingly.
643                  */
644                 switch (node->mj_JoinState)
645                 {
646                                 /*
647                                  * EXEC_MJ_INITIALIZE_OUTER means that this is the first time
648                                  * ExecMergeJoin() has been called and so we have to fetch the
649                                  * first matchable tuple for both outer and inner subplans. We
650                                  * do the outer side in INITIALIZE_OUTER state, then advance
651                                  * to INITIALIZE_INNER state for the inner subplan.
652                                  */
653                         case EXEC_MJ_INITIALIZE_OUTER:
654                                 MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE_OUTER\n");
655
656                                 outerTupleSlot = ExecProcNode(outerPlan);
657                                 node->mj_OuterTupleSlot = outerTupleSlot;
658
659                                 /* Compute join values and check for unmatchability */
660                                 switch (MJEvalOuterValues(node))
661                                 {
662                                         case MJEVAL_MATCHABLE:
663                                                 /* OK to go get the first inner tuple */
664                                                 node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
665                                                 break;
666                                         case MJEVAL_NONMATCHABLE:
667                                                 /* Stay in same state to fetch next outer tuple */
668                                                 if (doFillOuter)
669                                                 {
670                                                         /*
671                                                          * Generate a fake join tuple with nulls for the
672                                                          * inner tuple, and return it if it passes the
673                                                          * non-join quals.
674                                                          */
675                                                         TupleTableSlot *result;
676
677                                                         result = MJFillOuter(node);
678                                                         if (result)
679                                                                 return result;
680                                                 }
681                                                 break;
682                                         case MJEVAL_ENDOFJOIN:
683                                                 /* No more outer tuples */
684                                                 MJ_printf("ExecMergeJoin: nothing in outer subplan\n");
685                                                 if (doFillInner)
686                                                 {
687                                                         /*
688                                                          * Need to emit right-join tuples for remaining
689                                                          * inner tuples. We set MatchedInner = true to
690                                                          * force the ENDOUTER state to advance inner.
691                                                          */
692                                                         node->mj_JoinState = EXEC_MJ_ENDOUTER;
693                                                         node->mj_MatchedInner = true;
694                                                         break;
695                                                 }
696                                                 /* Otherwise we're done. */
697                                                 return NULL;
698                                 }
699                                 break;
700
701                         case EXEC_MJ_INITIALIZE_INNER:
702                                 MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE_INNER\n");
703
704                                 innerTupleSlot = ExecProcNode(innerPlan);
705                                 node->mj_InnerTupleSlot = innerTupleSlot;
706
707                                 /* Compute join values and check for unmatchability */
708                                 switch (MJEvalInnerValues(node, innerTupleSlot))
709                                 {
710                                         case MJEVAL_MATCHABLE:
711
712                                                 /*
713                                                  * OK, we have the initial tuples.  Begin by skipping
714                                                  * non-matching tuples.
715                                                  */
716                                                 node->mj_JoinState = EXEC_MJ_SKIP_TEST;
717                                                 break;
718                                         case MJEVAL_NONMATCHABLE:
719                                                 /* Mark before advancing, if wanted */
720                                                 if (node->mj_ExtraMarks)
721                                                         ExecMarkPos(innerPlan);
722                                                 /* Stay in same state to fetch next inner tuple */
723                                                 if (doFillInner)
724                                                 {
725                                                         /*
726                                                          * Generate a fake join tuple with nulls for the
727                                                          * outer tuple, and return it if it passes the
728                                                          * non-join quals.
729                                                          */
730                                                         TupleTableSlot *result;
731
732                                                         result = MJFillInner(node);
733                                                         if (result)
734                                                                 return result;
735                                                 }
736                                                 break;
737                                         case MJEVAL_ENDOFJOIN:
738                                                 /* No more inner tuples */
739                                                 MJ_printf("ExecMergeJoin: nothing in inner subplan\n");
740                                                 if (doFillOuter)
741                                                 {
742                                                         /*
743                                                          * Need to emit left-join tuples for all outer
744                                                          * tuples, including the one we just fetched.  We
745                                                          * set MatchedOuter = false to force the ENDINNER
746                                                          * state to emit first tuple before advancing
747                                                          * outer.
748                                                          */
749                                                         node->mj_JoinState = EXEC_MJ_ENDINNER;
750                                                         node->mj_MatchedOuter = false;
751                                                         break;
752                                                 }
753                                                 /* Otherwise we're done. */
754                                                 return NULL;
755                                 }
756                                 break;
757
758                                 /*
759                                  * EXEC_MJ_JOINTUPLES means we have two tuples which satisfied
760                                  * the merge clause so we join them and then proceed to get
761                                  * the next inner tuple (EXEC_MJ_NEXTINNER).
762                                  */
763                         case EXEC_MJ_JOINTUPLES:
764                                 MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");
765
766                                 /*
767                                  * Set the next state machine state.  The right things will
768                                  * happen whether we return this join tuple or just fall
769                                  * through to continue the state machine execution.
770                                  */
771                                 node->mj_JoinState = EXEC_MJ_NEXTINNER;
772
773                                 /*
774                                  * Check the extra qual conditions to see if we actually want
775                                  * to return this join tuple.  If not, can proceed with merge.
776                                  * We must distinguish the additional joinquals (which must
777                                  * pass to consider the tuples "matched" for outer-join logic)
778                                  * from the otherquals (which must pass before we actually
779                                  * return the tuple).
780                                  *
781                                  * We don't bother with a ResetExprContext here, on the
782                                  * assumption that we just did one while checking the merge
783                                  * qual.  One per tuple should be sufficient.  We do have to
784                                  * set up the econtext links to the tuples for ExecQual to
785                                  * use.
786                                  */
787                                 outerTupleSlot = node->mj_OuterTupleSlot;
788                                 econtext->ecxt_outertuple = outerTupleSlot;
789                                 innerTupleSlot = node->mj_InnerTupleSlot;
790                                 econtext->ecxt_innertuple = innerTupleSlot;
791
792                                 qualResult = (joinqual == NULL ||
793                                                           ExecQual(joinqual, econtext));
794                                 MJ_DEBUG_QUAL(joinqual, qualResult);
795
796                                 if (qualResult)
797                                 {
798                                         node->mj_MatchedOuter = true;
799                                         node->mj_MatchedInner = true;
800
801                                         /* In an antijoin, we never return a matched tuple */
802                                         if (node->js.jointype == JOIN_ANTI)
803                                         {
804                                                 node->mj_JoinState = EXEC_MJ_NEXTOUTER;
805                                                 break;
806                                         }
807
808                                         /*
809                                          * If we only need to join to the first matching inner
810                                          * tuple, then consider returning this one, but after that
811                                          * continue with next outer tuple.
812                                          */
813                                         if (node->js.single_match)
814                                                 node->mj_JoinState = EXEC_MJ_NEXTOUTER;
815
816                                         qualResult = (otherqual == NULL ||
817                                                                   ExecQual(otherqual, econtext));
818                                         MJ_DEBUG_QUAL(otherqual, qualResult);
819
820                                         if (qualResult)
821                                         {
822                                                 /*
823                                                  * qualification succeeded.  now form the desired
824                                                  * projection tuple and return the slot containing it.
825                                                  */
826                                                 MJ_printf("ExecMergeJoin: returning tuple\n");
827
828                                                 return ExecProject(node->js.ps.ps_ProjInfo);
829                                         }
830                                         else
831                                                 InstrCountFiltered2(node, 1);
832                                 }
833                                 else
834                                         InstrCountFiltered1(node, 1);
835                                 break;
836
837                                 /*
838                                  * EXEC_MJ_NEXTINNER means advance the inner scan to the next
839                                  * tuple. If the tuple is not nil, we then proceed to test it
840                                  * against the join qualification.
841                                  *
842                                  * Before advancing, we check to see if we must emit an
843                                  * outer-join fill tuple for this inner tuple.
844                                  */
845                         case EXEC_MJ_NEXTINNER:
846                                 MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");
847
848                                 if (doFillInner && !node->mj_MatchedInner)
849                                 {
850                                         /*
851                                          * Generate a fake join tuple with nulls for the outer
852                                          * tuple, and return it if it passes the non-join quals.
853                                          */
854                                         TupleTableSlot *result;
855
856                                         node->mj_MatchedInner = true;   /* do it only once */
857
858                                         result = MJFillInner(node);
859                                         if (result)
860                                                 return result;
861                                 }
862
863                                 /*
864                                  * now we get the next inner tuple, if any.  If there's none,
865                                  * advance to next outer tuple (which may be able to join to
866                                  * previously marked tuples).
867                                  *
868                                  * NB: must NOT do "extraMarks" here, since we may need to
869                                  * return to previously marked tuples.
870                                  */
871                                 innerTupleSlot = ExecProcNode(innerPlan);
872                                 node->mj_InnerTupleSlot = innerTupleSlot;
873                                 MJ_DEBUG_PROC_NODE(innerTupleSlot);
874                                 node->mj_MatchedInner = false;
875
876                                 /* Compute join values and check for unmatchability */
877                                 switch (MJEvalInnerValues(node, innerTupleSlot))
878                                 {
879                                         case MJEVAL_MATCHABLE:
880
881                                                 /*
882                                                  * Test the new inner tuple to see if it matches
883                                                  * outer.
884                                                  *
885                                                  * If they do match, then we join them and move on to
886                                                  * the next inner tuple (EXEC_MJ_JOINTUPLES).
887                                                  *
888                                                  * If they do not match then advance to next outer
889                                                  * tuple.
890                                                  */
891                                                 compareResult = MJCompare(node);
892                                                 MJ_DEBUG_COMPARE(compareResult);
893
894                                                 if (compareResult == 0)
895                                                         node->mj_JoinState = EXEC_MJ_JOINTUPLES;
896                                                 else
897                                                 {
898                                                         Assert(compareResult < 0);
899                                                         node->mj_JoinState = EXEC_MJ_NEXTOUTER;
900                                                 }
901                                                 break;
902                                         case MJEVAL_NONMATCHABLE:
903
904                                                 /*
905                                                  * It contains a NULL and hence can't match any outer
906                                                  * tuple, so we can skip the comparison and assume the
907                                                  * new tuple is greater than current outer.
908                                                  */
909                                                 node->mj_JoinState = EXEC_MJ_NEXTOUTER;
910                                                 break;
911                                         case MJEVAL_ENDOFJOIN:
912
913                                                 /*
914                                                  * No more inner tuples.  However, this might be only
915                                                  * effective and not physical end of inner plan, so
916                                                  * force mj_InnerTupleSlot to null to make sure we
917                                                  * don't fetch more inner tuples.  (We need this hack
918                                                  * because we are not transiting to a state where the
919                                                  * inner plan is assumed to be exhausted.)
920                                                  */
921                                                 node->mj_InnerTupleSlot = NULL;
922                                                 node->mj_JoinState = EXEC_MJ_NEXTOUTER;
923                                                 break;
924                                 }
925                                 break;
926
927                                 /*-------------------------------------------
928                                  * EXEC_MJ_NEXTOUTER means
929                                  *
930                                  *                              outer inner
931                                  * outer tuple -  5             5  - marked tuple
932                                  *                                5             5
933                                  *                                6             6  - inner tuple
934                                  *                                7             7
935                                  *
936                                  * we know we just bumped into the
937                                  * first inner tuple > current outer tuple (or possibly
938                                  * the end of the inner stream)
939                                  * so get a new outer tuple and then
940                                  * proceed to test it against the marked tuple
941                                  * (EXEC_MJ_TESTOUTER)
942                                  *
943                                  * Before advancing, we check to see if we must emit an
944                                  * outer-join fill tuple for this outer tuple.
945                                  *------------------------------------------------
946                                  */
947                         case EXEC_MJ_NEXTOUTER:
948                                 MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");
949
950                                 if (doFillOuter && !node->mj_MatchedOuter)
951                                 {
952                                         /*
953                                          * Generate a fake join tuple with nulls for the inner
954                                          * tuple, and return it if it passes the non-join quals.
955                                          */
956                                         TupleTableSlot *result;
957
958                                         node->mj_MatchedOuter = true;   /* do it only once */
959
960                                         result = MJFillOuter(node);
961                                         if (result)
962                                                 return result;
963                                 }
964
965                                 /*
966                                  * now we get the next outer tuple, if any
967                                  */
968                                 outerTupleSlot = ExecProcNode(outerPlan);
969                                 node->mj_OuterTupleSlot = outerTupleSlot;
970                                 MJ_DEBUG_PROC_NODE(outerTupleSlot);
971                                 node->mj_MatchedOuter = false;
972
973                                 /* Compute join values and check for unmatchability */
974                                 switch (MJEvalOuterValues(node))
975                                 {
976                                         case MJEVAL_MATCHABLE:
977                                                 /* Go test the new tuple against the marked tuple */
978                                                 node->mj_JoinState = EXEC_MJ_TESTOUTER;
979                                                 break;
980                                         case MJEVAL_NONMATCHABLE:
981                                                 /* Can't match, so fetch next outer tuple */
982                                                 node->mj_JoinState = EXEC_MJ_NEXTOUTER;
983                                                 break;
984                                         case MJEVAL_ENDOFJOIN:
985                                                 /* No more outer tuples */
986                                                 MJ_printf("ExecMergeJoin: end of outer subplan\n");
987                                                 innerTupleSlot = node->mj_InnerTupleSlot;
988                                                 if (doFillInner && !TupIsNull(innerTupleSlot))
989                                                 {
990                                                         /*
991                                                          * Need to emit right-join tuples for remaining
992                                                          * inner tuples.
993                                                          */
994                                                         node->mj_JoinState = EXEC_MJ_ENDOUTER;
995                                                         break;
996                                                 }
997                                                 /* Otherwise we're done. */
998                                                 return NULL;
999                                 }
1000                                 break;
1001
1002                                 /*--------------------------------------------------------
1003                                  * EXEC_MJ_TESTOUTER If the new outer tuple and the marked
1004                                  * tuple satisfy the merge clause then we know we have
1005                                  * duplicates in the outer scan so we have to restore the
1006                                  * inner scan to the marked tuple and proceed to join the
1007                                  * new outer tuple with the inner tuples.
1008                                  *
1009                                  * This is the case when
1010                                  *                                                outer inner
1011                                  *                                                      4         5  - marked tuple
1012                                  *                       outer tuple -  5         5
1013                                  *               new outer tuple -      5         5
1014                                  *                                                      6         8  - inner tuple
1015                                  *                                                      7        12
1016                                  *
1017                                  *                              new outer tuple == marked tuple
1018                                  *
1019                                  * If the outer tuple fails the test, then we are done
1020                                  * with the marked tuples, and we have to look for a
1021                                  * match to the current inner tuple.  So we will
1022                                  * proceed to skip outer tuples until outer >= inner
1023                                  * (EXEC_MJ_SKIP_TEST).
1024                                  *
1025                                  *              This is the case when
1026                                  *
1027                                  *                                                outer inner
1028                                  *                                                      5         5  - marked tuple
1029                                  *                       outer tuple -  5         5
1030                                  *               new outer tuple -      6         8  - inner tuple
1031                                  *                                                      7        12
1032                                  *
1033                                  *                              new outer tuple > marked tuple
1034                                  *
1035                                  *---------------------------------------------------------
1036                                  */
1037                         case EXEC_MJ_TESTOUTER:
1038                                 MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
1039
1040                                 /*
1041                                  * Here we must compare the outer tuple with the marked inner
1042                                  * tuple.  (We can ignore the result of MJEvalInnerValues,
1043                                  * since the marked inner tuple is certainly matchable.)
1044                                  */
1045                                 innerTupleSlot = node->mj_MarkedTupleSlot;
1046                                 (void) MJEvalInnerValues(node, innerTupleSlot);
1047
1048                                 compareResult = MJCompare(node);
1049                                 MJ_DEBUG_COMPARE(compareResult);
1050
1051                                 if (compareResult == 0)
1052                                 {
1053                                         /*
1054                                          * the merge clause matched so now we restore the inner
1055                                          * scan position to the first mark, and go join that tuple
1056                                          * (and any following ones) to the new outer.
1057                                          *
1058                                          * If we were able to determine mark and restore are not
1059                                          * needed, then we don't have to back up; the current
1060                                          * inner is already the first possible match.
1061                                          *
1062                                          * NOTE: we do not need to worry about the MatchedInner
1063                                          * state for the rescanned inner tuples.  We know all of
1064                                          * them will match this new outer tuple and therefore
1065                                          * won't be emitted as fill tuples.  This works *only*
1066                                          * because we require the extra joinquals to be constant
1067                                          * when doing a right or full join --- otherwise some of
1068                                          * the rescanned tuples might fail the extra joinquals.
1069                                          * This obviously won't happen for a constant-true extra
1070                                          * joinqual, while the constant-false case is handled by
1071                                          * forcing the merge clause to never match, so we never
1072                                          * get here.
1073                                          */
1074                                         if (!node->mj_SkipMarkRestore)
1075                                         {
1076                                                 ExecRestrPos(innerPlan);
1077
1078                                                 /*
1079                                                  * ExecRestrPos probably should give us back a new
1080                                                  * Slot, but since it doesn't, use the marked slot.
1081                                                  * (The previously returned mj_InnerTupleSlot cannot
1082                                                  * be assumed to hold the required tuple.)
1083                                                  */
1084                                                 node->mj_InnerTupleSlot = innerTupleSlot;
1085                                                 /* we need not do MJEvalInnerValues again */
1086                                         }
1087
1088                                         node->mj_JoinState = EXEC_MJ_JOINTUPLES;
1089                                 }
1090                                 else
1091                                 {
1092                                         /* ----------------
1093                                          *      if the new outer tuple didn't match the marked inner
1094                                          *      tuple then we have a case like:
1095                                          *
1096                                          *                       outer inner
1097                                          *                         4     4      - marked tuple
1098                                          * new outer - 5         4
1099                                          *                         6     5      - inner tuple
1100                                          *                         7
1101                                          *
1102                                          *      which means that all subsequent outer tuples will be
1103                                          *      larger than our marked inner tuples.  So we need not
1104                                          *      revisit any of the marked tuples but can proceed to
1105                                          *      look for a match to the current inner.  If there's
1106                                          *      no more inners, no more matches are possible.
1107                                          * ----------------
1108                                          */
1109                                         Assert(compareResult > 0);
1110                                         innerTupleSlot = node->mj_InnerTupleSlot;
1111
1112                                         /* reload comparison data for current inner */
1113                                         switch (MJEvalInnerValues(node, innerTupleSlot))
1114                                         {
1115                                                 case MJEVAL_MATCHABLE:
1116                                                         /* proceed to compare it to the current outer */
1117                                                         node->mj_JoinState = EXEC_MJ_SKIP_TEST;
1118                                                         break;
1119                                                 case MJEVAL_NONMATCHABLE:
1120
1121                                                         /*
1122                                                          * current inner can't possibly match any outer;
1123                                                          * better to advance the inner scan than the
1124                                                          * outer.
1125                                                          */
1126                                                         node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
1127                                                         break;
1128                                                 case MJEVAL_ENDOFJOIN:
1129                                                         /* No more inner tuples */
1130                                                         if (doFillOuter)
1131                                                         {
1132                                                                 /*
1133                                                                  * Need to emit left-join tuples for remaining
1134                                                                  * outer tuples.
1135                                                                  */
1136                                                                 node->mj_JoinState = EXEC_MJ_ENDINNER;
1137                                                                 break;
1138                                                         }
1139                                                         /* Otherwise we're done. */
1140                                                         return NULL;
1141                                         }
1142                                 }
1143                                 break;
1144
1145                                 /*----------------------------------------------------------
1146                                  * EXEC_MJ_SKIP means compare tuples and if they do not
1147                                  * match, skip whichever is lesser.
1148                                  *
1149                                  * For example:
1150                                  *
1151                                  *                              outer inner
1152                                  *                                5             5
1153                                  *                                5             5
1154                                  * outer tuple -  6             8  - inner tuple
1155                                  *                                7    12
1156                                  *                                8    14
1157                                  *
1158                                  * we have to advance the outer scan
1159                                  * until we find the outer 8.
1160                                  *
1161                                  * On the other hand:
1162                                  *
1163                                  *                              outer inner
1164                                  *                                5             5
1165                                  *                                5             5
1166                                  * outer tuple - 12             8  - inner tuple
1167                                  *                               14    10
1168                                  *                               17    12
1169                                  *
1170                                  * we have to advance the inner scan
1171                                  * until we find the inner 12.
1172                                  *----------------------------------------------------------
1173                                  */
1174                         case EXEC_MJ_SKIP_TEST:
1175                                 MJ_printf("ExecMergeJoin: EXEC_MJ_SKIP_TEST\n");
1176
1177                                 /*
1178                                  * before we advance, make sure the current tuples do not
1179                                  * satisfy the mergeclauses.  If they do, then we update the
1180                                  * marked tuple position and go join them.
1181                                  */
1182                                 compareResult = MJCompare(node);
1183                                 MJ_DEBUG_COMPARE(compareResult);
1184
1185                                 if (compareResult == 0)
1186                                 {
1187                                         if (!node->mj_SkipMarkRestore)
1188                                                 ExecMarkPos(innerPlan);
1189
1190                                         MarkInnerTuple(node->mj_InnerTupleSlot, node);
1191
1192                                         node->mj_JoinState = EXEC_MJ_JOINTUPLES;
1193                                 }
1194                                 else if (compareResult < 0)
1195                                         node->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;
1196                                 else
1197                                         /* compareResult > 0 */
1198                                         node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
1199                                 break;
1200
1201                                 /*
1202                                  * SKIPOUTER_ADVANCE: advance over an outer tuple that is
1203                                  * known not to join to any inner tuple.
1204                                  *
1205                                  * Before advancing, we check to see if we must emit an
1206                                  * outer-join fill tuple for this outer tuple.
1207                                  */
1208                         case EXEC_MJ_SKIPOUTER_ADVANCE:
1209                                 MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n");
1210
1211                                 if (doFillOuter && !node->mj_MatchedOuter)
1212                                 {
1213                                         /*
1214                                          * Generate a fake join tuple with nulls for the inner
1215                                          * tuple, and return it if it passes the non-join quals.
1216                                          */
1217                                         TupleTableSlot *result;
1218
1219                                         node->mj_MatchedOuter = true;   /* do it only once */
1220
1221                                         result = MJFillOuter(node);
1222                                         if (result)
1223                                                 return result;
1224                                 }
1225
1226                                 /*
1227                                  * now we get the next outer tuple, if any
1228                                  */
1229                                 outerTupleSlot = ExecProcNode(outerPlan);
1230                                 node->mj_OuterTupleSlot = outerTupleSlot;
1231                                 MJ_DEBUG_PROC_NODE(outerTupleSlot);
1232                                 node->mj_MatchedOuter = false;
1233
1234                                 /* Compute join values and check for unmatchability */
1235                                 switch (MJEvalOuterValues(node))
1236                                 {
1237                                         case MJEVAL_MATCHABLE:
1238                                                 /* Go test the new tuple against the current inner */
1239                                                 node->mj_JoinState = EXEC_MJ_SKIP_TEST;
1240                                                 break;
1241                                         case MJEVAL_NONMATCHABLE:
1242                                                 /* Can't match, so fetch next outer tuple */
1243                                                 node->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;
1244                                                 break;
1245                                         case MJEVAL_ENDOFJOIN:
1246                                                 /* No more outer tuples */
1247                                                 MJ_printf("ExecMergeJoin: end of outer subplan\n");
1248                                                 innerTupleSlot = node->mj_InnerTupleSlot;
1249                                                 if (doFillInner && !TupIsNull(innerTupleSlot))
1250                                                 {
1251                                                         /*
1252                                                          * Need to emit right-join tuples for remaining
1253                                                          * inner tuples.
1254                                                          */
1255                                                         node->mj_JoinState = EXEC_MJ_ENDOUTER;
1256                                                         break;
1257                                                 }
1258                                                 /* Otherwise we're done. */
1259                                                 return NULL;
1260                                 }
1261                                 break;
1262
1263                                 /*
1264                                  * SKIPINNER_ADVANCE: advance over an inner tuple that is
1265                                  * known not to join to any outer tuple.
1266                                  *
1267                                  * Before advancing, we check to see if we must emit an
1268                                  * outer-join fill tuple for this inner tuple.
1269                                  */
1270                         case EXEC_MJ_SKIPINNER_ADVANCE:
1271                                 MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n");
1272
1273                                 if (doFillInner && !node->mj_MatchedInner)
1274                                 {
1275                                         /*
1276                                          * Generate a fake join tuple with nulls for the outer
1277                                          * tuple, and return it if it passes the non-join quals.
1278                                          */
1279                                         TupleTableSlot *result;
1280
1281                                         node->mj_MatchedInner = true;   /* do it only once */
1282
1283                                         result = MJFillInner(node);
1284                                         if (result)
1285                                                 return result;
1286                                 }
1287
1288                                 /* Mark before advancing, if wanted */
1289                                 if (node->mj_ExtraMarks)
1290                                         ExecMarkPos(innerPlan);
1291
1292                                 /*
1293                                  * now we get the next inner tuple, if any
1294                                  */
1295                                 innerTupleSlot = ExecProcNode(innerPlan);
1296                                 node->mj_InnerTupleSlot = innerTupleSlot;
1297                                 MJ_DEBUG_PROC_NODE(innerTupleSlot);
1298                                 node->mj_MatchedInner = false;
1299
1300                                 /* Compute join values and check for unmatchability */
1301                                 switch (MJEvalInnerValues(node, innerTupleSlot))
1302                                 {
1303                                         case MJEVAL_MATCHABLE:
1304                                                 /* proceed to compare it to the current outer */
1305                                                 node->mj_JoinState = EXEC_MJ_SKIP_TEST;
1306                                                 break;
1307                                         case MJEVAL_NONMATCHABLE:
1308
1309                                                 /*
1310                                                  * current inner can't possibly match any outer;
1311                                                  * better to advance the inner scan than the outer.
1312                                                  */
1313                                                 node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
1314                                                 break;
1315                                         case MJEVAL_ENDOFJOIN:
1316                                                 /* No more inner tuples */
1317                                                 MJ_printf("ExecMergeJoin: end of inner subplan\n");
1318                                                 outerTupleSlot = node->mj_OuterTupleSlot;
1319                                                 if (doFillOuter && !TupIsNull(outerTupleSlot))
1320                                                 {
1321                                                         /*
1322                                                          * Need to emit left-join tuples for remaining
1323                                                          * outer tuples.
1324                                                          */
1325                                                         node->mj_JoinState = EXEC_MJ_ENDINNER;
1326                                                         break;
1327                                                 }
1328                                                 /* Otherwise we're done. */
1329                                                 return NULL;
1330                                 }
1331                                 break;
1332
1333                                 /*
1334                                  * EXEC_MJ_ENDOUTER means we have run out of outer tuples, but
1335                                  * are doing a right/full join and therefore must null-fill
1336                                  * any remaining unmatched inner tuples.
1337                                  */
1338                         case EXEC_MJ_ENDOUTER:
1339                                 MJ_printf("ExecMergeJoin: EXEC_MJ_ENDOUTER\n");
1340
1341                                 Assert(doFillInner);
1342
1343                                 if (!node->mj_MatchedInner)
1344                                 {
1345                                         /*
1346                                          * Generate a fake join tuple with nulls for the outer
1347                                          * tuple, and return it if it passes the non-join quals.
1348                                          */
1349                                         TupleTableSlot *result;
1350
1351                                         node->mj_MatchedInner = true;   /* do it only once */
1352
1353                                         result = MJFillInner(node);
1354                                         if (result)
1355                                                 return result;
1356                                 }
1357
1358                                 /* Mark before advancing, if wanted */
1359                                 if (node->mj_ExtraMarks)
1360                                         ExecMarkPos(innerPlan);
1361
1362                                 /*
1363                                  * now we get the next inner tuple, if any
1364                                  */
1365                                 innerTupleSlot = ExecProcNode(innerPlan);
1366                                 node->mj_InnerTupleSlot = innerTupleSlot;
1367                                 MJ_DEBUG_PROC_NODE(innerTupleSlot);
1368                                 node->mj_MatchedInner = false;
1369
1370                                 if (TupIsNull(innerTupleSlot))
1371                                 {
1372                                         MJ_printf("ExecMergeJoin: end of inner subplan\n");
1373                                         return NULL;
1374                                 }
1375
1376                                 /* Else remain in ENDOUTER state and process next tuple. */
1377                                 break;
1378
1379                                 /*
1380                                  * EXEC_MJ_ENDINNER means we have run out of inner tuples, but
1381                                  * are doing a left/full join and therefore must null- fill
1382                                  * any remaining unmatched outer tuples.
1383                                  */
1384                         case EXEC_MJ_ENDINNER:
1385                                 MJ_printf("ExecMergeJoin: EXEC_MJ_ENDINNER\n");
1386
1387                                 Assert(doFillOuter);
1388
1389                                 if (!node->mj_MatchedOuter)
1390                                 {
1391                                         /*
1392                                          * Generate a fake join tuple with nulls for the inner
1393                                          * tuple, and return it if it passes the non-join quals.
1394                                          */
1395                                         TupleTableSlot *result;
1396
1397                                         node->mj_MatchedOuter = true;   /* do it only once */
1398
1399                                         result = MJFillOuter(node);
1400                                         if (result)
1401                                                 return result;
1402                                 }
1403
1404                                 /*
1405                                  * now we get the next outer tuple, if any
1406                                  */
1407                                 outerTupleSlot = ExecProcNode(outerPlan);
1408                                 node->mj_OuterTupleSlot = outerTupleSlot;
1409                                 MJ_DEBUG_PROC_NODE(outerTupleSlot);
1410                                 node->mj_MatchedOuter = false;
1411
1412                                 if (TupIsNull(outerTupleSlot))
1413                                 {
1414                                         MJ_printf("ExecMergeJoin: end of outer subplan\n");
1415                                         return NULL;
1416                                 }
1417
1418                                 /* Else remain in ENDINNER state and process next tuple. */
1419                                 break;
1420
1421                                 /*
1422                                  * broken state value?
1423                                  */
1424                         default:
1425                                 elog(ERROR, "unrecognized mergejoin state: %d",
1426                                          (int) node->mj_JoinState);
1427                 }
1428         }
1429 }
1430
1431 /* ----------------------------------------------------------------
1432  *              ExecInitMergeJoin
1433  * ----------------------------------------------------------------
1434  */
1435 MergeJoinState *
1436 ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
1437 {
1438         MergeJoinState *mergestate;
1439         TupleDesc       outerDesc,
1440                                 innerDesc;
1441         const TupleTableSlotOps *innerOps;
1442
1443         /* check for unsupported flags */
1444         Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1445
1446         MJ1_printf("ExecInitMergeJoin: %s\n",
1447                            "initializing node");
1448
1449         /*
1450          * create state structure
1451          */
1452         mergestate = makeNode(MergeJoinState);
1453         mergestate->js.ps.plan = (Plan *) node;
1454         mergestate->js.ps.state = estate;
1455         mergestate->js.ps.ExecProcNode = ExecMergeJoin;
1456         mergestate->js.jointype = node->join.jointype;
1457         mergestate->mj_ConstFalseJoin = false;
1458
1459         /*
1460          * Miscellaneous initialization
1461          *
1462          * create expression context for node
1463          */
1464         ExecAssignExprContext(estate, &mergestate->js.ps);
1465
1466         /*
1467          * we need two additional econtexts in which we can compute the join
1468          * expressions from the left and right input tuples.  The node's regular
1469          * econtext won't do because it gets reset too often.
1470          */
1471         mergestate->mj_OuterEContext = CreateExprContext(estate);
1472         mergestate->mj_InnerEContext = CreateExprContext(estate);
1473
1474         /*
1475          * initialize child nodes
1476          *
1477          * inner child must support MARK/RESTORE, unless we have detected that we
1478          * don't need that.  Note that skip_mark_restore must never be set if
1479          * there are non-mergeclause joinquals, since the logic wouldn't work.
1480          */
1481         Assert(node->join.joinqual == NIL || !node->skip_mark_restore);
1482         mergestate->mj_SkipMarkRestore = node->skip_mark_restore;
1483
1484         outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate, eflags);
1485         outerDesc = ExecGetResultType(outerPlanState(mergestate));
1486         innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate,
1487                                                                                           mergestate->mj_SkipMarkRestore ?
1488                                                                                           eflags :
1489                                                                                           (eflags | EXEC_FLAG_MARK));
1490         innerDesc = ExecGetResultType(innerPlanState(mergestate));
1491
1492         /*
1493          * For certain types of inner child nodes, it is advantageous to issue
1494          * MARK every time we advance past an inner tuple we will never return to.
1495          * For other types, MARK on a tuple we cannot return to is a waste of
1496          * cycles.  Detect which case applies and set mj_ExtraMarks if we want to
1497          * issue "unnecessary" MARK calls.
1498          *
1499          * Currently, only Material wants the extra MARKs, and it will be helpful
1500          * only if eflags doesn't specify REWIND.
1501          *
1502          * Note that for IndexScan and IndexOnlyScan, it is *necessary* that we
1503          * not set mj_ExtraMarks; otherwise we might attempt to set a mark before
1504          * the first inner tuple, which they do not support.
1505          */
1506         if (IsA(innerPlan(node), Material) &&
1507                 (eflags & EXEC_FLAG_REWIND) == 0 &&
1508                 !mergestate->mj_SkipMarkRestore)
1509                 mergestate->mj_ExtraMarks = true;
1510         else
1511                 mergestate->mj_ExtraMarks = false;
1512
1513         /*
1514          * Initialize result slot, type and projection.
1515          */
1516         ExecInitResultTupleSlotTL(&mergestate->js.ps, &TTSOpsVirtual);
1517         ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
1518
1519         /*
1520          * tuple table initialization
1521          */
1522         innerOps = ExecGetResultSlotOps(innerPlanState(mergestate), NULL);
1523         mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc,
1524                                                                                                                         innerOps);
1525
1526         /*
1527          * initialize child expressions
1528          */
1529         mergestate->js.ps.qual =
1530                 ExecInitQual(node->join.plan.qual, (PlanState *) mergestate);
1531         mergestate->js.joinqual =
1532                 ExecInitQual(node->join.joinqual, (PlanState *) mergestate);
1533         /* mergeclauses are handled below */
1534
1535         /*
1536          * detect whether we need only consider the first matching inner tuple
1537          */
1538         mergestate->js.single_match = (node->join.inner_unique ||
1539                                                                    node->join.jointype == JOIN_SEMI);
1540
1541         /* set up null tuples for outer joins, if needed */
1542         switch (node->join.jointype)
1543         {
1544                 case JOIN_INNER:
1545                 case JOIN_SEMI:
1546                         mergestate->mj_FillOuter = false;
1547                         mergestate->mj_FillInner = false;
1548                         break;
1549                 case JOIN_LEFT:
1550                 case JOIN_ANTI:
1551                         mergestate->mj_FillOuter = true;
1552                         mergestate->mj_FillInner = false;
1553                         mergestate->mj_NullInnerTupleSlot =
1554                                 ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
1555                         break;
1556                 case JOIN_RIGHT:
1557                         mergestate->mj_FillOuter = false;
1558                         mergestate->mj_FillInner = true;
1559                         mergestate->mj_NullOuterTupleSlot =
1560                                 ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
1561
1562                         /*
1563                          * Can't handle right or full join with non-constant extra
1564                          * joinclauses.  This should have been caught by planner.
1565                          */
1566                         if (!check_constant_qual(node->join.joinqual,
1567                                                                          &mergestate->mj_ConstFalseJoin))
1568                                 ereport(ERROR,
1569                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1570                                                  errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
1571                         break;
1572                 case JOIN_FULL:
1573                         mergestate->mj_FillOuter = true;
1574                         mergestate->mj_FillInner = true;
1575                         mergestate->mj_NullOuterTupleSlot =
1576                                 ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
1577                         mergestate->mj_NullInnerTupleSlot =
1578                                 ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
1579
1580                         /*
1581                          * Can't handle right or full join with non-constant extra
1582                          * joinclauses.  This should have been caught by planner.
1583                          */
1584                         if (!check_constant_qual(node->join.joinqual,
1585                                                                          &mergestate->mj_ConstFalseJoin))
1586                                 ereport(ERROR,
1587                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1588                                                  errmsg("FULL JOIN is only supported with merge-joinable join conditions")));
1589                         break;
1590                 default:
1591                         elog(ERROR, "unrecognized join type: %d",
1592                                  (int) node->join.jointype);
1593         }
1594
1595         /*
1596          * preprocess the merge clauses
1597          */
1598         mergestate->mj_NumClauses = list_length(node->mergeclauses);
1599         mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,
1600                                                                                         node->mergeFamilies,
1601                                                                                         node->mergeCollations,
1602                                                                                         node->mergeStrategies,
1603                                                                                         node->mergeNullsFirst,
1604                                                                                         (PlanState *) mergestate);
1605
1606         /*
1607          * initialize join state
1608          */
1609         mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
1610         mergestate->mj_MatchedOuter = false;
1611         mergestate->mj_MatchedInner = false;
1612         mergestate->mj_OuterTupleSlot = NULL;
1613         mergestate->mj_InnerTupleSlot = NULL;
1614
1615         /*
1616          * initialization successful
1617          */
1618         MJ1_printf("ExecInitMergeJoin: %s\n",
1619                            "node initialized");
1620
1621         return mergestate;
1622 }
1623
1624 /* ----------------------------------------------------------------
1625  *              ExecEndMergeJoin
1626  *
1627  * old comments
1628  *              frees storage allocated through C routines.
1629  * ----------------------------------------------------------------
1630  */
1631 void
1632 ExecEndMergeJoin(MergeJoinState *node)
1633 {
1634         MJ1_printf("ExecEndMergeJoin: %s\n",
1635                            "ending node processing");
1636
1637         /*
1638          * Free the exprcontext
1639          */
1640         ExecFreeExprContext(&node->js.ps);
1641
1642         /*
1643          * clean out the tuple table
1644          */
1645         ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
1646         ExecClearTuple(node->mj_MarkedTupleSlot);
1647
1648         /*
1649          * shut down the subplans
1650          */
1651         ExecEndNode(innerPlanState(node));
1652         ExecEndNode(outerPlanState(node));
1653
1654         MJ1_printf("ExecEndMergeJoin: %s\n",
1655                            "node processing ended");
1656 }
1657
1658 void
1659 ExecReScanMergeJoin(MergeJoinState *node)
1660 {
1661         ExecClearTuple(node->mj_MarkedTupleSlot);
1662
1663         node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
1664         node->mj_MatchedOuter = false;
1665         node->mj_MatchedInner = false;
1666         node->mj_OuterTupleSlot = NULL;
1667         node->mj_InnerTupleSlot = NULL;
1668
1669         /*
1670          * if chgParam of subnodes is not null then plans will be re-scanned by
1671          * first ExecProcNode.
1672          */
1673         if (node->js.ps.lefttree->chgParam == NULL)
1674                 ExecReScan(node->js.ps.lefttree);
1675         if (node->js.ps.righttree->chgParam == NULL)
1676                 ExecReScan(node->js.ps.righttree);
1677
1678 }