Skip to content

Commit c7ff766

Browse files
committed
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.
1 parent 4756ff3 commit c7ff766

File tree

15 files changed

+257
-357
lines changed

15 files changed

+257
-357
lines changed

src/backend/executor/execMain.c

+93-25
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.288 2007/02/22 22:00:22 tgl Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.289 2007/02/27 01:11:25 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -70,6 +70,7 @@ static void initResultRelInfo(ResultRelInfo *resultRelInfo,
7070
List *rangeTable,
7171
CmdType operation,
7272
bool doInstrument);
73+
static void ExecEndPlan(PlanState *planstate, EState *estate);
7374
static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
7475
CmdType operation,
7576
long numberTuples,
@@ -466,6 +467,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
466467
PlanState *planstate;
467468
TupleDesc tupType;
468469
ListCell *l;
470+
int i;
469471

470472
/*
471473
* Do permissions checks
@@ -551,15 +553,25 @@ InitPlan(QueryDesc *queryDesc, int eflags)
551553
}
552554

553555
/*
554-
* initialize the executor "tuple" table. We need slots for all the plan
556+
* Initialize the executor "tuple" table. We need slots for all the plan
555557
* nodes, plus possibly output slots for the junkfilter(s). At this point
556558
* we aren't sure if we need junkfilters, so just add slots for them
557559
* unconditionally. Also, if it's not a SELECT, set up a slot for use for
558-
* trigger output tuples.
560+
* trigger output tuples. Also, one for RETURNING-list evaluation.
559561
*/
560562
{
561-
int nSlots = ExecCountSlotsNode(plan);
563+
int nSlots;
564+
565+
/* Slots for the main plan tree */
566+
nSlots = ExecCountSlotsNode(plan);
567+
/* Add slots for subplans and initplans */
568+
foreach(l, plannedstmt->subplans)
569+
{
570+
Plan *subplan = (Plan *) lfirst(l);
562571

572+
nSlots += ExecCountSlotsNode(subplan);
573+
}
574+
/* Add slots for junkfilter(s) */
563575
if (plannedstmt->resultRelations != NIL)
564576
nSlots += list_length(plannedstmt->resultRelations);
565577
else
@@ -584,7 +596,38 @@ InitPlan(QueryDesc *queryDesc, int eflags)
584596
estate->es_useEvalPlan = false;
585597

586598
/*
587-
* initialize the private state information for all the nodes in the query
599+
* Initialize private state information for each SubPlan. We must do
600+
* this before running ExecInitNode on the main query tree, since
601+
* ExecInitSubPlan expects to be able to find these entries.
602+
*/
603+
Assert(estate->es_subplanstates == NIL);
604+
i = 1; /* subplan indices count from 1 */
605+
foreach(l, plannedstmt->subplans)
606+
{
607+
Plan *subplan = (Plan *) lfirst(l);
608+
PlanState *subplanstate;
609+
int sp_eflags;
610+
611+
/*
612+
* A subplan will never need to do BACKWARD scan nor MARK/RESTORE.
613+
* If it is a parameterless subplan (not initplan), we suggest that it
614+
* be prepared to handle REWIND efficiently; otherwise there is no
615+
* need.
616+
*/
617+
sp_eflags = eflags & EXEC_FLAG_EXPLAIN_ONLY;
618+
if (bms_is_member(i, plannedstmt->rewindPlanIDs))
619+
sp_eflags |= EXEC_FLAG_REWIND;
620+
621+
subplanstate = ExecInitNode(subplan, estate, sp_eflags);
622+
623+
estate->es_subplanstates = lappend(estate->es_subplanstates,
624+
subplanstate);
625+
626+
i++;
627+
}
628+
629+
/*
630+
* Initialize the private state information for all the nodes in the query
588631
* tree. This opens files, allocates storage and leaves us ready to start
589632
* processing tuples.
590633
*/
@@ -648,7 +691,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
648691
PlanState **appendplans;
649692
int as_nplans;
650693
ResultRelInfo *resultRelInfo;
651-
int i;
652694

653695
/* Top plan had better be an Append here. */
654696
Assert(IsA(plan, Append));
@@ -768,20 +810,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
768810
resultRelInfo->ri_RelationDesc->rd_att);
769811
resultRelInfo++;
770812
}
771-
772-
/*
773-
* Because we already ran ExecInitNode() for the top plan node, any
774-
* subplans we just attached to it won't have been initialized; so we
775-
* have to do it here. (Ugly, but the alternatives seem worse.)
776-
*/
777-
foreach(l, planstate->subPlan)
778-
{
779-
SubPlanState *sstate = (SubPlanState *) lfirst(l);
780-
781-
Assert(IsA(sstate, SubPlanState));
782-
if (sstate->planstate == NULL) /* already inited? */
783-
ExecInitSubPlan(sstate, estate, eflags);
784-
}
785813
}
786814

