diff options
-rw-r--r-- | src/backend/executor/execAmi.c | 26 | ||||
-rw-r--r-- | src/backend/executor/execProcnode.c | 10 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 37 | ||||
-rw-r--r-- | src/backend/executor/nodeAgg.c | 4 | ||||
-rw-r--r-- | src/backend/executor/nodeAppend.c | 8 | ||||
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 79 | ||||
-rw-r--r-- | src/backend/executor/nodeSubqueryscan.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeTidscan.c | 4 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 6 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 6 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 12 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 222 | ||||
-rw-r--r-- | src/include/executor/executor.h | 4 | ||||
-rw-r--r-- | src/include/nodes/execnodes.h | 5 | ||||
-rw-r--r-- | src/include/nodes/plannodes.h | 20 | ||||
-rw-r--r-- | src/include/nodes/primnodes.h | 9 | ||||
-rw-r--r-- | src/include/optimizer/subselect.h | 4 |
17 files changed, 268 insertions, 194 deletions
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index c55e5ecd149..b22ad763498 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.68 2002/12/14 00:17:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.69 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,7 +55,7 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) InstrEndLoop(node->instrument); /* If we have changed parameters, propagate that info */ - if (node->chgParam != NIL) + if (node->chgParam != NULL) { List *lst; @@ -64,10 +64,10 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) SubPlanState *sstate = (SubPlanState *) lfirst(lst); PlanState *splan = sstate->planstate; - if (splan->plan->extParam != NIL) /* don't care about child - * locParam */ - SetChangedParamList(splan, node->chgParam); - if (splan->chgParam != NIL) + if (splan->plan->extParam != NULL) /* don't care about child + * local Params */ + UpdateChangedParamSet(splan, node->chgParam); + if (splan->chgParam != NULL) ExecReScanSetParamPlan(sstate, node); } foreach(lst, node->subPlan) @@ -75,14 +75,14 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) SubPlanState *sstate = (SubPlanState *) lfirst(lst); PlanState *splan = sstate->planstate; - if (splan->plan->extParam != NIL) - SetChangedParamList(splan, node->chgParam); + if (splan->plan->extParam != NULL) + UpdateChangedParamSet(splan, node->chgParam); } /* Well. Now set chgParam for left/right trees. */ if (node->lefttree != NULL) - SetChangedParamList(node->lefttree, node->chgParam); + UpdateChangedParamSet(node->lefttree, node->chgParam); if (node->righttree != NULL) - SetChangedParamList(node->righttree, node->chgParam); + UpdateChangedParamSet(node->righttree, node->chgParam); } switch (nodeTag(node)) @@ -165,10 +165,10 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) return; } - if (node->chgParam != NIL) + if (node->chgParam != NULL) { - freeList(node->chgParam); - node->chgParam = NIL; + bms_free(node->chgParam); + node->chgParam = NULL; } } diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index dc5a3085ead..8d2bc0f8bd9 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.34 2002/12/14 00:17:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.35 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -282,7 +282,7 @@ ExecProcNode(PlanState *node) if (node == NULL) return NULL; - if (node->chgParam != NIL) /* something changed */ + if (node->chgParam != NULL) /* something changed */ ExecReScan(node, NULL); /* let ReScan handle this */ if (node->instrument) @@ -504,10 +504,10 @@ ExecEndNode(PlanState *node) foreach(subp, node->subPlan) ExecEndSubPlan((SubPlanState *) lfirst(subp)); - if (node->chgParam != NIL) + if (node->chgParam != NULL) { - freeList(node->chgParam); - node->chgParam = NIL; + bms_free(node->chgParam); + node->chgParam = NULL; } switch (nodeTag(node)) diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 90bd8adf1ae..b2fe0a2276a 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.96 2003/01/23 05:10:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.97 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -874,25 +874,28 @@ ExecInsertIndexTuples(TupleTableSlot *slot, } } +/* + * UpdateChangedParamSet + * Add changed parameters to a plan node's chgParam set + */ void -SetChangedParamList(PlanState *node, List *newchg) +UpdateChangedParamSet(PlanState *node, Bitmapset *newchg) { - List *nl; - - foreach(nl, newchg) - { - int paramId = lfirsti(nl); + Bitmapset *parmset; - /* if this node doesn't depend on a param ... */ - if (!intMember(paramId, node->plan->extParam) && - !intMember(paramId, node->plan->locParam)) - continue; - /* if this param is already in list of changed ones ... */ - if (intMember(paramId, node->chgParam)) - continue; - /* else - add this param to the list */ - node->chgParam = lappendi(node->chgParam, paramId); - } + /* + * The plan node only depends on params listed in its allParam set. + * Don't include anything else into its chgParam set. + */ + parmset = bms_intersect(node->plan->allParam, newchg); + /* + * Keep node->chgParam == NULL if there's not actually any members; + * this allows the simplest possible tests in executor node files. + */ + if (!bms_is_empty(parmset)) + node->chgParam = bms_join(node->chgParam, parmset); + else + bms_free(parmset); } /* diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 0cb2f3e2b6f..bbdda3540a7 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -45,7 +45,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.103 2003/02/04 00:48:23 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.104 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1405,7 +1405,7 @@ ExecReScanAgg(AggState *node, ExprContext *exprCtxt) * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ - if (((PlanState *) node)->lefttree->chgParam == NIL) + if (((PlanState *) node)->lefttree->chgParam == NULL) ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index bcb50fb7979..e79d37fd857 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.51 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.52 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -361,14 +361,14 @@ ExecReScanAppend(AppendState *node, ExprContext *exprCtxt) * ExecReScan doesn't know about my subplans, so I have to do * changed-parameter signaling myself. */ - if (node->ps.chgParam != NIL) - SetChangedParamList(subnode, node->ps.chgParam); + if (node->ps.chgParam != NULL) + UpdateChangedParamSet(subnode, node->ps.chgParam); /* * if chgParam of subnode is not null then plan will be re-scanned * by first ExecProcNode. */ - if (subnode->chgParam == NIL) + if (subnode->chgParam == NULL) { /* make sure estate is correct for this subnode (needed??) */ node->as_whichplan = i; diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index d3f32913914..4fd8af2ae4d 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.43 2003/01/12 04:03:34 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.44 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -80,7 +80,7 @@ ExecHashSubPlan(SubPlanState *node, * If first time through or we need to rescan the subplan, build * the hash table. */ - if (node->hashtable == NULL || planstate->chgParam != NIL) + if (node->hashtable == NULL || planstate->chgParam != NULL) buildSubPlanHash(node); /* @@ -218,22 +218,18 @@ ExecScanSubPlan(SubPlanState *node, * Set Params of this plan from parent plan correlation Vars */ pvar = node->args; - if (subplan->parParam != NIL) + foreach(lst, subplan->parParam) { - foreach(lst, subplan->parParam) - { - ParamExecData *prm; - - prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); - Assert(pvar != NIL); - prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar), - econtext, - &(prm->isnull), - NULL); - pvar = lnext(pvar); - } - planstate->chgParam = nconc(planstate->chgParam, - listCopy(subplan->parParam)); + int paramid = lfirsti(lst); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); + + Assert(pvar != NIL); + prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar), + econtext, + &(prm->isnull), + NULL); + pvar = lnext(pvar); + planstate->chgParam = bms_add_member(planstate->chgParam, paramid); } Assert(pvar == NIL); @@ -686,7 +682,12 @@ ExecInitSubPlan(SubPlanState *node, EState *estate) /* * If this plan is un-correlated or undirect correlated one and want - * to set params for parent plan then prepare parameters. + * to set params for parent plan then mark parameters as needing + * evaluation. + * + * 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) { @@ -694,16 +695,11 @@ ExecInitSubPlan(SubPlanState *node, EState *estate) foreach(lst, subplan->setParam) { - ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); + int paramid = lfirsti(lst); + ParamExecData *prm = &(estate->es_param_exec_vals[paramid]); prm->execPlan = node; } - - /* - * 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... - */ } /* @@ -884,7 +880,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) if (subLinkType == EXISTS_SUBLINK) { - ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]); + /* There can be only one param... */ + int paramid = lfirsti(subplan->setParam); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); prm->execPlan = NULL; prm->value = BoolGetDatum(true); @@ -914,9 +912,13 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) node->curTuple = tup; MemoryContextSwitchTo(node->sub_estate->es_query_cxt); + /* + * Now set all the setParam params from the columns of the tuple + */ foreach(lst, subplan->setParam) { - ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); + int paramid = lfirsti(lst); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); prm->execPlan = NULL; prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull)); @@ -928,7 +930,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) { if (subLinkType == EXISTS_SUBLINK) { - ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]); + /* There can be only one param... */ + int paramid = lfirsti(subplan->setParam); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); prm->execPlan = NULL; prm->value = BoolGetDatum(false); @@ -938,7 +942,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) { foreach(lst, subplan->setParam) { - ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); + int paramid = lfirsti(lst); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); prm->execPlan = NULL; prm->value = (Datum) 0; @@ -979,12 +984,12 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) EState *estate = parent->state; List *lst; - if (subplan->parParam != NULL) + if (subplan->parParam != NIL) elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet"); - if (subplan->setParam == NULL) - elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL"); - if (planstate->plan->extParam == NULL) - elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL"); + if (subplan->setParam == NIL) + elog(ERROR, "ExecReScanSetParamPlan: setParam list is empty"); + if (bms_is_empty(planstate->plan->extParam)) + elog(ERROR, "ExecReScanSetParamPlan: extParam set of plan is empty"); /* * Don't actually re-scan: ExecSetParamPlan does it if needed. @@ -995,10 +1000,10 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) */ foreach(lst, subplan->setParam) { - ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); + int paramid = lfirsti(lst); + ParamExecData *prm = &(estate->es_param_exec_vals[paramid]); prm->execPlan = node; + parent->chgParam = bms_add_member(parent->chgParam, paramid); } - - parent->chgParam = nconc(parent->chgParam, listCopy(subplan->setParam)); } diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index c5ad1e9cd5f..ba4804fcebb 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.17 2003/01/12 22:01:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.18 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -261,10 +261,10 @@ ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt) * ExecReScan doesn't know about my subplan, so I have to do * changed-parameter signaling myself. This is just as well, * because the subplan has its own memory context in which its - * chgParam lists live. + * chgParam state lives. */ if (node->ss.ps.chgParam != NULL) - SetChangedParamList(node->subplan, node->ss.ps.chgParam); + UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam); /* * if chgParam of subnode is not null then plan will be re-scanned by diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index e1a2165709e..962d00cd144 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.32 2003/02/03 15:07:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.33 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -349,7 +349,7 @@ ExecInitTidScan(TidScan *node, EState *estate) Oid relid; Oid reloid; Relation currentRelation; - List *execParam = NIL; + Bitmapset *execParam = NULL; /* * create state structure diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 55b4eeaf4b7..ba7f48bc200 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.240 2003/02/08 20:20:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.241 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -120,8 +120,8 @@ CopyPlanFields(Plan *from, Plan *newnode) COPY_NODE_FIELD(lefttree); COPY_NODE_FIELD(righttree); COPY_NODE_FIELD(initPlan); - COPY_INTLIST_FIELD(extParam); - COPY_INTLIST_FIELD(locParam); + COPY_BITMAPSET_FIELD(extParam); + COPY_BITMAPSET_FIELD(allParam); COPY_SCALAR_FIELD(nParamExec); } diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index b4aefc78002..9d4f977f22d 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.196 2003/02/08 20:20:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.197 2003/02/09 00:30:39 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -255,8 +255,8 @@ _outPlanInfo(StringInfo str, Plan *node) WRITE_NODE_FIELD(lefttree); WRITE_NODE_FIELD(righttree); WRITE_NODE_FIELD(initPlan); - WRITE_INTLIST_FIELD(extParam); - WRITE_INTLIST_FIELD(locParam); + WRITE_BITMAPSET_FIELD(extParam); + WRITE_BITMAPSET_FIELD(allParam); WRITE_INT_FIELD(nParamExec); } diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index ad68253109d..9608d9a17fa 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.144 2003/02/04 00:50:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.145 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -268,14 +268,14 @@ subquery_planner(Query *parse, double tuple_fraction) /* * If any subplans were generated, or if we're inside a subplan, build - * initPlan, extParam and locParam lists for plan nodes. + * initPlan list and extParam/allParam sets for plan nodes. */ if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1) { Cost initplan_cost = 0; - /* Prepare extParam/locParam data for all nodes in tree */ - (void) SS_finalize_plan(plan, parse->rtable); + /* Prepare extParam/allParam sets for all nodes in tree */ + SS_finalize_plan(plan, parse->rtable); /* * SS_finalize_plan doesn't handle initPlans, so we have to manually @@ -293,8 +293,8 @@ subquery_planner(Query *parse, double tuple_fraction) { SubPlan *initplan = (SubPlan *) lfirst(lst); - plan->extParam = set_unioni(plan->extParam, - initplan->plan->extParam); + plan->extParam = bms_add_members(plan->extParam, + initplan->plan->extParam); initplan_cost += initplan->plan->total_cost; } diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index a2c8053b5dc..d28a6674764 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.70 2003/02/08 20:20:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.71 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,10 +57,11 @@ int PlannerPlanId = 0; /* to assign unique ID to subquery plans */ */ -typedef struct finalize_primnode_results +typedef struct finalize_primnode_context { - List *paramids; /* List of PARAM_EXEC paramids found */ -} finalize_primnode_results; + Bitmapset *paramids; /* Set of PARAM_EXEC paramids found */ + Bitmapset *outer_params; /* Set of accessible outer paramids */ +} finalize_primnode_context; static List *convert_sublink_opers(List *lefthand, List *operOids, @@ -69,7 +70,10 @@ static List *convert_sublink_opers(List *lefthand, List *operOids, static bool subplan_is_hashable(SubLink *slink, SubPlan *node); static Node *replace_correlation_vars_mutator(Node *node, void *context); static Node *process_sublinks_mutator(Node *node, bool *isTopQual); -static bool finalize_primnode(Node *node, finalize_primnode_results *results); +static Bitmapset *finalize_plan(Plan *plan, List *rtable, + Bitmapset *outer_params, + Bitmapset *valid_params); +static bool finalize_primnode(Node *node, finalize_primnode_context *context); /* @@ -178,6 +182,8 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) Query *subquery = (Query *) (slink->subselect); double tuple_fraction; Plan *plan; + Bitmapset *tmpset; + int paramid; List *lst; Node *result; @@ -246,15 +252,16 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) * Make parParam list of params that current query level will pass to * this child plan. */ - foreach(lst, plan->extParam) + tmpset = bms_copy(plan->extParam); + while ((paramid = bms_first_member(tmpset)) >= 0) { - int paramid = lfirsti(lst); Var *var = nth(paramid, PlannerParamVar); /* note varlevelsup is absolute level number */ if (var->varlevelsup == PlannerQueryLevel) node->parParam = lappendi(node->parParam, paramid); } + bms_free(tmpset); /* * Un-correlated or undirect correlated plans of EXISTS, EXPR, or @@ -269,7 +276,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) Param *prm; prm = generate_new_param(BOOLOID, -1); - node->setParam = lappendi(node->setParam, prm->paramid); + node->setParam = makeListi1(prm->paramid); PlannerInitPlan = lappend(PlannerInitPlan, node); result = (Node *) prm; } @@ -280,7 +287,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) Assert(!te->resdom->resjunk); prm = generate_new_param(te->resdom->restype, te->resdom->restypmod); - node->setParam = lappendi(node->setParam, prm->paramid); + node->setParam = makeListi1(prm->paramid); PlannerInitPlan = lappend(PlannerInitPlan, node); result = (Node *) prm; } @@ -294,7 +301,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) plan->targetlist, 0, &node->paramIds); - node->setParam = nconc(node->setParam, listCopy(node->paramIds)); + node->setParam = listCopy(node->paramIds); PlannerInitPlan = lappend(PlannerInitPlan, node); /* * The executable expressions are returned to become part of the @@ -387,8 +394,8 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual) matplan->plan_rows = plan->plan_rows; matplan->plan_width = plan->plan_width; /* parameter kluge --- see comments above */ - matplan->extParam = listCopy(plan->extParam); - matplan->locParam = listCopy(plan->locParam); + matplan->extParam = bms_copy(plan->extParam); + matplan->allParam = bms_copy(plan->allParam); node->plan = plan = matplan; } } @@ -769,44 +776,94 @@ process_sublinks_mutator(Node *node, bool *isTopQual) /* * SS_finalize_plan - do final sublink processing for a completed Plan. * - * This recursively computes and sets the extParam and locParam lists - * for every Plan node in the given tree. + * This recursively computes the extParam and allParam sets + * for every Plan node in the given plan tree. */ -List * +void SS_finalize_plan(Plan *plan, List *rtable) { - List *extParam = NIL; - List *locParam = NIL; - finalize_primnode_results results; + Bitmapset *outer_params = NULL; + Bitmapset *valid_params = NULL; + int paramid; + List *lst; + + /* + * First, scan the param list to discover the sets of params that + * are available from outer query levels and my own query level. + * We do this once to save time in the per-plan recursion steps. + */ + paramid = 0; + foreach(lst, PlannerParamVar) + { + Var *var = (Var *) lfirst(lst); + + /* note varlevelsup is absolute level number */ + if (var->varlevelsup < PlannerQueryLevel) + { + /* valid outer-level parameter */ + outer_params = bms_add_member(outer_params, paramid); + valid_params = bms_add_member(valid_params, paramid); + } + else if (var->varlevelsup == PlannerQueryLevel && + var->varno == 0 && var->varattno == 0) + { + /* valid local parameter (i.e., a setParam of my child) */ + valid_params = bms_add_member(valid_params, paramid); + } + + paramid++; + } + + /* + * Now recurse through plan tree. + */ + (void) finalize_plan(plan, rtable, outer_params, valid_params); + + bms_free(outer_params); + bms_free(valid_params); +} + +/* + * Recursive processing of all nodes in the plan tree + * + * The return value is the computed allParam set for the given Plan node. + * This is just an internal notational convenience. + */ +static Bitmapset * +finalize_plan(Plan *plan, List *rtable, + Bitmapset *outer_params, Bitmapset *valid_params) +{ + finalize_primnode_context context; List *lst; if (plan == NULL) - return NIL; + return NULL; - results.paramids = NIL; /* initialize list to NIL */ + context.paramids = NULL; /* initialize set to empty */ + context.outer_params = outer_params; /* - * When we call finalize_primnode, results.paramids lists are + * When we call finalize_primnode, context.paramids sets are * automatically merged together. But when recursing to self, we have - * to do it the hard way. We want the paramids list to include params + * to do it the hard way. We want the paramids set to include params * in subplans as well as at this level. */ /* Find params in targetlist and qual */ - finalize_primnode((Node *) plan->targetlist, &results); - finalize_primnode((Node *) plan->qual, &results); + finalize_primnode((Node *) plan->targetlist, &context); + finalize_primnode((Node *) plan->qual, &context); /* Check additional node-type-specific fields */ switch (nodeTag(plan)) { case T_Result: finalize_primnode(((Result *) plan)->resconstantqual, - &results); + &context); break; case T_IndexScan: finalize_primnode((Node *) ((IndexScan *) plan)->indxqual, - &results); + &context); /* * we need not look at indxqualorig, since it will have the @@ -816,7 +873,7 @@ SS_finalize_plan(Plan *plan, List *rtable) case T_TidScan: finalize_primnode((Node *) ((TidScan *) plan)->tideval, - &results); + &context); break; case T_SubqueryScan: @@ -828,7 +885,7 @@ SS_finalize_plan(Plan *plan, List *rtable) * subplan's extParams list, which represents the params it * needs from my level and higher levels. */ - results.paramids = set_unioni(results.paramids, + context.paramids = bms_add_members(context.paramids, ((SubqueryScan *) plan)->subplan->extParam); break; @@ -839,39 +896,44 @@ SS_finalize_plan(Plan *plan, List *rtable) rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid, rtable); Assert(rte->rtekind == RTE_FUNCTION); - finalize_primnode(rte->funcexpr, &results); + finalize_primnode(rte->funcexpr, &context); } break; case T_Append: foreach(lst, ((Append *) plan)->appendplans) - results.paramids = set_unioni(results.paramids, - SS_finalize_plan((Plan *) lfirst(lst), - rtable)); + { + context.paramids = + bms_add_members(context.paramids, + finalize_plan((Plan *) lfirst(lst), + rtable, + outer_params, + valid_params)); + } break; case T_NestLoop: finalize_primnode((Node *) ((Join *) plan)->joinqual, - &results); + &context); break; case T_MergeJoin: finalize_primnode((Node *) ((Join *) plan)->joinqual, - &results); + &context); finalize_primnode((Node *) ((MergeJoin *) plan)->mergeclauses, - &results); + &context); break; case T_HashJoin: finalize_primnode((Node *) ((Join *) plan)->joinqual, - &results); + &context); finalize_primnode((Node *) ((HashJoin *) plan)->hashclauses, - &results); + &context); break; case T_Hash: finalize_primnode((Node *) ((Hash *) plan)->hashkeys, - &results); + &context); break; case T_Agg: @@ -885,50 +947,55 @@ SS_finalize_plan(Plan *plan, List *rtable) break; default: - elog(ERROR, "SS_finalize_plan: node %d unsupported", + elog(ERROR, "finalize_plan: node %d unsupported", nodeTag(plan)); } /* Process left and right child plans, if any */ - results.paramids = set_unioni(results.paramids, - SS_finalize_plan(plan->lefttree, - rtable)); - results.paramids = set_unioni(results.paramids, - SS_finalize_plan(plan->righttree, - rtable)); + context.paramids = bms_add_members(context.paramids, + finalize_plan(plan->lefttree, + rtable, + outer_params, + valid_params)); + + context.paramids = bms_add_members(context.paramids, + finalize_plan(plan->righttree, + rtable, + outer_params, + valid_params)); /* Now we have all the paramids */ - foreach(lst, results.paramids) - { - int paramid = lfirsti(lst); - Var *var = nth(paramid, PlannerParamVar); + if (!bms_is_subset(context.paramids, valid_params)) + elog(ERROR, "finalize_plan: plan shouldn't reference subplan's variable"); - /* note varlevelsup is absolute level number */ - if (var->varlevelsup < PlannerQueryLevel) - extParam = lappendi(extParam, paramid); - else if (var->varlevelsup > PlannerQueryLevel) - elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable"); - else - { - Assert(var->varno == 0 && var->varattno == 0); - locParam = lappendi(locParam, paramid); - } - } + plan->extParam = bms_intersect(context.paramids, outer_params); + plan->allParam = context.paramids; - plan->extParam = extParam; - plan->locParam = locParam; + /* + * For speed at execution time, make sure extParam/allParam are actually + * NULL if they are empty sets. + */ + if (bms_is_empty(plan->extParam)) + { + bms_free(plan->extParam); + plan->extParam = NULL; + } + if (bms_is_empty(plan->allParam)) + { + bms_free(plan->allParam); + plan->allParam = NULL; + } - return results.paramids; + return plan->allParam; } /* - * finalize_primnode: build lists of params appearing - * in the given expression tree. NOTE: items are added to list passed in, - * so caller must initialize list to NIL before first call! + * finalize_primnode: add IDs of all PARAM_EXEC params appearing in the given + * expression tree to the result set. */ static bool -finalize_primnode(Node *node, finalize_primnode_results *results) +finalize_primnode(Node *node, finalize_primnode_context *context) { if (node == NULL) return false; @@ -938,29 +1005,20 @@ finalize_primnode(Node *node, finalize_primnode_results *results) { int paramid = (int) ((Param *) node)->paramid; - if (!intMember(paramid, results->paramids)) - results->paramids = lconsi(paramid, results->paramids); + context->paramids = bms_add_member(context->paramids, paramid); } return false; /* no more to do here */ } if (is_subplan(node)) { SubPlan *subplan = (SubPlan *) node; - List *lst; - /* Check extParam list for params to add to paramids */ - foreach(lst, subplan->plan->extParam) - { - int paramid = lfirsti(lst); - Var *var = nth(paramid, PlannerParamVar); - - /* note varlevelsup is absolute level number */ - if (var->varlevelsup < PlannerQueryLevel && - !intMember(paramid, results->paramids)) - results->paramids = lconsi(paramid, results->paramids); - } + /* Add outer-level params needed by the subplan to paramids */ + context->paramids = bms_join(context->paramids, + bms_intersect(subplan->plan->extParam, + context->outer_params)); /* fall through to recurse into subplan args */ } return expression_tree_walker(node, finalize_primnode, - (void *) results); + (void *) context); } diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 2f329ca57af..ee30f518969 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: executor.h,v 1.88 2003/02/03 15:07:07 tgl Exp $ + * $Id: executor.h,v 1.89 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -160,7 +160,7 @@ extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType); extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid); -extern void SetChangedParamList(PlanState *node, List *newchg); +extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg); typedef struct TupOutputState { diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index ccb25320662..8d2b1305984 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: execnodes.h,v 1.93 2003/02/03 21:15:44 tgl Exp $ + * $Id: execnodes.h,v 1.94 2003/02/09 00:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,7 @@ #include "executor/hashjoin.h" #include "executor/tuptable.h" #include "fmgr.h" +#include "nodes/bitmapset.h" #include "nodes/params.h" #include "nodes/plannodes.h" #include "utils/tuplestore.h" @@ -616,7 +617,7 @@ typedef struct PlanState /* * State for management of parameter-change-driven rescanning */ - List *chgParam; /* integer list of IDs of changed Params */ + Bitmapset *chgParam; /* set of IDs of changed Params */ /* * Other run-time state needed by most if not all node types. diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 67a4d48782f..2ca16b63272 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: plannodes.h,v 1.63 2002/12/12 15:49:40 tgl Exp $ + * $Id: plannodes.h,v 1.64 2003/02/09 00:30:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,6 +15,7 @@ #define PLANNODES_H #include "access/sdir.h" +#include "nodes/bitmapset.h" #include "nodes/primnodes.h" @@ -65,14 +66,17 @@ typedef struct Plan /* * Information for management of parameter-change-driven rescanning + * + * extParam includes the paramIDs of all external PARAM_EXEC params + * affecting this plan node or its children. setParam params from + * the node's initPlans are not included, but their extParams are. + * + * allParam includes all the extParam paramIDs, plus the IDs of local + * params that affect the node (i.e., the setParams of its initplans). + * These are _all_ the PARAM_EXEC params that affect this node. */ - List *extParam; /* indices of _all_ _external_ PARAM_EXEC - * for this plan in global - * es_param_exec_vals. Params from - * setParam from initPlan-s are not - * included, but their execParam-s are - * here!!! */ - List *locParam; /* someones from setParam-s */ + Bitmapset *extParam; + Bitmapset *allParam; /* * We really need in some TopPlan node to store range table and diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index ad1c7361255..be917c4f260 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.78 2003/02/03 21:15:44 tgl Exp $ + * $Id: primnodes.h,v 1.79 2003/02/09 00:30:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -435,9 +435,11 @@ typedef struct SubLink * expressions to be evaluated in the outer-query context (currently these * args are always just Vars, but in principle they could be any expression). * The values are assigned to the global PARAM_EXEC params indexed by parParam - * (the parParam and args lists must have the same length). setParam is a + * (the parParam and args lists must have the same ordering). setParam is a * list of the PARAM_EXEC params that are computed by the sub-select, if it - * is an initplan. + * is an initplan; they are listed in order by sub-select output column + * position. (parParam and setParam are integer Lists, not Bitmapsets, + * because their ordering is significant.) */ typedef struct SubPlan { @@ -449,6 +451,7 @@ typedef struct SubPlan /* The combining operators, transformed to executable expressions: */ List *exprs; /* list of OpExpr expression trees */ List *paramIds; /* IDs of Params embedded in the above */ + /* Note: paramIds has a one-to-one correspondence to the exprs list */ /* The subselect, transformed to a Plan: */ struct Plan *plan; /* subselect plan itself */ int plan_id; /* dummy thing because of we haven't equal diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h index 2e6a4640684..9dce88e0a8d 100644 --- a/src/include/optimizer/subselect.h +++ b/src/include/optimizer/subselect.h @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: subselect.h,v 1.17 2003/01/20 18:55:05 tgl Exp $ + * $Id: subselect.h,v 1.18 2003/02/09 00:30:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,6 @@ extern int PlannerPlanId; /* to assign unique ID to subquery plans */ extern Node *convert_IN_to_join(Query *parse, SubLink *sublink); extern Node *SS_replace_correlation_vars(Node *expr); extern Node *SS_process_sublinks(Node *expr, bool isQual); -extern List *SS_finalize_plan(Plan *plan, List *rtable); +extern void SS_finalize_plan(Plan *plan, List *rtable); #endif /* SUBSELECT_H */ |