mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Minor refactoring to eliminate duplicate code and make startup a
tad faster.
This commit is contained in:
parent
05b4293bd8
commit
fabef3044a
@ -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,16 +762,28 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
}
|
||||
|
||||
/* Compute join values and check for unmatchability */
|
||||
if (!MJEvalOuterValues(node) && !doFillOuter)
|
||||
{
|
||||
/* Stay in same state to fetch next outer tuple */
|
||||
node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
|
||||
}
|
||||
else
|
||||
if (MJEvalOuterValues(node))
|
||||
{
|
||||
/* OK to go get the first inner tuple */
|
||||
node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
|
||||
case EXEC_MJ_INITIALIZE_INNER:
|
||||
@ -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,38 +935,14 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
* tuple, and return it if it passes the non-join
|
||||
* quals.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
|
||||
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;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo,
|
||||
&isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
result = MJFillInner(node);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now we get the next inner tuple, if any. If there's
|
||||
@ -961,38 +1016,14 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
* tuple, and return it if it passes the non-join
|
||||
* quals.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
|
||||
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;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo,
|
||||
&isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
result = MJFillOuter(node);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now we get the next outer tuple, if any
|
||||
@ -1223,38 +1254,14 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
* tuple, and return it if it passes the non-join
|
||||
* quals.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
|
||||
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;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo,
|
||||
&isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
result = MJFillOuter(node);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now we get the next outer tuple, if any
|
||||
@ -1311,38 +1318,14 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
* tuple, and return it if it passes the non-join
|
||||
* quals.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
|
||||
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;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo,
|
||||
&isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
result = MJFillInner(node);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now we get the next inner tuple, if any
|
||||
@ -1402,38 +1385,14 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
* tuple, and return it if it passes the non-join
|
||||
* quals.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
|
||||
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;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo,
|
||||
&isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
result = MJFillInner(node);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now we get the next inner tuple, if any
|
||||
@ -1469,38 +1428,14 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
* tuple, and return it if it passes the non-join
|
||||
* quals.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
|
||||
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;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo,
|
||||
&isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
result = MJFillOuter(node);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now we get the next outer tuple, if any
|
||||
@ -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)));
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user