Make NestLoop plan nodes pass outer-relation variables into their inner

relation using the general PARAM_EXEC executor parameter mechanism, rather
than the ad-hoc kluge of passing the outer tuple down through ExecReScan.
The previous method was hard to understand and could never be extended to
handle parameters coming from multiple join levels.  This patch doesn't
change the set of possible plans nor have any significant performance effect,
but it's necessary infrastructure for future generalization of the concept
of an inner indexscan plan.

ExecReScan's second parameter is now unused, so it's removed.
This commit is contained in:
Tom Lane 2010-07-12 17:01:06 +00:00
parent 5a3489357f
commit 53e757689c
76 changed files with 802 additions and 700 deletions

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.108 2010/02/14 18:42:14 rhaas Exp $
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.109 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -59,17 +59,9 @@ static bool IndexSupportsBackwardScan(Oid indexid);
*
* Note that if the plan node has parameters that have changed value,
* the output might be different from last time.
*
* The second parameter is currently only used to pass a NestLoop plan's
* econtext down to its inner child plan, in case that is an indexscan that
* needs access to variables of the current outer tuple. (The handling of
* this parameter is currently pretty inconsistent: some callers pass NULL
* and some pass down their parent's value; so don't rely on it in other
* situations. It'd probably be better to remove the whole thing and use
* the generalized parameter mechanism instead.)
*/
void
ExecReScan(PlanState *node, ExprContext *exprCtxt)
ExecReScan(PlanState *node)
{
/* If collecting timing stats, update them */
if (node->instrument)
@ -126,119 +118,119 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
switch (nodeTag(node))
{
case T_ResultState:
ExecReScanResult((ResultState *) node, exprCtxt);
ExecReScanResult((ResultState *) node);
break;
case T_ModifyTableState:
ExecReScanModifyTable((ModifyTableState *) node, exprCtxt);
ExecReScanModifyTable((ModifyTableState *) node);
break;
case T_AppendState:
ExecReScanAppend((AppendState *) node, exprCtxt);
ExecReScanAppend((AppendState *) node);
break;
case T_RecursiveUnionState:
ExecRecursiveUnionReScan((RecursiveUnionState *) node, exprCtxt);
ExecReScanRecursiveUnion((RecursiveUnionState *) node);
break;
case T_BitmapAndState:
ExecReScanBitmapAnd((BitmapAndState *) node, exprCtxt);
ExecReScanBitmapAnd((BitmapAndState *) node);
break;
case T_BitmapOrState:
ExecReScanBitmapOr((BitmapOrState *) node, exprCtxt);
ExecReScanBitmapOr((BitmapOrState *) node);
break;
case T_SeqScanState:
ExecSeqReScan((SeqScanState *) node, exprCtxt);
ExecReScanSeqScan((SeqScanState *) node);
break;
case T_IndexScanState:
ExecIndexReScan((IndexScanState *) node, exprCtxt);
ExecReScanIndexScan((IndexScanState *) node);
break;
case T_BitmapIndexScanState:
ExecBitmapIndexReScan((BitmapIndexScanState *) node, exprCtxt);
ExecReScanBitmapIndexScan((BitmapIndexScanState *) node);
break;
case T_BitmapHeapScanState:
ExecBitmapHeapReScan((BitmapHeapScanState *) node, exprCtxt);
ExecReScanBitmapHeapScan((BitmapHeapScanState *) node);
break;
case T_TidScanState:
ExecTidReScan((TidScanState *) node, exprCtxt);
ExecReScanTidScan((TidScanState *) node);
break;
case T_SubqueryScanState:
ExecSubqueryReScan((SubqueryScanState *) node, exprCtxt);
ExecReScanSubqueryScan((SubqueryScanState *) node);
break;
case T_FunctionScanState:
ExecFunctionReScan((FunctionScanState *) node, exprCtxt);
ExecReScanFunctionScan((FunctionScanState *) node);
break;
case T_ValuesScanState:
ExecValuesReScan((ValuesScanState *) node, exprCtxt);
ExecReScanValuesScan((ValuesScanState *) node);
break;
case T_CteScanState:
ExecCteScanReScan((CteScanState *) node, exprCtxt);
ExecReScanCteScan((CteScanState *) node);
break;
case T_WorkTableScanState:
ExecWorkTableScanReScan((WorkTableScanState *) node, exprCtxt);
ExecReScanWorkTableScan((WorkTableScanState *) node);
break;
case T_NestLoopState:
ExecReScanNestLoop((NestLoopState *) node, exprCtxt);
ExecReScanNestLoop((NestLoopState *) node);
break;
case T_MergeJoinState:
ExecReScanMergeJoin((MergeJoinState *) node, exprCtxt);
ExecReScanMergeJoin((MergeJoinState *) node);
break;
case T_HashJoinState:
ExecReScanHashJoin((HashJoinState *) node, exprCtxt);
ExecReScanHashJoin((HashJoinState *) node);
break;
case T_MaterialState:
ExecMaterialReScan((MaterialState *) node, exprCtxt);
ExecReScanMaterial((MaterialState *) node);
break;
case T_SortState:
ExecReScanSort((SortState *) node, exprCtxt);
ExecReScanSort((SortState *) node);
break;
case T_GroupState:
ExecReScanGroup((GroupState *) node, exprCtxt);
ExecReScanGroup((GroupState *) node);
break;
case T_AggState:
ExecReScanAgg((AggState *) node, exprCtxt);
ExecReScanAgg((AggState *) node);
break;
case T_WindowAggState:
ExecReScanWindowAgg((WindowAggState *) node, exprCtxt);
ExecReScanWindowAgg((WindowAggState *) node);
break;
case T_UniqueState:
ExecReScanUnique((UniqueState *) node, exprCtxt);
ExecReScanUnique((UniqueState *) node);
break;
case T_HashState:
ExecReScanHash((HashState *) node, exprCtxt);
ExecReScanHash((HashState *) node);
break;
case T_SetOpState:
ExecReScanSetOp((SetOpState *) node, exprCtxt);
ExecReScanSetOp((SetOpState *) node);
break;
case T_LockRowsState:
ExecReScanLockRows((LockRowsState *) node, exprCtxt);
ExecReScanLockRows((LockRowsState *) node);
break;
case T_LimitState:
ExecReScanLimit((LimitState *) node, exprCtxt);
ExecReScanLimit((LimitState *) node);
break;
default:

View File

@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.350 2010/07/09 14:06:01 rhaas Exp $
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.351 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -400,7 +400,7 @@ ExecutorRewind(QueryDesc *queryDesc)
/*
* rescan plan
*/
ExecReScan(queryDesc->planstate, NULL);
ExecReScan(queryDesc->planstate);
MemoryContextSwitchTo(oldcontext);
}

View File

@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.70 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.71 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -341,7 +341,7 @@ ExecProcNode(PlanState *node)
CHECK_FOR_INTERRUPTS();
if (node->chgParam != NULL) /* something changed */
ExecReScan(node, NULL); /* let ReScan handle this */
ExecReScan(node); /* let ReScan handle this */
if (node->instrument)
InstrStartNode(node->instrument);
@ -504,7 +504,7 @@ MultiExecProcNode(PlanState *node)
CHECK_FOR_INTERRUPTS();
if (node->chgParam != NULL) /* something changed */
ExecReScan(node, NULL); /* let ReScan handle this */
ExecReScan(node); /* let ReScan handle this */
switch (nodeTag(node))
{

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.263 2010/02/26 02:00:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.264 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -78,7 +78,9 @@ static Datum ExecEvalWholeRowSlow(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
static Datum ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static void init_fcache(Oid foid, FuncExprState *fcache,
MemoryContext fcacheCxt, bool needDescForSets);
@ -961,80 +963,87 @@ ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
}
/* ----------------------------------------------------------------
* ExecEvalParam
* ExecEvalParamExec
*
* Returns the value of a parameter. A param node contains
* something like ($.name) and the expression context contains
* the current parameter bindings (name = "sam") (age = 34)...
* so our job is to find and return the appropriate datum ("sam").
* Returns the value of a PARAM_EXEC parameter.
* ----------------------------------------------------------------
*/
static Datum
ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
Param *expression = (Param *) exprstate->expr;
int thisParamId = expression->paramid;
ParamExecData *prm;
if (isDone)
*isDone = ExprSingleResult;
if (expression->paramkind == PARAM_EXEC)
/*
* PARAM_EXEC params (internal executor parameters) are stored in the
* ecxt_param_exec_vals array, and can be accessed by array index.
*/
prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
if (prm->execPlan != NULL)
{
/*
* PARAM_EXEC params (internal executor parameters) are stored in the
* ecxt_param_exec_vals array, and can be accessed by array index.
*/
ParamExecData *prm;
prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
if (prm->execPlan != NULL)
{
/* Parameter not evaluated yet, so go do it */
ExecSetParamPlan(prm->execPlan, econtext);
/* ExecSetParamPlan should have processed this param... */
Assert(prm->execPlan == NULL);
}
*isNull = prm->isnull;
return prm->value;
/* Parameter not evaluated yet, so go do it */
ExecSetParamPlan(prm->execPlan, econtext);
/* ExecSetParamPlan should have processed this param... */
Assert(prm->execPlan == NULL);
}
else
*isNull = prm->isnull;
return prm->value;
}
/* ----------------------------------------------------------------
* ExecEvalParamExtern
*
* Returns the value of a PARAM_EXTERN parameter.
* ----------------------------------------------------------------
*/
static Datum
ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
Param *expression = (Param *) exprstate->expr;
int thisParamId = expression->paramid;
ParamListInfo paramInfo = econtext->ecxt_param_list_info;
if (isDone)
*isDone = ExprSingleResult;
/*
* PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
*/
if (paramInfo &&
thisParamId > 0 && thisParamId <= paramInfo->numParams)
{
/*
* PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
*/
ParamListInfo paramInfo = econtext->ecxt_param_list_info;
ParamExternData *prm = &paramInfo->params[thisParamId - 1];
Assert(expression->paramkind == PARAM_EXTERN);
if (paramInfo &&
thisParamId > 0 && thisParamId <= paramInfo->numParams)
/* give hook a chance in case parameter is dynamic */
if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL)
(*paramInfo->paramFetch) (paramInfo, thisParamId);
if (OidIsValid(prm->ptype))
{
ParamExternData *prm = &paramInfo->params[thisParamId - 1];
/* safety check in case hook did something unexpected */
if (prm->ptype != expression->paramtype)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
thisParamId,
format_type_be(prm->ptype),
format_type_be(expression->paramtype))));
/* give hook a chance in case parameter is dynamic */
if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL)
(*paramInfo->paramFetch) (paramInfo, thisParamId);
if (OidIsValid(prm->ptype))
{
/* safety check in case hook did something unexpected */
if (prm->ptype != expression->paramtype)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
thisParamId,
format_type_be(prm->ptype),
format_type_be(expression->paramtype))));
*isNull = prm->isnull;
return prm->value;
}
*isNull = prm->isnull;
return prm->value;
}
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("no value found for parameter %d", thisParamId)));
return (Datum) 0; /* keep compiler quiet */
}
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("no value found for parameter %d", thisParamId)));
return (Datum) 0; /* keep compiler quiet */
}
@ -4228,7 +4237,19 @@ ExecInitExpr(Expr *node, PlanState *parent)
break;
case T_Param:
state = (ExprState *) makeNode(ExprState);
state->evalfunc = ExecEvalParam;
switch (((Param *) node)->paramkind)
{
case PARAM_EXEC:
state->evalfunc = ExecEvalParamExec;
break;
case PARAM_EXTERN:
state->evalfunc = ExecEvalParamExtern;
break;
default:
elog(ERROR, "unrecognized paramkind: %d",
(int) ((Param *) node)->paramkind);
break;
}
break;
case T_CoerceToDomainValue:
state = (ExprState *) makeNode(ExprState);

View File

@ -71,7 +71,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.175 2010/02/26 02:00:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.176 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1886,7 +1886,7 @@ ExecEndAgg(AggState *node)
}
void
ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
ExecReScanAgg(AggState *node)
{
ExprContext *econtext = node->ss.ps.ps_ExprContext;
int aggno;
@ -1911,7 +1911,7 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
* parameter changes, then we can just rescan the existing hash table;
* no need to build it again.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
if (node->ss.ps.lefttree->chgParam == NULL)
{
ResetTupleHashIterator(node->hashtable, &node->hashiter);
return;
@ -1967,8 +1967,8 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ss.ps.lefttree->chgParam == NULL)
ExecReScan(node->ss.ps.lefttree);
}
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeAppend.c,v 1.77 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeAppend.c,v 1.78 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -263,7 +263,7 @@ ExecEndAppend(AppendState *node)
}
void
ExecReScanAppend(AppendState *node, ExprContext *exprCtxt)
ExecReScanAppend(AppendState *node)
{
int i;
@ -280,12 +280,10 @@ ExecReScanAppend(AppendState *node, ExprContext *exprCtxt)
/*
* If chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode. However, if caller is passing us an exprCtxt
* then forcibly rescan all the subnodes now, so that we can pass the
* exprCtxt down to the subnodes (needed for appendrel indexscan).
* first ExecProcNode.
*/
if (subnode->chgParam == NULL || exprCtxt != NULL)
ExecReScan(subnode, exprCtxt);
if (subnode->chgParam == NULL)
ExecReScan(subnode);
}
node->as_whichplan = 0;
exec_append_initialize_next(node);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.13 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.14 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -185,7 +185,7 @@ ExecEndBitmapAnd(BitmapAndState *node)
}
void
ExecReScanBitmapAnd(BitmapAndState *node, ExprContext *exprCtxt)
ExecReScanBitmapAnd(BitmapAndState *node)
{
int i;
@ -201,9 +201,10 @@ ExecReScanBitmapAnd(BitmapAndState *node, ExprContext *exprCtxt)
UpdateChangedParamSet(subnode, node->ps.chgParam);
/*
* Always rescan the inputs immediately, to ensure we can pass down
* any outer tuple that might be used in index quals.
* If chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
ExecReScan(subnode, exprCtxt);
if (subnode->chgParam == NULL)
ExecReScan(subnode);
}
}

View File

@ -21,7 +21,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.38 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.39 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -30,7 +30,7 @@
* ExecBitmapHeapScan scans a relation using bitmap info
* ExecBitmapHeapNext workhorse for above
* ExecInitBitmapHeapScan creates and initializes state info.
* ExecBitmapHeapReScan prepares to rescan the plan.
* ExecReScanBitmapHeapScan prepares to rescan the plan.
* ExecEndBitmapHeapScan releases all storage.
*/
#include "postgres.h"
@ -420,24 +420,12 @@ ExecBitmapHeapScan(BitmapHeapScanState *node)
}
/* ----------------------------------------------------------------
* ExecBitmapHeapReScan(node)
* ExecReScanBitmapHeapScan(node)
* ----------------------------------------------------------------
*/
void
ExecBitmapHeapReScan(BitmapHeapScanState *node, ExprContext *exprCtxt)
ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
{
/*
* If we are being passed an outer tuple, link it into the "regular"
* per-tuple econtext for possible qual eval.
*/
if (exprCtxt != NULL)
{
ExprContext *stdecontext;
stdecontext = node->ss.ps.ps_ExprContext;
stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
}
/* rescan to release any page pin */
heap_rescan(node->ss.ss_currentScanDesc, NULL);
@ -455,10 +443,11 @@ ExecBitmapHeapReScan(BitmapHeapScanState *node, ExprContext *exprCtxt)
ExecScanReScan(&node->ss);
/*
* Always rescan the input immediately, to ensure we can pass down any
* outer tuple that might be used in index quals.
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
ExecReScan(outerPlanState(node), exprCtxt);
if (node->ss.ps.lefttree->chgParam == NULL)
ExecReScan(node->ss.ps.lefttree);
}
/* ----------------------------------------------------------------

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.33 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.34 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,7 +16,7 @@
* INTERFACE ROUTINES
* MultiExecBitmapIndexScan scans a relation using index.
* ExecInitBitmapIndexScan creates and initializes state info.
* ExecBitmapIndexReScan prepares to rescan the plan.
* ExecReScanBitmapIndexScan prepares to rescan the plan.
* ExecEndBitmapIndexScan releases all storage.
*/
#include "postgres.h"
@ -60,7 +60,7 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
if (!node->biss_RuntimeKeysReady &&
(node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
{
ExecReScan((PlanState *) node, NULL);
ExecReScan((PlanState *) node);
doscan = node->biss_RuntimeKeysReady;
}
else
@ -106,39 +106,28 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
}
/* ----------------------------------------------------------------
* ExecBitmapIndexReScan(node)
* ExecReScanBitmapIndexScan(node)
*
* Recalculates the value of the scan keys whose value depends on
* information known at runtime and rescans the indexed relation.
* Recalculates the values of any scan keys whose value depends on
* information known at runtime, then rescans the indexed relation.
* ----------------------------------------------------------------
*/
void
ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
{
ExprContext *econtext;
econtext = node->biss_RuntimeContext; /* context for runtime keys */
if (econtext)
{
/*
* If we are being passed an outer tuple, save it for runtime key
* calc.
*/
if (exprCtxt != NULL)
econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
/*
* Reset the runtime-key context so we don't leak memory as each outer
* tuple is scanned. Note this assumes that we will recalculate *all*
* runtime keys on each call.
*/
ResetExprContext(econtext);
}
ExprContext *econtext = node->biss_RuntimeContext;
/*
* If we are doing runtime key calculations (ie, the index keys depend on
* data from an outer scan), compute the new key values.
* Reset the runtime-key context so we don't leak memory as each outer
* tuple is scanned. Note this assumes that we will recalculate *all*
* runtime keys on each call.
*/
if (econtext)
ResetExprContext(econtext);
/*
* If we are doing runtime key calculations (ie, any of the index key
* values weren't simple Consts), compute the new key values.
*
* Array keys are also treated as runtime keys; note that if we return
* with biss_RuntimeKeysReady still false, then there is an empty array

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapOr.c,v 1.12 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapOr.c,v 1.13 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -201,7 +201,7 @@ ExecEndBitmapOr(BitmapOrState *node)
}
void
ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt)
ExecReScanBitmapOr(BitmapOrState *node)
{
int i;
@ -217,9 +217,10 @@ ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt)
UpdateChangedParamSet(subnode, node->ps.chgParam);
/*
* Always rescan the inputs immediately, to ensure we can pass down
* any outer tuple that might be used in index quals.
* If chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
ExecReScan(subnode, exprCtxt);
if (subnode->chgParam == NULL)
ExecReScan(subnode);
}
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeCtescan.c,v 1.8 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeCtescan.c,v 1.9 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -298,13 +298,13 @@ ExecEndCteScan(CteScanState *node)
}
/* ----------------------------------------------------------------
* ExecCteScanReScan
* ExecReScanCteScan
*
* Rescans the relation.
* ----------------------------------------------------------------
*/
void
ExecCteScanReScan(CteScanState *node, ExprContext *exprCtxt)
ExecReScanCteScan(CteScanState *node)
{
Tuplestorestate *tuplestorestate = node->leader->cte_table;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.55 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.56 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -18,7 +18,7 @@
* ExecFunctionNext retrieve next tuple in sequential order.
* ExecInitFunctionScan creates and initializes a functionscan node.
* ExecEndFunctionScan releases any storage allocated.
* ExecFunctionReScan rescans the function
* ExecReScanFunctionScan rescans the function
*/
#include "postgres.h"
@ -255,13 +255,13 @@ ExecEndFunctionScan(FunctionScanState *node)
}
/* ----------------------------------------------------------------
* ExecFunctionReScan
* ExecReScanFunctionScan
*
* Rescans the relation.
* ----------------------------------------------------------------
*/
void
ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
ExecReScanFunctionScan(FunctionScanState *node)
{
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);

View File

@ -15,7 +15,7 @@
* locate group boundaries.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.77 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.78 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -277,14 +277,18 @@ ExecEndGroup(GroupState *node)
}
void
ExecReScanGroup(GroupState *node, ExprContext *exprCtxt)
ExecReScanGroup(GroupState *node)
{
node->grp_done = FALSE;
node->ss.ps.ps_TupFromTlist = false;
/* must clear first tuple */
ExecClearTuple(node->ss.ss_ScanTupleSlot);
if (((PlanState *) node)->lefttree &&
((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
/*
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (node->ss.ps.lefttree &&
node->ss.ps.lefttree->chgParam == NULL)
ExecReScan(node->ss.ps.lefttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.129 2010/02/26 02:00:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.130 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -961,14 +961,14 @@ ExecHashTableReset(HashJoinTable hashtable)
}
void
ExecReScanHash(HashState *node, ExprContext *exprCtxt)
ExecReScanHash(HashState *node)
{
/*
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ps.lefttree->chgParam == NULL)
ExecReScan(node->ps.lefttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.103 2010/01/02 16:57:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.104 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -842,7 +842,7 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
void
ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
ExecReScanHashJoin(HashJoinState *node)
{
/*
* In a multi-batch join, we currently have to do rescans the hard way,
@ -854,7 +854,7 @@ ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
if (node->hj_HashTable != NULL)
{
if (node->hj_HashTable->nbatch == 1 &&
((PlanState *) node)->righttree->chgParam == NULL)
node->js.ps.righttree->chgParam == NULL)
{
/*
* okay to reuse the hash table; needn't rescan inner, either.
@ -880,8 +880,8 @@ ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned
* by first ExecProcNode.
*/
if (((PlanState *) node)->righttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->righttree, exprCtxt);
if (node->js.ps.righttree->chgParam == NULL)
ExecReScan(node->js.ps.righttree);
}
}
@ -900,6 +900,6 @@ ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->js.ps.lefttree->chgParam == NULL)
ExecReScan(node->js.ps.lefttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.139 2010/02/26 02:00:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.140 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -17,7 +17,7 @@
* ExecIndexScan scans a relation using indices
* ExecIndexNext using index to retrieve next tuple
* ExecInitIndexScan creates and initializes state info.
* ExecIndexReScan rescans the indexed relation.
* ExecReScanIndexScan rescans the indexed relation.
* ExecEndIndexScan releases all storage.
* ExecIndexMarkPos marks scan position.
* ExecIndexRestrPos restores scan position.
@ -141,7 +141,7 @@ ExecIndexScan(IndexScanState *node)
* If we have runtime keys and they've not already been set up, do it now.
*/
if (node->iss_NumRuntimeKeys != 0 && !node->iss_RuntimeKeysReady)
ExecReScan((PlanState *) node, NULL);
ExecReScan((PlanState *) node);
return ExecScan(&node->ss,
(ExecScanAccessMtd) IndexNext,
@ -149,54 +149,35 @@ ExecIndexScan(IndexScanState *node)
}
/* ----------------------------------------------------------------
* ExecIndexReScan(node)
* ExecReScanIndexScan(node)
*
* Recalculates the values of any scan keys whose value depends on
* information known at runtime, then rescans the indexed relation.
*
* Recalculates the value of the scan keys whose value depends on
* information known at runtime and rescans the indexed relation.
* Updating the scan key was formerly done separately in
* ExecUpdateIndexScanKeys. Integrating it into ReScan makes
* rescans of indices and relations/general streams more uniform.
* ----------------------------------------------------------------
*/
void
ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
ExecReScanIndexScan(IndexScanState *node)
{
ExprContext *econtext;
econtext = node->iss_RuntimeContext; /* context for runtime keys */
if (econtext)
{
/*
* If we are being passed an outer tuple, save it for runtime key
* calc. We also need to link it into the "regular" per-tuple
* econtext, so it can be used during indexqualorig evaluations.
*/
if (exprCtxt != NULL)
{
ExprContext *stdecontext;
econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
stdecontext = node->ss.ps.ps_ExprContext;
stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
}
/*
* Reset the runtime-key context so we don't leak memory as each outer
* tuple is scanned. Note this assumes that we will recalculate *all*
* runtime keys on each call.
*/
ResetExprContext(econtext);
}
/*
* If we are doing runtime key calculations (ie, the index keys depend on
* data from an outer scan), compute the new key values
* If we are doing runtime key calculations (ie, any of the index key
* values weren't simple Consts), compute the new key values. But first,
* reset the context so we don't leak memory as each outer tuple is
* scanned. Note this assumes that we will recalculate *all* runtime keys
* on each call.
*/
if (node->iss_NumRuntimeKeys != 0)
{
ExprContext *econtext = node->iss_RuntimeContext;
ResetExprContext(econtext);
ExecIndexEvalRuntimeKeys(econtext,
node->iss_RuntimeKeys,
node->iss_NumRuntimeKeys);
}
node->iss_RuntimeKeysReady = true;
/* reset index scan */
@ -229,11 +210,11 @@ ExecIndexEvalRuntimeKeys(ExprContext *econtext,
/*
* For each run-time key, extract the run-time expression and evaluate
* it with respect to the current outer tuple. We then stick the
* result into the proper scan key.
* it with respect to the current context. We then stick the result
* into the proper scan key.
*
* Note: the result of the eval could be a pass-by-ref value that's
* stored in the outer scan's tuple, not in
* stored in some outer scan's tuple, not in
* econtext->ecxt_per_tuple_memory. We assume that the outer tuple
* will stay put throughout our scan. If this is wrong, we could copy
* the result into our context explicitly, but I think that's not

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.41 2010/01/02 16:57:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.42 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -404,7 +404,7 @@ ExecEndLimit(LimitState *node)
void
ExecReScanLimit(LimitState *node, ExprContext *exprCtxt)
ExecReScanLimit(LimitState *node)
{
/*
* Recompute limit/offset in case parameters changed, and reset the state
@ -417,6 +417,6 @@ ExecReScanLimit(LimitState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ps.lefttree->chgParam == NULL)
ExecReScan(node->ps.lefttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeLockRows.c,v 1.4 2010/02/26 02:00:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeLockRows.c,v 1.5 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -339,12 +339,12 @@ ExecEndLockRows(LockRowsState *node)
void
ExecReScanLockRows(LockRowsState *node, ExprContext *exprCtxt)
ExecReScanLockRows(LockRowsState *node)
{
/*
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ps.lefttree->chgParam == NULL)
ExecReScan(node->ps.lefttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.71 2010/01/02 16:57:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.72 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -309,22 +309,22 @@ ExecMaterialRestrPos(MaterialState *node)
}
/* ----------------------------------------------------------------
* ExecMaterialReScan
* ExecReScanMaterial
*
* Rescans the materialized relation.
* ----------------------------------------------------------------
*/
void
ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
ExecReScanMaterial(MaterialState *node)
{
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
if (node->eflags != 0)
{
/*
* If we haven't materialized yet, just return. If outerplan' chgParam
* is not NULL then it will be re-scanned by ExecProcNode, else - no
* reason to re-scan it at all.
* If we haven't materialized yet, just return. If outerplan's
* chgParam is not NULL then it will be re-scanned by ExecProcNode,
* else no reason to re-scan it at all.
*/
if (!node->tuplestorestate)
return;
@ -339,13 +339,13 @@ ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
* Otherwise we can just rewind and rescan the stored output. The
* state of the subnode does not change.
*/
if (((PlanState *) node)->lefttree->chgParam != NULL ||
if (node->ss.ps.lefttree->chgParam != NULL ||
(node->eflags & EXEC_FLAG_REWIND) == 0)
{
tuplestore_end(node->tuplestorestate);
node->tuplestorestate = NULL;
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ss.ps.lefttree->chgParam == NULL)
ExecReScan(node->ss.ps.lefttree);
node->eof_underlying = false;
}
else
@ -359,8 +359,8 @@ ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ss.ps.lefttree->chgParam == NULL)
ExecReScan(node->ss.ps.lefttree);
node->eof_underlying = false;
}
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.103 2010/07/06 19:18:56 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.104 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1680,7 +1680,7 @@ ExecEndMergeJoin(MergeJoinState *node)
}
void
ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt)
ExecReScanMergeJoin(MergeJoinState *node)
{
ExecClearTuple(node->mj_MarkedTupleSlot);
@ -1695,9 +1695,9 @@ ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt)
* if chgParam of subnodes is not null then plans will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (((PlanState *) node)->righttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->righttree, exprCtxt);
if (node->js.ps.lefttree->chgParam == NULL)
ExecReScan(node->js.ps.lefttree);
if (node->js.ps.righttree->chgParam == NULL)
ExecReScan(node->js.ps.righttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeModifyTable.c,v 1.7 2010/02/26 02:00:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeModifyTable.c,v 1.8 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1045,7 +1045,7 @@ ExecEndModifyTable(ModifyTableState *node)
}
void
ExecReScanModifyTable(ModifyTableState *node, ExprContext *exprCtxt)
ExecReScanModifyTable(ModifyTableState *node)
{
/*
* Currently, we don't need to support rescan on ModifyTable nodes. The

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeNestloop.c,v 1.55 2010/01/02 16:57:44 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeNestloop.c,v 1.56 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -59,6 +59,7 @@
TupleTableSlot *
ExecNestLoop(NestLoopState *node)
{
NestLoop *nl;
PlanState *innerPlan;
PlanState *outerPlan;
TupleTableSlot *outerTupleSlot;
@ -66,12 +67,14 @@ ExecNestLoop(NestLoopState *node)
List *joinqual;
List *otherqual;
ExprContext *econtext;
ListCell *lc;
/*
* get information from the node
*/
ENL1_printf("getting info from node");
nl = (NestLoop *) node->js.ps.plan;
joinqual = node->js.joinqual;
otherqual = node->js.ps.qual;
outerPlan = outerPlanState(node);
@ -133,17 +136,34 @@ ExecNestLoop(NestLoopState *node)
node->nl_NeedNewOuter = false;
node->nl_MatchedOuter = false;
/*
* fetch the values of any outer Vars that must be passed to
* the inner scan, and store them in the appropriate PARAM_EXEC
* slots.
*/
foreach(lc, nl->nestParams)
{
NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
int paramno = nlp->paramno;
ParamExecData *prm;
prm = &(econtext->ecxt_param_exec_vals[paramno]);
/* Param value should be an OUTER var */
Assert(nlp->paramval->varno == OUTER);
Assert(nlp->paramval->varattno > 0);
prm->value = slot_getattr(outerTupleSlot,
nlp->paramval->varattno,
&(prm->isnull));
/* Flag parameter value as changed */
innerPlan->chgParam = bms_add_member(innerPlan->chgParam,
paramno);
}
/*
* now rescan the inner plan
*/
ENL1_printf("rescanning inner plan");
/*
* The scan key of the inner plan might depend on the current
* outer tuple (e.g. in index scans), that's why we pass our expr
* context.
*/
ExecReScan(innerPlan, econtext);
ExecReScan(innerPlan);
}
/*
@ -308,15 +328,18 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
/*
* initialize child nodes
*
* Tell the inner child that cheap rescans would be good. (This is
* unnecessary if we are doing nestloop with inner indexscan, because the
* rescan will always be with a fresh parameter --- but since
* nodeIndexscan doesn't actually care about REWIND, there's no point in
* dealing with that refinement.)
* If we have no parameters to pass into the inner rel from the outer,
* tell the inner child that cheap rescans would be good. If we do have
* such parameters, then there is no point in REWIND support at all in
* the inner child, because it will always be rescanned with fresh
* parameter values.
*/
outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate, eflags);
innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate,
eflags | EXEC_FLAG_REWIND);
if (node->nestParams == NIL)
eflags |= EXEC_FLAG_REWIND;
else
eflags &= ~EXEC_FLAG_REWIND;
innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate, eflags);
/*
* tuple table initialization
@ -395,18 +418,22 @@ ExecEndNestLoop(NestLoopState *node)
* ----------------------------------------------------------------
*/
void
ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt)
ExecReScanNestLoop(NestLoopState *node)
{
PlanState *outerPlan = outerPlanState(node);
/*
* If outerPlan->chgParam is not null then plan will be automatically
* re-scanned by first ExecProcNode. innerPlan is re-scanned for each new
* outer tuple and MUST NOT be re-scanned from here or you'll get troubles
* from inner index scans when outer Vars are used as run-time keys...
* re-scanned by first ExecProcNode.
*/
if (outerPlan->chgParam == NULL)
ExecReScan(outerPlan, exprCtxt);
ExecReScan(outerPlan);
/*
* innerPlan is re-scanned for each new outer tuple and MUST NOT be
* re-scanned from here or you'll get troubles from inner index scans when
* outer Vars are used as run-time keys...
*/
node->js.ps.ps_TupFromTlist = false;
node->nl_NeedNewOuter = true;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeRecursiveunion.c,v 1.6 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeRecursiveunion.c,v 1.7 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -299,13 +299,13 @@ ExecEndRecursiveUnion(RecursiveUnionState *node)
}
/* ----------------------------------------------------------------
* ExecRecursiveUnionReScan
* ExecReScanRecursiveUnion
*
* Rescans the relation.
* ----------------------------------------------------------------
*/
void
ExecRecursiveUnionReScan(RecursiveUnionState *node, ExprContext *exprCtxt)
ExecReScanRecursiveUnion(RecursiveUnionState *node)
{
PlanState *outerPlan = outerPlanState(node);
PlanState *innerPlan = innerPlanState(node);
@ -323,7 +323,7 @@ ExecRecursiveUnionReScan(RecursiveUnionState *node, ExprContext *exprCtxt)
* non-recursive term.
*/
if (outerPlan->chgParam == NULL)
ExecReScan(outerPlan, exprCtxt);
ExecReScan(outerPlan);
/* Release any hashtable storage */
if (node->tableContext)

View File

@ -38,7 +38,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeResult.c,v 1.45 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeResult.c,v 1.46 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -292,7 +292,7 @@ ExecEndResult(ResultState *node)
}
void
ExecReScanResult(ResultState *node, ExprContext *exprCtxt)
ExecReScanResult(ResultState *node)
{
node->rs_done = false;
node->ps.ps_TupFromTlist = false;
@ -300,11 +300,9 @@ ExecReScanResult(ResultState *node, ExprContext *exprCtxt)
/*
* If chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode. However, if caller is passing us an exprCtxt then
* forcibly rescan the subnode now, so that we can pass the exprCtxt down
* to the subnode (needed for gated indexscan).
* first ExecProcNode.
*/
if (node->ps.lefttree &&
(node->ps.lefttree->chgParam == NULL || exprCtxt != NULL))
ExecReScan(node->ps.lefttree, exprCtxt);
node->ps.lefttree->chgParam == NULL)
ExecReScan(node->ps.lefttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeSeqscan.c,v 1.70 2010/02/26 02:00:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeSeqscan.c,v 1.71 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -18,7 +18,7 @@
* ExecSeqNext retrieve next tuple in sequential order.
* ExecInitSeqScan creates and initializes a seqscan node.
* ExecEndSeqScan releases any storage allocated.
* ExecSeqReScan rescans the relation
* ExecReScanSeqScan rescans the relation
* ExecSeqMarkPos marks scan position
* ExecSeqRestrPos restores scan position
*/
@ -255,13 +255,13 @@ ExecEndSeqScan(SeqScanState *node)
*/
/* ----------------------------------------------------------------
* ExecSeqReScan
* ExecReScanSeqScan
*
* Rescans the relation.
* ----------------------------------------------------------------
*/
void
ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt)
ExecReScanSeqScan(SeqScanState *node)
{
HeapScanDesc scan;

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeSetOp.c,v 1.33 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeSetOp.c,v 1.34 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -597,7 +597,7 @@ ExecEndSetOp(SetOpState *node)
void
ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt)
ExecReScanSetOp(SetOpState *node)
{
ExecClearTuple(node->ps.ps_ResultTupleSlot);
node->setop_done = false;
@ -619,7 +619,7 @@ ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt)
* parameter changes, then we can just rescan the existing hash table;
* no need to build it again.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
if (node->ps.lefttree->chgParam == NULL)
{
ResetTupleHashIterator(node->hashtable, &node->hashiter);
return;
@ -648,6 +648,6 @@ ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ps.lefttree->chgParam == NULL)
ExecReScan(node->ps.lefttree);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeSort.c,v 1.67 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeSort.c,v 1.68 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -287,11 +287,11 @@ ExecSortRestrPos(SortState *node)
}
void
ExecReScanSort(SortState *node, ExprContext *exprCtxt)
ExecReScanSort(SortState *node)
{
/*
* If we haven't sorted yet, just return. If outerplan' chgParam is not
* NULL then it will be re-scanned by ExecProcNode, else - no reason to
* If we haven't sorted yet, just return. If outerplan's chgParam is not
* NULL then it will be re-scanned by ExecProcNode, else no reason to
* re-scan it at all.
*/
if (!node->sort_Done)
@ -307,7 +307,7 @@ ExecReScanSort(SortState *node, ExprContext *exprCtxt)
*
* Otherwise we can just rewind and rescan the sorted output.
*/
if (((PlanState *) node)->lefttree->chgParam != NULL ||
if (node->ss.ps.lefttree->chgParam != NULL ||
node->bounded != node->bounded_Done ||
node->bound != node->bound_Done ||
!node->randomAccess)
@ -320,8 +320,8 @@ ExecReScanSort(SortState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ss.ps.lefttree->chgParam == NULL)
ExecReScan(node->ss.ps.lefttree);
}
else
tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.101 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.102 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -256,7 +256,7 @@ ExecScanSubPlan(SubPlanState *node,
/*
* Now that we've set up its parameters, we can reset the subplan.
*/
ExecReScan(planstate, NULL);
ExecReScan(planstate);
/*
* For all sublink types except EXPR_SUBLINK and ARRAY_SUBLINK, the result
@ -508,7 +508,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
/*
* Reset subplan to start.
*/
ExecReScan(planstate, NULL);
ExecReScan(planstate);
/*
* Scan the subplan and load the hash table(s). Note that when there are
@ -884,7 +884,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
*
* Executes an InitPlan subplan and sets its output parameters.
*
* This is called from ExecEvalParam() when the value of a PARAM_EXEC
* This is called from ExecEvalParamExec() when the value of a PARAM_EXEC
* parameter is requested and the param's execPlan field is set (indicating
* that the param has not yet been evaluated). This allows lazy evaluation
* of initplans: we don't run the subplan until/unless we need its output.

View File

@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.45 2010/02/26 02:00:42 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.46 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -22,7 +22,7 @@
* ExecSubqueryNext retrieve next tuple in sequential order.
* ExecInitSubqueryScan creates and initializes a subqueryscan node.
* ExecEndSubqueryScan releases any storage allocated.
* ExecSubqueryReScan rescans the relation
* ExecReScanSubqueryScan rescans the relation
*
*/
#include "postgres.h"
@ -187,13 +187,13 @@ ExecEndSubqueryScan(SubqueryScanState *node)
}
/* ----------------------------------------------------------------
* ExecSubqueryReScan
* ExecReScanSubqueryScan
*
* Rescans the relation.
* ----------------------------------------------------------------
*/
void
ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
ExecReScanSubqueryScan(SubqueryScanState *node)
{
ExecScanReScan(&node->ss);
@ -210,5 +210,5 @@ ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
* first ExecProcNode.
*/
if (node->subplan->chgParam == NULL)
ExecReScan(node->subplan, NULL);
ExecReScan(node->subplan);
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.65 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.66 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -17,7 +17,7 @@
*
* ExecTidScan scans a relation using tids
* ExecInitTidScan creates and initializes state info.
* ExecTidReScan rescans the tid relation.
* ExecReScanTidScan rescans the tid relation.
* ExecEndTidScan releases all storage.
* ExecTidMarkPos marks scan position.
* ExecTidRestrPos restores scan position.
@ -398,17 +398,12 @@ ExecTidScan(TidScanState *node)
}
/* ----------------------------------------------------------------
* ExecTidReScan(node)
* ExecReScanTidScan(node)
* ----------------------------------------------------------------
*/
void
ExecTidReScan(TidScanState *node, ExprContext *exprCtxt)
ExecReScanTidScan(TidScanState *node)
{
/* If we are being passed an outer tuple, save it for runtime key calc */
if (exprCtxt != NULL)
node->ss.ps.ps_ExprContext->ecxt_outertuple =
exprCtxt->ecxt_outertuple;
if (node->tss_TidList)
pfree(node->tss_TidList);
node->tss_TidList = NULL;

View File

@ -16,7 +16,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeUnique.c,v 1.63 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeUnique.c,v 1.64 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -184,7 +184,7 @@ ExecEndUnique(UniqueState *node)
void
ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
ExecReScanUnique(UniqueState *node)
{
/* must clear result tuple so first input tuple is returned */
ExecClearTuple(node->ps.ps_ResultTupleSlot);
@ -193,6 +193,6 @@ ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ps.lefttree->chgParam == NULL)
ExecReScan(node->ps.lefttree);
}

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.12 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.13 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,7 +19,7 @@
* ExecValuesNext retrieve next tuple in sequential order.
* ExecInitValuesScan creates and initializes a valuesscan node.
* ExecEndValuesScan releases any storage allocated.
* ExecValuesReScan rescans the values list
* ExecReScanValuesScan rescans the values list
*/
#include "postgres.h"
@ -319,13 +319,13 @@ ExecValuesRestrPos(ValuesScanState *node)
}
/* ----------------------------------------------------------------
* ExecValuesReScan
* ExecReScanValuesScan
*
* Rescans the relation.
* ----------------------------------------------------------------
*/
void
ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt)
ExecReScanValuesScan(ValuesScanState *node)
{
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);

