aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeSubplan.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-10-04 21:56:55 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-10-04 21:56:55 +0000
commit44d5be0e5308e951c0c5dc522b4bcacf2bcbc476 (patch)
tree516f1c70436225751f631e7e686f7ea61b3db9df /src/backend/executor/nodeSubplan.c
parent607b2be7bb230ea4c558cb3101794f94de35ab85 (diff)
downloadpostgresql-44d5be0e5308e951c0c5dc522b4bcacf2bcbc476.tar.gz
postgresql-44d5be0e5308e951c0c5dc522b4bcacf2bcbc476.zip
Implement SQL-standard WITH clauses, including WITH RECURSIVE.
There are some unimplemented aspects: recursive queries must use UNION ALL (should allow UNION too), and we don't have SEARCH or CYCLE clauses. These might or might not get done for 8.4, but even without them it's a pretty useful feature. There are also a couple of small loose ends and definitional quibbles, which I'll send a memo about to pgsql-hackers shortly. But let's land the patch now so we can get on with other development. Yoshiyuki Asaba, with lots of help from Tatsuo Ishii and Tom Lane
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);
}
}