1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

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);