View File

@ -27,7 +27,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeWindowAgg.c,v 1.13 2010/03/21 00:17:58 petere Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeWindowAgg.c,v 1.14 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1664,7 +1664,7 @@ ExecEndWindowAgg(WindowAggState *node)
* -----------------
*/
void
ExecReScanWindowAgg(WindowAggState *node, ExprContext *exprCtxt)
ExecReScanWindowAgg(WindowAggState *node)
{
ExprContext *econtext = node->ss.ps.ps_ExprContext;
@ -1691,8 +1691,8 @@ ExecReScanWindowAgg(WindowAggState *node, ExprContext *exprCtxt)
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
if (node->ss.ps.lefttree->chgParam == NULL)
ExecReScan(node->ss.ps.lefttree);
}
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeWorktablescan.c,v 1.10 2010/01/02 16:57:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/nodeWorktablescan.c,v 1.11 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -203,13 +203,13 @@ ExecEndWorkTableScan(WorkTableScanState *node)
}
/* ----------------------------------------------------------------
* ExecWorkTableScanReScan
* ExecReScanWorkTableScan
*
* Rescans the relation.
* ----------------------------------------------------------------
*/
void
ExecWorkTableScanReScan(WorkTableScanState *node, ExprContext *exprCtxt)
ExecReScanWorkTableScan(WorkTableScanState *node)
{
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.464 2010/02/26 02:00:43 momjian Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.465 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -564,6 +564,11 @@ _copyNestLoop(NestLoop *from)
*/
CopyJoinFields((Join *) from, (Join *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(nestParams);
return newnode;
}
@ -844,6 +849,20 @@ _copyLimit(Limit *from)
return newnode;
}
/*
* _copyNestLoopParam
*/
static NestLoopParam *
_copyNestLoopParam(NestLoopParam *from)
{
NestLoopParam *newnode = makeNode(NestLoopParam);
COPY_SCALAR_FIELD(paramno);
COPY_NODE_FIELD(paramval);
return newnode;
}
/*
* _copyPlanRowMark
*/
@ -3671,6 +3690,9 @@ copyObject(void *from)
case T_Limit:
retval = _copyLimit(from);
break;
case T_NestLoopParam:
retval = _copyNestLoopParam(from);
break;
case T_PlanRowMark:
retval = _copyPlanRowMark(from);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.385 2010/03/30 21:58:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.386 2010/07/12 17:01:05 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@ -517,6 +517,8 @@ _outNestLoop(StringInfo str, NestLoop *node)
WRITE_NODE_TYPE("NESTLOOP");
_outJoinPlanInfo(str, (Join *) node);
WRITE_NODE_FIELD(nestParams);
}
static void
@ -748,6 +750,15 @@ _outLimit(StringInfo str, Limit *node)
WRITE_NODE_FIELD(limitCount);
}
static void
_outNestLoopParam(StringInfo str, NestLoopParam *node)
{
WRITE_NODE_TYPE("NESTLOOPPARAM");
WRITE_INT_FIELD(paramno);
WRITE_NODE_FIELD(paramval);
}
static void
_outPlanRowMark(StringInfo str, PlanRowMark *node)
{
@ -1565,6 +1576,8 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node)
WRITE_BOOL_FIELD(hasPseudoConstantQuals);
WRITE_BOOL_FIELD(hasRecursion);
WRITE_INT_FIELD(wt_param_id);
WRITE_BITMAPSET_FIELD(curOuterRels);
WRITE_NODE_FIELD(curOuterParams);
}
static void
@ -2562,6 +2575,9 @@ _outNode(StringInfo str, void *obj)
case T_Limit:
_outLimit(str, obj);
break;
case T_NestLoopParam:
_outNestLoopParam(str, obj);
break;
case T_PlanRowMark:
_outPlanRowMark(str, obj);
break;

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.275 2010/05/25 17:44:41 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.276 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -28,6 +28,7 @@
#include "optimizer/planmain.h"
#include "optimizer/predtest.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/subselect.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h"
#include "parser/parse_clause.h"
@ -35,6 +36,7 @@
#include "utils/lsyscache.h"
static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path);
static Plan *create_scan_plan(PlannerInfo *root, Path *best_path);
static List *build_relation_tlist(RelOptInfo *rel);
static bool use_physical_tlist(PlannerInfo *root, RelOptInfo *rel);
@ -72,7 +74,10 @@ static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,
Plan *outer_plan, Plan *inner_plan);
static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path,
Plan *outer_plan, Plan *inner_plan);
static List *fix_indexqual_references(List *indexquals, IndexPath *index_path);
static Node *replace_nestloop_params(PlannerInfo *root, Node *expr);
static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root);
static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
List *indexquals);
static List *get_switched_clauses(List *clauses, Relids outerrelids);
static List *order_qual_clauses(PlannerInfo *root, List *clauses);
static void copy_path_costsize(Plan *dest, Path *src);
@ -103,7 +108,7 @@ static WorkTableScan *make_worktablescan(List *qptlist, List *qpqual,
static BitmapAnd *make_bitmap_and(List *bitmapplans);
static BitmapOr *make_bitmap_or(List *bitmapplans);
static NestLoop *make_nestloop(List *tlist,
List *joinclauses, List *otherclauses,
List *joinclauses, List *otherclauses, List *nestParams,
Plan *lefttree, Plan *righttree,
JoinType jointype);
static HashJoin *make_hashjoin(List *tlist,
@ -133,8 +138,8 @@ static Material *make_material(Plan *lefttree);
/*
* create_plan
* Creates the access plan for a query by tracing backwards through the
* desired chain of pathnodes, starting at the node 'best_path'. For
* Creates the access plan for a query by recursively processing the
* desired tree of pathnodes, starting at the node 'best_path'. For
* every pathnode found, we create a corresponding plan node containing
* appropriate id, target list, and qualification information.
*
@ -151,6 +156,29 @@ create_plan(PlannerInfo *root, Path *best_path)
{
Plan *plan;
/* Initialize this module's private workspace in PlannerInfo */
root->curOuterRels = NULL;
root->curOuterParams = NIL;
/* Recursively process the path tree */
plan = create_plan_recurse(root, best_path);
/* Check we successfully assigned all NestLoopParams to plan nodes */
if (root->curOuterParams != NIL)
elog(ERROR, "failed to assign all NestLoopParams to plan nodes");
return plan;
}
/*
* create_plan_recurse
* Recursive guts of create_plan().
*/
static Plan *
create_plan_recurse(PlannerInfo *root, Path *best_path)
{
Plan *plan;
switch (best_path->pathtype)
{
case T_SeqScan:
@ -477,9 +505,16 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path)
Plan *outer_plan;
Plan *inner_plan;
Plan *plan;
Relids saveOuterRels = root->curOuterRels;
outer_plan = create_plan(root, best_path->outerjoinpath);
inner_plan = create_plan(root, best_path->innerjoinpath);
outer_plan = create_plan_recurse(root, best_path->outerjoinpath);
/* For a nestloop, include outer relids in curOuterRels for inner side */
if (best_path->path.pathtype == T_NestLoop)
root->curOuterRels = bms_union(root->curOuterRels,
best_path->outerjoinpath->parent->relids);
inner_plan = create_plan_recurse(root, best_path->innerjoinpath);
switch (best_path->path.pathtype)
{
@ -496,6 +531,10 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path)
inner_plan);
break;
case T_NestLoop:
/* Restore curOuterRels */
bms_free(root->curOuterRels);
root->curOuterRels = saveOuterRels;
plan = (Plan *) create_nestloop_plan(root,
(NestPath *) best_path,
outer_plan,
@ -571,7 +610,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path)
{
Path *subpath = (Path *) lfirst(subpaths);
subplans = lappend(subplans, create_plan(root, subpath));
subplans = lappend(subplans, create_plan_recurse(root, subpath));
}
plan = make_append(subplans, tlist);
@ -616,7 +655,7 @@ create_material_plan(PlannerInfo *root, MaterialPath *best_path)
Material *plan;
Plan *subplan;
subplan = create_plan(root, best_path->subpath);
subplan = create_plan_recurse(root, best_path->subpath);
/* We don't want any excess columns in the materialized tuples */
disuse_physical_tlist(subplan, best_path->subpath);
@ -650,7 +689,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
int groupColPos;
ListCell *l;
subplan = create_plan(root, best_path->subpath);
subplan = create_plan_recurse(root, best_path->subpath);
/* Done if we don't need to do any actual unique-ifying */
if (best_path->umethod == UNIQUE_PATH_NOOP)
@ -904,7 +943,7 @@ create_indexscan_plan(PlannerInfo *root,
* The executor needs a copy with the indexkey on the left of each clause
* and with index attr numbers substituted for table ones.
*/
fixed_indexquals = fix_indexqual_references(indexquals, best_path);
fixed_indexquals = fix_indexqual_references(root, best_path, indexquals);
/*
* If this is an innerjoin scan, the indexclauses will contain join
@ -975,6 +1014,22 @@ create_indexscan_plan(PlannerInfo *root,
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
qpqual = extract_actual_clauses(qpqual, false);
/*
* We have to replace any outer-relation variables with nestloop params
* in the indexqualorig and qpqual expressions. A bit annoying to have to
* do this separately from the processing in fix_indexqual_references ---
* rethink this when generalizing the inner indexscan support. But note
* we can't really do this earlier because it'd break the comparisons to
* predicates above ... (or would it? Those wouldn't have outer refs)
*/
if (best_path->isjoininner)
{
stripped_indexquals = (List *)
replace_nestloop_params(root, (Node *) stripped_indexquals);
qpqual = (List *)
replace_nestloop_params(root, (Node *) qpqual);
}
/* Finally ready to build the plan node */
scan_plan = make_indexscan(tlist,
qpqual,
@ -1267,6 +1322,17 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
*indexqual = lappend(*indexqual, pred);
}
}
/*
* Replace outer-relation variables with nestloop params, but only
* after doing the above comparisons to index predicates.
*/
if (ipath->isjoininner)
{
*qual = (List *)
replace_nestloop_params(root, (Node *) *qual);
*indexqual = (List *)
replace_nestloop_params(root, (Node *) *indexqual);
}
}
else
{
@ -1572,11 +1638,16 @@ create_nestloop_plan(PlannerInfo *root,
Plan *outer_plan,
Plan *inner_plan)
{
NestLoop *join_plan;
List *tlist = build_relation_tlist(best_path->path.parent);
List *joinrestrictclauses = best_path->joinrestrictinfo;
List *joinclauses;
List *otherclauses;
NestLoop *join_plan;
Relids outerrelids;
List *nestParams;
ListCell *cell;
ListCell *prev;
ListCell *next;
/*
* If the inner path is a nestloop inner indexscan, it might be using some
@ -1605,9 +1676,32 @@ create_nestloop_plan(PlannerInfo *root,
otherclauses = NIL;
}
/*
* Identify any nestloop parameters that should be supplied by this join
* node, and move them from root->curOuterParams to the nestParams list.
*/
outerrelids = best_path->outerjoinpath->parent->relids;
nestParams = NIL;
prev = NULL;
for (cell = list_head(root->curOuterParams); cell; cell = next)
{
NestLoopParam *nlp = (NestLoopParam *) lfirst(cell);
next = lnext(cell);
if (bms_is_member(nlp->paramval->varno, outerrelids))
{
root->curOuterParams = list_delete_cell(root->curOuterParams,
cell, prev);
nestParams = lappend(nestParams, nlp);
}
else
prev = cell;
}
join_plan = make_nestloop(tlist,
joinclauses,
otherclauses,
nestParams,
outer_plan,
inner_plan,
best_path->jointype);
@ -2015,13 +2109,73 @@ create_hashjoin_plan(PlannerInfo *root,
*
*****************************************************************************/
/*
* replace_nestloop_params
* Replace outer-relation Vars in the given expression with nestloop Params
*
* All Vars belonging to the relation(s) identified by root->curOuterRels
* are replaced by Params, and entries are added to root->curOuterParams if
* not already present.
*/
static Node *
replace_nestloop_params(PlannerInfo *root, Node *expr)
{
/* No setup needed for tree walk, so away we go */
return replace_nestloop_params_mutator(expr, root);
}
static Node *
replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
{
if (node == NULL)
return NULL;
if (IsA(node, Var))
{
Var *var = (Var *) node;
Param *param;
NestLoopParam *nlp;
ListCell *lc;
/* Upper-level Vars should be long gone at this point */
Assert(var->varlevelsup == 0);
/* If not to be replaced, we can just return the Var unmodified */
if (!bms_is_member(var->varno, root->curOuterRels))
return node;
/* Create a Param representing the Var */
param = assign_nestloop_param(root, var);
/* Is this param already listed in root->curOuterParams? */
foreach(lc, root->curOuterParams)
{
nlp = (NestLoopParam *) lfirst(lc);
if (nlp->paramno == param->paramid)
{
Assert(equal(var, nlp->paramval));
/* Present, so we can just return the Param */
return (Node *) param;
}
}
/* No, so add it */
nlp = makeNode(NestLoopParam);
nlp->paramno = param->paramid;
nlp->paramval = var;
root->curOuterParams = lappend(root->curOuterParams, nlp);
/* And return the replacement Param */
return (Node *) param;
}
return expression_tree_mutator(node,
replace_nestloop_params_mutator,
(void *) root);
}
/*
* fix_indexqual_references
* Adjust indexqual clauses to the form the executor's indexqual
* machinery needs.
*
* We have three tasks here:
* We have four tasks here:
* * Remove RestrictInfo nodes from the input clauses.
* * Replace any outer-relation Var nodes with nestloop Params.
* (XXX eventually, that responsibility should go elsewhere?)
* * Index keys must be represented by Var nodes with varattno set to the
* index's attribute number, not the attribute number in the original rel.
* * If the index key is on the right, commute the clause to put it on the
@ -2033,7 +2187,8 @@ create_hashjoin_plan(PlannerInfo *root,
* two separate copies of the subplan tree, or things will go awry).
*/
static List *
fix_indexqual_references(List *indexquals, IndexPath *index_path)
fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
List *indexquals)
{
IndexOptInfo *index = index_path->indexinfo;
List *fixed_indexquals;
@ -2041,26 +2196,20 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path)
fixed_indexquals = NIL;
/*
* For each qual clause, commute if needed to put the indexkey operand on
* the left, and then fix its varattno. (We do not need to change the
* other side of the clause.)
*/
foreach(l, indexquals)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
Expr *clause;
Node *clause;
Assert(IsA(rinfo, RestrictInfo));
/*
* Make a copy that will become the fixed clause.
* Replace any outer-relation variables with nestloop params.
*
* We used to try to do a shallow copy here, but that fails if there
* is a subplan in the arguments of the opclause. So just do a full
* copy.
* This also makes a copy of the clause, so it's safe to modify it
* in-place below.
*/
clause = (Expr *) copyObject((Node *) rinfo->clause);
clause = replace_nestloop_params(root, (Node *) rinfo->clause);
if (IsA(clause, OpExpr))
{
@ -2765,6 +2914,7 @@ static NestLoop *
make_nestloop(List *tlist,
List *joinclauses,
List *otherclauses,
List *nestParams,
Plan *lefttree,
Plan *righttree,
JoinType jointype)
@ -2779,6 +2929,7 @@ make_nestloop(List *tlist,
plan->righttree = righttree;
node->join.jointype = jointype;
node->join.joinqual = joinclauses;
node->nestParams = nestParams;
return node;
}

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.160 2010/02/26 02:00:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.161 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -89,8 +89,6 @@ static Node *fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset);
static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset);
static void set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan,
indexed_tlist *outer_itlist);
static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset);
static void set_dummy_tlist_references(Plan *plan, int rtoffset);
static indexed_tlist *build_tlist_index(List *tlist);
@ -878,12 +876,11 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Assert(var->varlevelsup == 0);
/*
* We should not see any Vars marked INNER, but in a nestloop inner
* scan there could be OUTER Vars. Leave them alone.
* We should not see any Vars marked INNER or OUTER.
*/
Assert(var->varno != INNER);
if (var->varno > 0 && var->varno != OUTER)
var->varno += context->rtoffset;
Assert(var->varno != OUTER);
var->varno += context->rtoffset;
if (var->varnoold > 0)
var->varnoold += context->rtoffset;
return (Node *) var;
@ -927,10 +924,6 @@ fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
* values to the result domain number of either the corresponding outer
* or inner join tuple item. Also perform opcode lookup for these
* expressions. and add regclass OIDs to glob->relationOids.
*
* In the case of a nestloop with inner indexscan, we will also need to
* apply the same transformation to any outer vars appearing in the
* quals of the child indexscan. set_inner_join_references does that.
*/
static void
set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
@ -966,8 +959,18 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
/* Now do join-type-specific stuff */
if (IsA(join, NestLoop))
{
/* This processing is split out to handle possible recursion */
set_inner_join_references(glob, inner_plan, outer_itlist);
NestLoop *nl = (NestLoop *) join;
ListCell *lc;
foreach(lc, nl->nestParams)
{
NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
nlp->paramval = (Var *) fix_upper_expr(glob,
(Node *) nlp->paramval,
outer_itlist,
rtoffset);
}
}
else if (IsA(join, MergeJoin))
{
@ -996,193 +999,6 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
pfree(inner_itlist);
}
/*
* set_inner_join_references
* Handle join references appearing in an inner indexscan's quals
*
* To handle bitmap-scan plan trees, we have to be able to recurse down
* to the bottom BitmapIndexScan nodes; likewise, appendrel indexscans
* require recursing through Append nodes. This is split out as a separate
* function so that it can recurse.
*
* Note we do *not* apply any rtoffset for non-join Vars; this is because
* the quals will be processed again by fix_scan_expr when the set_plan_refs
* recursion reaches the inner indexscan, and so we'd have done it twice.
*/
static void
set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan,
indexed_tlist *outer_itlist)
{
if (IsA(inner_plan, IndexScan))
{
/*
* An index is being used to reduce the number of tuples scanned in
* the inner relation. If there are join clauses being used with the
* index, we must update their outer-rel var nodes to refer to the
* outer side of the join.
*/
IndexScan *innerscan = (IndexScan *) inner_plan;
List *indexqualorig = innerscan->indexqualorig;
/* No work needed if indexqual refers only to its own rel... */
if (NumRelids((Node *) indexqualorig) > 1)
{
Index innerrel = innerscan->scan.scanrelid;
/* only refs to outer vars get changed in the inner qual */
innerscan->indexqualorig = fix_join_expr(glob,
indexqualorig,
outer_itlist,
NULL,
innerrel,
0);
innerscan->indexqual = fix_join_expr(glob,
innerscan->indexqual,
outer_itlist,
NULL,
innerrel,
0);
/*
* We must fix the inner qpqual too, if it has join clauses (this
* could happen if special operators are involved: some indexquals
* may get rechecked as qpquals).
*/
if (NumRelids((Node *) inner_plan->qual) > 1)
inner_plan->qual = fix_join_expr(glob,
inner_plan->qual,
outer_itlist,
NULL,
innerrel,
0);
}
}
else if (IsA(inner_plan, BitmapIndexScan))
{
/*
* Same, but index is being used within a bitmap plan.
*/
BitmapIndexScan *innerscan = (BitmapIndexScan *) inner_plan;
List *indexqualorig = innerscan->indexqualorig;
/* No work needed if indexqual refers only to its own rel... */
if (NumRelids((Node *) indexqualorig) > 1)
{
Index innerrel = innerscan->scan.scanrelid;
/* only refs to outer vars get changed in the inner qual */
innerscan->indexqualorig = fix_join_expr(glob,
indexqualorig,
outer_itlist,
NULL,
innerrel,
0);
innerscan->indexqual = fix_join_expr(glob,
innerscan->indexqual,
outer_itlist,
NULL,
innerrel,
0);
/* no need to fix inner qpqual */
Assert(inner_plan->qual == NIL);
}
}
else if (IsA(inner_plan, BitmapHeapScan))
{
/*
* The inner side is a bitmap scan plan. Fix the top node, and
* recurse to get the lower nodes.
*
* Note: create_bitmap_scan_plan removes clauses from bitmapqualorig
* if they are duplicated in qpqual, so must test these independently.
*/
BitmapHeapScan *innerscan = (BitmapHeapScan *) inner_plan;
Index innerrel = innerscan->scan.scanrelid;
List *bitmapqualorig = innerscan->bitmapqualorig;
/* only refs to outer vars get changed in the inner qual */
if (NumRelids((Node *) bitmapqualorig) > 1)
innerscan->bitmapqualorig = fix_join_expr(glob,
bitmapqualorig,
outer_itlist,
NULL,
innerrel,
0);
/*
* We must fix the inner qpqual too, if it has join clauses (this
* could happen if special operators are involved: some indexquals may
* get rechecked as qpquals).
*/
if (NumRelids((Node *) inner_plan->qual) > 1)
inner_plan->qual = fix_join_expr(glob,
inner_plan->qual,
outer_itlist,
NULL,
innerrel,
0);
/* Now recurse */
set_inner_join_references(glob, inner_plan->lefttree, outer_itlist);
}
else if (IsA(inner_plan, BitmapAnd))
{
/* All we need do here is recurse */
BitmapAnd *innerscan = (BitmapAnd *) inner_plan;
ListCell *l;
foreach(l, innerscan->bitmapplans)
{
set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist);
}
}
else if (IsA(inner_plan, BitmapOr))
{
/* All we need do here is recurse */
BitmapOr *innerscan = (BitmapOr *) inner_plan;
ListCell *l;
foreach(l, innerscan->bitmapplans)
{
set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist);
}
}
else if (IsA(inner_plan, TidScan))
{
TidScan *innerscan = (TidScan *) inner_plan;
Index innerrel = innerscan->scan.scanrelid;
innerscan->tidquals = fix_join_expr(glob,
innerscan->tidquals,
outer_itlist,
NULL,
innerrel,
0);
}
else if (IsA(inner_plan, Append))
{
/*
* The inner side is an append plan. Recurse to see if it contains
* indexscans that need to be fixed.
*/
Append *appendplan = (Append *) inner_plan;
ListCell *l;
foreach(l, appendplan->appendplans)
{
set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist);
}
}
else if (IsA(inner_plan, Result))
{
/* Recurse through a gating Result node (similar to Append case) */
Result *result = (Result *) inner_plan;
if (result->plan.lefttree)
set_inner_join_references(glob, result->plan.lefttree, outer_itlist);
}
}
/*
* set_upper_references
* Update the targetlist and quals of an upper-level plan node
@ -1532,23 +1348,21 @@ search_indexed_tlist_for_sortgroupref(Node *node,
*
* This is used in two different scenarios: a normal join clause, where
* all the Vars in the clause *must* be replaced by OUTER or INNER references;
* and an indexscan being used on the inner side of a nestloop join.
* In the latter case we want to replace the outer-relation Vars by OUTER
* references, while Vars of the inner relation should be adjusted by rtoffset.
* (We also implement RETURNING clause fixup using this second scenario.)
* and a RETURNING clause, which may contain both Vars of the target relation
* and Vars of other relations. In the latter case we want to replace the
* other-relation Vars by OUTER references, while leaving target Vars alone.
*
* For a normal join, acceptable_rel should be zero so that any failure to
* match a Var will be reported as an error. For the indexscan case,
* pass inner_itlist = NULL and acceptable_rel = the (not-offseted-yet) ID
* of the inner relation.
* match a Var will be reported as an error. For the RETURNING case, pass
* inner_itlist = NULL and acceptable_rel = the ID of the target relation.
*
* 'clauses' is the targetlist or list of join clauses
* 'outer_itlist' is the indexed target list of the outer join relation
* 'inner_itlist' is the indexed target list of the inner join relation,
* or NULL
* 'acceptable_rel' is either zero or the rangetable index of a relation
* whose Vars may appear in the clause without provoking an error.
* 'rtoffset' is what to add to varno for Vars of acceptable_rel.
* whose Vars may appear in the clause without provoking an error
* 'rtoffset': how much to increment varnoold by
*
* Returns the new expression tree. The original clause structure is
* not modified.
@ -1603,8 +1417,8 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
if (var->varno == context->acceptable_rel)
{
var = copyVar(var);
var->varno += context->rtoffset;
var->varnoold += context->rtoffset;
if (var->varnoold > 0)
var->varnoold += context->rtoffset;
return (Node *) var;
}
@ -1783,7 +1597,7 @@ set_returning_clause_references(PlannerGlobal *glob,
/*
* We can perform the desired Var fixup by abusing the fix_join_expr
* machinery that normally handles inner indexscan fixup. We search the
* machinery that formerly handled inner indexscan fixup. We search the
* top plan's targetlist for Vars of non-result relations, and use
* fix_join_expr to convert RETURNING Vars into references to those tlist
* entries, while leaving result-rel Vars as-is.

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.162 2010/04/19 00:55:25 rhaas Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.163 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -83,30 +83,20 @@ static bool finalize_primnode(Node *node, finalize_primnode_context *context);
/*
* Generate a Param node to replace the given Var,
* which is expected to have varlevelsup > 0 (ie, it is not local).
* Select a PARAM_EXEC number to identify the given Var.
* If the Var already has a param slot, return that one.
*/
static Param *
replace_outer_var(PlannerInfo *root, Var *var)
static int
assign_param_for_var(PlannerInfo *root, Var *var)
{
Param *retval;
ListCell *ppl;
PlannerParamItem *pitem;
Index abslevel;
int i;
Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
abslevel = root->query_level - var->varlevelsup;
/*
* If there's already a paramlist entry for this same Var, just use it.
* NOTE: in sufficiently complex querytrees, it is possible for the same
* varno/abslevel to refer to different RTEs in different parts of the
* parsetree, so that different fields might end up sharing the same Param
* number. As long as we check the vartype/typmod as well, I believe that
* this sort of aliasing will cause no trouble. The correct field should
* get stored into the Param slot at execution in each part of the tree.
*/
/* If there's already a paramlist entry for this same Var, just use it */
i = 0;
foreach(ppl, root->glob->paramlist)
{
@ -119,24 +109,76 @@ replace_outer_var(PlannerInfo *root, Var *var)
pvar->varattno == var->varattno &&
pvar->vartype == var->vartype &&
pvar->vartypmod == var->vartypmod)
break;
return i;
}
i++;
}
if (!ppl)
{
/* Nope, so make a new one */
var = (Var *) copyObject(var);
var->varlevelsup = 0;
/* Nope, so make a new one */
var = (Var *) copyObject(var);
var->varlevelsup = 0;
pitem = makeNode(PlannerParamItem);
pitem->item = (Node *) var;
pitem->abslevel = abslevel;
pitem = makeNode(PlannerParamItem);
pitem->item = (Node *) var;
pitem->abslevel = abslevel;
root->glob->paramlist = lappend(root->glob->paramlist, pitem);
/* i is already the correct index for the new item */
}
root->glob->paramlist = lappend(root->glob->paramlist, pitem);
/* i is already the correct list index for the new item */
return i;
}
/*
* Generate a Param node to replace the given Var,
* which is expected to have varlevelsup > 0 (ie, it is not local).
*/
static Param *
replace_outer_var(PlannerInfo *root, Var *var)
{
Param *retval;
int i;
Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
/*
* Find the Var in root->glob->paramlist, or add it if not present.
*
* NOTE: in sufficiently complex querytrees, it is possible for the same
* varno/abslevel to refer to different RTEs in different parts of the
* parsetree, so that different fields might end up sharing the same Param
* number. As long as we check the vartype/typmod as well, I believe that
* this sort of aliasing will cause no trouble. The correct field should
* get stored into the Param slot at execution in each part of the tree.
*/
i = assign_param_for_var(root, var);
retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
retval->paramid = i;
retval->paramtype = var->vartype;
retval->paramtypmod = var->vartypmod;
retval->location = -1;
return retval;
}
/*
* Generate a Param node to replace the given Var, which will be supplied
* from an upper NestLoop join node.
*
* Because we allow nestloop and subquery Params to alias each other,
* this is effectively the same as replace_outer_var, except that we expect
* the Var to be local to the current query level.
*/
Param *
assign_nestloop_param(PlannerInfo *root, Var *var)
{
Param *retval;
int i;
Assert(var->varlevelsup == 0);
i = assign_param_for_var(root, var);
retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
@ -1773,8 +1815,9 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans)
*
* Note: this is a bit overly generous since some parameters of upper
* query levels might belong to query subtrees that don't include this
* query. However, valid_params is only a debugging crosscheck, so it
* doesn't seem worth expending lots of cycles to try to be exact.
* query, or might be nestloop params that won't be passed down at all.
* However, valid_params is only a debugging crosscheck, so it doesn't
* seem worth expending lots of cycles to try to be exact.
*/
valid_params = bms_copy(initSetParam);
paramid = 0;
@ -1849,6 +1892,8 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
{
finalize_primnode_context context;
int locally_added_param;
Bitmapset *nestloop_params;
Bitmapset *child_params;
if (plan == NULL)
return NULL;
@ -1856,6 +1901,7 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
context.root = root;
context.paramids = NULL; /* initialize set to empty */
locally_added_param = -1; /* there isn't one */
nestloop_params = NULL; /* there aren't any */
/*
* When we call finalize_primnode, context.paramids sets are automatically
@ -2056,8 +2102,20 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
break;
case T_NestLoop:
finalize_primnode((Node *) ((Join *) plan)->joinqual,
&context);
{
ListCell *l;
finalize_primnode((Node *) ((Join *) plan)->joinqual,
&context);
/* collect set of params that will be passed to right child */
foreach(l, ((NestLoop *) plan)->nestParams)
{
NestLoopParam *nlp = (NestLoopParam *) lfirst(l);
nestloop_params = bms_add_member(nestloop_params,
nlp->paramno);
}
}
break;
case T_MergeJoin:
@ -2120,17 +2178,32 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
}
/* Process left and right child plans, if any */
context.paramids = bms_add_members(context.paramids,
finalize_plan(root,
plan->lefttree,
valid_params,
scan_params));
child_params = finalize_plan(root,
plan->lefttree,
valid_params,
scan_params);
context.paramids = bms_add_members(context.paramids, child_params);
context.paramids = bms_add_members(context.paramids,
finalize_plan(root,
plan->righttree,
valid_params,
scan_params));
if (nestloop_params)
{
/* right child can reference nestloop_params as well as valid_params */
child_params = finalize_plan(root,
plan->righttree,
bms_union(nestloop_params, valid_params),
scan_params);
/* ... and they don't count as parameters used at my level */
child_params = bms_difference(child_params, nestloop_params);
bms_free(nestloop_params);
}
else
{
/* easy case */
child_params = finalize_plan(root,
plan->righttree,
valid_params,
scan_params);
}
context.paramids = bms_add_members(context.paramids, child_params);
/*
* Any locally generated parameter doesn't count towards its generating

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.169 2010/07/09 14:06:01 rhaas Exp $
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.170 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -82,7 +82,7 @@ extern PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook;
/*
* prototypes from functions in execAmi.c
*/
extern void ExecReScan(PlanState *node, ExprContext *exprCtxt);
extern void ExecReScan(PlanState *node);
extern void ExecMarkPos(PlanState *node);
extern void ExecRestrPos(PlanState *node);
extern bool ExecSupportsMarkRestore(NodeTag plantype);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeAgg.h,v 1.32 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeAgg.h,v 1.33 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,7 +19,7 @@
extern AggState *ExecInitAgg(Agg *node, EState *estate, int eflags);
extern TupleTableSlot *ExecAgg(AggState *node);
extern void ExecEndAgg(AggState *node);
extern void ExecReScanAgg(AggState *node, ExprContext *exprCtxt);
extern void ExecReScanAgg(AggState *node);
extern Size hash_agg_entry_size(int numAggs);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeAppend.h,v 1.30 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeAppend.h,v 1.31 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern AppendState *ExecInitAppend(Append *node, EState *estate, int eflags);
extern TupleTableSlot *ExecAppend(AppendState *node);
extern void ExecEndAppend(AppendState *node);
extern void ExecReScanAppend(AppendState *node, ExprContext *exprCtxt);
extern void ExecReScanAppend(AppendState *node);
#endif /* NODEAPPEND_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapAnd.h,v 1.8 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapAnd.h,v 1.9 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern BitmapAndState *ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags);
extern Node *MultiExecBitmapAnd(BitmapAndState *node);
extern void ExecEndBitmapAnd(BitmapAndState *node);
extern void ExecReScanBitmapAnd(BitmapAndState *node, ExprContext *exprCtxt);
extern void ExecReScanBitmapAnd(BitmapAndState *node);
#endif /* NODEBITMAPAND_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapHeapscan.h,v 1.8 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapHeapscan.h,v 1.9 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern BitmapHeapScanState *ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecBitmapHeapScan(BitmapHeapScanState *node);
extern void ExecEndBitmapHeapScan(BitmapHeapScanState *node);
extern void ExecBitmapHeapReScan(BitmapHeapScanState *node, ExprContext *exprCtxt);
extern void ExecReScanBitmapHeapScan(BitmapHeapScanState *node);
#endif /* NODEBITMAPHEAPSCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapIndexscan.h,v 1.8 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapIndexscan.h,v 1.9 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern BitmapIndexScanState *ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags);
extern Node *MultiExecBitmapIndexScan(BitmapIndexScanState *node);
extern void ExecEndBitmapIndexScan(BitmapIndexScanState *node);
extern void ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt);
extern void ExecReScanBitmapIndexScan(BitmapIndexScanState *node);
#endif /* NODEBITMAPINDEXSCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapOr.h,v 1.8 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeBitmapOr.h,v 1.9 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern BitmapOrState *ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags);
extern Node *MultiExecBitmapOr(BitmapOrState *node);
extern void ExecEndBitmapOr(BitmapOrState *node);
extern void ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt);
extern void ExecReScanBitmapOr(BitmapOrState *node);
#endif /* NODEBITMAPOR_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeCtescan.h,v 1.4 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeCtescan.h,v 1.5 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern CteScanState *ExecInitCteScan(CteScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecCteScan(CteScanState *node);
extern void ExecEndCteScan(CteScanState *node);
extern void ExecCteScanReScan(CteScanState *node, ExprContext *exprCtxt);
extern void ExecReScanCteScan(CteScanState *node);
#endif /* NODECTESCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeFunctionscan.h,v 1.15 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeFunctionscan.h,v 1.16 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecFunctionScan(FunctionScanState *node);
extern void ExecEndFunctionScan(FunctionScanState *node);
extern void ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt);
extern void ExecReScanFunctionScan(FunctionScanState *node);
#endif /* NODEFUNCTIONSCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeGroup.h,v 1.35 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeGroup.h,v 1.36 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern GroupState *ExecInitGroup(Group *node, EState *estate, int eflags);
extern TupleTableSlot *ExecGroup(GroupState *node);
extern void ExecEndGroup(GroupState *node);
extern void ExecReScanGroup(GroupState *node, ExprContext *exprCtxt);
extern void ExecReScanGroup(GroupState *node);
#endif /* NODEGROUP_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.49 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.50 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,7 +20,7 @@ extern HashState *ExecInitHash(Hash *node, EState *estate, int eflags);
extern TupleTableSlot *ExecHash(HashState *node);
extern Node *MultiExecHash(HashState *node);
extern void ExecEndHash(HashState *node);
extern void ExecReScanHash(HashState *node, ExprContext *exprCtxt);
extern void ExecReScanHash(HashState *node);
extern HashJoinTable ExecHashTableCreate(Hash *node, List *hashOperators);
extern void ExecHashTableDestroy(HashJoinTable hashtable);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeHashjoin.h,v 1.40 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeHashjoin.h,v 1.41 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,7 +20,7 @@
extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate, int eflags);
extern TupleTableSlot *ExecHashJoin(HashJoinState *node);
extern void ExecEndHashJoin(HashJoinState *node);
extern void ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt);
extern void ExecReScanHashJoin(HashJoinState *node);
extern void ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue,
BufFile **fileptr);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeIndexscan.h,v 1.36 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeIndexscan.h,v 1.37 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,7 +21,7 @@ extern TupleTableSlot *ExecIndexScan(IndexScanState *node);
extern void ExecEndIndexScan(IndexScanState *node);
extern void ExecIndexMarkPos(IndexScanState *node);
extern void ExecIndexRestrPos(IndexScanState *node);
extern void ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt);
extern void ExecReScanIndexScan(IndexScanState *node);
/* routines exported to share code with nodeBitmapIndexscan.c */
extern void ExecIndexBuildScanKeys(PlanState *planstate, Relation index,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeLimit.h,v 1.18 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeLimit.h,v 1.19 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern LimitState *ExecInitLimit(Limit *node, EState *estate, int eflags);
extern TupleTableSlot *ExecLimit(LimitState *node);
extern void ExecEndLimit(LimitState *node);
extern void ExecReScanLimit(LimitState *node, ExprContext *exprCtxt);
extern void ExecReScanLimit(LimitState *node);
#endif /* NODELIMIT_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeLockRows.h,v 1.2 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeLockRows.h,v 1.3 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern LockRowsState *ExecInitLockRows(LockRows *node, EState *estate, int eflags);
extern TupleTableSlot *ExecLockRows(LockRowsState *node);
extern void ExecEndLockRows(LockRowsState *node);
extern void ExecReScanLockRows(LockRowsState *node, ExprContext *exprCtxt);
extern void ExecReScanLockRows(LockRowsState *node);
#endif /* NODELOCKROWS_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeMaterial.h,v 1.30 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeMaterial.h,v 1.31 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,6 @@ extern TupleTableSlot *ExecMaterial(MaterialState *node);
extern void ExecEndMaterial(MaterialState *node);
extern void ExecMaterialMarkPos(MaterialState *node);
extern void ExecMaterialRestrPos(MaterialState *node);
extern void ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt);
extern void ExecReScanMaterial(MaterialState *node);
#endif /* NODEMATERIAL_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeMergejoin.h,v 1.29 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeMergejoin.h,v 1.30 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags);
extern TupleTableSlot *ExecMergeJoin(MergeJoinState *node);
extern void ExecEndMergeJoin(MergeJoinState *node);
extern void ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt);
extern void ExecReScanMergeJoin(MergeJoinState *node);
#endif /* NODEMERGEJOIN_H */

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeModifyTable.h,v 1.2 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeModifyTable.h,v 1.3 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -18,6 +18,6 @@
extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags);
extern TupleTableSlot *ExecModifyTable(ModifyTableState *node);
extern void ExecEndModifyTable(ModifyTableState *node);
extern void ExecReScanModifyTable(ModifyTableState *node, ExprContext *exprCtxt);
extern void ExecReScanModifyTable(ModifyTableState *node);
#endif /* NODEMODIFYTABLE_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeNestloop.h,v 1.30 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeNestloop.h,v 1.31 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate, int eflags);
extern TupleTableSlot *ExecNestLoop(NestLoopState *node);
extern void ExecEndNestLoop(NestLoopState *node);
extern void ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt);
extern void ExecReScanNestLoop(NestLoopState *node);
#endif /* NODENESTLOOP_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeRecursiveunion.h,v 1.4 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeRecursiveunion.h,v 1.5 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern RecursiveUnionState *ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags);
extern TupleTableSlot *ExecRecursiveUnion(RecursiveUnionState *node);
extern void ExecEndRecursiveUnion(RecursiveUnionState *node);
extern void ExecRecursiveUnionReScan(RecursiveUnionState *node, ExprContext *exprCtxt);
extern void ExecReScanRecursiveUnion(RecursiveUnionState *node);
#endif /* NODERECURSIVEUNION_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeResult.h,v 1.28 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeResult.h,v 1.29 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,6 @@ extern TupleTableSlot *ExecResult(ResultState *node);
extern void ExecEndResult(ResultState *node);
extern void ExecResultMarkPos(ResultState *node);
extern void ExecResultRestrPos(ResultState *node);
extern void ExecReScanResult(ResultState *node, ExprContext *exprCtxt);
extern void ExecReScanResult(ResultState *node);
#endif /* NODERESULT_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeSeqscan.h,v 1.29 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeSeqscan.h,v 1.30 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,6 @@ extern TupleTableSlot *ExecSeqScan(SeqScanState *node);
extern void ExecEndSeqScan(SeqScanState *node);
extern void ExecSeqMarkPos(SeqScanState *node);
extern void ExecSeqRestrPos(SeqScanState *node);
extern void ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt);
extern void ExecReScanSeqScan(SeqScanState *node);
#endif /* NODESEQSCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeSetOp.h,v 1.18 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeSetOp.h,v 1.19 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate, int eflags);
extern TupleTableSlot *ExecSetOp(SetOpState *node);
extern void ExecEndSetOp(SetOpState *node);
extern void ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt);
extern void ExecReScanSetOp(SetOpState *node);
#endif /* NODESETOP_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeSort.h,v 1.27 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeSort.h,v 1.28 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,6 @@ extern TupleTableSlot *ExecSort(SortState *node);
extern void ExecEndSort(SortState *node);
extern void ExecSortMarkPos(SortState *node);
extern void ExecSortRestrPos(SortState *node);
extern void ExecReScanSort(SortState *node, ExprContext *exprCtxt);
extern void ExecReScanSort(SortState *node);
#endif /* NODESORT_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeSubqueryscan.h,v 1.18 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeSubqueryscan.h,v 1.19 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecSubqueryScan(SubqueryScanState *node);
extern void ExecEndSubqueryScan(SubqueryScanState *node);
extern void ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt);
extern void ExecReScanSubqueryScan(SubqueryScanState *node);
#endif /* NODESUBQUERYSCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeTidscan.h,v 1.22 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeTidscan.h,v 1.23 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,6 @@ extern TupleTableSlot *ExecTidScan(TidScanState *node);
extern void ExecEndTidScan(TidScanState *node);
extern void ExecTidMarkPos(TidScanState *node);
extern void ExecTidRestrPos(TidScanState *node);
extern void ExecTidReScan(TidScanState *node, ExprContext *exprCtxt);
extern void ExecReScanTidScan(TidScanState *node);
#endif /* NODETIDSCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeUnique.h,v 1.27 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeUnique.h,v 1.28 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern UniqueState *ExecInitUnique(Unique *node, EState *estate, int eflags);
extern TupleTableSlot *ExecUnique(UniqueState *node);
extern void ExecEndUnique(UniqueState *node);
extern void ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt);
extern void ExecReScanUnique(UniqueState *node);
#endif /* NODEUNIQUE_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeValuesscan.h,v 1.7 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeValuesscan.h,v 1.8 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,6 @@ extern TupleTableSlot *ExecValuesScan(ValuesScanState *node);
extern void ExecEndValuesScan(ValuesScanState *node);
extern void ExecValuesMarkPos(ValuesScanState *node);
extern void ExecValuesRestrPos(ValuesScanState *node);
extern void ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt);
extern void ExecReScanValuesScan(ValuesScanState *node);
#endif /* NODEVALUESSCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeWindowAgg.h,v 1.4 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeWindowAgg.h,v 1.5 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern WindowAggState *ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags);
extern TupleTableSlot *ExecWindowAgg(WindowAggState *node);
extern void ExecEndWindowAgg(WindowAggState *node);
extern void ExecReScanWindowAgg(WindowAggState *node, ExprContext *exprCtxt);
extern void ExecReScanWindowAgg(WindowAggState *node);
#endif /* NODEWINDOWAGG_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/nodeWorktablescan.h,v 1.4 2010/01/02 16:58:03 momjian Exp $
* $PostgreSQL: pgsql/src/include/executor/nodeWorktablescan.h,v 1.5 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,6 @@
extern WorkTableScanState *ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecWorkTableScan(WorkTableScanState *node);
extern void ExecEndWorkTableScan(WorkTableScanState *node);
extern void ExecWorkTableScanReScan(WorkTableScanState *node, ExprContext *exprCtxt);
extern void ExecReScanWorkTableScan(WorkTableScanState *node);
#endif /* NODEWORKTABLESCAN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.234 2010/03/28 22:59:33 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.235 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -74,6 +74,7 @@ typedef enum NodeTag
T_LockRows,
T_Limit,
/* these aren't subclasses of Plan: */
T_NestLoopParam,
T_PlanRowMark,
T_PlanInvalItem,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.117 2010/02/26 02:01:25 momjian Exp $
* $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.118 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -432,13 +432,26 @@ typedef struct Join
/* ----------------
* nest loop join node
*
* The nestParams list identifies any executor Params that must be passed
* into execution of the inner subplan carrying values from the current row
* of the outer subplan. Currently we restrict these values to be simple
* Vars, but perhaps someday that'd be worth relaxing.
* ----------------
*/
typedef struct NestLoop
{
Join join;
List *nestParams; /* list of NestLoopParam nodes */
} NestLoop;
typedef struct NestLoopParam
{
NodeTag type;
int paramno; /* number of the PARAM_EXEC Param to set */
Var *paramval; /* outer-relation Var to assign to Param */
} NestLoopParam;
/* ----------------
* merge join node
*

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.156 2010/02/26 02:01:25 momjian Exp $
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.157 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -175,7 +175,8 @@ typedef struct Const
* Such parameters are numbered from 1 to n.
*
* PARAM_EXEC: The parameter is an internal executor parameter, used
* for passing values into and out of sub-queries.
* for passing values into and out of sub-queries or from
* nestloop joins to their inner scans.
* For historical reasons, such parameters are numbered from 0.
* These numbers are independent of PARAM_EXTERN numbers.
*

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.187 2010/07/06 19:19:00 momjian Exp $
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.188 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -209,6 +209,10 @@ typedef struct PlannerInfo
int wt_param_id; /* PARAM_EXEC ID for the work table */
struct Plan *non_recursive_plan; /* plan for non-recursive term */
/* These fields are workspace for createplan.c */
Relids curOuterRels; /* outer rels above current node */
List *curOuterParams; /* not-yet-assigned NestLoopParams */
/* optional private data for join_search_hook, e.g., GEQO */
void *join_search_private;
} PlannerInfo;
@ -1330,16 +1334,20 @@ typedef struct PlaceHolderInfo
/*
* glob->paramlist keeps track of the PARAM_EXEC slots that we have decided
* we need for the query. At runtime these slots are used to pass values
* either down into subqueries (for outer references in subqueries) or up out
* of subqueries (for the results of a subplan). The n'th entry in the list
* (n counts from 0) corresponds to Param->paramid = n.
* around from one plan node to another. They can be used to pass values
* down into subqueries (for outer references in subqueries), or up out of
* subqueries (for the results of a subplan), or from a NestLoop plan node
* into its inner relation (when the inner scan is parameterized with values
* from the outer relation). The n'th entry in the list (n counts from 0)
* corresponds to Param->paramid = n.
*
* Each paramlist item shows the absolute query level it is associated with,
* where the outermost query is level 1 and nested subqueries have higher
* numbers. The item the parameter slot represents can be one of three kinds:
*
* A Var: the slot represents a variable of that level that must be passed
* down because subqueries have outer references to it. The varlevelsup
* down because subqueries have outer references to it, or must be passed
* from a NestLoop node of that level to its inner scan. The varlevelsup
* value in the Var will always be zero.
*
* An Aggref (with an expression tree representing its argument): the slot
@ -1352,7 +1360,13 @@ typedef struct PlaceHolderInfo
* to the parent query of the subplan.
*
* Note: we detect duplicate Var parameters and coalesce them into one slot,
* but we do not do this for Aggref or Param slots.
* but we do not bother to do this for Aggrefs, and it would be incorrect
* to do so for Param slots. Duplicate detection is actually *necessary*
* in the case of NestLoop parameters since it serves to match up the usage
* of a Param (in the inner scan) with the assignment of the value (in the
* NestLoop node). This might result in the same PARAM_EXEC slot being used
* by multiple NestLoop nodes or SubPlan nodes, but no harm is done since
* the same value would be assigned anyway.
*/
typedef struct PlannerParamItem
{

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.39 2010/01/02 16:58:07 momjian Exp $
* $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.40 2010/07/12 17:01:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -29,6 +29,7 @@ extern void SS_finalize_plan(PlannerInfo *root, Plan *plan,
bool attach_initplans);
extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
Oid resulttype, int32 resulttypmod);
extern Param *assign_nestloop_param(PlannerInfo *root, Var *var);
extern int SS_assign_special_param(PlannerInfo *root);
#endif /* SUBSELECT_H */

