diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-02-27 01:11:26 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-02-27 01:11:26 +0000 |
commit | c7ff7663e47fc4e295700101912f2b7dd53c1f4b (patch) | |
tree | 13e987e4894faca0086b78568b08b79cf124e8a1 /src/backend/executor/execMain.c | |
parent | 4756ff3dca903dfc525d1c27fd00fad8ca328188 (diff) | |
download | postgresql-c7ff7663e47fc4e295700101912f2b7dd53c1f4b.tar.gz postgresql-c7ff7663e47fc4e295700101912f2b7dd53c1f4b.zip |
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.
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r-- | src/backend/executor/execMain.c | 118 |
1 files changed, 93 insertions, 25 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index d0df0ea6f47..333edf69441 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -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; @@ -964,6 +992,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. */ ExecDropTupleTable(estate->es_tupleTable, true); @@ -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; |