aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeMergejoin.c
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>1997-09-08 02:41:22 +0000
committerBruce Momjian <bruce@momjian.us>1997-09-08 02:41:22 +0000
commit319dbfa7364721d3343af03a7ce063c2a2c9d385 (patch)
treea2146fe02c49ce1e497b7c287dfcaa367a703ae4 /src/backend/executor/nodeMergejoin.c
parenta90f12fd9d6886da4f0734288496361a304d3882 (diff)
downloadpostgresql-319dbfa7364721d3343af03a7ce063c2a2c9d385.tar.gz
postgresql-319dbfa7364721d3343af03a7ce063c2a2c9d385.zip
Another PGINDENT run that changes variable indenting and case label indenting. Also static variable indenting.
Diffstat (limited to 'src/backend/executor/nodeMergejoin.c')
-rw-r--r--src/backend/executor/nodeMergejoin.c997
1 files changed, 503 insertions, 494 deletions
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 348d3fa1e00..621cfcea901 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.9 1997/09/07 04:41:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.10 1997/09/08 02:22:46 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -84,7 +84,7 @@
#include "utils/lsyscache.h"
#include "utils/psort.h"
-static bool MergeCompare(List * eqQual, List * compareQual, ExprContext * econtext);
+static bool MergeCompare(List * eqQual, List * compareQual, ExprContext * econtext);
/* ----------------------------------------------------------------
* MarkInnerTuple and RestoreInnerTuple macros
@@ -142,13 +142,13 @@ static bool MergeCompare(List * eqQual, List * compareQual, ExprContext * econt
* by "sortOp".
* ----------------------------------------------------------------
*/
-static List *
+static List *
MJFormOSortopI(List * qualList, Oid sortOp)
{
- List *qualCopy;
- List *qualcdr;
- Expr *qual;
- Oper *op;
+ List *qualCopy;
+ List *qualcdr;
+ Expr *qual;
+ Oper *op;
/* ----------------
* qualList is a list: ((op .. ..) ...)
@@ -206,11 +206,11 @@ MJFormOSortopI(List * qualList, Oid sortOp)
* by "sortOp" and reversing the positions of the keys.
* ----------------------------------------------------------------
*/
-static List *
+static List *
MJFormISortopO(List * qualList, Oid sortOp)
{
- List *ISortopO;
- List *qualcdr;
+ List *ISortopO;
+ List *qualcdr;
/* ----------------
* first generate OSortopI, a list of the form
@@ -226,9 +226,9 @@ MJFormISortopO(List * qualList, Oid sortOp)
*/
foreach(qualcdr, ISortopO)
{
- Expr *qual;
- List *inner;
- List *outer;
+ Expr *qual;
+ List *inner;
+ List *outer;
qual = lfirst(qualcdr);
@@ -257,14 +257,14 @@ MJFormISortopO(List * qualList, Oid sortOp)
* if (key1i > key2i) is true and (key1j = key2j) for 0 < j < i.
* ----------------------------------------------------------------
*/
-static bool
+static bool
MergeCompare(List * eqQual, List * compareQual, ExprContext * econtext)
{
- List *clause;
- List *eqclause;
- Datum const_value;
- bool isNull;
- bool isDone;
+ List *clause;
+ List *eqclause;
+ Datum const_value;
+ bool isNull;
+ bool isDone;
/* ----------------
* if we have no compare qualification, return nil
@@ -394,7 +394,7 @@ CleanUpSort(Plan * plan)
if (plan->type == T_Sort)
{
- Sort *sort = (Sort *) plan;
+ Sort *sort = (Sort *) plan;
psort_end(sort);
}
@@ -451,25 +451,25 @@ CleanUpSort(Plan * plan)
TupleTableSlot *
ExecMergeJoin(MergeJoin * node)
{
- EState *estate;
+ EState *estate;
MergeJoinState *mergestate;
- ScanDirection direction;
- List *innerSkipQual;
- List *outerSkipQual;
- List *mergeclauses;
- List *qual;
- bool qualResult;
- bool compareResult;
-
- Plan *innerPlan;
+ ScanDirection direction;
+ List *innerSkipQual;
+ List *outerSkipQual;
+ List *mergeclauses;
+ List *qual;
+ bool qualResult;
+ bool compareResult;
+
+ Plan *innerPlan;
TupleTableSlot *innerTupleSlot;
- Plan *outerPlan;
+ Plan *outerPlan;
TupleTableSlot *outerTupleSlot;
TupleTableSlot *markedTupleSlot;
- ExprContext *econtext;
+ ExprContext *econtext;
/* ----------------
* get information from node
@@ -503,7 +503,7 @@ ExecMergeJoin(MergeJoin * node)
{
TupleTableSlot *result;
ProjectionInfo *projInfo;
- bool isDone;
+ bool isDone;
projInfo = mergestate->jstate.cs_ProjInfo;
result = ExecProject(projInfo, &isDone);
@@ -523,349 +523,185 @@ ExecMergeJoin(MergeJoin * node)
switch (mergestate->mj_JoinState)
{
- /*
- * ******************************** EXEC_MJ_INITIALIZE means
- * that this is the first time ExecMergeJoin() has been called
- * and so we have to initialize the inner, outer and marked
- * tuples as well as various stuff in the expression context. ********************************
- *
- */
- case EXEC_MJ_INITIALIZE:
- MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
- /* ----------------
- * Note: at this point, if either of our inner or outer
- * tuples are nil, then the join ends immediately because
- * we know one of the subplans is empty.
- * ----------------
- */
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
- if (TupIsNull(innerTupleSlot))
- {
- MJ_printf("ExecMergeJoin: **** inner tuple is nil ****\n");
- return NULL;
- }
+ /*
+ * ******************************** EXEC_MJ_INITIALIZE
+ * means that this is the first time ExecMergeJoin() has
+ * been called and so we have to initialize the inner,
+ * outer and marked tuples as well as various stuff in the
+ * expression context. ********************************
+ *
+ */
+ case EXEC_MJ_INITIALIZE:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
+ /* ----------------
+ * Note: at this point, if either of our inner or outer
+ * tuples are nil, then the join ends immediately because
+ * we know one of the subplans is empty.
+ * ----------------
+ */
+ innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
+ if (TupIsNull(innerTupleSlot))
+ {
+ MJ_printf("ExecMergeJoin: **** inner tuple is nil ****\n");
+ return NULL;
+ }
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
- if (TupIsNull(outerTupleSlot))
- {
- MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");
- return NULL;
- }
-
- /* ----------------
- * store the inner and outer tuple in the merge state
- * ----------------
- */
- econtext->ecxt_innertuple = innerTupleSlot;
- econtext->ecxt_outertuple = outerTupleSlot;
-
- /* ----------------
- * set the marked tuple to nil
- * and initialize its tuple descriptor atttributes.
- * -jeff 10 july 1991
- * ----------------
- */
- ExecClearTuple(mergestate->mj_MarkedTupleSlot);
- mergestate->mj_MarkedTupleSlot->ttc_tupleDescriptor =
- innerTupleSlot->ttc_tupleDescriptor;
+ outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
+ if (TupIsNull(outerTupleSlot))
+ {
+ MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");
+ return NULL;
+ }
+
+ /* ----------------
+ * store the inner and outer tuple in the merge state
+ * ----------------
+ */
+ econtext->ecxt_innertuple = innerTupleSlot;
+ econtext->ecxt_outertuple = outerTupleSlot;
+
+ /* ----------------
+ * set the marked tuple to nil
+ * and initialize its tuple descriptor atttributes.
+ * -jeff 10 july 1991
+ * ----------------
+ */
+ ExecClearTuple(mergestate->mj_MarkedTupleSlot);
+ mergestate->mj_MarkedTupleSlot->ttc_tupleDescriptor =
+ innerTupleSlot->ttc_tupleDescriptor;
/*
mergestate->mj_MarkedTupleSlot->ttc_execTupDescriptor =
innerTupleSlot->ttc_execTupDescriptor;
*/
- /* ----------------
- * initialize merge join state to skip inner tuples.
- * ----------------
- */
- mergestate->mj_JoinState = EXEC_MJ_SKIPINNER;
- break;
-
- /*
- * ******************************** EXEC_MJ_JOINMARK means we
- * have just found a new outer tuple and a possible matching
- * inner tuple. This is the case after the INITIALIZE,
- * SKIPOUTER or SKIPINNER states. ********************************
- *
- */
- case EXEC_MJ_JOINMARK:
- MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n");
- ExecMarkPos(innerPlan);
-
- innerTupleSlot = econtext->ecxt_innertuple;
- MarkInnerTuple(innerTupleSlot, mergestate);
-
- mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
- break;
-
- /*
- * ******************************** EXEC_MJ_JOINTEST means we
- * have two tuples which might satisify the merge clause, so
- * we test them.
- *
- * If they do satisify, then we join them and move on to the next
- * inner tuple (EXEC_MJ_JOINTUPLES).
- *
- * If they do not satisify then advance to next outer tuple. ********************************
- *
- */
- case EXEC_MJ_JOINTEST:
- MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTEST\n");
-
- qualResult = ExecQual((List *) mergeclauses, econtext);
- MJ_DEBUG_QUAL(mergeclauses, qualResult);
-
- if (qualResult)
- {
- mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
- }
- else
- {
- mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
- }
- break;
-
- /*
- * ******************************** EXEC_MJ_JOINTUPLES means
- * we have two tuples which satisified the merge clause so we
- * join them and then proceed to get the next inner tuple
- * (EXEC_NEXT_INNER). ********************************
- *
- */
- case EXEC_MJ_JOINTUPLES:
- MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");
- mergestate->mj_JoinState = EXEC_MJ_NEXTINNER;
-
- qualResult = ExecQual((List *) qual, econtext);
- MJ_DEBUG_QUAL(qual, qualResult);
-
- if (qualResult)
- {
/* ----------------
- * qualification succeeded. now form the desired
- * projection tuple and return the slot containing it.
+ * initialize merge join state to skip inner tuples.
* ----------------
*/
- ProjectionInfo *projInfo;
- TupleTableSlot *result;
- bool isDone;
-
- MJ_printf("ExecMergeJoin: **** returning tuple ****\n");
-
- projInfo = mergestate->jstate.cs_ProjInfo;
-
- result = ExecProject(projInfo, &isDone);
- mergestate->jstate.cs_TupFromTlist = !isDone;
- return result;
- }
- break;
-
- /*
- * ******************************** EXEC_MJ_NEXTINNER means
- * advance the inner scan to the next tuple. If the tuple is
- * not nil, we then proceed to test it against the join
- * qualification. ********************************
- *
- */
- case EXEC_MJ_NEXTINNER:
- MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");
-
- /* ----------------
- * now we get the next inner tuple, if any
- * ----------------
- */
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
- MJ_DEBUG_PROC_NODE(innerTupleSlot);
- econtext->ecxt_innertuple = innerTupleSlot;
-
- if (TupIsNull(innerTupleSlot))
- {
- mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
- }
- else
- {
- mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
- }
- break;
-
- /*
- * ******************************** EXEC_MJ_NEXTOUTER means
- *
- * outer inner outer tuple - 5 5 - marked tuple 5 5 6
- * 6 - inner tuple 7 7
- *
- * we know we just bumped into the first inner tuple > current
- * outer tuple so get a new outer tuple and then proceed to
- * test it against the marked tuple (EXEC_MJ_TESTOUTER) ********************************
- *
- */
- case EXEC_MJ_NEXTOUTER:
- MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");
-
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
- MJ_DEBUG_PROC_NODE(outerTupleSlot);
- econtext->ecxt_outertuple = outerTupleSlot;
-
- /* ----------------
- * if the outer tuple is null then we know
- * we are done with the join
- * ----------------
- */
- if (TupIsNull(outerTupleSlot))
- {
- MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");
- CleanUpSort(node->join.lefttree->lefttree);
- CleanUpSort(node->join.righttree->lefttree);
- return NULL;
- }
-
- mergestate->mj_JoinState = EXEC_MJ_TESTOUTER;
- break;
-
- /*
- * ******************************** EXEC_MJ_TESTOUTER If the
- * new outer tuple and the marked tuple satisify the merge
- * clause then we know we have duplicates in the outer scan so
- * we have to restore the inner scan to the marked tuple and
- * proceed to join the new outer tuples with the inner tuples
- * (EXEC_MJ_JOINTEST)
- *
- * This is the case when
- *
- * outer inner 4 5 - marked tuple outer tuple - 5 5 new
- * outer tuple - 5 5 6 8 - inner tuple 7 12
- *
- * new outer tuple = marked tuple
- *
- * If the outer tuple fails the test, then we know we have to
- * proceed to skip outer tuples until outer >= inner
- * (EXEC_MJ_SKIPOUTER).
- *
- * This is the case when
- *
- * outer inner 5 5 - marked tuple outer tuple - 5 5 new
- * outer tuple - 6 8 - inner tuple 7 12
- *
- * new outer tuple > marked tuple
- *
- ********************************
- *
- */
- case EXEC_MJ_TESTOUTER:
- MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
-
- /* ----------------
- * here we compare the outer tuple with the marked inner tuple
- * by using the marked tuple in place of the inner tuple.
- * ----------------
- */
- innerTupleSlot = econtext->ecxt_innertuple;
- markedTupleSlot = mergestate->mj_MarkedTupleSlot;
- econtext->ecxt_innertuple = markedTupleSlot;
-
- qualResult = ExecQual((List *) mergeclauses, econtext);
- MJ_DEBUG_QUAL(mergeclauses, qualResult);
-
- if (qualResult)
- {
- /* ----------------
- * the merge clause matched so now we juggle the slots
- * back the way they were and proceed to JOINTEST.
- * ----------------
+ mergestate->mj_JoinState = EXEC_MJ_SKIPINNER;
+ break;
+
+ /*
+ * ******************************** EXEC_MJ_JOINMARK means
+ * we have just found a new outer tuple and a possible
+ * matching inner tuple. This is the case after the
+ * INITIALIZE, SKIPOUTER or SKIPINNER states. ********************************
+ *
*/
- econtext->ecxt_innertuple = innerTupleSlot;
+ case EXEC_MJ_JOINMARK:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n");
+ ExecMarkPos(innerPlan);
- RestoreInnerTuple(innerTupleSlot, markedTupleSlot);
+ innerTupleSlot = econtext->ecxt_innertuple;
+ MarkInnerTuple(innerTupleSlot, mergestate);
- ExecRestrPos(innerPlan);
mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+ break;
- }
- else
- {
- /* ----------------
- * if the inner tuple was nil and the new outer
- * tuple didn't match the marked outer tuple then
- * we may have the case:
+ /*
+ * ******************************** EXEC_MJ_JOINTEST means
+ * we have two tuples which might satisify the merge
+ * clause, so we test them.
*
- * outer inner
- * 4 4 - marked tuple
- * new outer - 5 4
- * 6 nil - inner tuple
- * 7
+ * If they do satisify, then we join them and move on to the
+ * next inner tuple (EXEC_MJ_JOINTUPLES).
+ *
+ * If they do not satisify then advance to next outer tuple. ********************************
*
- * which means that all subsequent outer tuples will be
- * larger than our inner tuples.
- * ----------------
*/
- if (TupIsNull(innerTupleSlot))
+ case EXEC_MJ_JOINTEST:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTEST\n");
+
+ qualResult = ExecQual((List *) mergeclauses, econtext);
+ MJ_DEBUG_QUAL(mergeclauses, qualResult);
+
+ if (qualResult)
{
- MJ_printf("ExecMergeJoin: **** wierd case 1 ****\n");
- return NULL;
+ mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ }
+ else
+ {
+ mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
+ }
+ break;
+
+ /*
+ * ******************************** EXEC_MJ_JOINTUPLES
+ * means we have two tuples which satisified the merge
+ * clause so we join them and then proceed to get the next
+ * inner tuple (EXEC_NEXT_INNER). ********************************
+ *
+ */
+ case EXEC_MJ_JOINTUPLES:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");
+ mergestate->mj_JoinState = EXEC_MJ_NEXTINNER;
+
+ qualResult = ExecQual((List *) qual, econtext);
+ MJ_DEBUG_QUAL(qual, qualResult);
+
+ if (qualResult)
+ {
+ /* ----------------
+ * qualification succeeded. now form the desired
+ * projection tuple and return the slot containing it.
+ * ----------------
+ */
+ ProjectionInfo *projInfo;
+ TupleTableSlot *result;
+ bool isDone;
+
+ MJ_printf("ExecMergeJoin: **** returning tuple ****\n");
+
+ projInfo = mergestate->jstate.cs_ProjInfo;
+
+ result = ExecProject(projInfo, &isDone);
+ mergestate->jstate.cs_TupFromTlist = !isDone;
+ return result;
}
+ break;
+
+ /*
+ * ******************************** EXEC_MJ_NEXTINNER
+ * means advance the inner scan to the next tuple. If the
+ * tuple is not nil, we then proceed to test it against
+ * the join qualification. ********************************
+ *
+ */
+ case EXEC_MJ_NEXTINNER:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");
/* ----------------
- * restore the inner tuple and continue on to
- * skip outer tuples.
+ * now we get the next inner tuple, if any
* ----------------
*/
+ innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
+ MJ_DEBUG_PROC_NODE(innerTupleSlot);
econtext->ecxt_innertuple = innerTupleSlot;
- mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
- }
- break;
-
- /*
- * ******************************** EXEC_MJ_SKIPOUTER means
- * skip over tuples in the outer plan until we find an outer
- * tuple > current inner tuple.
- *
- * For example:
- *
- * outer inner 5 5 5 5 outer tuple - 6 8 - inner
- * tuple 7 12 8 14
- *
- * we have to advance the outer scan until we find the outer 8.
- *
- ********************************
- *
- */
- case EXEC_MJ_SKIPOUTER:
- MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER\n");
- /* ----------------
- * before we advance, make sure the current tuples
- * do not satisify the mergeclauses. If they do, then
- * we update the marked tuple and go join them.
- * ----------------
- */
- qualResult = ExecQual((List *) mergeclauses, econtext);
- MJ_DEBUG_QUAL(mergeclauses, qualResult);
-
- if (qualResult)
- {
- ExecMarkPos(innerPlan);
- innerTupleSlot = econtext->ecxt_innertuple;
- MarkInnerTuple(innerTupleSlot, mergestate);
-
- mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ if (TupIsNull(innerTupleSlot))
+ {
+ mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
+ }
+ else
+ {
+ mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+ }
break;
- }
-
- /* ----------------
- * ok, now test the skip qualification
- * ----------------
- */
- compareResult = MergeCompare(mergeclauses,
- outerSkipQual,
- econtext);
-
- MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
-
- /* ----------------
- * compareResult is true as long as we should
- * continue skipping tuples.
- * ----------------
- */
- if (compareResult)
- {
+
+ /*
+ * ******************************** EXEC_MJ_NEXTOUTER
+ * means
+ *
+ * outer inner outer tuple - 5 5 - marked tuple 5 5
+ * 6 6 - inner tuple 7 7
+ *
+ * we know we just bumped into the first inner tuple >
+ * current outer tuple so get a new outer tuple and then
+ * proceed to test it against the marked tuple
+ * (EXEC_MJ_TESTOUTER) ********************************
+ *
+ */
+ case EXEC_MJ_NEXTOUTER:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
MJ_DEBUG_PROC_NODE(outerTupleSlot);
@@ -878,169 +714,342 @@ ExecMergeJoin(MergeJoin * node)
*/
if (TupIsNull(outerTupleSlot))
{
- MJ_printf("ExecMergeJoin: **** outerTuple is nil ****\n");
+ MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");
+ CleanUpSort(node->join.lefttree->lefttree);
+ CleanUpSort(node->join.righttree->lefttree);
return NULL;
}
+
+ mergestate->mj_JoinState = EXEC_MJ_TESTOUTER;
+ break;
+
+ /*
+ * ******************************** EXEC_MJ_TESTOUTER If
+ * the new outer tuple and the marked tuple satisify the
+ * merge clause then we know we have duplicates in the
+ * outer scan so we have to restore the inner scan to the
+ * marked tuple and proceed to join the new outer tuples
+ * with the inner tuples (EXEC_MJ_JOINTEST)
+ *
+ * This is the case when
+ *
+ * outer inner 4 5 - marked tuple outer tuple - 5 5
+ * new outer tuple - 5 5 6 8 - inner tuple 7
+ * 12
+ *
+ * new outer tuple = marked tuple
+ *
+ * If the outer tuple fails the test, then we know we have to
+ * proceed to skip outer tuples until outer >= inner
+ * (EXEC_MJ_SKIPOUTER).
+ *
+ * This is the case when
+ *
+ * outer inner 5 5 - marked tuple outer tuple - 5 5
+ * new outer tuple - 6 8 - inner tuple 7 12
+ *
+ * new outer tuple > marked tuple
+ *
+ *******************************
+ *
+ *
+ */
+ case EXEC_MJ_TESTOUTER:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
+
/* ----------------
- * otherwise test the new tuple against the skip qual.
- * (we remain in the EXEC_MJ_SKIPOUTER state)
+ * here we compare the outer tuple with the marked inner tuple
+ * by using the marked tuple in place of the inner tuple.
* ----------------
*/
- break;
- }
-
- /* ----------------
- * now check the inner skip qual to see if we
- * should now skip inner tuples... if we fail the
- * inner skip qual, then we know we have a new pair
- * of matching tuples.
- * ----------------
- */
- compareResult = MergeCompare(mergeclauses,
- innerSkipQual,
- econtext);
-
- MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
-
- if (compareResult)
- {
- mergestate->mj_JoinState = EXEC_MJ_SKIPINNER;
- }
- else
- {
- mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
- }
- break;
-
- /*
- * ******************************** EXEC_MJ_SKIPINNER means
- * skip over tuples in the inner plan until we find an inner
- * tuple > current outer tuple.
- *
- * For example:
- *
- * outer inner 5 5 5 5 outer tuple - 12 8 - inner
- * tuple 14 10 17 12
- *
- * we have to advance the inner scan until we find the inner 12.
- *
- ********************************
- *
- */
- case EXEC_MJ_SKIPINNER:
- MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER\n");
- /* ----------------
- * before we advance, make sure the current tuples
- * do not satisify the mergeclauses. If they do, then
- * we update the marked tuple and go join them.
- * ----------------
- */
- qualResult = ExecQual((List *) mergeclauses, econtext);
- MJ_DEBUG_QUAL(mergeclauses, qualResult);
-
- if (qualResult)
- {
- ExecMarkPos(innerPlan);
innerTupleSlot = econtext->ecxt_innertuple;
+ markedTupleSlot = mergestate->mj_MarkedTupleSlot;
+ econtext->ecxt_innertuple = markedTupleSlot;
- MarkInnerTuple(innerTupleSlot, mergestate);
+ qualResult = ExecQual((List *) mergeclauses, econtext);
+ MJ_DEBUG_QUAL(mergeclauses, qualResult);
+
+ if (qualResult)
+ {
+ /* ----------------
+ * the merge clause matched so now we juggle the slots
+ * back the way they were and proceed to JOINTEST.
+ * ----------------
+ */
+ econtext->ecxt_innertuple = innerTupleSlot;
+
+ RestoreInnerTuple(innerTupleSlot, markedTupleSlot);
- mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ ExecRestrPos(innerPlan);
+ mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+
+ }
+ else
+ {
+ /* ----------------
+ * if the inner tuple was nil and the new outer
+ * tuple didn't match the marked outer tuple then
+ * we may have the case:
+ *
+ * outer inner
+ * 4 4 - marked tuple
+ * new outer - 5 4
+ * 6 nil - inner tuple
+ * 7
+ *
+ * which means that all subsequent outer tuples will be
+ * larger than our inner tuples.
+ * ----------------
+ */
+ if (TupIsNull(innerTupleSlot))
+ {
+ MJ_printf("ExecMergeJoin: **** wierd case 1 ****\n");
+ return NULL;
+ }
+
+ /* ----------------
+ * restore the inner tuple and continue on to
+ * skip outer tuples.
+ * ----------------
+ */
+ econtext->ecxt_innertuple = innerTupleSlot;
+ mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
+ }
break;
- }
-
- /* ----------------
- * ok, now test the skip qualification
- * ----------------
- */
- compareResult = MergeCompare(mergeclauses,
- innerSkipQual,
- econtext);
-
- MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
-
- /* ----------------
- * compareResult is true as long as we should
- * continue skipping tuples.
- * ----------------
- */
- if (compareResult)
- {
+
+ /*
+ * ******************************** EXEC_MJ_SKIPOUTER
+ * means skip over tuples in the outer plan until we find
+ * an outer tuple > current inner tuple.
+ *
+ * For example:
+ *
+ * outer inner 5 5 5 5 outer tuple - 6 8 -
+ * inner tuple 7 12 8 14
+ *
+ * we have to advance the outer scan until we find the outer
+ * 8.
+ *
+ *******************************
+ *
+ *
+ */
+ case EXEC_MJ_SKIPOUTER:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER\n");
/* ----------------
- * now try and get a new inner tuple
+ * before we advance, make sure the current tuples
+ * do not satisify the mergeclauses. If they do, then
+ * we update the marked tuple and go join them.
* ----------------
*/
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
- MJ_DEBUG_PROC_NODE(innerTupleSlot);
- econtext->ecxt_innertuple = innerTupleSlot;
+ qualResult = ExecQual((List *) mergeclauses, econtext);
+ MJ_DEBUG_QUAL(mergeclauses, qualResult);
+
+ if (qualResult)
+ {
+ ExecMarkPos(innerPlan);
+ innerTupleSlot = econtext->ecxt_innertuple;
+
+ MarkInnerTuple(innerTupleSlot, mergestate);
+
+ mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ break;
+ }
/* ----------------
- * if the inner tuple is null then we know
- * we have to restore the inner scan
- * and advance to the next outer tuple
+ * ok, now test the skip qualification
* ----------------
*/
- if (TupIsNull(innerTupleSlot))
+ compareResult = MergeCompare(mergeclauses,
+ outerSkipQual,
+ econtext);
+
+ MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
+
+ /* ----------------
+ * compareResult is true as long as we should
+ * continue skipping tuples.
+ * ----------------
+ */
+ if (compareResult)
{
+
+ outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
+ MJ_DEBUG_PROC_NODE(outerTupleSlot);
+ econtext->ecxt_outertuple = outerTupleSlot;
+
/* ----------------
- * this is an interesting case.. all our
- * inner tuples are smaller then our outer
- * tuples so we never found an inner tuple
- * to mark.
- *
- * outer inner
- * outer tuple - 5 4
- * 5 4
- * 6 nil - inner tuple
- * 7
- *
- * This means the join should end.
+ * if the outer tuple is null then we know
+ * we are done with the join
* ----------------
*/
- MJ_printf("ExecMergeJoin: **** wierd case 2 ****\n");
- return NULL;
+ if (TupIsNull(outerTupleSlot))
+ {
+ MJ_printf("ExecMergeJoin: **** outerTuple is nil ****\n");
+ return NULL;
+ }
+ /* ----------------
+ * otherwise test the new tuple against the skip qual.
+ * (we remain in the EXEC_MJ_SKIPOUTER state)
+ * ----------------
+ */
+ break;
}
/* ----------------
- * otherwise test the new tuple against the skip qual.
- * (we remain in the EXEC_MJ_SKIPINNER state)
+ * now check the inner skip qual to see if we
+ * should now skip inner tuples... if we fail the
+ * inner skip qual, then we know we have a new pair
+ * of matching tuples.
* ----------------
*/
+ compareResult = MergeCompare(mergeclauses,
+ innerSkipQual,
+ econtext);
+
+ MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
+
+ if (compareResult)
+ {
+ mergestate->mj_JoinState = EXEC_MJ_SKIPINNER;
+ }
+ else
+ {
+ mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
+ }
break;
- }
-
- /* ----------------
- * compare finally failed and we have stopped skipping
- * inner tuples so now check the outer skip qual
- * to see if we should now skip outer tuples...
- * ----------------
- */
- compareResult = MergeCompare(mergeclauses,
- outerSkipQual,
- econtext);
-
- MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
-
- if (compareResult)
- {
- mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
- }
- else
- {
- mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
- }
-
- break;
-
- /*
- * ******************************** if we get here it means
- * our code is fucked up and so we just end the join
- * prematurely. ********************************
- *
- */
- default:
- elog(NOTICE, "ExecMergeJoin: invalid join state. aborting");
- return NULL;
+
+ /*
+ * ******************************** EXEC_MJ_SKIPINNER
+ * means skip over tuples in the inner plan until we find
+ * an inner tuple > current outer tuple.
+ *
+ * For example:
+ *
+ * outer inner 5 5 5 5 outer tuple - 12 8 - inner
+ * tuple 14 10 17 12
+ *
+ * we have to advance the inner scan until we find the inner
+ * 12.
+ *
+ *******************************
+ *
+ *
+ */
+ case EXEC_MJ_SKIPINNER:
+ MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER\n");
+ /* ----------------
+ * before we advance, make sure the current tuples
+ * do not satisify the mergeclauses. If they do, then
+ * we update the marked tuple and go join them.
+ * ----------------
+ */
+ qualResult = ExecQual((List *) mergeclauses, econtext);
+ MJ_DEBUG_QUAL(mergeclauses, qualResult);
+
+ if (qualResult)
+ {
+ ExecMarkPos(innerPlan);
+ innerTupleSlot = econtext->ecxt_innertuple;
+
+ MarkInnerTuple(innerTupleSlot, mergestate);
+
+ mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ break;
+ }
+
+ /* ----------------
+ * ok, now test the skip qualification
+ * ----------------
+ */
+ compareResult = MergeCompare(mergeclauses,
+ innerSkipQual,
+ econtext);
+
+ MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
+
+ /* ----------------
+ * compareResult is true as long as we should
+ * continue skipping tuples.
+ * ----------------
+ */
+ if (compareResult)
+ {
+ /* ----------------
+ * now try and get a new inner tuple
+ * ----------------
+ */
+ innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
+ MJ_DEBUG_PROC_NODE(innerTupleSlot);
+ econtext->ecxt_innertuple = innerTupleSlot;
+
+ /* ----------------
+ * if the inner tuple is null then we know
+ * we have to restore the inner scan
+ * and advance to the next outer tuple
+ * ----------------
+ */
+ if (TupIsNull(innerTupleSlot))
+ {
+ /* ----------------
+ * this is an interesting case.. all our
+ * inner tuples are smaller then our outer
+ * tuples so we never found an inner tuple
+ * to mark.
+ *
+ * outer inner
+ * outer tuple - 5 4
+ * 5 4
+ * 6 nil - inner tuple
+ * 7
+ *
+ * This means the join should end.
+ * ----------------
+ */
+ MJ_printf("ExecMergeJoin: **** wierd case 2 ****\n");
+ return NULL;
+ }
+
+ /* ----------------
+ * otherwise test the new tuple against the skip qual.
+ * (we remain in the EXEC_MJ_SKIPINNER state)
+ * ----------------
+ */
+ break;
+ }
+
+ /* ----------------
+ * compare finally failed and we have stopped skipping
+ * inner tuples so now check the outer skip qual
+ * to see if we should now skip outer tuples...
+ * ----------------
+ */
+ compareResult = MergeCompare(mergeclauses,
+ outerSkipQual,
+ econtext);
+
+ MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
+
+ if (compareResult)
+ {
+ mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
+ }
+ else
+ {
+ mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
+ }
+
+ break;
+
+ /*
+ * ******************************** if we get here it
+ * means our code is fucked up and so we just end the join
+ * prematurely. ********************************
+ *
+ */
+ default:
+ elog(NOTICE, "ExecMergeJoin: invalid join state. aborting");
+ return NULL;
}
}
}
@@ -1057,13 +1066,13 @@ bool
ExecInitMergeJoin(MergeJoin * node, EState * estate, Plan * parent)
{
MergeJoinState *mergestate;
- List *joinclauses;
- RegProcedure rightsortop;
- RegProcedure leftsortop;
- RegProcedure sortop;
+ List *joinclauses;
+ RegProcedure rightsortop;
+ RegProcedure leftsortop;
+ RegProcedure sortop;
- List *OSortopI;
- List *ISortopO;
+ List *OSortopI;
+ List *ISortopO;
MJ1_printf("ExecInitMergeJoin: %s\n",
"initializing node");