diff options
Diffstat (limited to 'src/backend/executor')
34 files changed, 334 insertions, 338 deletions
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index dfc36365807..f37a7602ef4 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -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: diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 473fbcdae1c..9eb765378f5 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -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); } diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index b464e769933..2830bff8716 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -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)) { diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index e381e112821..e30689bba30 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -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 - { - /* - * PARAM_EXTERN parameters must be sought in ecxt_param_list_info. - */ - ParamListInfo paramInfo = econtext->ecxt_param_list_info; + *isNull = prm->isnull; + return prm->value; +} - Assert(expression->paramkind == PARAM_EXTERN); - if (paramInfo && - thisParamId > 0 && thisParamId <= paramInfo->numParams) - { - ParamExternData *prm = ¶mInfo->params[thisParamId - 1]; +/* ---------------------------------------------------------------- + * 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; - /* give hook a chance in case parameter is dynamic */ - if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL) - (*paramInfo->paramFetch) (paramInfo, thisParamId); + if (isDone) + *isDone = ExprSingleResult; - 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)))); + /* + * PARAM_EXTERN parameters must be sought in ecxt_param_list_info. + */ + if (paramInfo && + thisParamId > 0 && thisParamId <= paramInfo->numParams) + { + ParamExternData *prm = ¶mInfo->params[thisParamId - 1]; - *isNull = prm->isnull; - return prm->value; - } + /* 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; } - 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); diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 74fc87a66a5..a28d73fd32e 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -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); } /* diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 60026613c04..4a40b831ddf 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -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); diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c index dbfcfb1cab0..9ae2df76aff 100644 --- a/src/backend/executor/nodeBitmapAnd.c +++ b/src/backend/executor/nodeBitmapAnd.c @@ -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); } } diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 2a7ce624321..0ea3a88e451 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -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); } /* ---------------------------------------------------------------- diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index 0781c21676b..73b569458d3 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -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 */ + ExprContext *econtext = node->biss_RuntimeContext; + /* + * 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) - { - /* - * 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); - } /* - * 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. * * Array keys are also treated as runtime keys; note that if we return * with biss_RuntimeKeysReady still false, then there is an empty array diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c index 97cadd6b852..8faba8b3002 100644 --- a/src/backend/executor/nodeBitmapOr.c +++ b/src/backend/executor/nodeBitmapOr.c @@ -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); } } diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c index 0c90a1e37e3..408cd051207 100644 --- a/src/backend/executor/nodeCtescan.c +++ b/src/backend/executor/nodeCtescan.c @@ -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; diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 6989961f8a4..e64b57d09ad 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -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); diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index 26b59df8663..e56fddadd83 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -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); } diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index be45d732e09..0fa8b33606a 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -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); } diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 4749d353b99..a6cd481f7ed 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -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); } diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 0994dbf84ef..ad64c148241 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -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 diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index 48fb32d3843..a873ab88f65 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -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); } diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c index 0eafa0afa2c..d573853eba9 100644 --- a/src/backend/executor/nodeLockRows.c +++ b/src/backend/executor/nodeLockRows.c @@ -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); } diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 414ff533905..78f29d872e6 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -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; } } diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 948f5800958..104482a6336 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.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); } diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index adfe97cefde..a5e24def372 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -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 diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index 1bcaef96e60..d59ed92f018 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -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); @@ -134,16 +137,33 @@ ExecNestLoop(NestLoopState *node) node->nl_MatchedOuter = false; /* - * now rescan the inner plan + * fetch the values of any outer Vars that must be passed to + * the inner scan, and store them in the appropriate PARAM_EXEC + * slots. */ - ENL1_printf("rescanning inner plan"); + 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); + } /* - * 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. + * now rescan the inner plan */ - ExecReScan(innerPlan, econtext); + ENL1_printf("rescanning inner plan"); + 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; diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c index 68484ef0929..3cd9495f8a2 100644 --- a/src/backend/executor/nodeRecursiveunion.c +++ b/src/backend/executor/nodeRecursiveunion.c @@ -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) diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index 537df9d5d7b..a9ad0dca874 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -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); } diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index 75623be3715..f65a79310f9 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -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; diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index 7b3ee6d92db..1063ff701ba 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -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); } diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 5b925da75a0..5b993c199b0 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -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); diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index f5ac47402e1..419f3f36bd2 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -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. diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index dbd42d79720..9741a103b50 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -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); } diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index e66f97833fe..7a8c7479aa8 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -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; diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c index 82abb184775..1fd11090518 100644 --- a/src/backend/executor/nodeUnique.c +++ b/src/backend/executor/nodeUnique.c @@ -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); } diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c index 482577b2fe4..79d41ecc270 100644 --- a/src/backend/executor/nodeValuesscan.c +++ b/src/backend/executor/nodeValuesscan.c @@ -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); diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index de6d0385e92..ad20c3cca17 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -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); } /* diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c index 3fba4e3d9b3..d0d22e6481f 100644 --- a/src/backend/executor/nodeWorktablescan.c +++ b/src/backend/executor/nodeWorktablescan.c @@ -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); |