aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-05-14 21:29:23 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-05-14 21:29:23 +0000
commitfabef3044adbf167e08ff3015923a2ba0dc98546 (patch)
tree39e56ddbfd16ae74ab3d2fdfbe7a6ec59caac5cd
parent05b4293bd82035b22d673da90e64eae38beb4ceb (diff)
downloadpostgresql-fabef3044adbf167e08ff3015923a2ba0dc98546.tar.gz
postgresql-fabef3044adbf167e08ff3015923a2ba0dc98546.zip
Minor refactoring to eliminate duplicate code and make startup a
tad faster.
-rw-r--r--src/backend/executor/nodeMergejoin.c369
-rw-r--r--src/include/nodes/execnodes.h6
2 files changed, 161 insertions, 214 deletions
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index be4a97574e5..6eb2bcc364d 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.72 2005/05/13 21:20:16 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.73 2005/05/14 21:29:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -525,6 +525,86 @@ MJCompare(MergeJoinState *mergestate)
return result;
}
+
+/*
+ * Generate a fake join tuple with nulls for the inner tuple,
+ * and return it if it passes the non-join quals.
+ */
+static TupleTableSlot *
+MJFillOuter(MergeJoinState *node)
+{
+ ExprContext *econtext = node->js.ps.ps_ExprContext;
+ List *otherqual = node->js.ps.qual;
+
+ ResetExprContext(econtext);
+
+ econtext->ecxt_outertuple = node->mj_OuterTupleSlot;
+ econtext->ecxt_innertuple = node->mj_NullInnerTupleSlot;
+
+ if (ExecQual(otherqual, econtext, false))
+ {
+ /*
+ * qualification succeeded. now form the desired projection tuple
+ * and return the slot containing it.
+ */
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ MJ_printf("ExecMergeJoin: returning outer fill tuple\n");
+
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
+
+ if (isDone != ExprEndResult)
+ {
+ node->js.ps.ps_TupFromTlist =
+ (isDone == ExprMultipleResult);
+ return result;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Generate a fake join tuple with nulls for the outer tuple,
+ * and return it if it passes the non-join quals.
+ */
+static TupleTableSlot *
+MJFillInner(MergeJoinState *node)
+{
+ ExprContext *econtext = node->js.ps.ps_ExprContext;
+ List *otherqual = node->js.ps.qual;
+
+ ResetExprContext(econtext);
+
+ econtext->ecxt_outertuple = node->mj_NullOuterTupleSlot;
+ econtext->ecxt_innertuple = node->mj_InnerTupleSlot;
+
+ if (ExecQual(otherqual, econtext, false))
+ {
+ /*
+ * qualification succeeded. now form the desired projection tuple
+ * and return the slot containing it.
+ */
+ TupleTableSlot *result;
+ ExprDoneCond isDone;
+
+ MJ_printf("ExecMergeJoin: returning inner fill tuple\n");
+
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
+
+ if (isDone != ExprEndResult)
+ {
+ node->js.ps.ps_TupFromTlist =
+ (isDone == ExprMultipleResult);
+ return result;
+ }
+ }
+
+ return NULL;
+}
+
+
/* ----------------------------------------------------------------
* ExecMergeTupleDump
*
@@ -612,33 +692,8 @@ ExecMergeJoin(MergeJoinState *node)
econtext = node->js.ps.ps_ExprContext;
joinqual = node->js.joinqual;
otherqual = node->js.ps.qual;
-
- switch (node->js.jointype)
- {
- case JOIN_INNER:
- case JOIN_IN:
- doFillOuter = false;
- doFillInner = false;
- break;
- case JOIN_LEFT:
- doFillOuter = true;
- doFillInner = false;
- break;
- case JOIN_FULL:
- doFillOuter = true;
- doFillInner = true;
- break;
- case JOIN_RIGHT:
- doFillOuter = false;
- doFillInner = true;
- break;
- default:
- elog(ERROR, "unrecognized join type: %d",
- (int) node->js.jointype);
- doFillOuter = false; /* keep compiler quiet */
- doFillInner = false;
- break;
- }
+ doFillOuter = node->mj_FillOuter;
+ doFillInner = node->mj_FillInner;
/*
* Check to see if we're still projecting out tuples from a previous
@@ -707,15 +762,27 @@ ExecMergeJoin(MergeJoinState *node)
}
/* Compute join values and check for unmatchability */
- if (!MJEvalOuterValues(node) && !doFillOuter)
+ if (MJEvalOuterValues(node))
{
- /* Stay in same state to fetch next outer tuple */
- node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
+ /* OK to go get the first inner tuple */
+ node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
}
else
{
- /* OK to go get the first inner tuple */
- node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
+ /* Stay in same state to fetch next outer tuple */
+ if (doFillOuter)
+ {
+ /*
+ * Generate a fake join tuple with nulls for the inner
+ * tuple, and return it if it passes the non-join
+ * quals.
+ */
+ TupleTableSlot *result;
+
+ result = MJFillOuter(node);
+ if (result)
+ return result;
+ }
}
break;
@@ -745,12 +812,7 @@ ExecMergeJoin(MergeJoinState *node)
}
/* Compute join values and check for unmatchability */
- if (!MJEvalInnerValues(node, innerTupleSlot) && !doFillInner)
- {
- /* Stay in same state to fetch next inner tuple */
- node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
- }
- else
+ if (MJEvalInnerValues(node, innerTupleSlot))
{
/*
* OK, we have the initial tuples. Begin by skipping
@@ -758,6 +820,23 @@ ExecMergeJoin(MergeJoinState *node)
*/
node->mj_JoinState = EXEC_MJ_SKIP_TEST;
}
+ else
+ {
+ /* Stay in same state to fetch next inner tuple */
+ if (doFillInner)
+ {
+ /*
+ * Generate a fake join tuple with nulls for the outer
+ * tuple, and return it if it passes the non-join
+ * quals.
+ */
+ TupleTableSlot *result;
+
+ result = MJFillInner(node);
+ if (result)
+ return result;
+ }
+ }
break;
/*
@@ -856,37 +935,13 @@ ExecMergeJoin(MergeJoinState *node)
* tuple, and return it if it passes the non-join
* quals.
*/
- node->mj_MatchedInner = true; /* do it only once */
-
- ResetExprContext(econtext);
-
- outerTupleSlot = node->mj_NullOuterTupleSlot;
- econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = node->mj_InnerTupleSlot;
- econtext->ecxt_innertuple = innerTupleSlot;
+ TupleTableSlot *result;
- if (ExecQual(otherqual, econtext, false))
- {
- /*
- * qualification succeeded. now form the desired
- * projection tuple and return the slot containing
- * it.
- */
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
- result = ExecProject(node->js.ps.ps_ProjInfo,
- &isDone);
+ node->mj_MatchedInner = true; /* do it only once */
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ result = MJFillInner(node);
+ if (result)
+ return result;
}
/*
@@ -961,37 +1016,13 @@ ExecMergeJoin(MergeJoinState *node)
* tuple, and return it if it passes the non-join
* quals.
*/
- node->mj_MatchedOuter = true; /* do it only once */
+ TupleTableSlot *result;
- ResetExprContext(econtext);
-
- outerTupleSlot = node->mj_OuterTupleSlot;
- econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = node->mj_NullInnerTupleSlot;
- econtext->ecxt_innertuple = innerTupleSlot;
-
- if (ExecQual(otherqual, econtext, false))
- {
- /*
- * qualification succeeded. now form the desired
- * projection tuple and return the slot containing
- * it.
- */
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
- result = ExecProject(node->js.ps.ps_ProjInfo,
- &isDone);
+ node->mj_MatchedOuter = true; /* do it only once */
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ result = MJFillOuter(node);
+ if (result)
+ return result;
}
/*
@@ -1223,37 +1254,13 @@ ExecMergeJoin(MergeJoinState *node)
* tuple, and return it if it passes the non-join
* quals.
*/
- node->mj_MatchedOuter = true; /* do it only once */
-
- ResetExprContext(econtext);
-
- outerTupleSlot = node->mj_OuterTupleSlot;
- econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = node->mj_NullInnerTupleSlot;
- econtext->ecxt_innertuple = innerTupleSlot;
-
- if (ExecQual(otherqual, econtext, false))
- {
- /*
- * qualification succeeded. now form the desired
- * projection tuple and return the slot containing
- * it.
- */
- TupleTableSlot *result;
- ExprDoneCond isDone;
+ TupleTableSlot *result;
- MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
- result = ExecProject(node->js.ps.ps_ProjInfo,
- &isDone);
+ node->mj_MatchedOuter = true; /* do it only once */
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ result = MJFillOuter(node);
+ if (result)
+ return result;
}
/*
@@ -1311,37 +1318,13 @@ ExecMergeJoin(MergeJoinState *node)
* tuple, and return it if it passes the non-join
* quals.
*/
- node->mj_MatchedInner = true; /* do it only once */
-
- ResetExprContext(econtext);
-
- outerTupleSlot = node->mj_NullOuterTupleSlot;
- econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = node->mj_InnerTupleSlot;
- econtext->ecxt_innertuple = innerTupleSlot;
-
- if (ExecQual(otherqual, econtext, false))
- {
- /*
- * qualification succeeded. now form the desired
- * projection tuple and return the slot containing
- * it.
- */
- TupleTableSlot *result;
- ExprDoneCond isDone;
+ TupleTableSlot *result;
- MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
- result = ExecProject(node->js.ps.ps_ProjInfo,
- &isDone);
+ node->mj_MatchedInner = true; /* do it only once */
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ result = MJFillInner(node);
+ if (result)
+ return result;
}
/*
@@ -1402,37 +1385,13 @@ ExecMergeJoin(MergeJoinState *node)
* tuple, and return it if it passes the non-join
* quals.
*/
- node->mj_MatchedInner = true; /* do it only once */
-
- ResetExprContext(econtext);
-
- outerTupleSlot = node->mj_NullOuterTupleSlot;
- econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = node->mj_InnerTupleSlot;
- econtext->ecxt_innertuple = innerTupleSlot;
+ TupleTableSlot *result;
- if (ExecQual(otherqual, econtext, false))
- {
- /*
- * qualification succeeded. now form the desired
- * projection tuple and return the slot containing
- * it.
- */
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
- result = ExecProject(node->js.ps.ps_ProjInfo,
- &isDone);
+ node->mj_MatchedInner = true; /* do it only once */
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ result = MJFillInner(node);
+ if (result)
+ return result;
}
/*
@@ -1469,37 +1428,13 @@ ExecMergeJoin(MergeJoinState *node)
* tuple, and return it if it passes the non-join
* quals.
*/
- node->mj_MatchedOuter = true; /* do it only once */
+ TupleTableSlot *result;
- ResetExprContext(econtext);
-
- outerTupleSlot = node->mj_OuterTupleSlot;
- econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = node->mj_NullInnerTupleSlot;
- econtext->ecxt_innertuple = innerTupleSlot;
-
- if (ExecQual(otherqual, econtext, false))
- {
- /*
- * qualification succeeded. now form the desired
- * projection tuple and return the slot containing
- * it.
- */
- TupleTableSlot *result;
- ExprDoneCond isDone;
-
- MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
- result = ExecProject(node->js.ps.ps_ProjInfo,
- &isDone);
+ node->mj_MatchedOuter = true; /* do it only once */
- if (isDone != ExprEndResult)
- {
- node->js.ps.ps_TupFromTlist =
- (isDone == ExprMultipleResult);
- return result;
- }
- }
+ result = MJFillOuter(node);
+ if (result)
+ return result;
}
/*
@@ -1601,13 +1536,19 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
{
case JOIN_INNER:
case JOIN_IN:
+ mergestate->mj_FillOuter = false;
+ mergestate->mj_FillInner = false;
break;
case JOIN_LEFT:
+ mergestate->mj_FillOuter = true;
+ mergestate->mj_FillInner = false;
mergestate->mj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate,
ExecGetResultType(innerPlanState(mergestate)));
break;
case JOIN_RIGHT:
+ mergestate->mj_FillOuter = false;
+ mergestate->mj_FillInner = true;
mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate,
ExecGetResultType(outerPlanState(mergestate)));
@@ -1622,6 +1563,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
break;
case JOIN_FULL:
+ mergestate->mj_FillOuter = true;
+ mergestate->mj_FillInner = true;
mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate,
ExecGetResultType(outerPlanState(mergestate)));
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 9d47c17ad23..b92eb1722f1 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.132 2005/05/13 21:20:16 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.133 2005/05/14 21:29:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1031,6 +1031,8 @@ typedef struct NestLoopState
* NumClauses number of mergejoinable join clauses
* Clauses info for each mergejoinable clause
* JoinState current "state" of join. see execdefs.h
+ * FillOuter true if should emit unjoined outer tuples anyway
+ * FillInner true if should emit unjoined inner tuples anyway
* MatchedOuter true if found a join match for current outer tuple
* MatchedInner true if found a join match for current inner tuple
* OuterTupleSlot slot in tuple table for cur outer tuple
@@ -1051,6 +1053,8 @@ typedef struct MergeJoinState
int mj_NumClauses;
MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */
int mj_JoinState;
+ bool mj_FillOuter;
+ bool mj_FillInner;
bool mj_MatchedOuter;
bool mj_MatchedInner;
TupleTableSlot *mj_OuterTupleSlot;