OSDN Git Service

Make further use of new bitmapset code: executor's chgParam, extParam,
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 9 Feb 2003 00:30:41 +0000 (00:30 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 9 Feb 2003 00:30:41 +0000 (00:30 +0000)
locParam lists can be converted to bitmapsets to speed updating.  Also,
replace 'locParam' with 'allParam', which contains all the paramIDs
relevant to the node (i.e., the union of extParam and locParam); this
saves a step during SetChangedParamList() without costing anything
elsewhere.

17 files changed:
src/backend/executor/execAmi.c
src/backend/executor/execProcnode.c
src/backend/executor/execUtils.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeAppend.c
src/backend/executor/nodeSubplan.c
src/backend/executor/nodeSubqueryscan.c
src/backend/executor/nodeTidscan.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/subselect.c
src/include/executor/executor.h
src/include/nodes/execnodes.h
src/include/nodes/plannodes.h
src/include/nodes/primnodes.h
src/include/optimizer/subselect.h

index c55e5ec..b22ad76 100644 (file)
@@ -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;
        }
 }
 
index dc5a308..8d2bc0f 100644 (file)
@@ -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))
index 90bd8ad..b2fe0a2 100644 (file)
@@ -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);
 }
 
 /*
index 0cb2f3e..bbdda35 100644 (file)
@@ -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);
 }
 
index bcb50fb..e79d37f 100644 (file)
@@ -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;
index d3f3291..4fd8af2 100644 (file)
@@ -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));
 }
index c5ad1e9..ba4804f 100644 (file)
@@ -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
index e1a2165..962d00c 100644 (file)
@@ -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
index 55b4eea..ba7f48b 100644 (file)
@@ -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);
 }
 
index b4aefc7..9d4f977 100644 (file)
@@ -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);
 }
 
index ad68253..9608d9a 100644 (file)
@@ -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;
                }
 
index a2c8053..d28a667 100644 (file)
@@ -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);
 }
index 2f329ca..ee30f51 100644 (file)
@@ -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
 {
index ccb2532..8d2b130 100644 (file)
@@ -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.
index 67a4d48..2ca16b6 100644 (file)
@@ -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
index ad1c736..be917c4 100644 (file)
@@ -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
index 2e6a464..9dce88e 100644 (file)
@@ -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 */