aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeSubplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeSubplan.c')
-rw-r--r--src/backend/executor/nodeSubplan.c47
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);
}
}