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.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 3a2ca974aee..2f5ab52e213 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
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.38 2002/12/14 00:17:50 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.39 2002/12/15 16:17:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,9 +47,10 @@ ExecSubPlan(SubPlanState *node,
/*
* We are probably in a short-lived expression-evaluation context.
- * Switch to longer-lived per-query context.
+ * Switch to the child plan's per-query context for manipulating its
+ * chgParam, calling ExecProcNode on it, etc.
*/
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ oldcontext = MemoryContextSwitchTo(node->sub_estate->es_query_cxt);
if (subplan->setParam != NIL)
elog(ERROR, "ExecSubPlan: can't set parent params from subquery");
@@ -132,10 +133,13 @@ ExecSubPlan(SubPlanState *node,
* ExecProcNode() call. node->curTuple keeps track of the
* copied tuple for eventual freeing.
*/
+ MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
tup = heap_copytuple(tup);
if (node->curTuple)
heap_freetuple(node->curTuple);
node->curTuple = tup;
+ MemoryContextSwitchTo(node->sub_estate->es_query_cxt);
+
result = heap_getattr(tup, col, tdesc, isNull);
/* keep scanning subplan to make sure there's only one tuple */
continue;
@@ -295,6 +299,7 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
{
SubPlan *subplan = (SubPlan *) node->xprstate.expr;
EState *sp_estate;
+ MemoryContext oldcontext;
/*
* Do access checking on the rangetable entries in the subquery.
@@ -303,15 +308,23 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
/*
- * initialize state
+ * initialize my state
*/
node->needShutdown = false;
node->curTuple = NULL;
/*
* create an EState for the subplan
+ *
+ * The subquery needs its own EState because it has its own rangetable.
+ * It shares our Param ID space, however. XXX if rangetable access were
+ * done differently, the subquery could share our EState, which would
+ * eliminate some thrashing about in this module...
*/
sp_estate = CreateExecutorState();
+ node->sub_estate = sp_estate;
+
+ oldcontext = MemoryContextSwitchTo(sp_estate->es_query_cxt);
sp_estate->es_range_table = subplan->rtable;
sp_estate->es_param_list_info = estate->es_param_list_info;
@@ -322,12 +335,14 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
sp_estate->es_instrument = estate->es_instrument;
/*
- * Start up the subplan
+ * Start up the subplan (this is a very cut-down form of InitPlan())
*/
node->planstate = ExecInitNode(subplan->plan, sp_estate);
node->needShutdown = true; /* now we need to shutdown the subplan */
+ MemoryContextSwitchTo(oldcontext);
+
/*
* If this plan is un-correlated or undirect correlated one and want
* to set params for parent plan then prepare parameters.
@@ -376,10 +391,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
bool found = false;
/*
- * We are probably in a short-lived expression-evaluation context.
- * Switch to longer-lived per-query context.
+ * Must switch to child query's per-query memory context.
*/
- oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
+ oldcontext = MemoryContextSwitchTo(node->sub_estate->es_query_cxt);
if (subLinkType == ANY_SUBLINK ||
subLinkType == ALL_SUBLINK)
@@ -415,15 +429,18 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
found = true;
/*
- * We need to copy the subplan's tuple in case any of the params
- * are pass-by-ref type --- the pointers stored in the param
- * structs will point at this copied tuple! node->curTuple keeps
- * track of the copied tuple for eventual freeing.
+ * We need to copy the subplan's tuple into our own context,
+ * in case any of the params are pass-by-ref type --- the pointers
+ * stored in the param structs will point at this copied tuple!
+ * node->curTuple keeps track of the copied tuple for eventual
+ * freeing.
*/
+ MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
tup = heap_copytuple(tup);
if (node->curTuple)
heap_freetuple(node->curTuple);
node->curTuple = tup;
+ MemoryContextSwitchTo(node->sub_estate->es_query_cxt);
foreach(lst, subplan->setParam)
{
@@ -460,7 +477,10 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
if (planstate->plan->extParam == NULL) /* un-correlated ... */
{
- ExecEndNode(planstate);
+ ExecEndPlan(planstate, node->sub_estate);
+ /* mustn't free context while still in it... */
+ MemoryContextSwitchTo(oldcontext);
+ FreeExecutorState(node->sub_estate);
node->needShutdown = false;
}
@@ -476,7 +496,12 @@ ExecEndSubPlan(SubPlanState *node)
{
if (node->needShutdown)
{
- ExecEndNode(node->planstate);
+ MemoryContext oldcontext;
+
+ oldcontext = MemoryContextSwitchTo(node->sub_estate->es_query_cxt);
+ ExecEndPlan(node->planstate, node->sub_estate);
+ MemoryContextSwitchTo(oldcontext);
+ FreeExecutorState(node->sub_estate);
node->needShutdown = false;
}
if (node->curTuple)