View File

@ -281,7 +281,7 @@ INSERT INTO foorescan values(5007,5,'abc.5007.5');
INSERT INTO foorescan values(5008,5,'abc.5008.5');
INSERT INTO foorescan values(5009,5,'abc.5009.5');
CREATE FUNCTION foorescan(int,int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid >= $1 and fooid < $2 ;' LANGUAGE SQL;
--invokes ExecFunctionReScan
--invokes ExecReScanFunctionScan
SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,5004)) ORDER BY 1,2;
fooid | foosubid | fooname
-------+----------+------------
@ -298,7 +298,7 @@ SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,500
(10 rows)
CREATE VIEW vw_foorescan AS SELECT * FROM foorescan(5002,5004);
--invokes ExecFunctionReScan
--invokes ExecReScanFunctionScan
SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM vw_foorescan) ORDER BY 1,2;
fooid | foosubid | fooname
-------+----------+------------
@ -323,7 +323,7 @@ INSERT INTO barrescan values(5006);
INSERT INTO barrescan values(5007);
INSERT INTO barrescan values(5008);
CREATE FUNCTION foorescan(int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid = $1;' LANGUAGE SQL;
--invokes ExecFunctionReScan with chgParam != NULL
--invokes ExecReScanFunctionScan with chgParam != NULL
SELECT f.* FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) ORDER BY 1,2;
fooid | foosubid | fooname
-------+----------+------------

View File

@ -164,12 +164,12 @@ INSERT INTO foorescan values(5009,5,'abc.5009.5');
CREATE FUNCTION foorescan(int,int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid >= $1 and fooid < $2 ;' LANGUAGE SQL;
--invokes ExecFunctionReScan
--invokes ExecReScanFunctionScan
SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,5004)) ORDER BY 1,2;
CREATE VIEW vw_foorescan AS SELECT * FROM foorescan(5002,5004);
--invokes ExecFunctionReScan
--invokes ExecReScanFunctionScan
SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM vw_foorescan) ORDER BY 1,2;
CREATE TABLE barrescan (fooid int primary key);
@ -182,7 +182,7 @@ INSERT INTO barrescan values(5008);
CREATE FUNCTION foorescan(int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid = $1;' LANGUAGE SQL;
--invokes ExecFunctionReScan with chgParam != NULL
--invokes ExecReScanFunctionScan with chgParam != NULL
SELECT f.* FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) ORDER BY 1,2;
SELECT b.fooid, max(f.foosubid) FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) GROUP BY b.fooid ORDER BY 1,2;