From 53e757689ce94520f1c53a89dbaa14ea57b09da7 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 12 Jul 2010 17:01:06 +0000 Subject: [PATCH] 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. --- src/backend/executor/execAmi.c | 70 +++--- src/backend/executor/execMain.c | 4 +- src/backend/executor/execProcnode.c | 6 +- src/backend/executor/execQual.c | 137 +++++++----- src/backend/executor/nodeAgg.c | 10 +- src/backend/executor/nodeAppend.c | 12 +- src/backend/executor/nodeBitmapAnd.c | 11 +- src/backend/executor/nodeBitmapHeapscan.c | 27 +-- src/backend/executor/nodeBitmapIndexscan.c | 47 ++-- src/backend/executor/nodeBitmapOr.c | 11 +- src/backend/executor/nodeCtescan.c | 6 +- src/backend/executor/nodeFunctionscan.c | 8 +- src/backend/executor/nodeGroup.c | 14 +- src/backend/executor/nodeHash.c | 8 +- src/backend/executor/nodeHashjoin.c | 14 +- src/backend/executor/nodeIndexscan.c | 61 ++---- src/backend/executor/nodeLimit.c | 8 +- src/backend/executor/nodeLockRows.c | 8 +- src/backend/executor/nodeMaterial.c | 22 +- src/backend/executor/nodeMergejoin.c | 12 +- src/backend/executor/nodeModifyTable.c | 4 +- src/backend/executor/nodeNestloop.c | 67 ++++-- src/backend/executor/nodeRecursiveunion.c | 8 +- src/backend/executor/nodeResult.c | 12 +- src/backend/executor/nodeSeqscan.c | 8 +- src/backend/executor/nodeSetOp.c | 10 +- src/backend/executor/nodeSort.c | 14 +- src/backend/executor/nodeSubplan.c | 8 +- src/backend/executor/nodeSubqueryscan.c | 10 +- src/backend/executor/nodeTidscan.c | 13 +- src/backend/executor/nodeUnique.c | 8 +- src/backend/executor/nodeValuesscan.c | 8 +- src/backend/executor/nodeWindowAgg.c | 8 +- src/backend/executor/nodeWorktablescan.c | 6 +- src/backend/nodes/copyfuncs.c | 24 ++- src/backend/nodes/outfuncs.c | 18 +- src/backend/optimizer/plan/createplan.c | 201 ++++++++++++++--- src/backend/optimizer/plan/setrefs.c | 238 +++------------------ src/backend/optimizer/plan/subselect.c | 157 ++++++++++---- src/include/executor/executor.h | 4 +- src/include/executor/nodeAgg.h | 4 +- src/include/executor/nodeAppend.h | 4 +- src/include/executor/nodeBitmapAnd.h | 4 +- src/include/executor/nodeBitmapHeapscan.h | 4 +- src/include/executor/nodeBitmapIndexscan.h | 4 +- src/include/executor/nodeBitmapOr.h | 4 +- src/include/executor/nodeCtescan.h | 4 +- src/include/executor/nodeFunctionscan.h | 4 +- src/include/executor/nodeGroup.h | 4 +- src/include/executor/nodeHash.h | 4 +- src/include/executor/nodeHashjoin.h | 4 +- src/include/executor/nodeIndexscan.h | 4 +- src/include/executor/nodeLimit.h | 4 +- src/include/executor/nodeLockRows.h | 4 +- src/include/executor/nodeMaterial.h | 4 +- src/include/executor/nodeMergejoin.h | 4 +- src/include/executor/nodeModifyTable.h | 4 +- src/include/executor/nodeNestloop.h | 4 +- src/include/executor/nodeRecursiveunion.h | 4 +- src/include/executor/nodeResult.h | 4 +- src/include/executor/nodeSeqscan.h | 4 +- src/include/executor/nodeSetOp.h | 4 +- src/include/executor/nodeSort.h | 4 +- src/include/executor/nodeSubqueryscan.h | 4 +- src/include/executor/nodeTidscan.h | 4 +- src/include/executor/nodeUnique.h | 4 +- src/include/executor/nodeValuesscan.h | 4 +- src/include/executor/nodeWindowAgg.h | 4 +- src/include/executor/nodeWorktablescan.h | 4 +- src/include/nodes/nodes.h | 3 +- src/include/nodes/plannodes.h | 15 +- src/include/nodes/primnodes.h | 5 +- src/include/nodes/relation.h | 26 ++- src/include/optimizer/subselect.h | 3 +- src/test/regress/expected/rangefuncs.out | 6 +- src/test/regress/sql/rangefuncs.sql | 6 +- 76 files changed, 802 insertions(+), 700 deletions(-) diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index dfc3636580..f37a7602ef 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 473fbcdae1..9eb765378f 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 b464e76993..2830bff871 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 e381e11282..e30689bba3 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 + *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 = ¶mInfo->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 = ¶mInfo->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); diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 74fc87a66a..a28d73fd32 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 60026613c0..4a40b831dd 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 dbfcfb1cab..9ae2df76af 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 2a7ce62432..0ea3a88e45 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 0781c21676..73b569458d 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 */ - - 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 diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c index 97cadd6b85..8faba8b300 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 0c90a1e37e..408cd05120 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 6989961f8a..e64b57d09a 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 26b59df866..e56fddadd8 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 be45d732e0..0fa8b33606 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 4749d353b9..a6cd481f7e 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 0994dbf84e..ad64c14824 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 48fb32d384..a873ab88f6 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 0eafa0afa2..d573853eba 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 414ff53390..78f29d872e 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 948f580095..104482a633 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 adfe97cefd..a5e24def37 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 1bcaef96e6..d59ed92f01 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); @@ -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; diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c index 68484ef092..3cd9495f8a 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 537df9d5d7..a9ad0dca87 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 75623be371..f65a79310f 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 7b3ee6d92d..1063ff701b 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 5b925da75a..5b993c199b 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 f5ac47402e..419f3f36bd 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 dbd42d7972..9741a103b5 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 e66f97833f..7a8c7479aa 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 82abb18477..1fd1109051 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 482577b2fe..79d41ecc27 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 de6d0385e9..ad20c3cca1 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 3fba4e3d9b..d0d22e6481 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); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 829dc7ba8d..8e47403a48 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.464 2010/02/26 02:00:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.465 2010/07/12 17:01:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -564,6 +564,11 @@ _copyNestLoop(NestLoop *from) */ CopyJoinFields((Join *) from, (Join *) newnode); + /* + * copy remainder of node + */ + COPY_NODE_FIELD(nestParams); + return newnode; } @@ -844,6 +849,20 @@ _copyLimit(Limit *from) return newnode; } +/* + * _copyNestLoopParam + */ +static NestLoopParam * +_copyNestLoopParam(NestLoopParam *from) +{ + NestLoopParam *newnode = makeNode(NestLoopParam); + + COPY_SCALAR_FIELD(paramno); + COPY_NODE_FIELD(paramval); + + return newnode; +} + /* * _copyPlanRowMark */ @@ -3671,6 +3690,9 @@ copyObject(void *from) case T_Limit: retval = _copyLimit(from); break; + case T_NestLoopParam: + retval = _copyNestLoopParam(from); + break; case T_PlanRowMark: retval = _copyPlanRowMark(from); break; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index dba8d4b669..ff4a9aaeef 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.385 2010/03/30 21:58:10 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.386 2010/07/12 17:01:05 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -517,6 +517,8 @@ _outNestLoop(StringInfo str, NestLoop *node) WRITE_NODE_TYPE("NESTLOOP"); _outJoinPlanInfo(str, (Join *) node); + + WRITE_NODE_FIELD(nestParams); } static void @@ -748,6 +750,15 @@ _outLimit(StringInfo str, Limit *node) WRITE_NODE_FIELD(limitCount); } +static void +_outNestLoopParam(StringInfo str, NestLoopParam *node) +{ + WRITE_NODE_TYPE("NESTLOOPPARAM"); + + WRITE_INT_FIELD(paramno); + WRITE_NODE_FIELD(paramval); +} + static void _outPlanRowMark(StringInfo str, PlanRowMark *node) { @@ -1565,6 +1576,8 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node) WRITE_BOOL_FIELD(hasPseudoConstantQuals); WRITE_BOOL_FIELD(hasRecursion); WRITE_INT_FIELD(wt_param_id); + WRITE_BITMAPSET_FIELD(curOuterRels); + WRITE_NODE_FIELD(curOuterParams); } static void @@ -2562,6 +2575,9 @@ _outNode(StringInfo str, void *obj) case T_Limit: _outLimit(str, obj); break; + case T_NestLoopParam: + _outNestLoopParam(str, obj); + break; case T_PlanRowMark: _outPlanRowMark(str, obj); break; diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 3d6f9f94fa..434babc5d8 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.275 2010/05/25 17:44:41 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.276 2010/07/12 17:01:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "optimizer/planmain.h" #include "optimizer/predtest.h" #include "optimizer/restrictinfo.h" +#include "optimizer/subselect.h" #include "optimizer/tlist.h" #include "optimizer/var.h" #include "parser/parse_clause.h" @@ -35,6 +36,7 @@ #include "utils/lsyscache.h" +static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path); static Plan *create_scan_plan(PlannerInfo *root, Path *best_path); static List *build_relation_tlist(RelOptInfo *rel); static bool use_physical_tlist(PlannerInfo *root, RelOptInfo *rel); @@ -72,7 +74,10 @@ static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path, Plan *outer_plan, Plan *inner_plan); static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path, Plan *outer_plan, Plan *inner_plan); -static List *fix_indexqual_references(List *indexquals, IndexPath *index_path); +static Node *replace_nestloop_params(PlannerInfo *root, Node *expr); +static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root); +static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, + List *indexquals); static List *get_switched_clauses(List *clauses, Relids outerrelids); static List *order_qual_clauses(PlannerInfo *root, List *clauses); static void copy_path_costsize(Plan *dest, Path *src); @@ -103,7 +108,7 @@ static WorkTableScan *make_worktablescan(List *qptlist, List *qpqual, static BitmapAnd *make_bitmap_and(List *bitmapplans); static BitmapOr *make_bitmap_or(List *bitmapplans); static NestLoop *make_nestloop(List *tlist, - List *joinclauses, List *otherclauses, + List *joinclauses, List *otherclauses, List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype); static HashJoin *make_hashjoin(List *tlist, @@ -133,8 +138,8 @@ static Material *make_material(Plan *lefttree); /* * create_plan - * Creates the access plan for a query by tracing backwards through the - * desired chain of pathnodes, starting at the node 'best_path'. For + * Creates the access plan for a query by recursively processing the + * desired tree of pathnodes, starting at the node 'best_path'. For * every pathnode found, we create a corresponding plan node containing * appropriate id, target list, and qualification information. * @@ -151,6 +156,29 @@ create_plan(PlannerInfo *root, Path *best_path) { Plan *plan; + /* Initialize this module's private workspace in PlannerInfo */ + root->curOuterRels = NULL; + root->curOuterParams = NIL; + + /* Recursively process the path tree */ + plan = create_plan_recurse(root, best_path); + + /* Check we successfully assigned all NestLoopParams to plan nodes */ + if (root->curOuterParams != NIL) + elog(ERROR, "failed to assign all NestLoopParams to plan nodes"); + + return plan; +} + +/* + * create_plan_recurse + * Recursive guts of create_plan(). + */ +static Plan * +create_plan_recurse(PlannerInfo *root, Path *best_path) +{ + Plan *plan; + switch (best_path->pathtype) { case T_SeqScan: @@ -477,9 +505,16 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path) Plan *outer_plan; Plan *inner_plan; Plan *plan; + Relids saveOuterRels = root->curOuterRels; - outer_plan = create_plan(root, best_path->outerjoinpath); - inner_plan = create_plan(root, best_path->innerjoinpath); + outer_plan = create_plan_recurse(root, best_path->outerjoinpath); + + /* For a nestloop, include outer relids in curOuterRels for inner side */ + if (best_path->path.pathtype == T_NestLoop) + root->curOuterRels = bms_union(root->curOuterRels, + best_path->outerjoinpath->parent->relids); + + inner_plan = create_plan_recurse(root, best_path->innerjoinpath); switch (best_path->path.pathtype) { @@ -496,6 +531,10 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path) inner_plan); break; case T_NestLoop: + /* Restore curOuterRels */ + bms_free(root->curOuterRels); + root->curOuterRels = saveOuterRels; + plan = (Plan *) create_nestloop_plan(root, (NestPath *) best_path, outer_plan, @@ -571,7 +610,7 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path) { Path *subpath = (Path *) lfirst(subpaths); - subplans = lappend(subplans, create_plan(root, subpath)); + subplans = lappend(subplans, create_plan_recurse(root, subpath)); } plan = make_append(subplans, tlist); @@ -616,7 +655,7 @@ create_material_plan(PlannerInfo *root, MaterialPath *best_path) Material *plan; Plan *subplan; - subplan = create_plan(root, best_path->subpath); + subplan = create_plan_recurse(root, best_path->subpath); /* We don't want any excess columns in the materialized tuples */ disuse_physical_tlist(subplan, best_path->subpath); @@ -650,7 +689,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path) int groupColPos; ListCell *l; - subplan = create_plan(root, best_path->subpath); + subplan = create_plan_recurse(root, best_path->subpath); /* Done if we don't need to do any actual unique-ifying */ if (best_path->umethod == UNIQUE_PATH_NOOP) @@ -904,7 +943,7 @@ create_indexscan_plan(PlannerInfo *root, * The executor needs a copy with the indexkey on the left of each clause * and with index attr numbers substituted for table ones. */ - fixed_indexquals = fix_indexqual_references(indexquals, best_path); + fixed_indexquals = fix_indexqual_references(root, best_path, indexquals); /* * If this is an innerjoin scan, the indexclauses will contain join @@ -975,6 +1014,22 @@ create_indexscan_plan(PlannerInfo *root, /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */ qpqual = extract_actual_clauses(qpqual, false); + /* + * We have to replace any outer-relation variables with nestloop params + * in the indexqualorig and qpqual expressions. A bit annoying to have to + * do this separately from the processing in fix_indexqual_references --- + * rethink this when generalizing the inner indexscan support. But note + * we can't really do this earlier because it'd break the comparisons to + * predicates above ... (or would it? Those wouldn't have outer refs) + */ + if (best_path->isjoininner) + { + stripped_indexquals = (List *) + replace_nestloop_params(root, (Node *) stripped_indexquals); + qpqual = (List *) + replace_nestloop_params(root, (Node *) qpqual); + } + /* Finally ready to build the plan node */ scan_plan = make_indexscan(tlist, qpqual, @@ -1267,6 +1322,17 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, *indexqual = lappend(*indexqual, pred); } } + /* + * Replace outer-relation variables with nestloop params, but only + * after doing the above comparisons to index predicates. + */ + if (ipath->isjoininner) + { + *qual = (List *) + replace_nestloop_params(root, (Node *) *qual); + *indexqual = (List *) + replace_nestloop_params(root, (Node *) *indexqual); + } } else { @@ -1572,11 +1638,16 @@ create_nestloop_plan(PlannerInfo *root, Plan *outer_plan, Plan *inner_plan) { + NestLoop *join_plan; List *tlist = build_relation_tlist(best_path->path.parent); List *joinrestrictclauses = best_path->joinrestrictinfo; List *joinclauses; List *otherclauses; - NestLoop *join_plan; + Relids outerrelids; + List *nestParams; + ListCell *cell; + ListCell *prev; + ListCell *next; /* * If the inner path is a nestloop inner indexscan, it might be using some @@ -1605,9 +1676,32 @@ create_nestloop_plan(PlannerInfo *root, otherclauses = NIL; } + /* + * Identify any nestloop parameters that should be supplied by this join + * node, and move them from root->curOuterParams to the nestParams list. + */ + outerrelids = best_path->outerjoinpath->parent->relids; + nestParams = NIL; + prev = NULL; + for (cell = list_head(root->curOuterParams); cell; cell = next) + { + NestLoopParam *nlp = (NestLoopParam *) lfirst(cell); + + next = lnext(cell); + if (bms_is_member(nlp->paramval->varno, outerrelids)) + { + root->curOuterParams = list_delete_cell(root->curOuterParams, + cell, prev); + nestParams = lappend(nestParams, nlp); + } + else + prev = cell; + } + join_plan = make_nestloop(tlist, joinclauses, otherclauses, + nestParams, outer_plan, inner_plan, best_path->jointype); @@ -2015,13 +2109,73 @@ create_hashjoin_plan(PlannerInfo *root, * *****************************************************************************/ +/* + * replace_nestloop_params + * Replace outer-relation Vars in the given expression with nestloop Params + * + * All Vars belonging to the relation(s) identified by root->curOuterRels + * are replaced by Params, and entries are added to root->curOuterParams if + * not already present. + */ +static Node * +replace_nestloop_params(PlannerInfo *root, Node *expr) +{ + /* No setup needed for tree walk, so away we go */ + return replace_nestloop_params_mutator(expr, root); +} + +static Node * +replace_nestloop_params_mutator(Node *node, PlannerInfo *root) +{ + if (node == NULL) + return NULL; + if (IsA(node, Var)) + { + Var *var = (Var *) node; + Param *param; + NestLoopParam *nlp; + ListCell *lc; + + /* Upper-level Vars should be long gone at this point */ + Assert(var->varlevelsup == 0); + /* If not to be replaced, we can just return the Var unmodified */ + if (!bms_is_member(var->varno, root->curOuterRels)) + return node; + /* Create a Param representing the Var */ + param = assign_nestloop_param(root, var); + /* Is this param already listed in root->curOuterParams? */ + foreach(lc, root->curOuterParams) + { + nlp = (NestLoopParam *) lfirst(lc); + if (nlp->paramno == param->paramid) + { + Assert(equal(var, nlp->paramval)); + /* Present, so we can just return the Param */ + return (Node *) param; + } + } + /* No, so add it */ + nlp = makeNode(NestLoopParam); + nlp->paramno = param->paramid; + nlp->paramval = var; + root->curOuterParams = lappend(root->curOuterParams, nlp); + /* And return the replacement Param */ + return (Node *) param; + } + return expression_tree_mutator(node, + replace_nestloop_params_mutator, + (void *) root); +} + /* * fix_indexqual_references * Adjust indexqual clauses to the form the executor's indexqual * machinery needs. * - * We have three tasks here: + * We have four tasks here: * * Remove RestrictInfo nodes from the input clauses. + * * Replace any outer-relation Var nodes with nestloop Params. + * (XXX eventually, that responsibility should go elsewhere?) * * Index keys must be represented by Var nodes with varattno set to the * index's attribute number, not the attribute number in the original rel. * * If the index key is on the right, commute the clause to put it on the @@ -2033,7 +2187,8 @@ create_hashjoin_plan(PlannerInfo *root, * two separate copies of the subplan tree, or things will go awry). */ static List * -fix_indexqual_references(List *indexquals, IndexPath *index_path) +fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, + List *indexquals) { IndexOptInfo *index = index_path->indexinfo; List *fixed_indexquals; @@ -2041,26 +2196,20 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path) fixed_indexquals = NIL; - /* - * For each qual clause, commute if needed to put the indexkey operand on - * the left, and then fix its varattno. (We do not need to change the - * other side of the clause.) - */ foreach(l, indexquals) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(l); - Expr *clause; + Node *clause; Assert(IsA(rinfo, RestrictInfo)); /* - * Make a copy that will become the fixed clause. + * Replace any outer-relation variables with nestloop params. * - * We used to try to do a shallow copy here, but that fails if there - * is a subplan in the arguments of the opclause. So just do a full - * copy. + * This also makes a copy of the clause, so it's safe to modify it + * in-place below. */ - clause = (Expr *) copyObject((Node *) rinfo->clause); + clause = replace_nestloop_params(root, (Node *) rinfo->clause); if (IsA(clause, OpExpr)) { @@ -2765,6 +2914,7 @@ static NestLoop * make_nestloop(List *tlist, List *joinclauses, List *otherclauses, + List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype) @@ -2779,6 +2929,7 @@ make_nestloop(List *tlist, plan->righttree = righttree; node->join.jointype = jointype; node->join.joinqual = joinclauses; + node->nestParams = nestParams; return node; } diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 70be2e66f2..450970e5c3 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.160 2010/02/26 02:00:45 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.161 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -89,8 +89,6 @@ static Node *fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset); static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context); static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context); static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset); -static void set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan, - indexed_tlist *outer_itlist); static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset); static void set_dummy_tlist_references(Plan *plan, int rtoffset); static indexed_tlist *build_tlist_index(List *tlist); @@ -878,12 +876,11 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context) Assert(var->varlevelsup == 0); /* - * We should not see any Vars marked INNER, but in a nestloop inner - * scan there could be OUTER Vars. Leave them alone. + * We should not see any Vars marked INNER or OUTER. */ Assert(var->varno != INNER); - if (var->varno > 0 && var->varno != OUTER) - var->varno += context->rtoffset; + Assert(var->varno != OUTER); + var->varno += context->rtoffset; if (var->varnoold > 0) var->varnoold += context->rtoffset; return (Node *) var; @@ -927,10 +924,6 @@ fix_scan_expr_walker(Node *node, fix_scan_expr_context *context) * values to the result domain number of either the corresponding outer * or inner join tuple item. Also perform opcode lookup for these * expressions. and add regclass OIDs to glob->relationOids. - * - * In the case of a nestloop with inner indexscan, we will also need to - * apply the same transformation to any outer vars appearing in the - * quals of the child indexscan. set_inner_join_references does that. */ static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset) @@ -966,8 +959,18 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset) /* Now do join-type-specific stuff */ if (IsA(join, NestLoop)) { - /* This processing is split out to handle possible recursion */ - set_inner_join_references(glob, inner_plan, outer_itlist); + NestLoop *nl = (NestLoop *) join; + ListCell *lc; + + foreach(lc, nl->nestParams) + { + NestLoopParam *nlp = (NestLoopParam *) lfirst(lc); + + nlp->paramval = (Var *) fix_upper_expr(glob, + (Node *) nlp->paramval, + outer_itlist, + rtoffset); + } } else if (IsA(join, MergeJoin)) { @@ -996,193 +999,6 @@ set_join_references(PlannerGlobal *glob, Join *join, int rtoffset) pfree(inner_itlist); } -/* - * set_inner_join_references - * Handle join references appearing in an inner indexscan's quals - * - * To handle bitmap-scan plan trees, we have to be able to recurse down - * to the bottom BitmapIndexScan nodes; likewise, appendrel indexscans - * require recursing through Append nodes. This is split out as a separate - * function so that it can recurse. - * - * Note we do *not* apply any rtoffset for non-join Vars; this is because - * the quals will be processed again by fix_scan_expr when the set_plan_refs - * recursion reaches the inner indexscan, and so we'd have done it twice. - */ -static void -set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan, - indexed_tlist *outer_itlist) -{ - if (IsA(inner_plan, IndexScan)) - { - /* - * An index is being used to reduce the number of tuples scanned in - * the inner relation. If there are join clauses being used with the - * index, we must update their outer-rel var nodes to refer to the - * outer side of the join. - */ - IndexScan *innerscan = (IndexScan *) inner_plan; - List *indexqualorig = innerscan->indexqualorig; - - /* No work needed if indexqual refers only to its own rel... */ - if (NumRelids((Node *) indexqualorig) > 1) - { - Index innerrel = innerscan->scan.scanrelid; - - /* only refs to outer vars get changed in the inner qual */ - innerscan->indexqualorig = fix_join_expr(glob, - indexqualorig, - outer_itlist, - NULL, - innerrel, - 0); - innerscan->indexqual = fix_join_expr(glob, - innerscan->indexqual, - outer_itlist, - NULL, - innerrel, - 0); - - /* - * We must fix the inner qpqual too, if it has join clauses (this - * could happen if special operators are involved: some indexquals - * may get rechecked as qpquals). - */ - if (NumRelids((Node *) inner_plan->qual) > 1) - inner_plan->qual = fix_join_expr(glob, - inner_plan->qual, - outer_itlist, - NULL, - innerrel, - 0); - } - } - else if (IsA(inner_plan, BitmapIndexScan)) - { - /* - * Same, but index is being used within a bitmap plan. - */ - BitmapIndexScan *innerscan = (BitmapIndexScan *) inner_plan; - List *indexqualorig = innerscan->indexqualorig; - - /* No work needed if indexqual refers only to its own rel... */ - if (NumRelids((Node *) indexqualorig) > 1) - { - Index innerrel = innerscan->scan.scanrelid; - - /* only refs to outer vars get changed in the inner qual */ - innerscan->indexqualorig = fix_join_expr(glob, - indexqualorig, - outer_itlist, - NULL, - innerrel, - 0); - innerscan->indexqual = fix_join_expr(glob, - innerscan->indexqual, - outer_itlist, - NULL, - innerrel, - 0); - /* no need to fix inner qpqual */ - Assert(inner_plan->qual == NIL); - } - } - else if (IsA(inner_plan, BitmapHeapScan)) - { - /* - * The inner side is a bitmap scan plan. Fix the top node, and - * recurse to get the lower nodes. - * - * Note: create_bitmap_scan_plan removes clauses from bitmapqualorig - * if they are duplicated in qpqual, so must test these independently. - */ - BitmapHeapScan *innerscan = (BitmapHeapScan *) inner_plan; - Index innerrel = innerscan->scan.scanrelid; - List *bitmapqualorig = innerscan->bitmapqualorig; - - /* only refs to outer vars get changed in the inner qual */ - if (NumRelids((Node *) bitmapqualorig) > 1) - innerscan->bitmapqualorig = fix_join_expr(glob, - bitmapqualorig, - outer_itlist, - NULL, - innerrel, - 0); - - /* - * We must fix the inner qpqual too, if it has join clauses (this - * could happen if special operators are involved: some indexquals may - * get rechecked as qpquals). - */ - if (NumRelids((Node *) inner_plan->qual) > 1) - inner_plan->qual = fix_join_expr(glob, - inner_plan->qual, - outer_itlist, - NULL, - innerrel, - 0); - - /* Now recurse */ - set_inner_join_references(glob, inner_plan->lefttree, outer_itlist); - } - else if (IsA(inner_plan, BitmapAnd)) - { - /* All we need do here is recurse */ - BitmapAnd *innerscan = (BitmapAnd *) inner_plan; - ListCell *l; - - foreach(l, innerscan->bitmapplans) - { - set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist); - } - } - else if (IsA(inner_plan, BitmapOr)) - { - /* All we need do here is recurse */ - BitmapOr *innerscan = (BitmapOr *) inner_plan; - ListCell *l; - - foreach(l, innerscan->bitmapplans) - { - set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist); - } - } - else if (IsA(inner_plan, TidScan)) - { - TidScan *innerscan = (TidScan *) inner_plan; - Index innerrel = innerscan->scan.scanrelid; - - innerscan->tidquals = fix_join_expr(glob, - innerscan->tidquals, - outer_itlist, - NULL, - innerrel, - 0); - } - else if (IsA(inner_plan, Append)) - { - /* - * The inner side is an append plan. Recurse to see if it contains - * indexscans that need to be fixed. - */ - Append *appendplan = (Append *) inner_plan; - ListCell *l; - - foreach(l, appendplan->appendplans) - { - set_inner_join_references(glob, (Plan *) lfirst(l), outer_itlist); - } - } - else if (IsA(inner_plan, Result)) - { - /* Recurse through a gating Result node (similar to Append case) */ - Result *result = (Result *) inner_plan; - - if (result->plan.lefttree) - set_inner_join_references(glob, result->plan.lefttree, outer_itlist); - } -} - /* * set_upper_references * Update the targetlist and quals of an upper-level plan node @@ -1532,23 +1348,21 @@ search_indexed_tlist_for_sortgroupref(Node *node, * * This is used in two different scenarios: a normal join clause, where * all the Vars in the clause *must* be replaced by OUTER or INNER references; - * and an indexscan being used on the inner side of a nestloop join. - * In the latter case we want to replace the outer-relation Vars by OUTER - * references, while Vars of the inner relation should be adjusted by rtoffset. - * (We also implement RETURNING clause fixup using this second scenario.) + * and a RETURNING clause, which may contain both Vars of the target relation + * and Vars of other relations. In the latter case we want to replace the + * other-relation Vars by OUTER references, while leaving target Vars alone. * * For a normal join, acceptable_rel should be zero so that any failure to - * match a Var will be reported as an error. For the indexscan case, - * pass inner_itlist = NULL and acceptable_rel = the (not-offseted-yet) ID - * of the inner relation. + * match a Var will be reported as an error. For the RETURNING case, pass + * inner_itlist = NULL and acceptable_rel = the ID of the target relation. * * 'clauses' is the targetlist or list of join clauses * 'outer_itlist' is the indexed target list of the outer join relation * 'inner_itlist' is the indexed target list of the inner join relation, * or NULL * 'acceptable_rel' is either zero or the rangetable index of a relation - * whose Vars may appear in the clause without provoking an error. - * 'rtoffset' is what to add to varno for Vars of acceptable_rel. + * whose Vars may appear in the clause without provoking an error + * 'rtoffset': how much to increment varnoold by * * Returns the new expression tree. The original clause structure is * not modified. @@ -1603,8 +1417,8 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context) if (var->varno == context->acceptable_rel) { var = copyVar(var); - var->varno += context->rtoffset; - var->varnoold += context->rtoffset; + if (var->varnoold > 0) + var->varnoold += context->rtoffset; return (Node *) var; } @@ -1783,7 +1597,7 @@ set_returning_clause_references(PlannerGlobal *glob, /* * We can perform the desired Var fixup by abusing the fix_join_expr - * machinery that normally handles inner indexscan fixup. We search the + * machinery that formerly handled inner indexscan fixup. We search the * top plan's targetlist for Vars of non-result relations, and use * fix_join_expr to convert RETURNING Vars into references to those tlist * entries, while leaving result-rel Vars as-is. diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index cf503d5113..b94419a09d 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.162 2010/04/19 00:55:25 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.163 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -83,30 +83,20 @@ static bool finalize_primnode(Node *node, finalize_primnode_context *context); /* - * Generate a Param node to replace the given Var, - * which is expected to have varlevelsup > 0 (ie, it is not local). + * Select a PARAM_EXEC number to identify the given Var. + * If the Var already has a param slot, return that one. */ -static Param * -replace_outer_var(PlannerInfo *root, Var *var) +static int +assign_param_for_var(PlannerInfo *root, Var *var) { - Param *retval; ListCell *ppl; PlannerParamItem *pitem; Index abslevel; int i; - Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level); abslevel = root->query_level - var->varlevelsup; - /* - * If there's already a paramlist entry for this same Var, just use it. - * NOTE: in sufficiently complex querytrees, it is possible for the same - * varno/abslevel to refer to different RTEs in different parts of the - * parsetree, so that different fields might end up sharing the same Param - * number. As long as we check the vartype/typmod as well, I believe that - * this sort of aliasing will cause no trouble. The correct field should - * get stored into the Param slot at execution in each part of the tree. - */ + /* If there's already a paramlist entry for this same Var, just use it */ i = 0; foreach(ppl, root->glob->paramlist) { @@ -119,24 +109,76 @@ replace_outer_var(PlannerInfo *root, Var *var) pvar->varattno == var->varattno && pvar->vartype == var->vartype && pvar->vartypmod == var->vartypmod) - break; + return i; } i++; } - if (!ppl) - { - /* Nope, so make a new one */ - var = (Var *) copyObject(var); - var->varlevelsup = 0; + /* Nope, so make a new one */ + var = (Var *) copyObject(var); + var->varlevelsup = 0; - pitem = makeNode(PlannerParamItem); - pitem->item = (Node *) var; - pitem->abslevel = abslevel; + pitem = makeNode(PlannerParamItem); + pitem->item = (Node *) var; + pitem->abslevel = abslevel; - root->glob->paramlist = lappend(root->glob->paramlist, pitem); - /* i is already the correct index for the new item */ - } + root->glob->paramlist = lappend(root->glob->paramlist, pitem); + + /* i is already the correct list index for the new item */ + return i; +} + +/* + * Generate a Param node to replace the given Var, + * which is expected to have varlevelsup > 0 (ie, it is not local). + */ +static Param * +replace_outer_var(PlannerInfo *root, Var *var) +{ + Param *retval; + int i; + + Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level); + + /* + * Find the Var in root->glob->paramlist, or add it if not present. + * + * NOTE: in sufficiently complex querytrees, it is possible for the same + * varno/abslevel to refer to different RTEs in different parts of the + * parsetree, so that different fields might end up sharing the same Param + * number. As long as we check the vartype/typmod as well, I believe that + * this sort of aliasing will cause no trouble. The correct field should + * get stored into the Param slot at execution in each part of the tree. + */ + i = assign_param_for_var(root, var); + + retval = makeNode(Param); + retval->paramkind = PARAM_EXEC; + retval->paramid = i; + retval->paramtype = var->vartype; + retval->paramtypmod = var->vartypmod; + retval->location = -1; + + return retval; +} + +/* + * Generate a Param node to replace the given Var, which will be supplied + * from an upper NestLoop join node. + * + * Because we allow nestloop and subquery Params to alias each other, + * this is effectively the same as replace_outer_var, except that we expect + * the Var to be local to the current query level. + */ +Param * +assign_nestloop_param(PlannerInfo *root, Var *var) +{ + Param *retval; + int i; + + Assert(var->varlevelsup == 0); + + i = assign_param_for_var(root, var); retval = makeNode(Param); retval->paramkind = PARAM_EXEC; @@ -1773,8 +1815,9 @@ SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans) * * Note: this is a bit overly generous since some parameters of upper * query levels might belong to query subtrees that don't include this - * query. However, valid_params is only a debugging crosscheck, so it - * doesn't seem worth expending lots of cycles to try to be exact. + * query, or might be nestloop params that won't be passed down at all. + * However, valid_params is only a debugging crosscheck, so it doesn't + * seem worth expending lots of cycles to try to be exact. */ valid_params = bms_copy(initSetParam); paramid = 0; @@ -1849,6 +1892,8 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, { finalize_primnode_context context; int locally_added_param; + Bitmapset *nestloop_params; + Bitmapset *child_params; if (plan == NULL) return NULL; @@ -1856,6 +1901,7 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, context.root = root; context.paramids = NULL; /* initialize set to empty */ locally_added_param = -1; /* there isn't one */ + nestloop_params = NULL; /* there aren't any */ /* * When we call finalize_primnode, context.paramids sets are automatically @@ -2056,8 +2102,20 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, break; case T_NestLoop: - finalize_primnode((Node *) ((Join *) plan)->joinqual, - &context); + { + ListCell *l; + + finalize_primnode((Node *) ((Join *) plan)->joinqual, + &context); + /* collect set of params that will be passed to right child */ + foreach(l, ((NestLoop *) plan)->nestParams) + { + NestLoopParam *nlp = (NestLoopParam *) lfirst(l); + + nestloop_params = bms_add_member(nestloop_params, + nlp->paramno); + } + } break; case T_MergeJoin: @@ -2120,17 +2178,32 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, } /* Process left and right child plans, if any */ - context.paramids = bms_add_members(context.paramids, - finalize_plan(root, - plan->lefttree, - valid_params, - scan_params)); + child_params = finalize_plan(root, + plan->lefttree, + valid_params, + scan_params); + context.paramids = bms_add_members(context.paramids, child_params); - context.paramids = bms_add_members(context.paramids, - finalize_plan(root, - plan->righttree, - valid_params, - scan_params)); + if (nestloop_params) + { + /* right child can reference nestloop_params as well as valid_params */ + child_params = finalize_plan(root, + plan->righttree, + bms_union(nestloop_params, valid_params), + scan_params); + /* ... and they don't count as parameters used at my level */ + child_params = bms_difference(child_params, nestloop_params); + bms_free(nestloop_params); + } + else + { + /* easy case */ + child_params = finalize_plan(root, + plan->righttree, + valid_params, + scan_params); + } + context.paramids = bms_add_members(context.paramids, child_params); /* * Any locally generated parameter doesn't count towards its generating diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 119cc2505b..ecaaab5f75 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.169 2010/07/09 14:06:01 rhaas Exp $ + * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.170 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,7 +82,7 @@ extern PGDLLIMPORT ExecutorCheckPerms_hook_type ExecutorCheckPerms_hook; /* * prototypes from functions in execAmi.c */ -extern void ExecReScan(PlanState *node, ExprContext *exprCtxt); +extern void ExecReScan(PlanState *node); extern void ExecMarkPos(PlanState *node); extern void ExecRestrPos(PlanState *node); extern bool ExecSupportsMarkRestore(NodeTag plantype); diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h index 67cc71c84b..5e7ab5913b 100644 --- a/src/include/executor/nodeAgg.h +++ b/src/include/executor/nodeAgg.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeAgg.h,v 1.32 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeAgg.h,v 1.33 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,7 @@ extern AggState *ExecInitAgg(Agg *node, EState *estate, int eflags); extern TupleTableSlot *ExecAgg(AggState *node); extern void ExecEndAgg(AggState *node); -extern void ExecReScanAgg(AggState *node, ExprContext *exprCtxt); +extern void ExecReScanAgg(AggState *node); extern Size hash_agg_entry_size(int numAggs); diff --git a/src/include/executor/nodeAppend.h b/src/include/executor/nodeAppend.h index fbecd82049..9e3f293785 100644 --- a/src/include/executor/nodeAppend.h +++ b/src/include/executor/nodeAppend.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeAppend.h,v 1.30 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeAppend.h,v 1.31 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern AppendState *ExecInitAppend(Append *node, EState *estate, int eflags); extern TupleTableSlot *ExecAppend(AppendState *node); extern void ExecEndAppend(AppendState *node); -extern void ExecReScanAppend(AppendState *node, ExprContext *exprCtxt); +extern void ExecReScanAppend(AppendState *node); #endif /* NODEAPPEND_H */ diff --git a/src/include/executor/nodeBitmapAnd.h b/src/include/executor/nodeBitmapAnd.h index 6a8bdf4363..fa09a790fb 100644 --- a/src/include/executor/nodeBitmapAnd.h +++ b/src/include/executor/nodeBitmapAnd.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeBitmapAnd.h,v 1.8 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeBitmapAnd.h,v 1.9 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern BitmapAndState *ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags); extern Node *MultiExecBitmapAnd(BitmapAndState *node); extern void ExecEndBitmapAnd(BitmapAndState *node); -extern void ExecReScanBitmapAnd(BitmapAndState *node, ExprContext *exprCtxt); +extern void ExecReScanBitmapAnd(BitmapAndState *node); #endif /* NODEBITMAPAND_H */ diff --git a/src/include/executor/nodeBitmapHeapscan.h b/src/include/executor/nodeBitmapHeapscan.h index 174f60dd0a..472181881f 100644 --- a/src/include/executor/nodeBitmapHeapscan.h +++ b/src/include/executor/nodeBitmapHeapscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeBitmapHeapscan.h,v 1.8 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeBitmapHeapscan.h,v 1.9 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern BitmapHeapScanState *ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags); extern TupleTableSlot *ExecBitmapHeapScan(BitmapHeapScanState *node); extern void ExecEndBitmapHeapScan(BitmapHeapScanState *node); -extern void ExecBitmapHeapReScan(BitmapHeapScanState *node, ExprContext *exprCtxt); +extern void ExecReScanBitmapHeapScan(BitmapHeapScanState *node); #endif /* NODEBITMAPHEAPSCAN_H */ diff --git a/src/include/executor/nodeBitmapIndexscan.h b/src/include/executor/nodeBitmapIndexscan.h index 480494be0c..bb4b28cc1a 100644 --- a/src/include/executor/nodeBitmapIndexscan.h +++ b/src/include/executor/nodeBitmapIndexscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeBitmapIndexscan.h,v 1.8 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeBitmapIndexscan.h,v 1.9 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern BitmapIndexScanState *ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags); extern Node *MultiExecBitmapIndexScan(BitmapIndexScanState *node); extern void ExecEndBitmapIndexScan(BitmapIndexScanState *node); -extern void ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt); +extern void ExecReScanBitmapIndexScan(BitmapIndexScanState *node); #endif /* NODEBITMAPINDEXSCAN_H */ diff --git a/src/include/executor/nodeBitmapOr.h b/src/include/executor/nodeBitmapOr.h index a9ada8f63f..8987c700c5 100644 --- a/src/include/executor/nodeBitmapOr.h +++ b/src/include/executor/nodeBitmapOr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeBitmapOr.h,v 1.8 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeBitmapOr.h,v 1.9 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern BitmapOrState *ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags); extern Node *MultiExecBitmapOr(BitmapOrState *node); extern void ExecEndBitmapOr(BitmapOrState *node); -extern void ExecReScanBitmapOr(BitmapOrState *node, ExprContext *exprCtxt); +extern void ExecReScanBitmapOr(BitmapOrState *node); #endif /* NODEBITMAPOR_H */ diff --git a/src/include/executor/nodeCtescan.h b/src/include/executor/nodeCtescan.h index 54008f8b74..22e6dd2152 100644 --- a/src/include/executor/nodeCtescan.h +++ b/src/include/executor/nodeCtescan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeCtescan.h,v 1.4 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeCtescan.h,v 1.5 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern CteScanState *ExecInitCteScan(CteScan *node, EState *estate, int eflags); extern TupleTableSlot *ExecCteScan(CteScanState *node); extern void ExecEndCteScan(CteScanState *node); -extern void ExecCteScanReScan(CteScanState *node, ExprContext *exprCtxt); +extern void ExecReScanCteScan(CteScanState *node); #endif /* NODECTESCAN_H */ diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h index 21e868aff6..1584783ed0 100644 --- a/src/include/executor/nodeFunctionscan.h +++ b/src/include/executor/nodeFunctionscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeFunctionscan.h,v 1.15 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeFunctionscan.h,v 1.16 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags); extern TupleTableSlot *ExecFunctionScan(FunctionScanState *node); extern void ExecEndFunctionScan(FunctionScanState *node); -extern void ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt); +extern void ExecReScanFunctionScan(FunctionScanState *node); #endif /* NODEFUNCTIONSCAN_H */ diff --git a/src/include/executor/nodeGroup.h b/src/include/executor/nodeGroup.h index a7362b2a79..8af917a83f 100644 --- a/src/include/executor/nodeGroup.h +++ b/src/include/executor/nodeGroup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeGroup.h,v 1.35 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeGroup.h,v 1.36 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern GroupState *ExecInitGroup(Group *node, EState *estate, int eflags); extern TupleTableSlot *ExecGroup(GroupState *node); extern void ExecEndGroup(GroupState *node); -extern void ExecReScanGroup(GroupState *node, ExprContext *exprCtxt); +extern void ExecReScanGroup(GroupState *node); #endif /* NODEGROUP_H */ diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h index c5e18a93e7..53348c435f 100644 --- a/src/include/executor/nodeHash.h +++ b/src/include/executor/nodeHash.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.49 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.50 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,7 @@ extern HashState *ExecInitHash(Hash *node, EState *estate, int eflags); extern TupleTableSlot *ExecHash(HashState *node); extern Node *MultiExecHash(HashState *node); extern void ExecEndHash(HashState *node); -extern void ExecReScanHash(HashState *node, ExprContext *exprCtxt); +extern void ExecReScanHash(HashState *node); extern HashJoinTable ExecHashTableCreate(Hash *node, List *hashOperators); extern void ExecHashTableDestroy(HashJoinTable hashtable); diff --git a/src/include/executor/nodeHashjoin.h b/src/include/executor/nodeHashjoin.h index 462410d95c..0a68e65f51 100644 --- a/src/include/executor/nodeHashjoin.h +++ b/src/include/executor/nodeHashjoin.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeHashjoin.h,v 1.40 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeHashjoin.h,v 1.41 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,7 @@ extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate, int eflags); extern TupleTableSlot *ExecHashJoin(HashJoinState *node); extern void ExecEndHashJoin(HashJoinState *node); -extern void ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt); +extern void ExecReScanHashJoin(HashJoinState *node); extern void ExecHashJoinSaveTuple(MinimalTuple tuple, uint32 hashvalue, BufFile **fileptr); diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h index 15608cdff8..2a740a4f3e 100644 --- a/src/include/executor/nodeIndexscan.h +++ b/src/include/executor/nodeIndexscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeIndexscan.h,v 1.36 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeIndexscan.h,v 1.37 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,7 +21,7 @@ extern TupleTableSlot *ExecIndexScan(IndexScanState *node); extern void ExecEndIndexScan(IndexScanState *node); extern void ExecIndexMarkPos(IndexScanState *node); extern void ExecIndexRestrPos(IndexScanState *node); -extern void ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt); +extern void ExecReScanIndexScan(IndexScanState *node); /* routines exported to share code with nodeBitmapIndexscan.c */ extern void ExecIndexBuildScanKeys(PlanState *planstate, Relation index, diff --git a/src/include/executor/nodeLimit.h b/src/include/executor/nodeLimit.h index 33cd5e298d..1e57eca559 100644 --- a/src/include/executor/nodeLimit.h +++ b/src/include/executor/nodeLimit.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeLimit.h,v 1.18 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeLimit.h,v 1.19 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern LimitState *ExecInitLimit(Limit *node, EState *estate, int eflags); extern TupleTableSlot *ExecLimit(LimitState *node); extern void ExecEndLimit(LimitState *node); -extern void ExecReScanLimit(LimitState *node, ExprContext *exprCtxt); +extern void ExecReScanLimit(LimitState *node); #endif /* NODELIMIT_H */ diff --git a/src/include/executor/nodeLockRows.h b/src/include/executor/nodeLockRows.h index c2ea69611e..b3bb3a277c 100644 --- a/src/include/executor/nodeLockRows.h +++ b/src/include/executor/nodeLockRows.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeLockRows.h,v 1.2 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeLockRows.h,v 1.3 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern LockRowsState *ExecInitLockRows(LockRows *node, EState *estate, int eflags); extern TupleTableSlot *ExecLockRows(LockRowsState *node); extern void ExecEndLockRows(LockRowsState *node); -extern void ExecReScanLockRows(LockRowsState *node, ExprContext *exprCtxt); +extern void ExecReScanLockRows(LockRowsState *node); #endif /* NODELOCKROWS_H */ diff --git a/src/include/executor/nodeMaterial.h b/src/include/executor/nodeMaterial.h index bc350d1bde..ff1087b0cc 100644 --- a/src/include/executor/nodeMaterial.h +++ b/src/include/executor/nodeMaterial.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeMaterial.h,v 1.30 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeMaterial.h,v 1.31 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,6 @@ extern TupleTableSlot *ExecMaterial(MaterialState *node); extern void ExecEndMaterial(MaterialState *node); extern void ExecMaterialMarkPos(MaterialState *node); extern void ExecMaterialRestrPos(MaterialState *node); -extern void ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt); +extern void ExecReScanMaterial(MaterialState *node); #endif /* NODEMATERIAL_H */ diff --git a/src/include/executor/nodeMergejoin.h b/src/include/executor/nodeMergejoin.h index 24b4835ec0..6a176d90f0 100644 --- a/src/include/executor/nodeMergejoin.h +++ b/src/include/executor/nodeMergejoin.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeMergejoin.h,v 1.29 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeMergejoin.h,v 1.30 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags); extern TupleTableSlot *ExecMergeJoin(MergeJoinState *node); extern void ExecEndMergeJoin(MergeJoinState *node); -extern void ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt); +extern void ExecReScanMergeJoin(MergeJoinState *node); #endif /* NODEMERGEJOIN_H */ diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h index a503581943..373ae1c13f 100644 --- a/src/include/executor/nodeModifyTable.h +++ b/src/include/executor/nodeModifyTable.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeModifyTable.h,v 1.2 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeModifyTable.h,v 1.3 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,6 @@ extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags); extern TupleTableSlot *ExecModifyTable(ModifyTableState *node); extern void ExecEndModifyTable(ModifyTableState *node); -extern void ExecReScanModifyTable(ModifyTableState *node, ExprContext *exprCtxt); +extern void ExecReScanModifyTable(ModifyTableState *node); #endif /* NODEMODIFYTABLE_H */ diff --git a/src/include/executor/nodeNestloop.h b/src/include/executor/nodeNestloop.h index ce960de8f2..01e22b6082 100644 --- a/src/include/executor/nodeNestloop.h +++ b/src/include/executor/nodeNestloop.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeNestloop.h,v 1.30 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeNestloop.h,v 1.31 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate, int eflags); extern TupleTableSlot *ExecNestLoop(NestLoopState *node); extern void ExecEndNestLoop(NestLoopState *node); -extern void ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt); +extern void ExecReScanNestLoop(NestLoopState *node); #endif /* NODENESTLOOP_H */ diff --git a/src/include/executor/nodeRecursiveunion.h b/src/include/executor/nodeRecursiveunion.h index 8d8c99b0e6..87d9888f86 100644 --- a/src/include/executor/nodeRecursiveunion.h +++ b/src/include/executor/nodeRecursiveunion.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeRecursiveunion.h,v 1.4 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeRecursiveunion.h,v 1.5 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern RecursiveUnionState *ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags); extern TupleTableSlot *ExecRecursiveUnion(RecursiveUnionState *node); extern void ExecEndRecursiveUnion(RecursiveUnionState *node); -extern void ExecRecursiveUnionReScan(RecursiveUnionState *node, ExprContext *exprCtxt); +extern void ExecReScanRecursiveUnion(RecursiveUnionState *node); #endif /* NODERECURSIVEUNION_H */ diff --git a/src/include/executor/nodeResult.h b/src/include/executor/nodeResult.h index 89085e8945..4c6234d688 100644 --- a/src/include/executor/nodeResult.h +++ b/src/include/executor/nodeResult.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeResult.h,v 1.28 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeResult.h,v 1.29 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,6 @@ extern TupleTableSlot *ExecResult(ResultState *node); extern void ExecEndResult(ResultState *node); extern void ExecResultMarkPos(ResultState *node); extern void ExecResultRestrPos(ResultState *node); -extern void ExecReScanResult(ResultState *node, ExprContext *exprCtxt); +extern void ExecReScanResult(ResultState *node); #endif /* NODERESULT_H */ diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h index 6184c3edcd..334fd44920 100644 --- a/src/include/executor/nodeSeqscan.h +++ b/src/include/executor/nodeSeqscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeSeqscan.h,v 1.29 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeSeqscan.h,v 1.30 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,6 @@ extern TupleTableSlot *ExecSeqScan(SeqScanState *node); extern void ExecEndSeqScan(SeqScanState *node); extern void ExecSeqMarkPos(SeqScanState *node); extern void ExecSeqRestrPos(SeqScanState *node); -extern void ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt); +extern void ExecReScanSeqScan(SeqScanState *node); #endif /* NODESEQSCAN_H */ diff --git a/src/include/executor/nodeSetOp.h b/src/include/executor/nodeSetOp.h index 791b6595aa..cdb0579afd 100644 --- a/src/include/executor/nodeSetOp.h +++ b/src/include/executor/nodeSetOp.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeSetOp.h,v 1.18 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeSetOp.h,v 1.19 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate, int eflags); extern TupleTableSlot *ExecSetOp(SetOpState *node); extern void ExecEndSetOp(SetOpState *node); -extern void ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt); +extern void ExecReScanSetOp(SetOpState *node); #endif /* NODESETOP_H */ diff --git a/src/include/executor/nodeSort.h b/src/include/executor/nodeSort.h index d5a87e8923..ee63274af2 100644 --- a/src/include/executor/nodeSort.h +++ b/src/include/executor/nodeSort.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeSort.h,v 1.27 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeSort.h,v 1.28 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,6 @@ extern TupleTableSlot *ExecSort(SortState *node); extern void ExecEndSort(SortState *node); extern void ExecSortMarkPos(SortState *node); extern void ExecSortRestrPos(SortState *node); -extern void ExecReScanSort(SortState *node, ExprContext *exprCtxt); +extern void ExecReScanSort(SortState *node); #endif /* NODESORT_H */ diff --git a/src/include/executor/nodeSubqueryscan.h b/src/include/executor/nodeSubqueryscan.h index 387a12b045..1139ce3f3e 100644 --- a/src/include/executor/nodeSubqueryscan.h +++ b/src/include/executor/nodeSubqueryscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeSubqueryscan.h,v 1.18 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeSubqueryscan.h,v 1.19 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags); extern TupleTableSlot *ExecSubqueryScan(SubqueryScanState *node); extern void ExecEndSubqueryScan(SubqueryScanState *node); -extern void ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt); +extern void ExecReScanSubqueryScan(SubqueryScanState *node); #endif /* NODESUBQUERYSCAN_H */ diff --git a/src/include/executor/nodeTidscan.h b/src/include/executor/nodeTidscan.h index 1bbbb1e52f..45b9b814cb 100644 --- a/src/include/executor/nodeTidscan.h +++ b/src/include/executor/nodeTidscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeTidscan.h,v 1.22 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeTidscan.h,v 1.23 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,6 @@ extern TupleTableSlot *ExecTidScan(TidScanState *node); extern void ExecEndTidScan(TidScanState *node); extern void ExecTidMarkPos(TidScanState *node); extern void ExecTidRestrPos(TidScanState *node); -extern void ExecTidReScan(TidScanState *node, ExprContext *exprCtxt); +extern void ExecReScanTidScan(TidScanState *node); #endif /* NODETIDSCAN_H */ diff --git a/src/include/executor/nodeUnique.h b/src/include/executor/nodeUnique.h index 4fd4d92d4d..1c57a23fb1 100644 --- a/src/include/executor/nodeUnique.h +++ b/src/include/executor/nodeUnique.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeUnique.h,v 1.27 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeUnique.h,v 1.28 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern UniqueState *ExecInitUnique(Unique *node, EState *estate, int eflags); extern TupleTableSlot *ExecUnique(UniqueState *node); extern void ExecEndUnique(UniqueState *node); -extern void ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt); +extern void ExecReScanUnique(UniqueState *node); #endif /* NODEUNIQUE_H */ diff --git a/src/include/executor/nodeValuesscan.h b/src/include/executor/nodeValuesscan.h index 81b2f4108d..049d66923a 100644 --- a/src/include/executor/nodeValuesscan.h +++ b/src/include/executor/nodeValuesscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeValuesscan.h,v 1.7 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeValuesscan.h,v 1.8 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,6 @@ extern TupleTableSlot *ExecValuesScan(ValuesScanState *node); extern void ExecEndValuesScan(ValuesScanState *node); extern void ExecValuesMarkPos(ValuesScanState *node); extern void ExecValuesRestrPos(ValuesScanState *node); -extern void ExecValuesReScan(ValuesScanState *node, ExprContext *exprCtxt); +extern void ExecReScanValuesScan(ValuesScanState *node); #endif /* NODEVALUESSCAN_H */ diff --git a/src/include/executor/nodeWindowAgg.h b/src/include/executor/nodeWindowAgg.h index 759120a7e7..5e944e45a8 100644 --- a/src/include/executor/nodeWindowAgg.h +++ b/src/include/executor/nodeWindowAgg.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeWindowAgg.h,v 1.4 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeWindowAgg.h,v 1.5 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern WindowAggState *ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags); extern TupleTableSlot *ExecWindowAgg(WindowAggState *node); extern void ExecEndWindowAgg(WindowAggState *node); -extern void ExecReScanWindowAgg(WindowAggState *node, ExprContext *exprCtxt); +extern void ExecReScanWindowAgg(WindowAggState *node); #endif /* NODEWINDOWAGG_H */ diff --git a/src/include/executor/nodeWorktablescan.h b/src/include/executor/nodeWorktablescan.h index cda6d0a91e..53e465ce33 100644 --- a/src/include/executor/nodeWorktablescan.h +++ b/src/include/executor/nodeWorktablescan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/nodeWorktablescan.h,v 1.4 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/executor/nodeWorktablescan.h,v 1.5 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,6 @@ extern WorkTableScanState *ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags); extern TupleTableSlot *ExecWorkTableScan(WorkTableScanState *node); extern void ExecEndWorkTableScan(WorkTableScanState *node); -extern void ExecWorkTableScanReScan(WorkTableScanState *node, ExprContext *exprCtxt); +extern void ExecReScanWorkTableScan(WorkTableScanState *node); #endif /* NODEWORKTABLESCAN_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 401b69e088..24ddb3f0d3 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.234 2010/03/28 22:59:33 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.235 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -74,6 +74,7 @@ typedef enum NodeTag T_LockRows, T_Limit, /* these aren't subclasses of Plan: */ + T_NestLoopParam, T_PlanRowMark, T_PlanInvalItem, diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 79876100d5..5ca1b0f8fb 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.117 2010/02/26 02:01:25 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.118 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -432,13 +432,26 @@ typedef struct Join /* ---------------- * nest loop join node + * + * The nestParams list identifies any executor Params that must be passed + * into execution of the inner subplan carrying values from the current row + * of the outer subplan. Currently we restrict these values to be simple + * Vars, but perhaps someday that'd be worth relaxing. * ---------------- */ typedef struct NestLoop { Join join; + List *nestParams; /* list of NestLoopParam nodes */ } NestLoop; +typedef struct NestLoopParam +{ + NodeTag type; + int paramno; /* number of the PARAM_EXEC Param to set */ + Var *paramval; /* outer-relation Var to assign to Param */ +} NestLoopParam; + /* ---------------- * merge join node * diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 3fc3d3483b..484eb0d627 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.156 2010/02/26 02:01:25 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.157 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -175,7 +175,8 @@ typedef struct Const * Such parameters are numbered from 1 to n. * * PARAM_EXEC: The parameter is an internal executor parameter, used - * for passing values into and out of sub-queries. + * for passing values into and out of sub-queries or from + * nestloop joins to their inner scans. * For historical reasons, such parameters are numbered from 0. * These numbers are independent of PARAM_EXTERN numbers. * diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index a684f19222..3374e5fae7 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.187 2010/07/06 19:19:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.188 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -209,6 +209,10 @@ typedef struct PlannerInfo int wt_param_id; /* PARAM_EXEC ID for the work table */ struct Plan *non_recursive_plan; /* plan for non-recursive term */ + /* These fields are workspace for createplan.c */ + Relids curOuterRels; /* outer rels above current node */ + List *curOuterParams; /* not-yet-assigned NestLoopParams */ + /* optional private data for join_search_hook, e.g., GEQO */ void *join_search_private; } PlannerInfo; @@ -1330,16 +1334,20 @@ typedef struct PlaceHolderInfo /* * glob->paramlist keeps track of the PARAM_EXEC slots that we have decided * we need for the query. At runtime these slots are used to pass values - * either down into subqueries (for outer references in subqueries) or up out - * of subqueries (for the results of a subplan). The n'th entry in the list - * (n counts from 0) corresponds to Param->paramid = n. + * around from one plan node to another. They can be used to pass values + * down into subqueries (for outer references in subqueries), or up out of + * subqueries (for the results of a subplan), or from a NestLoop plan node + * into its inner relation (when the inner scan is parameterized with values + * from the outer relation). The n'th entry in the list (n counts from 0) + * corresponds to Param->paramid = n. * * Each paramlist item shows the absolute query level it is associated with, * where the outermost query is level 1 and nested subqueries have higher * numbers. The item the parameter slot represents can be one of three kinds: * * A Var: the slot represents a variable of that level that must be passed - * down because subqueries have outer references to it. The varlevelsup + * down because subqueries have outer references to it, or must be passed + * from a NestLoop node of that level to its inner scan. The varlevelsup * value in the Var will always be zero. * * An Aggref (with an expression tree representing its argument): the slot @@ -1352,7 +1360,13 @@ typedef struct PlaceHolderInfo * to the parent query of the subplan. * * Note: we detect duplicate Var parameters and coalesce them into one slot, - * but we do not do this for Aggref or Param slots. + * but we do not bother to do this for Aggrefs, and it would be incorrect + * to do so for Param slots. Duplicate detection is actually *necessary* + * in the case of NestLoop parameters since it serves to match up the usage + * of a Param (in the inner scan) with the assignment of the value (in the + * NestLoop node). This might result in the same PARAM_EXEC slot being used + * by multiple NestLoop nodes or SubPlan nodes, but no harm is done since + * the same value would be assigned anyway. */ typedef struct PlannerParamItem { diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h index 1bc52cc14c..abbbd58c24 100644 --- a/src/include/optimizer/subselect.h +++ b/src/include/optimizer/subselect.h @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.39 2010/01/02 16:58:07 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.40 2010/07/12 17:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,6 +29,7 @@ extern void SS_finalize_plan(PlannerInfo *root, Plan *plan, bool attach_initplans); extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan, Oid resulttype, int32 resulttypmod); +extern Param *assign_nestloop_param(PlannerInfo *root, Var *var); extern int SS_assign_special_param(PlannerInfo *root); #endif /* SUBSELECT_H */ diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index 66736a3564..f1466e0d44 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -281,7 +281,7 @@ INSERT INTO foorescan values(5007,5,'abc.5007.5'); INSERT INTO foorescan values(5008,5,'abc.5008.5'); INSERT INTO foorescan values(5009,5,'abc.5009.5'); CREATE FUNCTION foorescan(int,int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid >= $1 and fooid < $2 ;' LANGUAGE SQL; ---invokes ExecFunctionReScan +--invokes ExecReScanFunctionScan SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,5004)) ORDER BY 1,2; fooid | foosubid | fooname -------+----------+------------ @@ -298,7 +298,7 @@ SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,500 (10 rows) CREATE VIEW vw_foorescan AS SELECT * FROM foorescan(5002,5004); ---invokes ExecFunctionReScan +--invokes ExecReScanFunctionScan SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM vw_foorescan) ORDER BY 1,2; fooid | foosubid | fooname -------+----------+------------ @@ -323,7 +323,7 @@ INSERT INTO barrescan values(5006); INSERT INTO barrescan values(5007); INSERT INTO barrescan values(5008); CREATE FUNCTION foorescan(int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid = $1;' LANGUAGE SQL; ---invokes ExecFunctionReScan with chgParam != NULL +--invokes ExecReScanFunctionScan with chgParam != NULL SELECT f.* FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) ORDER BY 1,2; fooid | foosubid | fooname -------+----------+------------ diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql index db74770228..d1b9db7e51 100644 --- a/src/test/regress/sql/rangefuncs.sql +++ b/src/test/regress/sql/rangefuncs.sql @@ -164,12 +164,12 @@ INSERT INTO foorescan values(5009,5,'abc.5009.5'); CREATE FUNCTION foorescan(int,int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid >= $1 and fooid < $2 ;' LANGUAGE SQL; ---invokes ExecFunctionReScan +--invokes ExecReScanFunctionScan SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM foorescan(5002,5004)) ORDER BY 1,2; CREATE VIEW vw_foorescan AS SELECT * FROM foorescan(5002,5004); ---invokes ExecFunctionReScan +--invokes ExecReScanFunctionScan SELECT * FROM foorescan f WHERE f.fooid IN (SELECT fooid FROM vw_foorescan) ORDER BY 1,2; CREATE TABLE barrescan (fooid int primary key); @@ -182,7 +182,7 @@ INSERT INTO barrescan values(5008); CREATE FUNCTION foorescan(int) RETURNS setof foorescan AS 'SELECT * FROM foorescan WHERE fooid = $1;' LANGUAGE SQL; ---invokes ExecFunctionReScan with chgParam != NULL +--invokes ExecReScanFunctionScan with chgParam != NULL SELECT f.* FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) ORDER BY 1,2; SELECT b.fooid, max(f.foosubid) FROM barrescan b, foorescan f WHERE f.fooid = b.fooid AND b.fooid IN (SELECT fooid FROM foorescan(b.fooid)) GROUP BY b.fooid ORDER BY 1,2;