diff options
Diffstat (limited to 'src/backend/executor/nodeSubplan.c')
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 3ebb045f922..338d94e7608 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.94 2008/08/22 00:16:03 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.95 2008/10/04 21:56:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -66,9 +66,13 @@ ExecSubPlan(SubPlanState *node, if (isDone) *isDone = ExprSingleResult; + /* Sanity checks */ + if (subplan->subLinkType == CTE_SUBLINK) + elog(ERROR, "CTE subplans should not be executed via ExecSubPlan"); if (subplan->setParam != NIL) elog(ERROR, "cannot set parent params from subquery"); + /* Select appropriate evaluation strategy */ if (subplan->useHashTable) return ExecHashSubPlan(node, econtext, isNull); else @@ -688,11 +692,14 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) * If this plan is un-correlated or undirect correlated one and want to * set params for parent plan then mark parameters as needing evaluation. * + * A CTE subplan's output parameter is never to be evaluated in the normal + * way, so skip this in that case. + * * Note that in the case of un-correlated subqueries we don't care about * setting parent->chgParam here: indices take care about it, for others - * it doesn't matter... */ - if (subplan->setParam != NIL) + if (subplan->setParam != NIL && subplan->subLinkType != CTE_SUBLINK) { ListCell *lst; @@ -907,22 +914,21 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) bool found = false; ArrayBuildState *astate = NULL; - /* - * Must switch to per-query memory context. - */ - oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); - if (subLinkType == ANY_SUBLINK || subLinkType == ALL_SUBLINK) elog(ERROR, "ANY/ALL subselect unsupported as initplan"); + if (subLinkType == CTE_SUBLINK) + elog(ERROR, "CTE subplans should not be executed via ExecSetParamPlan"); /* - * By definition, an initplan has no parameters from our query level, but - * it could have some from an outer level. Rescan it if needed. + * Must switch to per-query memory context. */ - if (planstate->chgParam != NULL) - ExecReScan(planstate, NULL); + oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); + /* + * Run the plan. (If it needs to be rescanned, the first ExecProcNode + * call will take care of that.) + */ for (slot = ExecProcNode(planstate); !TupIsNull(slot); slot = ExecProcNode(planstate)) @@ -932,7 +938,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) if (subLinkType == EXISTS_SUBLINK) { - /* There can be only one param... */ + /* There can be only one setParam... */ int paramid = linitial_int(subplan->setParam); ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); @@ -994,7 +1000,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) if (subLinkType == ARRAY_SUBLINK) { - /* There can be only one param... */ + /* There can be only one setParam... */ int paramid = linitial_int(subplan->setParam); ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); @@ -1014,7 +1020,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) { if (subLinkType == EXISTS_SUBLINK) { - /* There can be only one param... */ + /* There can be only one setParam... */ int paramid = linitial_int(subplan->setParam); ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); @@ -1059,18 +1065,25 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) elog(ERROR, "extParam set of initplan is empty"); /* - * Don't actually re-scan: ExecSetParamPlan does it if needed. + * Don't actually re-scan: it'll happen inside ExecSetParamPlan if needed. */ /* - * Mark this subplan's output parameters as needing recalculation + * Mark this subplan's output parameters as needing recalculation. + * + * CTE subplans are never executed via parameter recalculation; instead + * they get run when called by nodeCtescan.c. So don't mark the output + * parameter of a CTE subplan as dirty, but do set the chgParam bit + * for it so that dependent plan nodes will get told to rescan. */ foreach(l, subplan->setParam) { int paramid = lfirst_int(l); ParamExecData *prm = &(estate->es_param_exec_vals[paramid]); - prm->execPlan = node; + if (subplan->subLinkType != CTE_SUBLINK) + prm->execPlan = node; + parent->chgParam = bms_add_member(parent->chgParam, paramid); } } |