787815
queryDesc->tupDesc = tupType;
@@ -945,7 +973,7 @@ ExecContextForcesOids(PlanState *planstate, bool *hasoids)
945973
* tuple tables must be cleared or dropped to ensure pins are released.
946974
* ----------------------------------------------------------------
947975
*/
948-
void
976+
static void
949977
ExecEndPlan(PlanState *planstate, EState *estate)
950978
{
951979
ResultRelInfo *resultRelInfo;
@@ -963,6 +991,16 @@ ExecEndPlan(PlanState *planstate, EState *estate)
963991
*/
964992
ExecEndNode(planstate);
965993

994+
/*
995+
* for subplans too
996+
*/
997+
foreach(l, estate->es_subplanstates)
998+
{
999+
PlanState *subplanstate = (PlanState *) lfirst(l);
1000+
1001+
ExecEndNode(subplanstate);
1002+
}
1003+
9661004
/*
9671005
* destroy the executor "tuple" table.
9681006
*/
@@ -2205,13 +2243,10 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
22052243
EState *epqstate;
22062244
int rtsize;
22072245
MemoryContext oldcontext;
2246+
ListCell *l;
22082247

22092248
rtsize = list_length(estate->es_range_table);
22102249

2211-
/*
2212-
* It's tempting to think about using CreateSubExecutorState here, but
2213-
* at present we can't because of memory leakage concerns ...
2214-
*/
22152250
epq->estate = epqstate = CreateExecutorState();
22162251

22172252
oldcontext = MemoryContextSwitchTo(epqstate->es_query_cxt);
@@ -2256,9 +2291,34 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
22562291
/* later stack entries share the same storage */
22572292
epqstate->es_evTuple = priorepq->estate->es_evTuple;
22582293

2294+
/*
2295+
* Create sub-tuple-table; we needn't redo the CountSlots work though.
2296+
*/
22592297
epqstate->es_tupleTable =
22602298
ExecCreateTupleTable(estate->es_tupleTable->size);
22612299

2300+
/*
2301+
* Initialize private state information for each SubPlan. We must do
2302+
* this before running ExecInitNode on the main query tree, since
2303+
* ExecInitSubPlan expects to be able to find these entries.
2304+
*/
2305+
Assert(epqstate->es_subplanstates == NIL);
2306+
foreach(l, estate->es_plannedstmt->subplans)
2307+
{
2308+
Plan *subplan = (Plan *) lfirst(l);
2309+
PlanState *subplanstate;
2310+
2311+
subplanstate = ExecInitNode(subplan, epqstate, 0);
2312+
2313+
epqstate->es_subplanstates = lappend(epqstate->es_subplanstates,
2314+
subplanstate);
2315+
}
2316+
2317+
/*
2318+
* Initialize the private state information for all the nodes in the query
2319+
* tree. This opens files, allocates storage and leaves us ready to start
2320+
* processing tuples.
2321+
*/
22622322
epq->planstate = ExecInitNode(estate->es_plannedstmt->planTree, epqstate, 0);
22632323

22642324
MemoryContextSwitchTo(oldcontext);
@@ -2276,11 +2336,19 @@ EvalPlanQualStop(evalPlanQual *epq)
22762336
{
22772337
EState *epqstate = epq->estate;
22782338
MemoryContext oldcontext;
2339+
ListCell *l;
22792340

22802341
oldcontext = MemoryContextSwitchTo(epqstate->es_query_cxt);
22812342

22822343
ExecEndNode(epq->planstate);
22832344

2345+
foreach(l, epqstate->es_subplanstates)
2346+
{
2347+
PlanState *subplanstate = (PlanState *) lfirst(l);
2348+
2349+
ExecEndNode(subplanstate);
2350+
}
2351+
22842352
ExecDropTupleTable(epqstate->es_tupleTable, true);
22852353
epqstate->es_tupleTable = NULL;
22862354

src/backend/executor/execProcnode.c

+2-25
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.60 2007/01/05 22:19:27 momjian Exp $
15+
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.61 2007/02/27 01:11:25 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -278,26 +278,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
278278
SubPlanState *sstate;
279279

280280
Assert(IsA(subplan, SubPlan));
281-
sstate = ExecInitExprInitPlan(subplan, result);
282-
ExecInitSubPlan(sstate, estate, eflags);
281+
sstate = ExecInitSubPlan(subplan, result);
283282
subps = lappend(subps, sstate);
284283
}
285284
result->initPlan = subps;
286285

287-
/*
288-
* Initialize any subPlans present in this node. These were found by
289-
* ExecInitExpr during initialization of the PlanState. Note we must do
290-
* this after initializing initPlans, in case their arguments contain
291-
* subPlans (is that actually possible? perhaps not).
292-
*/
293-
foreach(l, result->subPlan)
294-
{
295-
SubPlanState *sstate = (SubPlanState *) lfirst(l);
296-
297-
Assert(IsA(sstate, SubPlanState));
298-
ExecInitSubPlan(sstate, estate, eflags);
299-
}
300-
301286
/* Set up instrumentation for this node if requested */
302287
if (estate->es_instrument)
303288
result->instrument = InstrAlloc(1);
@@ -610,20 +595,12 @@ ExecCountSlotsNode(Plan *node)
610595
void
611596
ExecEndNode(PlanState *node)
612597
{
613-
ListCell *subp;
614-
615598
/*
616599
* do nothing when we get to the end of a leaf on tree.
617600
*/
618601
if (node == NULL)
619602
return;
620603

621-
/* Clean up initPlans and subPlans */
622-
foreach(subp, node->initPlan)
623-
ExecEndSubPlan((SubPlanState *) lfirst(subp));
624-
foreach(subp, node->subPlan)
625-
ExecEndSubPlan((SubPlanState *) lfirst(subp));
626-
627604
if (node->chgParam != NULL)
628605
{
629606
bms_free(node->chgParam);

src/backend/executor/execQual.c

+5-42
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.213 2007/02/06 17:35:20 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.214 2007/02/27 01:11:25 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -3723,27 +3723,16 @@ ExecInitExpr(Expr *node, PlanState *parent)
37233723
break;
37243724
case T_SubPlan:
37253725
{
3726-
/* Keep this in sync with ExecInitExprInitPlan, below */
37273726
SubPlan *subplan = (SubPlan *) node;
3728-
SubPlanState *sstate = makeNode(SubPlanState);
3729-
3730-
sstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecSubPlan;
3727+
SubPlanState *sstate;
37313728

37323729
if (!parent)
37333730
elog(ERROR, "SubPlan found with no parent plan");
37343731

3735-
/*
3736-
* Here we just add the SubPlanState nodes to parent->subPlan.
3737-
* The subplans will be initialized later.
3738-
*/
3739-
parent->subPlan = lcons(sstate, parent->subPlan);
3740-
sstate->sub_estate = NULL;
3741-
sstate->planstate = NULL;
3732+
sstate = ExecInitSubPlan(subplan, parent);
37423733

3743-
sstate->testexpr =
3744-
ExecInitExpr((Expr *) subplan->testexpr, parent);
3745-
sstate->args = (List *)
3746-
ExecInitExpr((Expr *) subplan->args, parent);
3734+
/* Add SubPlanState nodes to parent->subPlan */
3735+
parent->subPlan = lcons(sstate, parent->subPlan);
37473736

37483737
state = (ExprState *) sstate;
37493738
}
@@ -4157,32 +4146,6 @@ ExecInitExpr(Expr *node, PlanState *parent)
41574146
return state;
41584147
}
41594148

4160-
/*
4161-
* ExecInitExprInitPlan --- initialize a subplan expr that's being handled
4162-
* as an InitPlan. This is identical to ExecInitExpr's handling of a regular
4163-
* subplan expr, except we do NOT want to add the node to the parent's
4164-
* subplan list.
4165-
*/
4166-
SubPlanState *
4167-
ExecInitExprInitPlan(SubPlan *node, PlanState *parent)
4168-
{
4169-
SubPlanState *sstate = makeNode(SubPlanState);
4170-
4171-
if (!parent)
4172-
elog(ERROR, "SubPlan found with no parent plan");
4173-
4174-
/* The subplan's state will be initialized later */
4175-
sstate->sub_estate = NULL;
4176-
sstate->planstate = NULL;
4177-
4178-
sstate->testexpr = ExecInitExpr((Expr *) node->testexpr, parent);
4179-
sstate->args = (List *) ExecInitExpr((Expr *) node->args, parent);
4180-
4181-
sstate->xprstate.expr = (Expr *) node;
4182-
4183-
return sstate;
4184-
}
4185-
41864149
/*
41874150
* ExecPrepareExpr --- initialize for expression execution outside a normal
41884151
* Plan tree context.

0 commit comments

Comments
 (0)