Make further use of new bitmapset code: executor's chgParam, extParam,
authorTom Lane
Sun, 9 Feb 2003 00:30:41 +0000 (00:30 +0000)
committerTom Lane
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 c55e5ecd1494e05d3946b63aad9c6a11ee68411e..b22ad7634982003f66f721dea37dc7bcf2079cd6 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 dc5a3085ead72f835ff64e2c355a8469c9ffbeb1..8d2bc0f8bd93faff9125cc94f10b52bf81d7c3c5 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 90bd8adf1ae13beef3fb1230e223979127473bae..b2fe0a2276a94d00f2f1d29825dc5d29f5e387ed 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 0cb2f3e2b6ffc994b9cee44be9b872527afcfc95..bbdda3540a7ec4e910d8bf7dc124a8305d9f2971 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 bcb50fb7979917e0baa79f838cb2082b1835a3d0..e79d37fd857e184c86dac00482a63de1a248b376 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 d3f32913914f6fae8cc2689959be060725f935c4..4fd8af2ae4d77b65dfb8eb92c8c4ed62e154763e 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 c5ad1e9cd5fff8f0e460312fe9f50b106869fecd..ba4804fcebb4d48aefdefbb12a13c7f727e95354 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 e1a2165709e778af8747000d0290b89e2bbb79eb..962d00cd144e1cac15d8a40040c8bfd7e019e0f0 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 55b4eeaf4b736adb7de5fccebad96af7de1c978f..ba7f48bc20089b47e320a7751f3317ba930e1376 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 b4aefc78002f363453610f79d55e0d9e28402b59..9d4f977f22d3d7d5d10e5a487c5c260e3b394c40 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 ad68253109d7cb1da979680970db17ad3e0ace81..9608d9a17fa3f77f27e4813cba9f648bff7d23d0 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 a2c8053b5dcfeb6e91a055fd5333e415ca76c948..d28a6674764ae020a05b9e09db5668a98c6e67d9 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 2f329ca57af3a1285458846a18b2fe247d728597..ee30f51896974e74b279589bedf93f6437d9bb0f 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 ccb253206624c3b7f003a63a066ced472f940c11..8d2b13059840ad6511bfdeb7fc544d570a94551b 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 67a4d48782f1c072f2964ef74307cfefaadc36c5..2ca16b63272e16030a518996abda1707798dba71 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 ad1c73612554cfdf01215908943801816e2f1fd2..be917c4f2606e36311f23e2596e075ad23f4c665 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 2e6a4640684f916d96583e46a428663129c7e280..9dce88e0a8d0a3beb7f73417a47985dabd892e28 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 */