1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

Get rid of the separate EState for subplans, and just let them share the

parent query's EState.  Now that there's a single flat rangetable for both
the main plan and subplans, there's no need anymore for a separate EState,
and removing it allows cleaning up some crufty code in nodeSubplan.c and
nodeSubqueryscan.c.  Should be a tad faster too, although any difference
will probably be hard to measure.  This is the last bit of subsidiary
mop-up work from changing to a flat rangetable.
This commit is contained in:
Tom Lane
2007-02-27 01:11:26 +00:00
parent 4756ff3dca
commit c7ff7663e4
15 changed files with 258 additions and 358 deletions

View File

@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.288 2007/02/22 22:00:22 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.289 2007/02/27 01:11:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -70,6 +70,7 @@ static void initResultRelInfo(ResultRelInfo *resultRelInfo,
List *rangeTable,
CmdType operation,
bool doInstrument);
static void ExecEndPlan(PlanState *planstate, EState *estate);
static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
CmdType operation,
long numberTuples,
@ -466,6 +467,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
PlanState *planstate;
TupleDesc tupType;
ListCell *l;
int i;
/*
* Do permissions checks
@ -551,15 +553,25 @@ InitPlan(QueryDesc *queryDesc, int eflags)
}
/*
* initialize the executor "tuple" table. We need slots for all the plan
* Initialize the executor "tuple" table. We need slots for all the plan
* nodes, plus possibly output slots for the junkfilter(s). At this point
* we aren't sure if we need junkfilters, so just add slots for them
* unconditionally. Also, if it's not a SELECT, set up a slot for use for
* trigger output tuples.
* trigger output tuples. Also, one for RETURNING-list evaluation.
*/
{
int nSlots = ExecCountSlotsNode(plan);
int nSlots;
/* Slots for the main plan tree */
nSlots = ExecCountSlotsNode(plan);
/* Add slots for subplans and initplans */
foreach(l, plannedstmt->subplans)
{
Plan *subplan = (Plan *) lfirst(l);
nSlots += ExecCountSlotsNode(subplan);
}
/* Add slots for junkfilter(s) */
if (plannedstmt->resultRelations != NIL)
nSlots += list_length(plannedstmt->resultRelations);
else
@ -584,7 +596,38 @@ InitPlan(QueryDesc *queryDesc, int eflags)
estate->es_useEvalPlan = false;
/*
* initialize the private state information for all the nodes in the query
* Initialize private state information for each SubPlan. We must do
* this before running ExecInitNode on the main query tree, since
* ExecInitSubPlan expects to be able to find these entries.
*/
Assert(estate->es_subplanstates == NIL);
i = 1; /* subplan indices count from 1 */
foreach(l, plannedstmt->subplans)
{
Plan *subplan = (Plan *) lfirst(l);
PlanState *subplanstate;
int sp_eflags;
/*
* A subplan will never need to do BACKWARD scan nor MARK/RESTORE.
* If it is a parameterless subplan (not initplan), we suggest that it
* be prepared to handle REWIND efficiently; otherwise there is no
* need.
*/
sp_eflags = eflags & EXEC_FLAG_EXPLAIN_ONLY;
if (bms_is_member(i, plannedstmt->rewindPlanIDs))
sp_eflags |= EXEC_FLAG_REWIND;
subplanstate = ExecInitNode(subplan, estate, sp_eflags);
estate->es_subplanstates = lappend(estate->es_subplanstates,
subplanstate);
i++;
}
/*
* Initialize the private state information for all the nodes in the query
* tree. This opens files, allocates storage and leaves us ready to start
* processing tuples.
*/
@ -648,7 +691,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
PlanState **appendplans;
int as_nplans;
ResultRelInfo *resultRelInfo;
int i;
/* Top plan had better be an Append here. */
Assert(IsA(plan, Append));
@ -768,20 +810,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
resultRelInfo->ri_RelationDesc->rd_att);
resultRelInfo++;
}
/*
* Because we already ran ExecInitNode() for the top plan node, any
* subplans we just attached to it won't have been initialized; so we
* have to do it here. (Ugly, but the alternatives seem worse.)
*/
foreach(l, planstate->subPlan)
{
SubPlanState *sstate = (SubPlanState *) lfirst(l);
Assert(IsA(sstate, SubPlanState));
if (sstate->planstate == NULL) /* already inited? */
ExecInitSubPlan(sstate, estate, eflags);
}
}
queryDesc->tupDesc = tupType;
@ -945,7 +973,7 @@ ExecContextForcesOids(PlanState *planstate, bool *hasoids)
* tuple tables must be cleared or dropped to ensure pins are released.
* ----------------------------------------------------------------
*/
void
static void
ExecEndPlan(PlanState *planstate, EState *estate)
{
ResultRelInfo *resultRelInfo;
@ -963,6 +991,16 @@ ExecEndPlan(PlanState *planstate, EState *estate)
*/
ExecEndNode(planstate);
/*
* for subplans too
*/
foreach(l, estate->es_subplanstates)
{
PlanState *subplanstate = (PlanState *) lfirst(l);
ExecEndNode(subplanstate);
}
/*
* destroy the executor "tuple" table.
*/
@ -2205,13 +2243,10 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
EState *epqstate;
int rtsize;
MemoryContext oldcontext;
ListCell *l;
rtsize = list_length(estate->es_range_table);
/*
* It's tempting to think about using CreateSubExecutorState here, but
* at present we can't because of memory leakage concerns ...
*/
epq->estate = epqstate = CreateExecutorState();
oldcontext = MemoryContextSwitchTo(epqstate->es_query_cxt);
@ -2256,9 +2291,34 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
/* later stack entries share the same storage */
epqstate->es_evTuple = priorepq->estate->es_evTuple;
/*
* Create sub-tuple-table; we needn't redo the CountSlots work though.
*/
epqstate->es_tupleTable =
ExecCreateTupleTable(estate->es_tupleTable->size);
/*
* Initialize private state information for each SubPlan. We must do
* this before running ExecInitNode on the main query tree, since
* ExecInitSubPlan expects to be able to find these entries.
*/
Assert(epqstate->es_subplanstates == NIL);
foreach(l, estate->es_plannedstmt->subplans)
{
Plan *subplan = (Plan *) lfirst(l);
PlanState *subplanstate;
subplanstate = ExecInitNode(subplan, epqstate, 0);
epqstate->es_subplanstates = lappend(epqstate->es_subplanstates,
subplanstate);
}
/*
* Initialize the private state information for all the nodes in the query
* tree. This opens files, allocates storage and leaves us ready to start
* processing tuples.
*/
epq->planstate = ExecInitNode(estate->es_plannedstmt->planTree, epqstate, 0);
MemoryContextSwitchTo(oldcontext);
@ -2276,11 +2336,19 @@ EvalPlanQualStop(evalPlanQual *epq)
{
EState *epqstate = epq->estate;
MemoryContext oldcontext;
ListCell *l;
oldcontext = MemoryContextSwitchTo(epqstate->es_query_cxt);
ExecEndNode(epq->planstate);
foreach(l, epqstate->es_subplanstates)
{
PlanState *subplanstate = (PlanState *) lfirst(l);
ExecEndNode(subplanstate);
}
ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL;