]> granicus.if.org Git - postgresql/commitdiff
Get rid of some old and crufty global variables in the planner. When
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 19 Feb 2007 07:03:34 +0000 (07:03 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 19 Feb 2007 07:03:34 +0000 (07:03 +0000)
this code was last gone over, there wasn't really any alternative to
globals because we didn't have the PlannerInfo struct being passed all
through the planner code.  Now that we do, we can restructure things
to avoid non-reentrancy.  I'm fooling with this because otherwise I'd
have had to add another global variable for the planned compact
range table list.

18 files changed:
src/backend/nodes/outfuncs.c
src/backend/optimizer/README
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/path/clausesel.c
src/backend/optimizer/plan/planagg.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepjointree.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/prep/prepunion.c
src/backend/optimizer/util/clauses.c
src/backend/utils/adt/selfuncs.c
src/include/nodes/nodes.h
src/include/nodes/primnodes.h
src/include/nodes/relation.h
src/include/optimizer/clauses.h
src/include/optimizer/planner.h
src/include/optimizer/subselect.h

index a173cf59dff671e75bde996a1b6778d61a1ed8f9..0600f63b5567616427dab633f0f4c3d5793d5623 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.298 2007/02/19 02:23:12 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.299 2007/02/19 07:03:27 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1225,6 +1225,16 @@ _outHashPath(StringInfo str, HashPath *node)
        WRITE_NODE_FIELD(path_hashclauses);
 }
 
+static void
+_outPlannerGlobal(StringInfo str, PlannerGlobal *node)
+{
+       WRITE_NODE_TYPE("PLANNERGLOBAL");
+
+       /* NB: this isn't a complete set of fields */
+       WRITE_NODE_FIELD(paramlist);
+       WRITE_INT_FIELD(next_plan_id);
+}
+
 static void
 _outPlannerInfo(StringInfo str, PlannerInfo *node)
 {
@@ -1232,7 +1242,10 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node)
 
        /* NB: this isn't a complete set of fields */
        WRITE_NODE_FIELD(parse);
+       WRITE_NODE_FIELD(glob);
+       WRITE_UINT_FIELD(query_level);
        WRITE_NODE_FIELD(join_rel_list);
+       WRITE_NODE_FIELD(init_plans);
        WRITE_NODE_FIELD(eq_classes);
        WRITE_NODE_FIELD(canon_pathkeys);
        WRITE_NODE_FIELD(left_join_clauses);
@@ -1416,6 +1429,15 @@ _outAppendRelInfo(StringInfo str, AppendRelInfo *node)
        WRITE_OID_FIELD(parent_reloid);
 }
 
+static void
+_outPlannerParamItem(StringInfo str, PlannerParamItem *node)
+{
+       WRITE_NODE_TYPE("PLANNERPARAMITEM");
+
+       WRITE_NODE_FIELD(item);
+       WRITE_UINT_FIELD(abslevel);
+}
+
 /*****************************************************************************
  *
  *     Stuff from parsenodes.h.
@@ -2195,6 +2217,9 @@ _outNode(StringInfo str, void *obj)
                        case T_HashPath:
                                _outHashPath(str, obj);
                                break;
+                       case T_PlannerGlobal:
+                               _outPlannerGlobal(str, obj);
+                               break;
                        case T_PlannerInfo:
                                _outPlannerInfo(str, obj);
                                break;
@@ -2228,6 +2253,9 @@ _outNode(StringInfo str, void *obj)
                        case T_AppendRelInfo:
                                _outAppendRelInfo(str, obj);
                                break;
+                       case T_PlannerParamItem:
+                               _outPlannerParamItem(str, obj);
+                               break;
 
                        case T_CreateStmt:
                                _outCreateStmt(str, obj);
index 60505814fd49c1f1cb8a11b5c54d2aec2f59d0ec..6f9d008cbfffa5abe99a45c49fe13dcb638575b6 100644 (file)
@@ -317,7 +317,10 @@ planner()
 Optimizer Data Structures
 -------------------------
 
-PlannerInfo     - global information for planning a particular Query
+PlannerGlobal   - global information for a single planner invocation
+
+PlannerInfo     - information for planning a particular Query (we make
+                  a separate PlannerInfo node for each sub-Query)
 
 RelOptInfo      - a relation or joined relations
 
index 43891a184594b0bde3f57bad62fd838d6744e6dc..1cb1d86be1b58374dc2c0f94a328e29e94f58dc9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.158 2007/01/28 18:50:40 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.159 2007/02/19 07:03:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -517,7 +517,9 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
                tuple_fraction = root->tuple_fraction;
 
        /* Generate the plan for the subquery */
-       rel->subplan = subquery_planner(subquery, tuple_fraction,
+       rel->subplan = subquery_planner(root->glob, subquery,
+                                                                       root->query_level + 1,
+                                                                       tuple_fraction,
                                                                        &subquery_pathkeys);
 
        /* Copy number of output rows from subplan */
index f80e18a202093721e0efdcfc247f68bab1ad28c6..405ab6fcc3a6275dc1a132e547693b6ce6bbde07 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.83 2007/01/05 22:19:31 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.84 2007/02/19 07:03:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -537,7 +537,7 @@ clause_selectivity(PlannerInfo *root,
        else if (IsA(clause, Param))
        {
                /* see if we can replace the Param */
-               Node       *subst = estimate_expression_value(clause);
+               Node       *subst = estimate_expression_value(root, clause);
 
                if (IsA(subst, Const))
                {
index 77ad0176db256f448ba06ee4d74fdcedf63d60a1..be26d17a28a2bca78bffb6a63e3a483e2e5677fe 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.26 2007/02/06 06:50:26 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.27 2007/02/19 07:03:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -450,6 +450,7 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
         */
        memcpy(&subroot, root, sizeof(PlannerInfo));
        subroot.parse = subparse = (Query *) copyObject(root->parse);
+       subroot.init_plans = NIL;
        subparse->commandType = CMD_SELECT;
        subparse->resultRelation = 0;
        subparse->resultRelations = NIL;
@@ -524,6 +525,9 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
        info->param = SS_make_initplan_from_plan(&subroot, plan,
                                                                                         exprType((Node *) tle->expr),
                                                                                         -1);
+
+       /* Make sure the InitPlan gets into the outer list */
+       root->init_plans = list_concat(root->init_plans, subroot.init_plans);
 }
 
 /*
index ae9c10fc6b6f9fb4d50c5b9b0764c210e6535733..f4a940175ea5c89c08ed9c8bd2e703072fcd585a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.212 2007/01/20 20:45:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.213 2007/02/19 07:03:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,9 +42,6 @@
 #include "utils/syscache.h"
 
 
-ParamListInfo PlannerBoundParamList = NULL;            /* current boundParams */
-
-
 /* Expression kind codes for preprocess_expression */
 #define EXPRKIND_QUAL          0
 #define EXPRKIND_TARGET                1
@@ -86,35 +83,21 @@ Plan *
 planner(Query *parse, bool isCursor, int cursorOptions,
                ParamListInfo boundParams)
 {
+       PlannerGlobal *glob;
        double          tuple_fraction;
        Plan       *result_plan;
-       Index           save_PlannerQueryLevel;
-       List       *save_PlannerParamList;
-       ParamListInfo save_PlannerBoundParamList;
 
        /*
-        * The planner can be called recursively (an example is when
-        * eval_const_expressions tries to pre-evaluate an SQL function). So,
-        * these global state variables must be saved and restored.
-        *
-        * Query level and the param list cannot be moved into the per-query
-        * PlannerInfo structure since their whole purpose is communication across
-        * multiple sub-queries. Also, boundParams is explicitly info from outside
-        * the query, and so is likewise better handled as a global variable.
-        *
-        * Note we do NOT save and restore PlannerPlanId: it exists to assign
-        * unique IDs to SubPlan nodes, and we want those IDs to be unique for the
-        * life of a backend.  Also, PlannerInitPlan is saved/restored in
-        * subquery_planner, not here.
+        * Set up global state for this planner invocation.  This data is needed
+        * across all levels of sub-Query that might exist in the given command,
+        * so we keep it in a separate struct that's linked to by each per-Query
+        * PlannerInfo.
         */
-       save_PlannerQueryLevel = PlannerQueryLevel;
-       save_PlannerParamList = PlannerParamList;
-       save_PlannerBoundParamList = PlannerBoundParamList;
+       glob = makeNode(PlannerGlobal);
 
-       /* Initialize state for handling outer-level references and params */
-       PlannerQueryLevel = 0;          /* will be 1 in top-level subquery_planner */
-       PlannerParamList = NIL;
-       PlannerBoundParamList = boundParams;
+       glob->boundParams = boundParams;
+       glob->paramlist = NIL;
+       glob->next_plan_id = 0;
 
        /* Determine what fraction of the plan is likely to be scanned */
        if (isCursor)
@@ -134,10 +117,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
        }
 
        /* primary planning entry point (may recurse for subqueries) */
-       result_plan = subquery_planner(parse, tuple_fraction, NULL);
-
-       /* check we popped out the right number of levels */
-       Assert(PlannerQueryLevel == 0);
+       result_plan = subquery_planner(glob, parse, 1, tuple_fraction, NULL);
 
        /*
         * If creating a plan for a scrollable cursor, make sure it can run
@@ -153,12 +133,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
        result_plan = set_plan_references(result_plan, parse->rtable);
 
        /* executor wants to know total number of Params used overall */
-       result_plan->nParamExec = list_length(PlannerParamList);
-
-       /* restore state for outer planner, if any */
-       PlannerQueryLevel = save_PlannerQueryLevel;
-       PlannerParamList = save_PlannerParamList;
-       PlannerBoundParamList = save_PlannerBoundParamList;
+       result_plan->nParamExec = list_length(glob->paramlist);
 
        return result_plan;
 }
@@ -169,7 +144,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
  *       Invokes the planner on a subquery.  We recurse to here for each
  *       sub-SELECT found in the query tree.
  *
+ * glob is the global state for the current planner run.
  * parse is the querytree produced by the parser & rewriter.
+ * level is the current recursion depth (1 at the top-level Query).
  * tuple_fraction is the fraction of tuples we expect will be retrieved.
  * tuple_fraction is interpreted as explained for grouping_planner, below.
  *
@@ -189,24 +166,23 @@ planner(Query *parse, bool isCursor, int cursorOptions,
  *--------------------
  */
 Plan *
-subquery_planner(Query *parse, double tuple_fraction,
+subquery_planner(PlannerGlobal *glob, Query *parse,
+                                Index level, double tuple_fraction,
                                 List **subquery_pathkeys)
 {
-       List       *saved_initplan = PlannerInitPlan;
-       int                     saved_planid = PlannerPlanId;
+       int                     saved_plan_id = glob->next_plan_id;
        PlannerInfo *root;
        Plan       *plan;
        List       *newHaving;
        ListCell   *l;
 
-       /* Set up for a new level of subquery */
-       PlannerQueryLevel++;
-       PlannerInitPlan = NIL;
-
        /* Create a PlannerInfo data structure for this subquery */
        root = makeNode(PlannerInfo);
        root->parse = parse;
+       root->glob = glob;
+       root->query_level = level;
        root->planner_cxt = CurrentMemoryContext;
+       root->init_plans = NIL;
        root->eq_classes = NIL;
        root->in_info_list = NIL;
        root->append_rel_list = NIL;
@@ -396,18 +372,13 @@ subquery_planner(Query *parse, double tuple_fraction,
         * initPlan list and extParam/allParam sets for plan nodes, and attach the
         * initPlans to the top plan node.
         */
-       if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1)
-               SS_finalize_plan(plan, parse->rtable);
+       if (root->glob->next_plan_id != saved_plan_id || root->query_level > 1)
+               SS_finalize_plan(root, plan);
 
        /* Return sort ordering info if caller wants it */
        if (subquery_pathkeys)
                *subquery_pathkeys = root->query_pathkeys;
 
-       /* Return to outer subquery context */
-       PlannerQueryLevel--;
-       PlannerInitPlan = saved_initplan;
-       /* we do NOT restore PlannerPlanId; that's not an oversight! */
-
        return plan;
 }
 
@@ -460,7 +431,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
        if (kind != EXPRKIND_VALUES &&
                (root->parse->jointree->fromlist != NIL ||
                 kind == EXPRKIND_QUAL ||
-                PlannerQueryLevel > 1))
+                root->query_level > 1))
                expr = eval_const_expressions(expr);
 
        /*
@@ -478,7 +449,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
 
        /* Expand SubLinks to SubPlans */
        if (root->parse->hasSubLinks)
-               expr = SS_process_sublinks(expr, (kind == EXPRKIND_QUAL));
+               expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
 
        /*
         * XXX do not insert anything here unless you have grokked the comments in
@@ -486,8 +457,8 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
         */
 
        /* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
-       if (PlannerQueryLevel > 1)
-               expr = SS_replace_correlation_vars(expr);
+       if (root->query_level > 1)
+               expr = SS_replace_correlation_vars(root, expr);
 
        /*
         * If it's a qual or havingQual, convert it to implicit-AND format. (We
@@ -590,6 +561,7 @@ inheritance_planner(PlannerInfo *root)
                subroot.in_info_list = (List *)
                        adjust_appendrel_attrs((Node *) root->in_info_list,
                                                                   appinfo);
+               subroot.init_plans = NIL;
                /* There shouldn't be any OJ info to translate, as yet */
                Assert(subroot.oj_info_list == NIL);
 
@@ -612,6 +584,9 @@ inheritance_planner(PlannerInfo *root)
 
                subplans = lappend(subplans, subplan);
 
+               /* Make sure any initplans from this rel get into the outer list */
+               root->init_plans = list_concat(root->init_plans, subroot.init_plans);
+
                /* Build target-relations list for the executor */
                resultRelations = lappend_int(resultRelations, appinfo->child_relid);
 
@@ -1201,7 +1176,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
         */
        if (parse->limitCount)
        {
-               est = estimate_expression_value(parse->limitCount);
+               est = estimate_expression_value(root, parse->limitCount);
                if (est && IsA(est, Const))
                {
                        if (((Const *) est)->constisnull)
@@ -1224,7 +1199,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
 
        if (parse->limitOffset)
        {
-               est = estimate_expression_value(parse->limitOffset);
+               est = estimate_expression_value(root, parse->limitOffset);
                if (est && IsA(est, Const))
                {
                        if (((Const *) est)->constisnull)
index af035d9b104cbbff3e3fd395f85fa7c3d019f122..b62aeb853d85e0e4e460c1e8cb696ff3afe6a1cc 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.119 2007/02/19 02:23:12 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.120 2007/02/19 07:03:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/syscache.h"
 
 
-Index          PlannerQueryLevel;      /* level of current query */
-List      *PlannerInitPlan;    /* init subplans for current query */
-List      *PlannerParamList;   /* to keep track of cross-level Params */
-
-int                    PlannerPlanId = 0;      /* to assign unique ID to subquery plans */
-
-/*
- * PlannerParamList keeps track of the PARAM_EXEC slots that we have decided
- * we need for the query.  At runtime these slots are used to pass values
- * either down into subqueries (for outer references in subqueries) or up out
- * of subqueries (for the results of a subplan).  The n'th entry in the list
- * (n counts from 0) corresponds to Param->paramid = n.
- *
- * Each ParamList item shows the absolute query level it is associated with,
- * where the outermost query is level 1 and nested subqueries have higher
- * numbers.  The item the parameter slot represents can be one of three kinds:
- *
- * A Var: the slot represents a variable of that level that must be passed
- * down because subqueries have outer references to it.  The varlevelsup
- * value in the Var will always be zero.
- *
- * An Aggref (with an expression tree representing its argument): the slot
- * represents an aggregate expression that is an outer reference for some
- * subquery.  The Aggref itself has agglevelsup = 0, and its argument tree
- * is adjusted to match in level.
- *
- * A Param: the slot holds the result of a subplan (it is a setParam item
- * for that subplan).  The absolute level shown for such items corresponds
- * to the parent query of the subplan.
- *
- * Note: we detect duplicate Var parameters and coalesce them into one slot,
- * but we do not do this for Aggref or Param slots.
- */
-typedef struct PlannerParamItem
-{
-       Node       *item;                       /* the Var, Aggref, or Param */
-       Index           abslevel;               /* its absolute query level */
-} PlannerParamItem;
-
-
 typedef struct convert_testexpr_context
 {
+       PlannerInfo *root;
        int                     rtindex;                /* RT index for Vars, or 0 for Params */
        List       *righthandIds;       /* accumulated list of Vars or Param IDs */
 } convert_testexpr_context;
 
+typedef struct process_sublinks_context
+{
+       PlannerInfo *root;
+       bool            isTopQual;
+} process_sublinks_context;
+
 typedef struct finalize_primnode_context
 {
        Bitmapset  *paramids;           /* Set of PARAM_EXEC paramids found */
@@ -84,15 +51,17 @@ typedef struct finalize_primnode_context
 } finalize_primnode_context;
 
 
-static Node *convert_testexpr(Node *testexpr,
-                                int rtindex,
-                                List **righthandIds);
+static Node *convert_testexpr(PlannerInfo *root,
+                                                         Node *testexpr,
+                                                         int rtindex,
+                                                         List **righthandIds);
 static Node *convert_testexpr_mutator(Node *node,
                                                 convert_testexpr_context *context);
 static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
 static bool hash_ok_operator(OpExpr *expr);
-static Node *replace_correlation_vars_mutator(Node *node, void *context);
-static Node *process_sublinks_mutator(Node *node, bool *isTopQual);
+static Node *replace_correlation_vars_mutator(Node *node, PlannerInfo *root);
+static Node *process_sublinks_mutator(Node *node,
+                                                                         process_sublinks_context *context);
 static Bitmapset *finalize_plan(Plan *plan, List *rtable,
                          Bitmapset *outer_params,
                          Bitmapset *valid_params);
@@ -104,7 +73,7 @@ static bool finalize_primnode(Node *node, finalize_primnode_context *context);
  * which is expected to have varlevelsup > 0 (ie, it is not local).
  */
 static Param *
-replace_outer_var(Var *var)
+replace_outer_var(PlannerInfo *root, Var *var)
 {
        Param      *retval;
        ListCell   *ppl;
@@ -112,11 +81,11 @@ replace_outer_var(Var *var)
        Index           abslevel;
        int                     i;
 
-       Assert(var->varlevelsup > 0 && var->varlevelsup < PlannerQueryLevel);
-       abslevel = PlannerQueryLevel - var->varlevelsup;
+       Assert(var->varlevelsup > 0 && var->varlevelsup < root->query_level);
+       abslevel = root->query_level - var->varlevelsup;
 
        /*
-        * If there's already a PlannerParamList entry for this same Var, just use
+        * If there's already a paramlist entry for this same Var, just use
         * it.  NOTE: in sufficiently complex querytrees, it is possible for the
         * same varno/abslevel to refer to different RTEs in different parts of
         * the parsetree, so that different fields might end up sharing the same
@@ -130,7 +99,7 @@ replace_outer_var(Var *var)
         * a subplan's args list.
         */
        i = 0;
-       foreach(ppl, PlannerParamList)
+       foreach(ppl, root->glob->paramlist)
        {
                pitem = (PlannerParamItem *) lfirst(ppl);
                if (pitem->abslevel == abslevel && IsA(pitem->item, Var))
@@ -152,11 +121,11 @@ replace_outer_var(Var *var)
                var = (Var *) copyObject(var);
                var->varlevelsup = 0;
 
-               pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
+               pitem = makeNode(PlannerParamItem);
                pitem->item = (Node *) var;
                pitem->abslevel = abslevel;
 
-               PlannerParamList = lappend(PlannerParamList, pitem);
+               root->glob->paramlist = lappend(root->glob->paramlist, pitem);
                /* i is already the correct index for the new item */
        }
 
@@ -174,15 +143,15 @@ replace_outer_var(Var *var)
  * which is expected to have agglevelsup > 0 (ie, it is not local).
  */
 static Param *
-replace_outer_agg(Aggref *agg)
+replace_outer_agg(PlannerInfo *root, Aggref *agg)
 {
        Param      *retval;
        PlannerParamItem *pitem;
        Index           abslevel;
        int                     i;
 
-       Assert(agg->agglevelsup > 0 && agg->agglevelsup < PlannerQueryLevel);
-       abslevel = PlannerQueryLevel - agg->agglevelsup;
+       Assert(agg->agglevelsup > 0 && agg->agglevelsup < root->query_level);
+       abslevel = root->query_level - agg->agglevelsup;
 
        /*
         * It does not seem worthwhile to try to match duplicate outer aggs. Just
@@ -192,12 +161,12 @@ replace_outer_agg(Aggref *agg)
        IncrementVarSublevelsUp((Node *) agg, -((int) agg->agglevelsup), 0);
        Assert(agg->agglevelsup == 0);
 
-       pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
+       pitem = makeNode(PlannerParamItem);
        pitem->item = (Node *) agg;
        pitem->abslevel = abslevel;
 
-       PlannerParamList = lappend(PlannerParamList, pitem);
-       i = list_length(PlannerParamList) - 1;
+       root->glob->paramlist = lappend(root->glob->paramlist, pitem);
+       i = list_length(root->glob->paramlist) - 1;
 
        retval = makeNode(Param);
        retval->paramkind = PARAM_EXEC;
@@ -214,22 +183,22 @@ replace_outer_agg(Aggref *agg)
  * This is used to allocate PARAM_EXEC slots for subplan outputs.
  */
 static Param *
-generate_new_param(Oid paramtype, int32 paramtypmod)
+generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod)
 {
        Param      *retval;
        PlannerParamItem *pitem;
 
        retval = makeNode(Param);
        retval->paramkind = PARAM_EXEC;
-       retval->paramid = list_length(PlannerParamList);
+       retval->paramid = list_length(root->glob->paramlist);
        retval->paramtype = paramtype;
        retval->paramtypmod = paramtypmod;
 
-       pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
+       pitem = makeNode(PlannerParamItem);
        pitem->item = (Node *) retval;
-       pitem->abslevel = PlannerQueryLevel;
+       pitem->abslevel = root->query_level;
 
-       PlannerParamList = lappend(PlannerParamList, pitem);
+       root->glob->paramlist = lappend(root->glob->paramlist, pitem);
 
        return retval;
 }
@@ -248,7 +217,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
  * tree containing InitPlan Param nodes.
  */
 static Node *
-make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
+make_subplan(PlannerInfo *root, SubLink *slink, Node *testexpr, bool isTopQual)
 {
        SubPlan    *node = makeNode(SubPlan);
        Query      *subquery = (Query *) (slink->subselect);
@@ -297,9 +266,13 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
        /*
         * Generate the plan for the subquery.
         */
-       node->plan = plan = subquery_planner(subquery, tuple_fraction, NULL);
+       node->plan = plan = subquery_planner(root->glob, subquery,
+                                                                                root->query_level + 1,
+                                                                                tuple_fraction,
+                                                                                NULL);
 
-       node->plan_id = PlannerPlanId++;        /* Assign unique ID to this SubPlan */
+       /* Assign quasi-unique ID to this SubPlan */
+       node->plan_id = root->glob->next_plan_id++;
 
        node->rtable = subquery->rtable;
 
@@ -323,9 +296,9 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
        tmpset = bms_copy(plan->extParam);
        while ((paramid = bms_first_member(tmpset)) >= 0)
        {
-               PlannerParamItem *pitem = list_nth(PlannerParamList, paramid);
+               PlannerParamItem *pitem = list_nth(root->glob->paramlist, paramid);
 
-               if (pitem->abslevel == PlannerQueryLevel)
+               if (pitem->abslevel == root->query_level)
                        node->parParam = lappend_int(node->parParam, paramid);
        }
        bms_free(tmpset);
@@ -342,9 +315,9 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
        {
                Param      *prm;
 
-               prm = generate_new_param(BOOLOID, -1);
+               prm = generate_new_param(root, BOOLOID, -1);
                node->setParam = list_make1_int(prm->paramid);
-               PlannerInitPlan = lappend(PlannerInitPlan, node);
+               root->init_plans = lappend(root->init_plans, node);
                result = (Node *) prm;
        }
        else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
@@ -353,10 +326,11 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
                Param      *prm;
 
                Assert(!te->resjunk);
-               prm = generate_new_param(exprType((Node *) te->expr),
+               prm = generate_new_param(root,
+                                                                exprType((Node *) te->expr),
                                                                 exprTypmod((Node *) te->expr));
                node->setParam = list_make1_int(prm->paramid);
-               PlannerInitPlan = lappend(PlannerInitPlan, node);
+               root->init_plans = lappend(root->init_plans, node);
                result = (Node *) prm;
        }
        else if (node->parParam == NIL && slink->subLinkType == ARRAY_SUBLINK)
@@ -370,19 +344,22 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
                if (!OidIsValid(arraytype))
                        elog(ERROR, "could not find array type for datatype %s",
                                 format_type_be(exprType((Node *) te->expr)));
-               prm = generate_new_param(arraytype, exprTypmod((Node *) te->expr));
+               prm = generate_new_param(root,
+                                                                arraytype,
+                                                                exprTypmod((Node *) te->expr));
                node->setParam = list_make1_int(prm->paramid);
-               PlannerInitPlan = lappend(PlannerInitPlan, node);
+               root->init_plans = lappend(root->init_plans, node);
                result = (Node *) prm;
        }
        else if (node->parParam == NIL && slink->subLinkType == ROWCOMPARE_SUBLINK)
        {
                /* Adjust the Params */
-               result = convert_testexpr(testexpr,
+               result = convert_testexpr(root,
+                                                                 testexpr,
                                                                  0,
                                                                  &node->paramIds);
                node->setParam = list_copy(node->paramIds);
-               PlannerInitPlan = lappend(PlannerInitPlan, node);
+               root->init_plans = lappend(root->init_plans, node);
 
                /*
                 * The executable expression is returned to become part of the outer
@@ -395,7 +372,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
                ListCell   *l;
 
                /* Adjust the Params */
-               node->testexpr = convert_testexpr(testexpr,
+               node->testexpr = convert_testexpr(root,
+                                                                                 testexpr,
                                                                                  0,
                                                                                  &node->paramIds);
 
@@ -442,7 +420,8 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
                args = NIL;
                foreach(l, node->parParam)
                {
-                       PlannerParamItem *pitem = list_nth(PlannerParamList, lfirst_int(l));
+                       PlannerParamItem *pitem = list_nth(root->glob->paramlist,
+                                                                                          lfirst_int(l));
 
                        /*
                         * The Var or Aggref has already been adjusted to have the correct
@@ -477,13 +456,15 @@ make_subplan(SubLink *slink, Node *testexpr, bool isTopQual)
  * any we find are for our own level of SubLink.
  */
 static Node *
-convert_testexpr(Node *testexpr,
+convert_testexpr(PlannerInfo *root,
+                                Node *testexpr,
                                 int rtindex,
                                 List **righthandIds)
 {
        Node       *result;
        convert_testexpr_context context;
 
+       context.root = root;
        context.rtindex = rtindex;
        context.righthandIds = NIL;
        result = convert_testexpr_mutator(testexpr, &context);
@@ -536,7 +517,8 @@ convert_testexpr_mutator(Node *node,
                                /* Make the Param node representing the subplan's result */
                                Param      *newparam;
 
-                               newparam = generate_new_param(param->paramtype,
+                               newparam = generate_new_param(context->root,
+                                                                                         param->paramtype,
                                                                                          param->paramtypmod);
                                /* Record its ID */
                                context->righthandIds = lappend_int(context->righthandIds,
@@ -765,7 +747,8 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
         * ininfo->sub_targetlist is filled with a list of Vars representing the
         * subselect outputs.
         */
-       result = convert_testexpr(sublink->testexpr,
+       result = convert_testexpr(root,
+                                                         sublink->testexpr,
                                                          rtindex,
                                                          &ininfo->sub_targetlist);
 
@@ -795,30 +778,30 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
  * argument expressions, either in the parent or the child level.
  */
 Node *
-SS_replace_correlation_vars(Node *expr)
+SS_replace_correlation_vars(PlannerInfo *root, Node *expr)
 {
        /* No setup needed for tree walk, so away we go */
-       return replace_correlation_vars_mutator(expr, NULL);
+       return replace_correlation_vars_mutator(expr, root);
 }
 
 static Node *
-replace_correlation_vars_mutator(Node *node, void *context)
+replace_correlation_vars_mutator(Node *node, PlannerInfo *root)
 {
        if (node == NULL)
                return NULL;
        if (IsA(node, Var))
        {
                if (((Var *) node)->varlevelsup > 0)
-                       return (Node *) replace_outer_var((Var *) node);
+                       return (Node *) replace_outer_var(root, (Var *) node);
        }
        if (IsA(node, Aggref))
        {
                if (((Aggref *) node)->agglevelsup > 0)
-                       return (Node *) replace_outer_agg((Aggref *) node);
+                       return (Node *) replace_outer_agg(root, (Aggref *) node);
        }
        return expression_tree_mutator(node,
                                                                   replace_correlation_vars_mutator,
-                                                                  context);
+                                                                  (void *) root);
 }
 
 /*
@@ -829,16 +812,21 @@ replace_correlation_vars_mutator(Node *node, void *context)
  * not distinguish FALSE from UNKNOWN return values.
  */
 Node *
-SS_process_sublinks(Node *expr, bool isQual)
+SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual)
 {
-       /* The only context needed is the initial are-we-in-a-qual flag */
-       return process_sublinks_mutator(expr, &isQual);
+       process_sublinks_context context;
+
+       context.root = root;
+       context.isTopQual = isQual;
+       return process_sublinks_mutator(expr, &context);
 }
 
 static Node *
-process_sublinks_mutator(Node *node, bool *isTopQual)
+process_sublinks_mutator(Node *node, process_sublinks_context *context)
 {
-       bool            locTopQual;
+       process_sublinks_context locContext;
+
+       locContext.root = context->root;
 
        if (node == NULL)
                return NULL;
@@ -849,14 +837,18 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
 
                /*
                 * First, recursively process the lefthand-side expressions, if any.
+                * They're not top-level anymore.
                 */
-               locTopQual = false;
-               testexpr = process_sublinks_mutator(sublink->testexpr, &locTopQual);
+               locContext.isTopQual = false;
+               testexpr = process_sublinks_mutator(sublink->testexpr, &locContext);
 
                /*
                 * Now build the SubPlan node and make the expr to return.
                 */
-               return make_subplan(sublink, testexpr, *isTopQual);
+               return make_subplan(context->root,
+                                                       sublink,
+                                                       testexpr,
+                                                       context->isTopQual);
        }
 
        /*
@@ -883,14 +875,13 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
                ListCell   *l;
 
                /* Still at qual top-level */
-               locTopQual = *isTopQual;
+               locContext.isTopQual = context->isTopQual;
 
                foreach(l, ((BoolExpr *) node)->args)
                {
                        Node       *newarg;
 
-                       newarg = process_sublinks_mutator(lfirst(l),
-                                                                                         (void *) &locTopQual);
+                       newarg = process_sublinks_mutator(lfirst(l), &locContext);
                        if (and_clause(newarg))
                                newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
                        else
@@ -900,7 +891,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
        }
 
        /* otherwise not at qual top-level */
-       locTopQual = false;
+       locContext.isTopQual = false;
 
        if (or_clause(node))
        {
@@ -911,8 +902,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
                {
                        Node       *newarg;
 
-                       newarg = process_sublinks_mutator(lfirst(l),
-                                                                                         (void *) &locTopQual);
+                       newarg = process_sublinks_mutator(lfirst(l), &locContext);
                        if (or_clause(newarg))
                                newargs = list_concat(newargs, ((BoolExpr *) newarg)->args);
                        else
@@ -923,7 +913,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
 
        return expression_tree_mutator(node,
                                                                   process_sublinks_mutator,
-                                                                  (void *) &locTopQual);
+                                                                  (void *) &locContext);
 }
 
 /*
@@ -934,7 +924,7 @@ process_sublinks_mutator(Node *node, bool *isTopQual)
  * to the top plan node.
  */
 void
-SS_finalize_plan(Plan *plan, List *rtable)
+SS_finalize_plan(PlannerInfo *root, Plan *plan)
 {
        Bitmapset  *outer_params,
                           *valid_params,
@@ -951,17 +941,17 @@ SS_finalize_plan(Plan *plan, List *rtable)
         */
        outer_params = valid_params = NULL;
        paramid = 0;
-       foreach(l, PlannerParamList)
+       foreach(l, root->glob->paramlist)
        {
                PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l);
 
-               if (pitem->abslevel < PlannerQueryLevel)
+               if (pitem->abslevel < root->query_level)
                {
                        /* valid outer-level parameter */
                        outer_params = bms_add_member(outer_params, paramid);
                        valid_params = bms_add_member(valid_params, paramid);
                }
-               else if (pitem->abslevel == PlannerQueryLevel &&
+               else if (pitem->abslevel == root->query_level &&
                                 IsA(pitem->item, Param))
                {
                        /* valid local parameter (i.e., a setParam of my child) */
@@ -974,7 +964,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
        /*
         * Now recurse through plan tree.
         */
-       (void) finalize_plan(plan, rtable, outer_params, valid_params);
+       (void) finalize_plan(plan, root->parse->rtable, outer_params, valid_params);
 
        bms_free(outer_params);
        bms_free(valid_params);
@@ -991,8 +981,8 @@ SS_finalize_plan(Plan *plan, List *rtable)
         * top node.  This is a conservative overestimate, since in fact each
         * initPlan might be executed later than plan startup, or even not at all.
         */
-       plan->initPlan = PlannerInitPlan;
-       PlannerInitPlan = NIL;          /* make sure they're not attached twice */
+       plan->initPlan = root->init_plans;
+       root->init_plans = NIL;         /* make sure they're not attached twice */
 
        initExtParam = initSetParam = NULL;
        initplan_cost = 0;
@@ -1287,25 +1277,27 @@ Param *
 SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
                                                   Oid resulttype, int32 resulttypmod)
 {
-       List       *saved_initplan = PlannerInitPlan;
+       List       *saved_init_plans;
        SubPlan    *node;
        Param      *prm;
 
        /*
         * Set up for a new level of subquery.  This is just to keep
-        * SS_finalize_plan from becoming confused.
+        * SS_finalize_plan from becoming confused; we don't bother with making
+        * a whole new PlannerInfo struct.
         */
-       PlannerQueryLevel++;
-       PlannerInitPlan = NIL;
+       root->query_level++;
+       saved_init_plans = root->init_plans;
+       root->init_plans = NIL;
 
        /*
         * Build extParam/allParam sets for plan nodes.
         */
-       SS_finalize_plan(plan, root->parse->rtable);
+       SS_finalize_plan(root, plan);
 
        /* Return to outer subquery context */
-       PlannerQueryLevel--;
-       PlannerInitPlan = saved_initplan;
+       root->query_level--;
+       root->init_plans = saved_init_plans;
 
        /*
         * Create a SubPlan node and add it to the outer list of InitPlans.
@@ -1313,11 +1305,12 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
        node = makeNode(SubPlan);
        node->subLinkType = EXPR_SUBLINK;
        node->plan = plan;
-       node->plan_id = PlannerPlanId++;        /* Assign unique ID to this SubPlan */
+       /* Assign quasi-unique ID to this SubPlan */
+       node->plan_id = root->glob->next_plan_id++;
 
        node->rtable = root->parse->rtable;
 
-       PlannerInitPlan = lappend(PlannerInitPlan, node);
+       root->init_plans = lappend(root->init_plans, node);
 
        /*
         * The node can't have any inputs (since it's an initplan), so the
@@ -1327,7 +1320,7 @@ SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
        /*
         * Make a Param that will be the subplan's output.
         */
-       prm = generate_new_param(resulttype, resulttypmod);
+       prm = generate_new_param(root, resulttype, resulttypmod);
        node->setParam = list_make1_int(prm->paramid);
 
        return prm;
index ce6f9cc38e4b470b0fc88a59076db765eaf6fdda..1519c01e60e725c8c5ad72ddd0a6f96fda58edc5 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.46 2007/01/20 20:45:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.47 2007/02/19 07:03:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -292,7 +292,10 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
         */
        subroot = makeNode(PlannerInfo);
        subroot->parse = subquery;
+       subroot->glob = root->glob;
+       subroot->query_level = root->query_level;
        subroot->planner_cxt = CurrentMemoryContext;
+       subroot->init_plans = NIL;
        subroot->in_info_list = NIL;
        subroot->append_rel_list = NIL;
 
index b8d98cc9e3cd7ead395795c6d02324cef13ace42..310b57392cd9460e14039d3920929e9f6256d45d 100644 (file)
@@ -16,7 +16,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.85 2007/01/05 22:19:32 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.86 2007/02/19 07:03:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -124,7 +124,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
                /*
                 * Currently the executor only supports FOR UPDATE/SHARE at top level
                 */
-               if (PlannerQueryLevel > 1)
+               if (root->query_level > 1)
                        ereport(ERROR,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                        errmsg("SELECT FOR UPDATE/SHARE is not allowed in subqueries")));
index 5ee03b75cffd7e87e9d1322eda94390cb5f8f710..2f06e1bf5322dfe3a03c14d310c9dbc03d964590 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.137 2007/01/22 20:00:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.138 2007/02/19 07:03:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -177,7 +177,10 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
                /*
                 * Generate plan for primitive subquery
                 */
-               subplan = subquery_planner(subquery, tuple_fraction, NULL);
+               subplan = subquery_planner(root->glob, subquery,
+                                                                  root->query_level + 1,
+                                                                  tuple_fraction,
+                                                                  NULL);
 
                /*
                 * Add a SubqueryScan with the caller-requested targetlist
index 528f02ed111389beef7c228d18678d0002db662d..f90d55001979b65c15f8fdb222473cc349e83a1e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.234 2007/02/16 23:32:08 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.235 2007/02/19 07:03:30 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -49,6 +49,7 @@
 
 typedef struct
 {
+       ParamListInfo boundParams;
        List       *active_fns;
        Node       *case_val;
        bool            estimate;
@@ -1578,6 +1579,7 @@ eval_const_expressions(Node *node)
 {
        eval_const_expressions_context context;
 
+       context.boundParams = NULL;     /* don't use any bound params */
        context.active_fns = NIL;       /* nothing being recursively simplified */
        context.case_val = NULL;        /* no CASE being examined */
        context.estimate = false;       /* safe transformations only */
@@ -1601,10 +1603,11 @@ eval_const_expressions(Node *node)
  *--------------------
  */
 Node *
-estimate_expression_value(Node *node)
+estimate_expression_value(PlannerInfo *root, Node *node)
 {
        eval_const_expressions_context context;
 
+       context.boundParams = root->glob->boundParams;  /* bound Params */
        context.active_fns = NIL;       /* nothing being recursively simplified */
        context.case_val = NULL;        /* no CASE being examined */
        context.estimate = true;        /* unsafe transformations OK */
@@ -1623,11 +1626,11 @@ eval_const_expressions_mutator(Node *node,
 
                /* Look to see if we've been given a value for this Param */
                if (param->paramkind == PARAM_EXTERN &&
-                       PlannerBoundParamList != NULL &&
+                       context->boundParams != NULL &&
                        param->paramid > 0 &&
-                       param->paramid <= PlannerBoundParamList->numParams)
+                       param->paramid <= context->boundParams->numParams)
                {
-                       ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
+                       ParamExternData *prm = &context->boundParams->params[param->paramid - 1];
 
                        if (OidIsValid(prm->ptype))
                        {
index 7908ab15167a74ddf34a705fd33458d45b027f67..c6b8e8481c498d822de7700ca293713910021716 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.225 2007/01/31 16:54:51 teodor Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.226 2007/02/19 07:03:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3411,7 +3411,7 @@ get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
        if (vardata->rel && rdata.rel == NULL)
        {
                *varonleft = true;
-               *other = estimate_expression_value(rdata.var);
+               *other = estimate_expression_value(root, rdata.var);
                /* Assume we need no ReleaseVariableStats(rdata) here */
                return true;
        }
@@ -3419,7 +3419,7 @@ get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
        if (vardata->rel == NULL && rdata.rel)
        {
                *varonleft = false;
-               *other = estimate_expression_value(vardata->var);
+               *other = estimate_expression_value(root, vardata->var);
                /* Assume we need no ReleaseVariableStats(*vardata) here */
                *vardata = rdata;
                return true;
index 2452f792940788985bb36782abc2ab9d9bfbb7e4..44175591e7502c38910a2286bfecff1bd57a8940 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.194 2007/02/03 14:06:55 petere Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.195 2007/02/19 07:03:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -175,6 +175,7 @@ typedef enum NodeTag
         * TAGS FOR PLANNER NODES (relation.h)
         */
        T_PlannerInfo = 500,
+       T_PlannerGlobal,
        T_RelOptInfo,
        T_IndexOptInfo,
        T_Path,
@@ -198,6 +199,7 @@ typedef enum NodeTag
        T_OuterJoinInfo,
        T_InClauseInfo,
        T_AppendRelInfo,
+       T_PlannerParamItem,
 
        /*
         * TAGS FOR MEMORY NODES (memnodes.h)
index 298ac0d95d6f7920b3312bdd7e3e8151227f3bd1..caa689e262379074e18b09fd35dcd769fe068b29 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.124 2007/02/03 14:06:56 petere Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.125 2007/02/19 07:03:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -442,10 +442,9 @@ typedef struct SubPlan
        List       *paramIds;           /* IDs of Params embedded in the above */
        /* The subselect, transformed to a Plan: */
        struct Plan *plan;                      /* subselect plan itself */
-       int                     plan_id;                /* dummy thing because of we haven't equal
-                                                                * funcs for plan nodes... actually, we could
-                                                                * put *plan itself somewhere else (TopPlan
-                                                                * node ?)... */
+       int                     plan_id;                /* kluge because we haven't equal-funcs for
+                                                                * plan nodes... we compare this instead of
+                                                                * subselect plan */
        List       *rtable;                     /* range table for subselect */
        /* Information about execution strategy: */
        bool            useHashTable;   /* TRUE to store subselect output in a hash
index dac7d959bbd23bd8dcbd5a6ad779f8eec693ad5e..6de06ebc918f769327cf32ca075b3ab26ff9262a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.135 2007/02/16 20:57:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.136 2007/02/19 07:03:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "access/sdir.h"
 #include "nodes/bitmapset.h"
+#include "nodes/params.h"
 #include "nodes/parsenodes.h"
 #include "storage/block.h"
 
@@ -46,6 +47,27 @@ typedef struct QualCost
 } QualCost;
 
 
+/*----------
+ * PlannerGlobal
+ *             Global information for planning/optimization
+ *
+ * PlannerGlobal holds state for an entire planner invocation; this state
+ * is shared across all levels of sub-Queries that exist in the command being
+ * planned.
+ *----------
+ */
+typedef struct PlannerGlobal
+{
+       NodeTag         type;
+
+       ParamListInfo boundParams;      /* Param values provided to planner() */
+
+       List       *paramlist;          /* to keep track of cross-level Params */
+
+       int                     next_plan_id;   /* hack for distinguishing SubPlans */
+} PlannerGlobal;
+
+
 /*----------
  * PlannerInfo
  *             Per-query information for planning/optimization
@@ -62,6 +84,10 @@ typedef struct PlannerInfo
 
        Query      *parse;                      /* the Query being planned */
 
+       PlannerGlobal *glob;            /* global info for current planner run */
+
+       Index           query_level;    /* 1 at the outermost Query */
+
        /*
         * simple_rel_array holds pointers to "base rels" and "other rels" (see
         * comments for RelOptInfo for more info).      It is indexed by rangetable
@@ -84,6 +110,8 @@ typedef struct PlannerInfo
        List       *join_rel_list;      /* list of join-relation RelOptInfos */
        struct HTAB *join_rel_hash; /* optional hashtable for join relations */
 
+       List       *init_plans;                         /* init subplans for query */
+
        List       *eq_classes;                         /* list of active EquivalenceClasses */
 
        List       *canon_pathkeys;                     /* list of "canonical" PathKeys */
@@ -1109,4 +1137,39 @@ typedef struct AppendRelInfo
        Oid                     parent_reloid;  /* OID of parent relation */
 } AppendRelInfo;
 
+/*
+ * glob->paramlist keeps track of the PARAM_EXEC slots that we have decided
+ * we need for the query.  At runtime these slots are used to pass values
+ * either down into subqueries (for outer references in subqueries) or up out
+ * of subqueries (for the results of a subplan).  The n'th entry in the list
+ * (n counts from 0) corresponds to Param->paramid = n.
+ *
+ * Each paramlist item shows the absolute query level it is associated with,
+ * where the outermost query is level 1 and nested subqueries have higher
+ * numbers.  The item the parameter slot represents can be one of three kinds:
+ *
+ * A Var: the slot represents a variable of that level that must be passed
+ * down because subqueries have outer references to it.  The varlevelsup
+ * value in the Var will always be zero.
+ *
+ * An Aggref (with an expression tree representing its argument): the slot
+ * represents an aggregate expression that is an outer reference for some
+ * subquery.  The Aggref itself has agglevelsup = 0, and its argument tree
+ * is adjusted to match in level.
+ *
+ * A Param: the slot holds the result of a subplan (it is a setParam item
+ * for that subplan).  The absolute level shown for such items corresponds
+ * to the parent query of the subplan.
+ *
+ * Note: we detect duplicate Var parameters and coalesce them into one slot,
+ * but we do not do this for Aggref or Param slots.
+ */
+typedef struct PlannerParamItem
+{
+       NodeTag         type;
+
+       Node       *item;                       /* the Var, Aggref, or Param */
+       Index           abslevel;               /* its absolute query level */
+} PlannerParamItem;
+
 #endif   /* RELATION_H */
index 500112591429a58a92915e014ab855dd098c24d9..bd4a7964355f3473db5324a3ac7851ee49c664b2 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.86 2007/01/22 01:35:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.87 2007/02/19 07:03:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -77,7 +77,7 @@ extern void set_coercionform_dontcare(Node *node);
 
 extern Node *eval_const_expressions(Node *node);
 
-extern Node *estimate_expression_value(Node *node);
+extern Node *estimate_expression_value(PlannerInfo *root, Node *node);
 
 extern bool expression_tree_walker(Node *node, bool (*walker) (),
                                                                                           void *context);
index 6567e5b8b77920e566079a77aaedbb0a3d2c3f80..44d03602694120f59dd557b3328ea1f2005f6420 100644 (file)
@@ -7,23 +7,21 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.36 2007/01/05 22:19:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.37 2007/02/19 07:03:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef PLANNER_H
 #define PLANNER_H
 
-#include "nodes/params.h"
-#include "nodes/parsenodes.h"
 #include "nodes/plannodes.h"
+#include "nodes/relation.h"
 
 
-extern ParamListInfo PlannerBoundParamList;            /* current boundParams */
-
 extern Plan *planner(Query *parse, bool isCursor, int cursorOptions,
                ParamListInfo boundParams);
-extern Plan *subquery_planner(Query *parse, double tuple_fraction,
-                                List **subquery_pathkeys);
+extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse,
+                                                         Index level, double tuple_fraction,
+                                                         List **subquery_pathkeys);
 
 #endif   /* PLANNER_H */
index 8a4328bd1f2d487017b7af1e5d39dc32885986f2..17c94bf6099ee8cfe4b68486b77f20277d1e93e0 100644 (file)
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.28 2007/01/05 22:19:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.29 2007/02/19 07:03:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "nodes/plannodes.h"
 #include "nodes/relation.h"
 
-
-extern Index PlannerQueryLevel; /* level of current query */
-extern List *PlannerInitPlan;  /* init subplans for current query */
-extern List *PlannerParamList; /* to keep track of cross-level Params */
-extern int     PlannerPlanId;          /* to assign unique ID to subquery plans */
-
 extern Node *convert_IN_to_join(PlannerInfo *root, SubLink *sublink);
-extern Node *SS_replace_correlation_vars(Node *expr);
-extern Node *SS_process_sublinks(Node *expr, bool isQual);
-extern void SS_finalize_plan(Plan *plan, List *rtable);
+extern Node *SS_replace_correlation_vars(PlannerInfo *root, Node *expr);
+extern Node *SS_process_sublinks(PlannerInfo *root, Node *expr, bool isQual);
+extern void SS_finalize_plan(PlannerInfo *root, Plan *plan);
 extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
                                                   Oid resulttype, int32 resulttypmod);