Remove planner's private fields from Query struct, and put them into
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Jun 2005 22:32:58 +0000 (22:32 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 5 Jun 2005 22:32:58 +0000 (22:32 +0000)
a new PlannerInfo struct, which is passed around instead of the bare
Query in all the planning code.  This commit is essentially just a
code-beautification exercise, but it does open the door to making
larger changes to the planner data structures without having to muck
with the widely-known Query struct.

51 files changed:
doc/src/sgml/indexam.sgml
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/README
src/backend/optimizer/geqo/geqo_eval.c
src/backend/optimizer/geqo/geqo_main.c
src/backend/optimizer/path/allpaths.c
src/backend/optimizer/path/clausesel.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/joinpath.c
src/backend/optimizer/path/joinrels.c
src/backend/optimizer/path/orindxpath.c
src/backend/optimizer/path/pathkeys.c
src/backend/optimizer/path/tidpath.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/planagg.c
src/backend/optimizer/plan/planmain.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/optimizer/util/joininfo.c
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/plancat.c
src/backend/optimizer/util/relnode.c
src/backend/optimizer/util/restrictinfo.c
src/backend/optimizer/util/var.c
src/backend/parser/parse_agg.c
src/backend/utils/adt/selfuncs.c
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/nodes/relation.h
src/include/optimizer/cost.h
src/include/optimizer/geqo.h
src/include/optimizer/joininfo.h
src/include/optimizer/pathnode.h
src/include/optimizer/paths.h
src/include/optimizer/plancat.h
src/include/optimizer/planmain.h
src/include/optimizer/planner.h
src/include/optimizer/prep.h
src/include/optimizer/restrictinfo.h
src/include/optimizer/subselect.h
src/include/optimizer/var.h
src/include/utils/selfuncs.h

index 9a84509f749aba91bada4777fec2df50d63b89e0..cbc01bae8c437e3ec538d9ad45020bdf2d48ea52 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.4 2005/04/20 22:19:58 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.5 2005/06/05 22:32:53 tgl Exp $
 -->
 
 <chapter id="indexam">
@@ -319,7 +319,7 @@ amrestrpos (IndexScanDesc scan);
   <para>
 <programlisting>
 void
-amcostestimate (Query *root,
+amcostestimate (PlannerInfo *root,
                 IndexOptInfo *index,
                 List *indexQuals,
                 Cost *indexStartupCost,
@@ -656,7 +656,7 @@ amcostestimate (Query *root,
 
 <programlisting>
 void
-amcostestimate (Query *root,
+amcostestimate (PlannerInfo *root,
                 IndexOptInfo *index,
                 List *indexQuals,
                 Cost *indexStartupCost,
@@ -672,7 +672,7 @@ amcostestimate (Query *root,
      <term>root</term>
      <listitem>
       <para>
-       The query being processed.
+       The planner's information about the query being processed.
       </para>
      </listitem>
     </varlistentry>
index 2d5dd7b2b5c74d39dd69ca8a3f7fbb56a0467f9a..2f7642276cf959ea0a8bc378584cf6ae53f75c5b 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.304 2005/04/28 21:47:12 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.305 2005/06/05 22:32:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1615,18 +1615,6 @@ _copyQuery(Query *from)
        COPY_NODE_FIELD(limitCount);
        COPY_NODE_FIELD(setOperations);
        COPY_NODE_FIELD(resultRelations);
-       COPY_NODE_FIELD(in_info_list);
-       COPY_SCALAR_FIELD(hasJoinRTEs);
-       COPY_SCALAR_FIELD(hasHavingQual);
-
-       /*
-        * We do not copy the other planner internal fields: base_rel_list,
-        * other_rel_list, join_rel_list, equi_key_list, query_pathkeys. That
-        * would get us into copying RelOptInfo/Path trees, which we don't
-        * want to do.  It is necessary to copy in_info_list, hasJoinRTEs,
-        * and hasHavingQual for the benefit of inheritance_planner(), which
-        * may try to copy a Query in which these are already set.
-        */
 
        return newnode;
 }
index a9570201be26753f82e76fb9202c29a3f743453c..a1d951112c8ed1930b68e1c69ab3610e0c7e11df 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.241 2005/04/28 21:47:12 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.242 2005/06/05 22:32:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -653,10 +653,6 @@ _equalQuery(Query *a, Query *b)
        COMPARE_NODE_FIELD(setOperations);
        COMPARE_NODE_FIELD(resultRelations);
 
-       /*
-        * We do not check the planner-internal fields.  They might not be set
-        * yet, and in any case they should be derivable from the other fields.
-        */
        return true;
 }
 
index 37918e865842cfb6c7410060813333ade9450c95..51a85a90b3c11475a588aa01ac29aaac05283ac5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.252 2005/05/09 15:09:19 ishii Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.253 2005/06/05 22:32:54 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1145,6 +1145,69 @@ _outHashPath(StringInfo str, HashPath *node)
        WRITE_NODE_FIELD(path_hashclauses);
 }
 
+static void
+_outPlannerInfo(StringInfo str, PlannerInfo *node)
+{
+       WRITE_NODE_TYPE("PLANNERINFO");
+
+       WRITE_NODE_FIELD(parse);
+       WRITE_NODE_FIELD(base_rel_list);
+       WRITE_NODE_FIELD(other_rel_list);
+       WRITE_NODE_FIELD(join_rel_list);
+       WRITE_NODE_FIELD(equi_key_list);
+       WRITE_NODE_FIELD(in_info_list);
+       WRITE_NODE_FIELD(query_pathkeys);
+       WRITE_BOOL_FIELD(hasJoinRTEs);
+       WRITE_BOOL_FIELD(hasHavingQual);
+}
+
+static void
+_outRelOptInfo(StringInfo str, RelOptInfo *node)
+{
+       WRITE_NODE_TYPE("RELOPTINFO");
+
+       /* NB: this isn't a complete set of fields */
+       WRITE_ENUM_FIELD(reloptkind, RelOptKind);
+       WRITE_BITMAPSET_FIELD(relids);
+       WRITE_FLOAT_FIELD(rows, "%.0f");
+       WRITE_INT_FIELD(width);
+       WRITE_NODE_FIELD(reltargetlist);
+       WRITE_NODE_FIELD(pathlist);
+       WRITE_NODE_FIELD(cheapest_startup_path);
+       WRITE_NODE_FIELD(cheapest_total_path);
+       WRITE_NODE_FIELD(cheapest_unique_path);
+       WRITE_UINT_FIELD(relid);
+       WRITE_ENUM_FIELD(rtekind, RTEKind);
+       WRITE_UINT_FIELD(min_attr);
+       WRITE_UINT_FIELD(max_attr);
+       WRITE_NODE_FIELD(indexlist);
+       WRITE_UINT_FIELD(pages);
+       WRITE_FLOAT_FIELD(tuples, "%.0f");
+       WRITE_NODE_FIELD(subplan);
+       WRITE_NODE_FIELD(baserestrictinfo);
+       WRITE_BITMAPSET_FIELD(outerjoinset);
+       WRITE_NODE_FIELD(joininfo);
+       WRITE_BITMAPSET_FIELD(index_outer_relids);
+       WRITE_NODE_FIELD(index_inner_paths);
+}
+
+static void
+_outIndexOptInfo(StringInfo str, IndexOptInfo *node)
+{
+       WRITE_NODE_TYPE("INDEXOPTINFO");
+
+       /* NB: this isn't a complete set of fields */
+       WRITE_OID_FIELD(indexoid);
+       /* Do NOT print rel field, else infinite recursion */
+       WRITE_UINT_FIELD(pages);
+       WRITE_FLOAT_FIELD(tuples, "%.0f");
+       WRITE_INT_FIELD(ncolumns);
+       WRITE_NODE_FIELD(indexprs);
+       WRITE_NODE_FIELD(indpred);
+       WRITE_BOOL_FIELD(predOK);
+       WRITE_BOOL_FIELD(unique);
+}
+
 static void
 _outPathKeyItem(StringInfo str, PathKeyItem *node)
 {
@@ -1185,6 +1248,15 @@ _outJoinInfo(StringInfo str, JoinInfo *node)
        WRITE_NODE_FIELD(jinfo_restrictinfo);
 }
 
+static void
+_outInnerIndexscanInfo(StringInfo str, InnerIndexscanInfo *node)
+{
+       WRITE_NODE_TYPE("INNERINDEXSCANINFO");
+       WRITE_BITMAPSET_FIELD(other_relids);
+       WRITE_BOOL_FIELD(isouterjoin);
+       WRITE_NODE_FIELD(best_innerpath);
+}
+
 static void
 _outInClauseInfo(StringInfo str, InClauseInfo *node)
 {
@@ -1395,8 +1467,6 @@ _outQuery(StringInfo str, Query *node)
        WRITE_NODE_FIELD(limitCount);
        WRITE_NODE_FIELD(setOperations);
        WRITE_NODE_FIELD(resultRelations);
-
-       /* planner-internal fields are not written out */
 }
 
 static void
@@ -1905,6 +1975,15 @@ _outNode(StringInfo str, void *obj)
                        case T_HashPath:
                                _outHashPath(str, obj);
                                break;
+                       case T_PlannerInfo:
+                               _outPlannerInfo(str, obj);
+                               break;
+                       case T_RelOptInfo:
+                               _outRelOptInfo(str, obj);
+                               break;
+                       case T_IndexOptInfo:
+                               _outIndexOptInfo(str, obj);
+                               break;
                        case T_PathKeyItem:
                                _outPathKeyItem(str, obj);
                                break;
@@ -1914,6 +1993,9 @@ _outNode(StringInfo str, void *obj)
                        case T_JoinInfo:
                                _outJoinInfo(str, obj);
                                break;
+                       case T_InnerIndexscanInfo:
+                               _outInnerIndexscanInfo(str, obj);
+                               break;
                        case T_InClauseInfo:
                                _outInClauseInfo(str, obj);
                                break;
index ef405f7a0223ea0d7c006e341c97acb2eed0a988..e01646a71d13e61baf54a926450160c69011f4e8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.177 2005/04/28 21:47:13 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.178 2005/06/05 22:32:54 tgl Exp $
  *
  * NOTES
  *       Path and Plan nodes do not have any readfuncs support, because we
@@ -156,8 +156,6 @@ _readQuery(void)
        READ_NODE_FIELD(setOperations);
        READ_NODE_FIELD(resultRelations);
 
-       /* planner-internal fields are left zero */
-
        READ_DONE();
 }
 
index 174ad4fd0a029dc4518fdb25a11f760a9b902d70..3c2fd32d5203883b0b92c7f21da175dc1bc85f6e 100644 (file)
@@ -245,6 +245,8 @@ planner()
 Optimizer Data Structures
 -------------------------
 
+PlannerInfo     - global information for planning a particular Query
+
 RelOptInfo      - a relation or joined relations
 
  RestrictInfo   - WHERE clauses, like "x = 3" or "y = z"
index 08d80f80b7d46872be325c98f33854dd19035ed9..3460eb5b8e3cf51b3154fcb9d7dd31ffcb4da4a1 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.73 2004/12/31 21:59:58 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.74 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,7 @@
 #include "utils/memutils.h"
 
 
-static bool desirable_join(Query *root,
+static bool desirable_join(PlannerInfo *root,
                           RelOptInfo *outer_rel, RelOptInfo *inner_rel);
 
 
@@ -241,7 +241,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata)
  * Heuristics for gimme_tree: do we want to join these two relations?
  */
 static bool
-desirable_join(Query *root,
+desirable_join(PlannerInfo *root,
                           RelOptInfo *outer_rel, RelOptInfo *inner_rel)
 {
        ListCell   *l;
index f827e865bf40eaeec69b162ba70ee8e24d66215a..f19f5f7c34d611e4faeed528680d411413bb8590 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.48 2004/12/31 21:59:58 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.49 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,7 @@ static int    gimme_number_generations(int pool_size);
  */
 
 RelOptInfo *
-geqo(Query *root, int number_of_rels, List *initial_rels)
+geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
 {
        GeqoEvalData evaldata;
        int                     generation;
index 7e7666015a1e7c51d13a516ae0897be3070c85ac..e41701d044bff3216a4e06525886dd137a7c25fa 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.130 2005/06/04 19:19:41 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.131 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,17 +38,17 @@ bool                enable_geqo = false;    /* just in case GUC doesn't set it */
 int                    geqo_threshold;
 
 
-static void set_base_rel_pathlists(Query *root);
-static void set_plain_rel_pathlist(Query *root, RelOptInfo *rel,
+static void set_base_rel_pathlists(PlannerInfo *root);
+static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                           RangeTblEntry *rte);
-static void set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
+static void set_inherited_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                                   Index rti, RangeTblEntry *rte,
                                                   List *inheritlist);
-static void set_subquery_pathlist(Query *root, RelOptInfo *rel,
+static void set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                          Index rti, RangeTblEntry *rte);
-static void set_function_pathlist(Query *root, RelOptInfo *rel,
+static void set_function_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                          RangeTblEntry *rte);
-static RelOptInfo *make_one_rel_by_joins(Query *root, int levels_needed,
+static RelOptInfo *make_one_rel_by_joins(PlannerInfo *root, int levels_needed,
                                          List *initial_rels);
 static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
                                                  bool *differentTypes);
@@ -70,7 +70,7 @@ static void recurse_push_qual(Node *setOp, Query *topquery,
  *       single rel that represents the join of all base rels in the query.
  */
 RelOptInfo *
-make_one_rel(Query *root)
+make_one_rel(PlannerInfo *root)
 {
        RelOptInfo *rel;
 
@@ -82,9 +82,10 @@ make_one_rel(Query *root)
        /*
         * Generate access paths for the entire join tree.
         */
-       Assert(root->jointree != NULL && IsA(root->jointree, FromExpr));
+       Assert(root->parse->jointree != NULL &&
+                  IsA(root->parse->jointree, FromExpr));
 
-       rel = make_fromexpr_rel(root, root->jointree);
+       rel = make_fromexpr_rel(root, root->parse->jointree);
 
        /*
         * The result should join all the query's base rels.
@@ -101,7 +102,7 @@ make_one_rel(Query *root)
  *       Each useful path is attached to its relation's 'pathlist' field.
  */
 static void
-set_base_rel_pathlists(Query *root)
+set_base_rel_pathlists(PlannerInfo *root)
 {
        ListCell   *l;
 
@@ -113,7 +114,7 @@ set_base_rel_pathlists(Query *root)
                List       *inheritlist;
 
                Assert(rti > 0);                /* better be base rel */
-               rte = rt_fetch(rti, root->rtable);
+               rte = rt_fetch(rti, root->parse->rtable);
 
                if (rel->rtekind == RTE_SUBQUERY)
                {
@@ -147,7 +148,7 @@ set_base_rel_pathlists(Query *root)
  *       Build access paths for a plain relation (no subquery, no inheritance)
  */
 static void
-set_plain_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte)
+set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 {
        /* Mark rel with estimated output rows, width, etc */
        set_baserel_size_estimates(root, rel);
@@ -204,7 +205,7 @@ set_plain_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte)
  * not the same size.
  */
 static void
-set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
+set_inherited_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                                   Index rti, RangeTblEntry *rte,
                                                   List *inheritlist)
 {
@@ -217,7 +218,7 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
         * XXX for now, can't handle inherited expansion of FOR UPDATE/SHARE;
         * can we do better?
         */
-       if (list_member_int(root->rowMarks, parentRTindex))
+       if (list_member_int(root->parse->rowMarks, parentRTindex))
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("SELECT FOR UPDATE/SHARE is not supported for inheritance queries")));
@@ -241,7 +242,7 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
                ListCell   *parentvars;
                ListCell   *childvars;
 
-               childrte = rt_fetch(childRTindex, root->rtable);
+               childrte = rt_fetch(childRTindex, root->parse->rtable);
                childOID = childrte->relid;
 
                /*
@@ -321,12 +322,13 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
  *             Build the (single) access path for a subquery RTE
  */
 static void
-set_subquery_pathlist(Query *root, RelOptInfo *rel,
+set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                          Index rti, RangeTblEntry *rte)
 {
        Query      *subquery = rte->subquery;
        bool       *differentTypes;
        List       *pathkeys;
+       List       *subquery_pathkeys;
 
        /* We need a workspace for keeping track of set-op type coercions */
        differentTypes = (bool *)
@@ -379,7 +381,8 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
        pfree(differentTypes);
 
        /* Generate the plan for the subquery */
-       rel->subplan = subquery_planner(subquery, 0.0 /* default case */ );
+       rel->subplan = subquery_planner(subquery, 0.0 /* default case */,
+                                                                       &subquery_pathkeys);
 
        /* Copy number of output rows from subplan */
        rel->tuples = rel->subplan->plan_rows;
@@ -388,7 +391,7 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
        set_baserel_size_estimates(root, rel);
 
        /* Convert subquery pathkeys to outer representation */
-       pathkeys = build_subquery_pathkeys(root, rel, subquery);
+       pathkeys = convert_subquery_pathkeys(root, rel, subquery_pathkeys);
 
        /* Generate appropriate path */
        add_path(rel, create_subqueryscan_path(rel, pathkeys));
@@ -402,7 +405,7 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
  *             Build the (single) access path for a function RTE
  */
 static void
-set_function_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte)
+set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 {
        /* Mark rel with estimated output rows, width, etc */
        set_function_size_estimates(root, rel);
@@ -419,7 +422,7 @@ set_function_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *rte)
  *       Build access paths for a FromExpr jointree node.
  */
 RelOptInfo *
-make_fromexpr_rel(Query *root, FromExpr *from)
+make_fromexpr_rel(PlannerInfo *root, FromExpr *from)
 {
        int                     levels_needed;
        List       *initial_rels = NIL;
@@ -483,7 +486,7 @@ make_fromexpr_rel(Query *root, FromExpr *from)
  * the result of joining all the original relations together.
  */
 static RelOptInfo *
-make_one_rel_by_joins(Query *root, int levels_needed, List *initial_rels)
+make_one_rel_by_joins(PlannerInfo *root, int levels_needed, List *initial_rels)
 {
        List      **joinitems;
        int                     lev;
@@ -867,7 +870,7 @@ print_relids(Relids relids)
 }
 
 static void
-print_restrictclauses(Query *root, List *clauses)
+print_restrictclauses(PlannerInfo *root, List *clauses)
 {
        ListCell   *l;
 
@@ -875,14 +878,14 @@ print_restrictclauses(Query *root, List *clauses)
        {
                RestrictInfo *c = lfirst(l);
 
-               print_expr((Node *) c->clause, root->rtable);
+               print_expr((Node *) c->clause, root->parse->rtable);
                if (lnext(l))
                        printf(", ");
        }
 }
 
 static void
-print_path(Query *root, Path *path, int indent)
+print_path(PlannerInfo *root, Path *path, int indent)
 {
        const char *ptype;
        bool            join = false;
@@ -958,7 +961,7 @@ print_path(Query *root, Path *path, int indent)
                for (i = 0; i < indent; i++)
                        printf("\t");
                printf("  pathkeys: ");
-               print_pathkeys(path->pathkeys, root->rtable);
+               print_pathkeys(path->pathkeys, root->parse->rtable);
        }
 
        if (join)
@@ -994,7 +997,7 @@ print_path(Query *root, Path *path, int indent)
 }
 
 void
-debug_print_rel(Query *root, RelOptInfo *rel)
+debug_print_rel(PlannerInfo *root, RelOptInfo *rel)
 {
        ListCell   *l;
 
index 580a386d3d870ac711fa91127860b4ee5c903d52..f6cd34327516708268e00a149f54d4e5616ee3cf 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.72 2004/12/31 22:00:04 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.73 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -92,7 +92,7 @@ static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
  * scalarltsel/scalargtsel; perhaps some day we can generalize the approach.
  */
 Selectivity
-clauselist_selectivity(Query *root,
+clauselist_selectivity(PlannerInfo *root,
                                           List *clauses,
                                           int varRelid,
                                           JoinType jointype)
@@ -406,7 +406,7 @@ bms_is_subset_singleton(const Bitmapset *s, int x)
  * if the clause isn't a join clause or the context is uncertain.
  */
 Selectivity
-clause_selectivity(Query *root,
+clause_selectivity(PlannerInfo *root,
                                   Node *clause,
                                   int varRelid,
                                   JoinType jointype)
@@ -476,7 +476,7 @@ clause_selectivity(Query *root,
                if (var->varlevelsup == 0 &&
                        (varRelid == 0 || varRelid == (int) var->varno))
                {
-                       RangeTblEntry *rte = rt_fetch(var->varno, root->rtable);
+                       RangeTblEntry *rte = rt_fetch(var->varno, root->parse->rtable);
 
                        if (rte->rtekind == RTE_SUBQUERY)
                        {
index c721a85d8801b8d5321cf55d842a6d49318fafd5..b70b544e221769f45081e3f043e1ff817ab6d195 100644 (file)
@@ -49,7 +49,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.145 2005/04/22 21:58:31 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.146 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -104,10 +104,10 @@ bool              enable_hashjoin = true;
 
 
 static bool cost_qual_eval_walker(Node *node, QualCost *total);
-static Selectivity approx_selectivity(Query *root, List *quals,
+static Selectivity approx_selectivity(PlannerInfo *root, List *quals,
                                   JoinType jointype);
-static Selectivity join_in_selectivity(JoinPath *path, Query *root);
-static void set_rel_width(Query *root, RelOptInfo *rel);
+static Selectivity join_in_selectivity(JoinPath *path, PlannerInfo *root);
+static void set_rel_width(PlannerInfo *root, RelOptInfo *rel);
 static double relation_byte_size(double tuples, int width);
 static double page_size(double tuples, int width);
 
@@ -138,7 +138,7 @@ clamp_row_est(double nrows)
  *       Determines and returns the cost of scanning a relation sequentially.
  */
 void
-cost_seqscan(Path *path, Query *root,
+cost_seqscan(Path *path, PlannerInfo *root,
                         RelOptInfo *baserel)
 {
        Cost            startup_cost = 0;
@@ -227,7 +227,6 @@ cost_nonsequential_access(double relpages)
  *       NOTE: an indexscan plan node can actually represent several passes,
  *       but here we consider the cost of just one pass.
  *
- * 'root' is the query root
  * 'index' is the index to be used
  * 'indexQuals' is the list of applicable qual clauses (implicit AND semantics)
  * 'is_injoin' is T if we are considering using the index scan as the inside
@@ -246,7 +245,7 @@ cost_nonsequential_access(double relpages)
  * it was a list of bare clause expressions.
  */
 void
-cost_index(IndexPath *path, Query *root,
+cost_index(IndexPath *path, PlannerInfo *root,
                   IndexOptInfo *index,
                   List *indexQuals,
                   bool is_injoin)
@@ -418,14 +417,13 @@ cost_index(IndexPath *path, Query *root,
  *       Determines and returns the cost of scanning a relation using a bitmap
  *       index-then-heap plan.
  *
- * 'root' is the query root
  * 'baserel' is the relation to be scanned
  * 'bitmapqual' is a tree of IndexPaths, BitmapAndPaths, and BitmapOrPaths
  * 'is_injoin' is T if we are considering using the scan as the inside
  *             of a nestloop join (hence, some of the quals are join clauses)
  */
 void
-cost_bitmap_heap_scan(Path *path, Query *root, RelOptInfo *baserel,
+cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
                                          Path *bitmapqual, bool is_injoin)
 {
        Cost            startup_cost = 0;
@@ -534,7 +532,7 @@ cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec)
  * to warrant treating it as one.
  */
 void
-cost_bitmap_and_node(BitmapAndPath *path, Query *root)
+cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root)
 {
        Cost            totalCost;
        Selectivity     selec;
@@ -577,7 +575,7 @@ cost_bitmap_and_node(BitmapAndPath *path, Query *root)
  * See comments for cost_bitmap_and_node.
  */
 void
-cost_bitmap_or_node(BitmapOrPath *path, Query *root)
+cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root)
 {
        Cost            totalCost;
        Selectivity     selec;
@@ -620,7 +618,7 @@ cost_bitmap_or_node(BitmapOrPath *path, Query *root)
  *       Determines and returns the cost of scanning a relation using TIDs.
  */
 void
-cost_tidscan(Path *path, Query *root,
+cost_tidscan(Path *path, PlannerInfo *root,
                         RelOptInfo *baserel, List *tideval)
 {
        Cost            startup_cost = 0;
@@ -684,7 +682,7 @@ cost_subqueryscan(Path *path, RelOptInfo *baserel)
  *       Determines and returns the cost of scanning a function RTE.
  */
 void
-cost_functionscan(Path *path, Query *root, RelOptInfo *baserel)
+cost_functionscan(Path *path, PlannerInfo *root, RelOptInfo *baserel)
 {
        Cost            startup_cost = 0;
        Cost            run_cost = 0;
@@ -748,7 +746,7 @@ cost_functionscan(Path *path, Query *root, RelOptInfo *baserel)
  * of sort keys, which all callers *could* supply.)
  */
 void
-cost_sort(Path *path, Query *root,
+cost_sort(Path *path, PlannerInfo *root,
                  List *pathkeys, Cost input_cost, double tuples, int width)
 {
        Cost            startup_cost = input_cost;
@@ -857,7 +855,7 @@ cost_material(Path *path,
  * are for appropriately-sorted input.
  */
 void
-cost_agg(Path *path, Query *root,
+cost_agg(Path *path, PlannerInfo *root,
                 AggStrategy aggstrategy, int numAggs,
                 int numGroupCols, double numGroups,
                 Cost input_startup_cost, Cost input_total_cost,
@@ -925,7 +923,7 @@ cost_agg(Path *path, Query *root,
  * input.
  */
 void
-cost_group(Path *path, Query *root,
+cost_group(Path *path, PlannerInfo *root,
                   int numGroupCols, double numGroups,
                   Cost input_startup_cost, Cost input_total_cost,
                   double input_tuples)
@@ -954,7 +952,7 @@ cost_group(Path *path, Query *root,
  * 'path' is already filled in except for the cost fields
  */
 void
-cost_nestloop(NestPath *path, Query *root)
+cost_nestloop(NestPath *path, PlannerInfo *root)
 {
        Path       *outer_path = path->outerjoinpath;
        Path       *inner_path = path->innerjoinpath;
@@ -1046,7 +1044,7 @@ cost_nestloop(NestPath *path, Query *root)
  * sort is needed because the source path is already ordered.
  */
 void
-cost_mergejoin(MergePath *path, Query *root)
+cost_mergejoin(MergePath *path, PlannerInfo *root)
 {
        Path       *outer_path = path->jpath.outerjoinpath;
        Path       *inner_path = path->jpath.innerjoinpath;
@@ -1275,7 +1273,7 @@ cost_mergejoin(MergePath *path, Query *root)
  * Note: path's hashclauses should be a subset of the joinrestrictinfo list
  */
 void
-cost_hashjoin(HashPath *path, Query *root)
+cost_hashjoin(HashPath *path, PlannerInfo *root)
 {
        Path       *outer_path = path->jpath.outerjoinpath;
        Path       *inner_path = path->jpath.innerjoinpath;
@@ -1673,7 +1671,7 @@ cost_qual_eval_walker(Node *node, QualCost *total)
  * seems OK to live with the approximation.
  */
 static Selectivity
-approx_selectivity(Query *root, List *quals, JoinType jointype)
+approx_selectivity(PlannerInfo *root, List *quals, JoinType jointype)
 {
        Selectivity total = 1.0;
        ListCell   *l;
@@ -1703,7 +1701,7 @@ approx_selectivity(Query *root, List *quals, JoinType jointype)
  *     baserestrictcost: estimated cost of evaluating baserestrictinfo clauses.
  */
 void
-set_baserel_size_estimates(Query *root, RelOptInfo *rel)
+set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel)
 {
        double          nrows;
 
@@ -1749,7 +1747,7 @@ set_baserel_size_estimates(Query *root, RelOptInfo *rel)
  * build_joinrel_tlist, and baserestrictcost is not used for join rels.
  */
 void
-set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
+set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
                                                   RelOptInfo *outer_rel,
                                                   RelOptInfo *inner_rel,
                                                   JoinType jointype,
@@ -1836,7 +1834,7 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
  * 'path' is already filled in except for the cost fields
  */
 static Selectivity
-join_in_selectivity(JoinPath *path, Query *root)
+join_in_selectivity(JoinPath *path, PlannerInfo *root)
 {
        RelOptInfo *innerrel;
        UniquePath *innerunique;
@@ -1896,7 +1894,7 @@ join_in_selectivity(JoinPath *path, Query *root)
  * We set the same fields as set_baserel_size_estimates.
  */
 void
-set_function_size_estimates(Query *root, RelOptInfo *rel)
+set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel)
 {
        /* Should only be applied to base relations that are functions */
        Assert(rel->relid > 0);
@@ -1929,7 +1927,7 @@ set_function_size_estimates(Query *root, RelOptInfo *rel)
  * building join relations.
  */
 static void
-set_rel_width(Query *root, RelOptInfo *rel)
+set_rel_width(PlannerInfo *root, RelOptInfo *rel)
 {
        int32           tuple_width = 0;
        ListCell   *tllist;
@@ -1960,7 +1958,7 @@ set_rel_width(Query *root, RelOptInfo *rel)
                        continue;
                }
 
-               relid = getrelid(var->varno, root->rtable);
+               relid = getrelid(var->varno, root->parse->rtable);
                if (relid != InvalidOid)
                {
                        item_width = get_attavgwidth(relid, var->varattno);
index a6a780f4778554ab717ad4a8a0f58262164652b7..0d5a4e99b364a5d2e82e47a89fbf6c7531cc8750 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.180 2005/05/06 17:24:54 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.181 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
        ((opclass) == BOOL_BTREE_OPS_OID || (opclass) == BOOL_HASH_OPS_OID)
 
 
-static List *find_usable_indexes(Query *root, RelOptInfo *rel,
+static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
                                                                 List *clauses, List *outer_clauses,
                                                                 bool istoplevel, bool isjoininner,
                                                                 Relids outer_relids);
-static Path *choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths);
+static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths);
 static int     bitmap_path_comparator(const void *a, const void *b);
-static Cost bitmap_and_cost_est(Query *root, RelOptInfo *rel, List *paths);
+static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths);
 static bool match_clause_to_indexcol(IndexOptInfo *index,
                                                 int indexcol, Oid opclass,
                                                 RestrictInfo *rinfo,
@@ -75,7 +75,7 @@ static bool list_matches_any_index(List *clauses, RelOptInfo *rel,
                                                                   Relids outer_relids);
 static bool matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel,
                                                          Relids outer_relids);
-static List *find_clauses_for_join(Query *root, RelOptInfo *rel,
+static List *find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
                                                                   Relids outer_relids, bool isouterjoin);
 static bool match_boolean_index_clause(Node *clause, int indexcol,
                                                                           IndexOptInfo *index);
@@ -124,7 +124,7 @@ static Const *string_to_const(const char *str, Oid datatype);
  * Note: check_partial_indexes() must have been run previously.
  */
 void
-create_index_paths(Query *root, RelOptInfo *rel)
+create_index_paths(PlannerInfo *root, RelOptInfo *rel)
 {
        List       *indexpaths;
        List       *bitindexpaths;
@@ -231,7 +231,7 @@ create_index_paths(Query *root, RelOptInfo *rel)
  *----------
  */
 static List *
-find_usable_indexes(Query *root, RelOptInfo *rel,
+find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
                                        List *clauses, List *outer_clauses,
                                        bool istoplevel, bool isjoininner,
                                        Relids outer_relids)
@@ -363,7 +363,7 @@ find_usable_indexes(Query *root, RelOptInfo *rel,
  * ORs.  (See find_usable_indexes() for motivation.)
  */
 List *
-generate_bitmap_or_paths(Query *root, RelOptInfo *rel,
+generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
                                                 List *clauses, List *outer_clauses,
                                                 bool isjoininner,
                                                 Relids outer_relids)
@@ -473,7 +473,7 @@ generate_bitmap_or_paths(Query *root, RelOptInfo *rel,
  * combining multiple inputs.
  */
 static Path *
-choose_bitmap_and(Query *root, RelOptInfo *rel, List *paths)
+choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
 {
        int                     npaths = list_length(paths);
        Path      **patharray;
@@ -593,7 +593,7 @@ bitmap_path_comparator(const void *a, const void *b)
  * inputs.
  */
 static Cost
-bitmap_and_cost_est(Query *root, RelOptInfo *rel, List *paths)
+bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths)
 {
        BitmapAndPath apath;
        Path            bpath;
@@ -864,7 +864,7 @@ indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left)
  *             depending on whether the predicate is satisfied for this query.
  */
 void
-check_partial_indexes(Query *root, RelOptInfo *rel)
+check_partial_indexes(PlannerInfo *root, RelOptInfo *rel)
 {
        List       *restrictinfo_list = rel->baserestrictinfo;
        ListCell   *ilist;
@@ -1675,7 +1675,7 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids)
  * sufficient to return a single "best" path.
  */
 Path *
-best_inner_indexscan(Query *root, RelOptInfo *rel,
+best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
                                         Relids outer_relids, JoinType jointype)
 {
        Path       *cheapest;
@@ -1828,7 +1828,7 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
  * indicating that there isn't any potential win here.
  */
 static List *
-find_clauses_for_join(Query *root, RelOptInfo *rel,
+find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
                                          Relids outer_relids, bool isouterjoin)
 {
        List       *clause_list = NIL;
index 7ee1542ecdf6edf294e6b1369aa1a6549091351a..b02f67ba1f65aa3cc397130de95d6b400a52f874 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.94 2005/05/24 18:02:31 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.95 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/lsyscache.h"
 
 
-static void sort_inner_and_outer(Query *root, RelOptInfo *joinrel,
+static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
                                         RelOptInfo *outerrel, RelOptInfo *innerrel,
                                         List *restrictlist, List *mergeclause_list,
                                         JoinType jointype);
-static void match_unsorted_outer(Query *root, RelOptInfo *joinrel,
+static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel,
                                         RelOptInfo *outerrel, RelOptInfo *innerrel,
                                         List *restrictlist, List *mergeclause_list,
                                         JoinType jointype);
-static void hash_inner_and_outer(Query *root, RelOptInfo *joinrel,
+static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
                                         RelOptInfo *outerrel, RelOptInfo *innerrel,
                                         List *restrictlist, JoinType jointype);
 static List *select_mergejoin_clauses(RelOptInfo *joinrel,
@@ -54,7 +54,7 @@ static List *select_mergejoin_clauses(RelOptInfo *joinrel,
  * paths found so far.
  */
 void
-add_paths_to_joinrel(Query *root,
+add_paths_to_joinrel(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         RelOptInfo *outerrel,
                                         RelOptInfo *innerrel,
@@ -133,7 +133,7 @@ add_paths_to_joinrel(Query *root,
  * 'jointype' is the type of join to do
  */
 static void
-sort_inner_and_outer(Query *root,
+sort_inner_and_outer(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         RelOptInfo *outerrel,
                                         RelOptInfo *innerrel,
@@ -324,7 +324,7 @@ sort_inner_and_outer(Query *root,
  * 'jointype' is the type of join to do
  */
 static void
-match_unsorted_outer(Query *root,
+match_unsorted_outer(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         RelOptInfo *outerrel,
                                         RelOptInfo *innerrel,
@@ -664,7 +664,7 @@ match_unsorted_outer(Query *root,
  * 'jointype' is the type of join to do
  */
 static void
-hash_inner_and_outer(Query *root,
+hash_inner_and_outer(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         RelOptInfo *outerrel,
                                         RelOptInfo *innerrel,
index bc0ac54ca6e6f72328f68cc922d45906594a6f3d..a1681ae994fe07f521957e94d3f975dabbbfc634 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.72 2004/12/31 22:00:04 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.73 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "optimizer/paths.h"
 
 
-static List *make_rels_by_clause_joins(Query *root,
+static List *make_rels_by_clause_joins(PlannerInfo *root,
                                                  RelOptInfo *old_rel,
                                                  ListCell *other_rels);
-static List *make_rels_by_clauseless_joins(Query *root,
+static List *make_rels_by_clauseless_joins(PlannerInfo *root,
                                                          RelOptInfo *old_rel,
                                                          ListCell *other_rels);
-static bool is_inside_IN(Query *root, RelOptInfo *rel);
+static bool is_inside_IN(PlannerInfo *root, RelOptInfo *rel);
 
 
 /*
@@ -39,7 +39,7 @@ static bool is_inside_IN(Query *root, RelOptInfo *rel);
  * joinrels[j], 1 <= j < level, is a list of rels containing j items.
  */
 List *
-make_rels_by_joins(Query *root, int level, List **joinrels)
+make_rels_by_joins(PlannerInfo *root, int level, List **joinrels)
 {
        List       *result_rels = NIL;
        List       *new_rels;
@@ -284,7 +284,7 @@ make_rels_by_joins(Query *root, int level, List **joinrels)
  * only succeed when other_rel is not already part of old_rel.)
  */
 static List *
-make_rels_by_clause_joins(Query *root,
+make_rels_by_clause_joins(PlannerInfo *root,
                                                  RelOptInfo *old_rel,
                                                  ListCell *other_rels)
 {
@@ -335,7 +335,7 @@ make_rels_by_clause_joins(Query *root,
  * work for joining to joinrels too.
  */
 static List *
-make_rels_by_clauseless_joins(Query *root,
+make_rels_by_clauseless_joins(PlannerInfo *root,
                                                          RelOptInfo *old_rel,
                                                          ListCell *other_rels)
 {
@@ -373,7 +373,7 @@ make_rels_by_clauseless_joins(Query *root,
  * out of an IN, so the routine name is a slight misnomer.
  */
 static bool
-is_inside_IN(Query *root, RelOptInfo *rel)
+is_inside_IN(PlannerInfo *root, RelOptInfo *rel)
 {
        ListCell   *l;
 
@@ -395,7 +395,7 @@ is_inside_IN(Query *root, RelOptInfo *rel)
  *             path that corresponds exactly to what the user wrote.
  */
 RelOptInfo *
-make_jointree_rel(Query *root, Node *jtnode)
+make_jointree_rel(PlannerInfo *root, Node *jtnode)
 {
        if (IsA(jtnode, RangeTblRef))
        {
@@ -460,7 +460,7 @@ make_jointree_rel(Query *root, Node *jtnode)
  * happen when working with IN clauses that have been turned into joins.
  */
 RelOptInfo *
-make_join_rel(Query *root, RelOptInfo *rel1, RelOptInfo *rel2,
+make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
                          JoinType jointype)
 {
        Relids          joinrelids;
index 5ea528ef26e46b2405269e06ccee8434b1b826cc..0e2eefc868cd457a6bef01f2fdb0a6f553f9ca4c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.70 2005/04/25 02:14:47 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.71 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -79,7 +79,7 @@
  *----------
  */
 bool
-create_or_index_quals(Query *root, RelOptInfo *rel)
+create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
 {
        BitmapOrPath *bestpath = NULL;
        RestrictInfo *bestrinfo = NULL;
index 766aa1d11651bfeb01cfa7438461e2208a04f08b..2994421e5b7a1fc50dc3d9e676e2e6a8befea24a 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.66 2005/04/06 16:34:05 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.67 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,8 +32,8 @@
 
 
 static PathKeyItem *makePathKeyItem(Node *key, Oid sortop, bool checkType);
-static List *make_canonical_pathkey(Query *root, PathKeyItem *item);
-static Var *find_indexkey_var(Query *root, RelOptInfo *rel,
+static List *make_canonical_pathkey(PlannerInfo *root, PathKeyItem *item);
+static Var *find_indexkey_var(PlannerInfo *root, RelOptInfo *rel,
                                  AttrNumber varattno);
 
 
@@ -87,7 +87,7 @@ makePathKeyItem(Node *key, Oid sortop, bool checkType)
  * that involves an equijoined variable.
  */
 void
-add_equijoined_keys(Query *root, RestrictInfo *restrictinfo)
+add_equijoined_keys(PlannerInfo *root, RestrictInfo *restrictinfo)
 {
        Expr       *clause = restrictinfo->clause;
        PathKeyItem *item1 = makePathKeyItem(get_leftop(clause),
@@ -198,7 +198,7 @@ add_equijoined_keys(Query *root, RestrictInfo *restrictinfo)
  * restrictinfo datastructures for each pair.
  */
 void
-generate_implied_equalities(Query *root)
+generate_implied_equalities(PlannerInfo *root)
 {
        ListCell   *cursetlink;
 
@@ -293,7 +293,7 @@ generate_implied_equalities(Query *root)
  * check that case if it's possible to pass identical items.
  */
 bool
-exprs_known_equal(Query *root, Node *item1, Node *item2)
+exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2)
 {
        ListCell   *cursetlink;
 
@@ -333,7 +333,7 @@ exprs_known_equal(Query *root, Node *item1, Node *item2)
  * scanning the WHERE clause for equijoin operators.
  */
 static List *
-make_canonical_pathkey(Query *root, PathKeyItem *item)
+make_canonical_pathkey(PlannerInfo *root, PathKeyItem *item)
 {
        List       *newset;
        ListCell   *cursetlink;
@@ -358,7 +358,7 @@ make_canonical_pathkey(Query *root, PathKeyItem *item)
  * scanning the WHERE clause for equijoin operators.
  */
 List *
-canonicalize_pathkeys(Query *root, List *pathkeys)
+canonicalize_pathkeys(PlannerInfo *root, List *pathkeys)
 {
        List       *new_pathkeys = NIL;
        ListCell   *l;
@@ -398,10 +398,10 @@ canonicalize_pathkeys(Query *root, List *pathkeys)
  *       If not, return 0 (without actually adding it to our equi_key_list).
  *
  * This is a hack to support the rather bogus heuristics in
- * build_subquery_pathkeys.
+ * convert_subquery_pathkeys.
  */
 static int
-count_canonical_peers(Query *root, PathKeyItem *item)
+count_canonical_peers(PlannerInfo *root, PathKeyItem *item)
 {
        ListCell   *cursetlink;
 
@@ -441,7 +441,7 @@ compare_pathkeys(List *keys1, List *keys2)
 
                /*
                 * XXX would like to check that we've been given canonicalized
-                * input, but query root not accessible here...
+                * input, but PlannerInfo not accessible here...
                 */
 #ifdef NOT_USED
                Assert(list_member_ptr(root->equi_key_list, subkey1));
@@ -647,7 +647,7 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
  * current query.  Caller should do truncate_useless_pathkeys().
  */
 List *
-build_index_pathkeys(Query *root,
+build_index_pathkeys(PlannerInfo *root,
                                         IndexOptInfo *index,
                                         ScanDirection scandir)
 {
@@ -714,7 +714,7 @@ build_index_pathkeys(Query *root,
  * gin up a Var node the hard way.
  */
 static Var *
-find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
+find_indexkey_var(PlannerInfo *root, RelOptInfo *rel, AttrNumber varattno)
 {
        ListCell   *temp;
        Index           relid;
@@ -732,24 +732,28 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno)
        }
 
        relid = rel->relid;
-       reloid = getrelid(relid, root->rtable);
+       reloid = getrelid(relid, root->parse->rtable);
        get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod);
 
        return makeVar(relid, varattno, vartypeid, type_mod, 0);
 }
 
 /*
- * build_subquery_pathkeys
+ * convert_subquery_pathkeys
  *       Build a pathkeys list that describes the ordering of a subquery's
- *       result (in the terms of the outer query).  The subquery must already
- *       have been planned, so that its query_pathkeys field has been set.
+ *       result, in the terms of the outer query.  This is essentially a
+ *       task of conversion.
+ *
+ * 'rel': outer query's RelOptInfo for the subquery relation.
+ * 'subquery_pathkeys': the subquery's output pathkeys, in its terms.
  *
  * It is not necessary for caller to do truncate_useless_pathkeys(),
  * because we select keys in a way that takes usefulness of the keys into
  * account.
  */
 List *
-build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery)
+convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
+                                                 List *subquery_pathkeys)
 {
        List       *retval = NIL;
        int                     retvallen = 0;
@@ -757,7 +761,7 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery)
        List       *sub_tlist = rel->subplan->targetlist;
        ListCell   *i;
 
-       foreach(i, subquery->query_pathkeys)
+       foreach(i, subquery_pathkeys)
        {
                List       *sub_pathkey = (List *) lfirst(i);
                ListCell   *j;
@@ -869,7 +873,7 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery)
  * Returns the list of new path keys.
  */
 List *
-build_join_pathkeys(Query *root,
+build_join_pathkeys(PlannerInfo *root,
                                        RelOptInfo *joinrel,
                                        JoinType jointype,
                                        List *outer_pathkeys)
@@ -954,7 +958,7 @@ make_pathkeys_for_sortclauses(List *sortclauses,
  * problem for normal planning, but it is an issue for GEQO planning.
  */
 void
-cache_mergeclause_pathkeys(Query *root, RestrictInfo *restrictinfo)
+cache_mergeclause_pathkeys(PlannerInfo *root, RestrictInfo *restrictinfo)
 {
        Node       *key;
        PathKeyItem *item;
@@ -1000,7 +1004,7 @@ cache_mergeclause_pathkeys(Query *root, RestrictInfo *restrictinfo)
  * of the join.
  */
 List *
-find_mergeclauses_for_pathkeys(Query *root,
+find_mergeclauses_for_pathkeys(PlannerInfo *root,
                                                           List *pathkeys,
                                                           List *restrictinfos)
 {
@@ -1093,7 +1097,7 @@ find_mergeclauses_for_pathkeys(Query *root,
  * just make the keys, eh?
  */
 List *
-make_pathkeys_for_mergeclauses(Query *root,
+make_pathkeys_for_mergeclauses(PlannerInfo *root,
                                                           List *mergeclauses,
                                                           RelOptInfo *rel)
 {
@@ -1162,7 +1166,7 @@ make_pathkeys_for_mergeclauses(Query *root,
  * to be more trouble than it's worth.
  */
 int
-pathkeys_useful_for_merging(Query *root, RelOptInfo *rel, List *pathkeys)
+pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
 {
        int                     useful = 0;
        ListCell   *i;
@@ -1226,7 +1230,7 @@ pathkeys_useful_for_merging(Query *root, RelOptInfo *rel, List *pathkeys)
  * So the result is always either 0 or list_length(root->query_pathkeys).
  */
 int
-pathkeys_useful_for_ordering(Query *root, List *pathkeys)
+pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys)
 {
        if (root->query_pathkeys == NIL)
                return 0;                               /* no special ordering requested */
@@ -1248,7 +1252,7 @@ pathkeys_useful_for_ordering(Query *root, List *pathkeys)
  *             Shorten the given pathkey list to just the useful pathkeys.
  */
 List *
-truncate_useless_pathkeys(Query *root,
+truncate_useless_pathkeys(PlannerInfo *root,
                                                  RelOptInfo *rel,
                                                  List *pathkeys)
 {
index 7468fbf59d7b5a00845bb1ba29653928c6f0fc2f..239e20c96358638e7ddcfdbe90644b8b2aec226b 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.22 2004/12/31 22:00:04 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.23 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "parser/parse_coerce.h"
 #include "utils/lsyscache.h"
 
+
 static List *TidqualFromRestrictinfo(Relids relids, List *restrictinfo);
 static bool isEvaluable(int varno, Node *node);
 static Node *TidequalClause(int varno, OpExpr *node);
 static List *TidqualFromExpr(int varno, Expr *expr);
 
+
 static bool
 isEvaluable(int varno, Node *node)
 {
@@ -228,7 +230,7 @@ TidqualFromRestrictinfo(Relids relids, List *restrictinfo)
  *       Candidate paths are added to the rel's pathlist (using add_path).
  */
 void
-create_tidscan_paths(Query *root, RelOptInfo *rel)
+create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel)
 {
        List       *tideval = TidqualFromRestrictinfo(rel->relids,
                                                                                                  rel->baserestrictinfo);
index b743c8348ed68e40a2b105b8f9beb9e8f86d8495..5c1142cd0e10002743374e6345ae3f7d7b183825 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.190 2005/05/30 18:55:49 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.191 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/syscache.h"
 
 
-static Scan *create_scan_plan(Query *root, Path *best_path);
+static Scan *create_scan_plan(PlannerInfo *root, Path *best_path);
 static List *build_relation_tlist(RelOptInfo *rel);
 static bool use_physical_tlist(RelOptInfo *rel);
 static void disuse_physical_tlist(Plan *plan, Path *path);
-static Join *create_join_plan(Query *root, JoinPath *best_path);
-static Append *create_append_plan(Query *root, AppendPath *best_path);
-static Result *create_result_plan(Query *root, ResultPath *best_path);
-static Material *create_material_plan(Query *root, MaterialPath *best_path);
-static Plan *create_unique_plan(Query *root, UniquePath *best_path);
-static SeqScan *create_seqscan_plan(Query *root, Path *best_path,
+static Join *create_join_plan(PlannerInfo *root, JoinPath *best_path);
+static Append *create_append_plan(PlannerInfo *root, AppendPath *best_path);
+static Result *create_result_plan(PlannerInfo *root, ResultPath *best_path);
+static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path);
+static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path);
+static SeqScan *create_seqscan_plan(PlannerInfo *root, Path *best_path,
                                        List *tlist, List *scan_clauses);
-static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path,
+static IndexScan *create_indexscan_plan(PlannerInfo *root, IndexPath *best_path,
                                          List *tlist, List *scan_clauses,
                                          List **nonlossy_clauses);
-static BitmapHeapScan *create_bitmap_scan_plan(Query *root,
+static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,
                                                                                           BitmapHeapPath *best_path,
                                                                                           List *tlist, List *scan_clauses);
-static Plan *create_bitmap_subplan(Query *root, Path *bitmapqual,
+static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
                                                                   List **qual, List **indexqual);
-static TidScan *create_tidscan_plan(Query *root, TidPath *best_path,
+static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
                                        List *tlist, List *scan_clauses);
-static SubqueryScan *create_subqueryscan_plan(Query *root, Path *best_path,
+static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
                                                 List *tlist, List *scan_clauses);
-static FunctionScan *create_functionscan_plan(Query *root, Path *best_path,
+static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path,
                                                 List *tlist, List *scan_clauses);
-static NestLoop *create_nestloop_plan(Query *root, NestPath *best_path,
+static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path,
                                         Plan *outer_plan, Plan *inner_plan);
-static MergeJoin *create_mergejoin_plan(Query *root, MergePath *best_path,
+static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,
                                          Plan *outer_plan, Plan *inner_plan);
-static HashJoin *create_hashjoin_plan(Query *root, HashPath *best_path,
+static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path,
                                         Plan *outer_plan, Plan *inner_plan);
 static void fix_indexqual_references(List *indexquals, IndexPath *index_path,
                                                 List **fixed_indexquals,
@@ -112,9 +112,9 @@ static MergeJoin *make_mergejoin(List *tlist,
                           List *mergeclauses,
                           Plan *lefttree, Plan *righttree,
                           JoinType jointype);
-static Sort *make_sort(Query *root, Plan *lefttree, int numCols,
+static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
                  AttrNumber *sortColIdx, Oid *sortOperators);
-static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree,
+static Sort *make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree,
                                                List *pathkeys);
 
 
@@ -134,7 +134,7 @@ static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree,
  *       Returns a Plan tree.
  */
 Plan *
-create_plan(Query *root, Path *best_path)
+create_plan(PlannerInfo *root, Path *best_path)
 {
        Plan       *plan;
 
@@ -187,7 +187,7 @@ create_plan(Query *root, Path *best_path)
  *      Returns a Plan node.
  */
 static Scan *
-create_scan_plan(Query *root, Path *best_path)
+create_scan_plan(PlannerInfo *root, Path *best_path)
 {
        RelOptInfo *rel = best_path->parent;
        List       *tlist;
@@ -376,7 +376,7 @@ disuse_physical_tlist(Plan *plan, Path *path)
  *       Returns a Plan node.
  */
 static Join *
-create_join_plan(Query *root, JoinPath *best_path)
+create_join_plan(PlannerInfo *root, JoinPath *best_path)
 {
        Plan       *outer_plan;
        Plan       *inner_plan;
@@ -436,7 +436,7 @@ create_join_plan(Query *root, JoinPath *best_path)
  *       Returns a Plan node.
  */
 static Append *
-create_append_plan(Query *root, AppendPath *best_path)
+create_append_plan(PlannerInfo *root, AppendPath *best_path)
 {
        Append     *plan;
        List       *tlist = build_relation_tlist(best_path->path.parent);
@@ -463,7 +463,7 @@ create_append_plan(Query *root, AppendPath *best_path)
  *       Returns a Plan node.
  */
 static Result *
-create_result_plan(Query *root, ResultPath *best_path)
+create_result_plan(PlannerInfo *root, ResultPath *best_path)
 {
        Result     *plan;
        List       *tlist;
@@ -495,7 +495,7 @@ create_result_plan(Query *root, ResultPath *best_path)
  *       Returns a Plan node.
  */
 static Material *
-create_material_plan(Query *root, MaterialPath *best_path)
+create_material_plan(PlannerInfo *root, MaterialPath *best_path)
 {
        Material   *plan;
        Plan       *subplan;
@@ -520,7 +520,7 @@ create_material_plan(Query *root, MaterialPath *best_path)
  *       Returns a Plan node.
  */
 static Plan *
-create_unique_plan(Query *root, UniquePath *best_path)
+create_unique_plan(PlannerInfo *root, UniquePath *best_path)
 {
        Plan       *plan;
        Plan       *subplan;
@@ -535,7 +535,7 @@ create_unique_plan(Query *root, UniquePath *best_path)
 
        subplan = create_plan(root, best_path->subpath);
 
-       /*
+       /*----------
         * As constructed, the subplan has a "flat" tlist containing just the
         * Vars needed here and at upper levels.  The values we are supposed
         * to unique-ify may be expressions in these variables.  We have to
@@ -545,19 +545,20 @@ create_unique_plan(Query *root, UniquePath *best_path)
         * existing subplan outputs, not all the output columns may be used
         * for grouping.)
         *
-        * Note: the reason we don't remove any subplan outputs is that there are
-        * scenarios where a Var is needed at higher levels even though it is
-        * not one of the nominal outputs of an IN clause.      Consider WHERE x
-        * IN (SELECT y FROM t1,t2 WHERE y = z) Implied equality deduction
-        * will generate an "x = z" clause, which may get used instead of "x =
-        * y" in the upper join step.  Therefore the sub-select had better
-        * deliver both y and z in its targetlist.      It is sufficient to
-        * unique-ify on y, however.
+        * Note: the reason we don't remove any subplan outputs is that there
+        * are scenarios where a Var is needed at higher levels even though
+        * it is not one of the nominal outputs of an IN clause.        Consider
+        *              WHERE x IN (SELECT y FROM t1,t2 WHERE y = z)
+        * Implied equality deduction will generate an "x = z" clause, which may
+        * get used instead of "x = y" in the upper join step.  Therefore the
+        * sub-select had better deliver both y and z in its targetlist.
+        * It is sufficient to unique-ify on y, however.
         *
         * To find the correct list of values to unique-ify, we look in the
         * information saved for IN expressions.  If this code is ever used in
         * other scenarios, some other way of finding what to unique-ify will
         * be needed.
+        *----------
         */
        uniq_exprs = NIL;                       /* just to keep compiler quiet */
        foreach(l, root->in_info_list)
@@ -672,7 +673,7 @@ create_unique_plan(Query *root, UniquePath *best_path)
  *      with restriction clauses 'scan_clauses' and targetlist 'tlist'.
  */
 static SeqScan *
-create_seqscan_plan(Query *root, Path *best_path,
+create_seqscan_plan(PlannerInfo *root, Path *best_path,
                                        List *tlist, List *scan_clauses)
 {
        SeqScan    *scan_plan;
@@ -710,7 +711,7 @@ create_seqscan_plan(Query *root, Path *best_path,
  * nonlossy indexquals.
  */
 static IndexScan *
-create_indexscan_plan(Query *root,
+create_indexscan_plan(PlannerInfo *root,
                                          IndexPath *best_path,
                                          List *tlist,
                                          List *scan_clauses,
@@ -827,7 +828,7 @@ create_indexscan_plan(Query *root,
  *       with restriction clauses 'scan_clauses' and targetlist 'tlist'.
  */
 static BitmapHeapScan *
-create_bitmap_scan_plan(Query *root,
+create_bitmap_scan_plan(PlannerInfo *root,
                                                BitmapHeapPath *best_path,
                                                List *tlist,
                                                List *scan_clauses)
@@ -925,7 +926,7 @@ create_bitmap_scan_plan(Query *root,
  * exclude lossy index operators.
  */
 static Plan *
-create_bitmap_subplan(Query *root, Path *bitmapqual,
+create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
                                          List **qual, List **indexqual)
 {
        Plan       *plan;
@@ -1029,7 +1030,7 @@ create_bitmap_subplan(Query *root, Path *bitmapqual,
  *      with restriction clauses 'scan_clauses' and targetlist 'tlist'.
  */
 static TidScan *
-create_tidscan_plan(Query *root, TidPath *best_path,
+create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
                                        List *tlist, List *scan_clauses)
 {
        TidScan    *scan_plan;
@@ -1061,7 +1062,7 @@ create_tidscan_plan(Query *root, TidPath *best_path,
  *      with restriction clauses 'scan_clauses' and targetlist 'tlist'.
  */
 static SubqueryScan *
-create_subqueryscan_plan(Query *root, Path *best_path,
+create_subqueryscan_plan(PlannerInfo *root, Path *best_path,
                                                 List *tlist, List *scan_clauses)
 {
        SubqueryScan *scan_plan;
@@ -1093,7 +1094,7 @@ create_subqueryscan_plan(Query *root, Path *best_path,
  *      with restriction clauses 'scan_clauses' and targetlist 'tlist'.
  */
 static FunctionScan *
-create_functionscan_plan(Query *root, Path *best_path,
+create_functionscan_plan(PlannerInfo *root, Path *best_path,
                                                 List *tlist, List *scan_clauses)
 {
        FunctionScan *scan_plan;
@@ -1123,7 +1124,7 @@ create_functionscan_plan(Query *root, Path *best_path,
  *****************************************************************************/
 
 static NestLoop *
-create_nestloop_plan(Query *root,
+create_nestloop_plan(PlannerInfo *root,
                                         NestPath *best_path,
                                         Plan *outer_plan,
                                         Plan *inner_plan)
@@ -1213,7 +1214,7 @@ create_nestloop_plan(Query *root,
 }
 
 static MergeJoin *
-create_mergejoin_plan(Query *root,
+create_mergejoin_plan(PlannerInfo *root,
                                          MergePath *best_path,
                                          Plan *outer_plan,
                                          Plan *inner_plan)
@@ -1296,7 +1297,7 @@ create_mergejoin_plan(Query *root,
 }
 
 static HashJoin *
-create_hashjoin_plan(Query *root,
+create_hashjoin_plan(PlannerInfo *root,
                                         HashPath *best_path,
                                         Plan *outer_plan,
                                         Plan *inner_plan)
@@ -1608,14 +1609,14 @@ get_switched_clauses(List *clauses, Relids outerrelids)
  * InitPlan references) to the end of the list.
  */
 List *
-order_qual_clauses(Query *root, List *clauses)
+order_qual_clauses(PlannerInfo *root, List *clauses)
 {
        List       *nosubplans;
        List       *withsubplans;
        ListCell   *l;
 
        /* No need to work hard if the query is subselect-free */
-       if (!root->hasSubLinks)
+       if (!root->parse->hasSubLinks)
                return clauses;
 
        nosubplans = NIL;
@@ -2018,7 +2019,7 @@ make_mergejoin(List *tlist,
  * Caller must have built the sortColIdx and sortOperators arrays already.
  */
 static Sort *
-make_sort(Query *root, Plan *lefttree, int numCols,
+make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
                  AttrNumber *sortColIdx, Oid *sortOperators)
 {
        Sort       *node = makeNode(Sort);
@@ -2090,7 +2091,7 @@ add_sort_column(AttrNumber colIdx, Oid sortOp,
  * adding a Result node just to do the projection.
  */
 static Sort *
-make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys)
+make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys)
 {
        List       *tlist = lefttree->targetlist;
        ListCell   *i;
@@ -2201,7 +2202,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree, List *pathkeys)
  *       'lefttree' is the node which yields input tuples
  */
 Sort *
-make_sort_from_sortclauses(Query *root, List *sortcls, Plan *lefttree)
+make_sort_from_sortclauses(PlannerInfo *root, List *sortcls, Plan *lefttree)
 {
        List       *sub_tlist = lefttree->targetlist;
        ListCell   *l;
@@ -2253,7 +2254,7 @@ make_sort_from_sortclauses(Query *root, List *sortcls, Plan *lefttree)
  * GroupClause entries.
  */
 Sort *
-make_sort_from_groupcols(Query *root,
+make_sort_from_groupcols(PlannerInfo *root,
                                                 List *groupcls,
                                                 AttrNumber *grpColIdx,
                                                 Plan *lefttree)
@@ -2347,7 +2348,7 @@ materialize_finished_plan(Plan *subplan)
 }
 
 Agg *
-make_agg(Query *root, List *tlist, List *qual,
+make_agg(PlannerInfo *root, List *tlist, List *qual,
                 AggStrategy aggstrategy,
                 int numGroupCols, AttrNumber *grpColIdx,
                 long numGroups, int numAggs,
@@ -2412,7 +2413,7 @@ make_agg(Query *root, List *tlist, List *qual,
 }
 
 Group *
-make_group(Query *root,
+make_group(PlannerInfo *root,
                   List *tlist,
                   List *qual,
                   int numGroupCols,
index 22878c0099e11145f1a1c42138d6101c2358e7a1..c5b027637988da2cf87f702aa38540dc1610dd1d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.105 2005/04/28 21:47:13 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.106 2005/06/05 22:32:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "utils/syscache.h"
 
 
-static void mark_baserels_for_outer_join(Query *root, Relids rels,
+static void mark_baserels_for_outer_join(PlannerInfo *root, Relids rels,
                                                         Relids outerrels);
-static void distribute_qual_to_rels(Query *root, Node *clause,
+static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
                                                bool is_pushed_down,
                                                bool isdeduced,
                                                Relids outerjoin_nonnullable,
                                                Relids qualscope);
-static void add_vars_to_targetlist(Query *root, List *vars,
+static void add_vars_to_targetlist(PlannerInfo *root, List *vars,
                                           Relids where_needed);
-static bool qual_is_redundant(Query *root, RestrictInfo *restrictinfo,
+static bool qual_is_redundant(PlannerInfo *root, RestrictInfo *restrictinfo,
                                  List *restrictlist);
 static void check_mergejoinable(RestrictInfo *restrictinfo);
 static void check_hashjoinable(RestrictInfo *restrictinfo);
@@ -68,7 +68,7 @@ static void check_hashjoinable(RestrictInfo *restrictinfo);
  * will be used later to build rels for inheritance children.
  */
 void
-add_base_rels_to_query(Query *root, Node *jtnode)
+add_base_rels_to_query(PlannerInfo *root, Node *jtnode)
 {
        if (jtnode == NULL)
                return;
@@ -114,7 +114,7 @@ add_base_rels_to_query(Query *root, Node *jtnode)
  * propagate up through all join plan steps.
  */
 void
-build_base_rel_tlists(Query *root, List *final_tlist)
+build_base_rel_tlists(PlannerInfo *root, List *final_tlist)
 {
        List       *tlist_vars = pull_var_clause((Node *) final_tlist, false);
 
@@ -133,7 +133,7 @@ build_base_rel_tlists(Query *root, List *final_tlist)
  *       where_needed includes "relation 0").
  */
 static void
-add_vars_to_targetlist(Query *root, List *vars, Relids where_needed)
+add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
 {
        ListCell   *temp;
 
@@ -189,7 +189,7 @@ add_vars_to_targetlist(Query *root, List *vars, Relids where_needed)
  * internal convenience; no outside callers pay attention to the result.
  */
 Relids
-distribute_quals_to_rels(Query *root, Node *jtnode)
+distribute_quals_to_rels(PlannerInfo *root, Node *jtnode)
 {
        Relids          result = NULL;
 
@@ -306,7 +306,7 @@ distribute_quals_to_rels(Query *root, Node *jtnode)
  *       Mark all base rels listed in 'rels' as having the given outerjoinset.
  */
 static void
-mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels)
+mark_baserels_for_outer_join(PlannerInfo *root, Relids rels, Relids outerrels)
 {
        Relids          tmprelids;
        int                     relno;
@@ -333,7 +333,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels)
                 */
                if (rel->outerjoinset == NULL)
                {
-                       if (list_member_int(root->rowMarks, relno))
+                       if (list_member_int(root->parse->rowMarks, relno))
                                ereport(ERROR,
                                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                 errmsg("SELECT FOR UPDATE/SHARE cannot be applied to the nullable side of an outer join")));
@@ -367,7 +367,7 @@ mark_baserels_for_outer_join(Query *root, Relids rels, Relids outerrels)
  * 'is_pushed_down' will be TRUE.
  */
 static void
-distribute_qual_to_rels(Query *root, Node *clause,
+distribute_qual_to_rels(PlannerInfo *root, Node *clause,
                                                bool is_pushed_down,
                                                bool isdeduced,
                                                Relids outerjoin_nonnullable,
@@ -626,7 +626,7 @@ distribute_qual_to_rels(Query *root, Node *clause,
  * for more details.
  */
 void
-process_implied_equality(Query *root,
+process_implied_equality(PlannerInfo *root,
                                                 Node *item1, Node *item2,
                                                 Oid sortop1, Oid sortop2,
                                                 Relids item1_relids, Relids item2_relids,
@@ -796,7 +796,7 @@ process_implied_equality(Query *root,
  * all the "var = const" quals.
  */
 static bool
-qual_is_redundant(Query *root,
+qual_is_redundant(PlannerInfo *root,
                                  RestrictInfo *restrictinfo,
                                  List *restrictlist)
 {
index 38c859dfbcbb743d10568c371cd84fa32c7e200a..0a47799707c49933befde7b85afbe0edc5bb69eb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.4 2005/04/22 21:58:31 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.5 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,11 +42,11 @@ typedef struct
 } MinMaxAggInfo;
 
 static bool find_minmax_aggs_walker(Node *node, List **context);
-static bool build_minmax_path(Query *root, RelOptInfo *rel,
+static bool build_minmax_path(PlannerInfo *root, RelOptInfo *rel,
                                                          MinMaxAggInfo *info);
 static ScanDirection match_agg_to_index_col(MinMaxAggInfo *info,
                                                                                        IndexOptInfo *index, int indexcol);
-static void make_agg_subplan(Query *root, MinMaxAggInfo *info,
+static void make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info,
                                                         List *constant_quals);
 static Node *replace_aggs_with_params_mutator(Node *node,  List **context);
 static Oid     fetch_agg_sort_op(Oid aggfnoid);
@@ -61,15 +61,16 @@ static Oid  fetch_agg_sort_op(Oid aggfnoid);
  * Given a suitable index on tab.col, this can be much faster than the
  * generic scan-all-the-rows plan.
  *
- * We are passed the Query, the preprocessed tlist, and the best path
+ * We are passed the preprocessed tlist, and the best path
  * devised for computing the input of a standard Agg node.  If we are able
  * to optimize all the aggregates, and the result is estimated to be cheaper
  * than the generic aggregate method, then generate and return a Plan that
  * does it that way.  Otherwise, return NULL.
  */
 Plan *
-optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
+optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path)
 {
+       Query      *parse = root->parse;
        RangeTblRef *rtr;
        RangeTblEntry *rte;
        RelOptInfo *rel;
@@ -83,11 +84,11 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
        List       *constant_quals;
 
        /* Nothing to do if query has no aggregates */
-       if (!root->hasAggs)
+       if (!parse->hasAggs)
                return NULL;
 
-       Assert(!root->setOperations); /* shouldn't get here if a setop */
-       Assert(root->rowMarks == NIL); /* nor if FOR UPDATE */
+       Assert(!parse->setOperations); /* shouldn't get here if a setop */
+       Assert(parse->rowMarks == NIL); /* nor if FOR UPDATE */
 
        /*
         * Reject unoptimizable cases.
@@ -96,7 +97,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
         * grouping require looking at all the rows anyway, and so there's not
         * much point in optimizing MIN/MAX.
         */
-       if (root->groupClause)
+       if (parse->groupClause)
                return NULL;
 
        /*
@@ -105,13 +106,13 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
         * handle a query containing cartesian-product joins, but it hardly
         * seems worth the trouble.)
         */
-       Assert(root->jointree != NULL && IsA(root->jointree, FromExpr));
-       if (list_length(root->jointree->fromlist) != 1)
+       Assert(parse->jointree != NULL && IsA(parse->jointree, FromExpr));
+       if (list_length(parse->jointree->fromlist) != 1)
                return NULL;
-       rtr = (RangeTblRef *) linitial(root->jointree->fromlist);
+       rtr = (RangeTblRef *) linitial(parse->jointree->fromlist);
        if (!IsA(rtr, RangeTblRef))
                return NULL;
-       rte = rt_fetch(rtr->rtindex, root->rtable);
+       rte = rt_fetch(rtr->rtindex, parse->rtable);
        if (rte->rtekind != RTE_RELATION)
                return NULL;
        rel = find_base_rel(root, rtr->rtindex);
@@ -121,8 +122,8 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
         * This may be overly paranoid, but it's not entirely clear if the
         * transformation is safe then.
         */
-       if (contain_subplans(root->jointree->quals) ||
-               contain_volatile_functions(root->jointree->quals))
+       if (contain_subplans(parse->jointree->quals) ||
+               contain_volatile_functions(parse->jointree->quals))
                return NULL;
 
        /*
@@ -143,7 +144,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
        aggs_list = NIL;
        if (find_minmax_aggs_walker((Node *) tlist, &aggs_list))
                return NULL;
-       if (find_minmax_aggs_walker(root->havingQual, &aggs_list))
+       if (find_minmax_aggs_walker(parse->havingQual, &aggs_list))
                return NULL;
 
        /* Pass 2: see if each one is optimizable */
@@ -202,7 +203,7 @@ optimize_minmax_aggregates(Query *root, List *tlist, Path *best_path)
         */
        tlist = (List *) replace_aggs_with_params_mutator((Node *) tlist,
                                                                                                          &aggs_list);
-       hqual = replace_aggs_with_params_mutator(root->havingQual,
+       hqual = replace_aggs_with_params_mutator(parse->havingQual,
                                                                                         &aggs_list);
 
        /*
@@ -298,7 +299,7 @@ find_minmax_aggs_walker(Node *node, List **context)
  * Note: check_partial_indexes() must have been run previously.
  */
 static bool
-build_minmax_path(Query *root, RelOptInfo *rel, MinMaxAggInfo *info)
+build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info)
 {
        IndexPath  *best_path = NULL;
        Cost            best_cost = 0;
@@ -441,46 +442,48 @@ match_agg_to_index_col(MinMaxAggInfo *info, IndexOptInfo *index, int indexcol)
  * Construct a suitable plan for a converted aggregate query
  */
 static void
-make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals)
+make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info, List *constant_quals)
 {
-       Query      *subquery;
+       PlannerInfo subroot;
+       Query      *subparse;
        Plan       *plan;
        TargetEntry *tle;
        SortClause *sortcl;
        NullTest   *ntest;
 
        /*
-        * Generate a suitably modified Query node.  Much of the work here is
+        * Generate a suitably modified query.  Much of the work here is
         * probably unnecessary in the normal case, but we want to make it look
         * good if someone tries to EXPLAIN the result.
         */
-       subquery = (Query *) copyObject(root);
-       subquery->commandType = CMD_SELECT;
-       subquery->resultRelation = 0;
-       subquery->resultRelations = NIL;
-       subquery->into = NULL;
-       subquery->hasAggs = false;
-       subquery->groupClause = NIL;
-       subquery->havingQual = NULL;
-       subquery->hasHavingQual = false;
-       subquery->distinctClause = NIL;
+       memcpy(&subroot, root, sizeof(PlannerInfo));
+       subroot.parse = subparse = (Query *) copyObject(root->parse);
+       subparse->commandType = CMD_SELECT;
+       subparse->resultRelation = 0;
+       subparse->resultRelations = NIL;
+       subparse->into = NULL;
+       subparse->hasAggs = false;
+       subparse->groupClause = NIL;
+       subparse->havingQual = NULL;
+       subparse->distinctClause = NIL;
+       subroot.hasHavingQual = false;
 
        /* single tlist entry that is the aggregate target */
        tle = makeTargetEntry(copyObject(info->target),
                                                  1,
                                                  pstrdup("agg_target"),
                                                  false);
-       subquery->targetList = list_make1(tle);
+       subparse->targetList = list_make1(tle);
 
        /* set up the appropriate ORDER BY entry */
        sortcl = makeNode(SortClause);
-       sortcl->tleSortGroupRef = assignSortGroupRef(tle, subquery->targetList);
+       sortcl->tleSortGroupRef = assignSortGroupRef(tle, subparse->targetList);
        sortcl->sortop = info->aggsortop;
-       subquery->sortClause = list_make1(sortcl);
+       subparse->sortClause = list_make1(sortcl);
 
        /* set up LIMIT 1 */
-       subquery->limitOffset = NULL;
-       subquery->limitCount = (Node *) makeConst(INT4OID, sizeof(int4),
+       subparse->limitOffset = NULL;
+       subparse->limitCount = (Node *) makeConst(INT4OID, sizeof(int4),
                                                                                          Int32GetDatum(1),
                                                                                          false, true);
 
@@ -498,9 +501,9 @@ make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals)
         * most cases the fraction of NULLs isn't high enough to change the
         * decision.
         */
-       plan = create_plan(subquery, (Path *) info->path);
+       plan = create_plan(&subroot, (Path *) info->path);
 
-       plan->targetlist = copyObject(subquery->targetList);
+       plan->targetlist = copyObject(subparse->targetList);
 
        ntest = makeNode(NullTest);
        ntest->nulltesttype = IS_NOT_NULL;
@@ -514,13 +517,13 @@ make_agg_subplan(Query *root, MinMaxAggInfo *info, List *constant_quals)
                                                                        plan);
 
        plan = (Plan *) make_limit(plan, 
-                                                          subquery->limitOffset,
-                                                          subquery->limitCount);
+                                                          subparse->limitOffset,
+                                                          subparse->limitCount);
 
        /*
         * Convert the plan into an InitPlan, and make a Param for its result.
         */
-       info->param = SS_make_initplan_from_plan(subquery, plan,
+       info->param = SS_make_initplan_from_plan(&subroot, plan,
                                                                                         exprType((Node *) tle->expr),
                                                                                         -1);
 }
index 78b2d127fa8ca195ad8bb02bd3d9d4af3dbfff3c..79a28cae3a95e32ad63d2c36393364bbe144e595 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.81 2004/12/31 22:00:09 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.82 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,8 +42,9 @@
  * will make the final decision about which to use.
  *
  * Input parameters:
- * root is the query to plan
- * tlist is the target list the query should produce (NOT root->targetList!)
+ * root describes the query to plan
+ * tlist is the target list the query should produce
+ *             (this is NOT necessarily root->parse->targetList!)
  * tuple_fraction is the fraction of tuples we expect will be retrieved
  *
  * Output parameters:
  * *sorted_path receives the cheapest presorted path for the query,
  *                             if any (NULL if there is no useful presorted path)
  *
- * Note: the Query node also includes a query_pathkeys field, which is both
- * an input and an output of query_planner().  The input value signals
+ * Note: the PlannerInfo node also includes a query_pathkeys field, which is
+ * both an input and an output of query_planner().  The input value signals
  * query_planner that the indicated sort order is wanted in the final output
  * plan.  But this value has not yet been "canonicalized", since the needed
  * info does not get computed until we scan the qual clauses.  We canonicalize
  * it as soon as that task is done.  (The main reason query_pathkeys is a
- * Query field and not a passed parameter is that the low-level routines in
- * indxpath.c need to see it.)
+ * PlannerInfo field and not a passed parameter is that the low-level routines
+ * in indxpath.c need to see it.)
  *
  * tuple_fraction is interpreted as follows:
  *       0: expect all tuples to be retrieved (normal case)
  *--------------------
  */
 void
-query_planner(Query *root, List *tlist, double tuple_fraction,
+query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
                          Path **cheapest_path, Path **sorted_path)
 {
+       Query      *parse = root->parse;
        List       *constant_quals;
        RelOptInfo *final_rel;
        Path       *cheapestpath;
@@ -81,10 +83,10 @@ query_planner(Query *root, List *tlist, double tuple_fraction,
         * If the query has an empty join tree, then it's something easy like
         * "SELECT 2+2;" or "INSERT ... VALUES()".      Fall through quickly.
         */
-       if (root->jointree->fromlist == NIL)
+       if (parse->jointree->fromlist == NIL)
        {
                *cheapest_path = (Path *) create_result_path(NULL, NULL,
-                                                                                (List *) root->jointree->quals);
+                                                                                (List *) parse->jointree->quals);
                *sorted_path = NULL;
                return;
        }
@@ -99,8 +101,8 @@ query_planner(Query *root, List *tlist, double tuple_fraction,
         * vars, although if the qual reduces to "WHERE FALSE" this path will
         * also be taken.
         */
-       root->jointree->quals = (Node *)
-               pull_constant_clauses((List *) root->jointree->quals,
+       parse->jointree->quals = (Node *)
+               pull_constant_clauses((List *) parse->jointree->quals,
                                                          &constant_quals);
 
        /*
@@ -116,7 +118,7 @@ query_planner(Query *root, List *tlist, double tuple_fraction,
        /*
         * Construct RelOptInfo nodes for all base relations in query.
         */
-       add_base_rels_to_query(root, (Node *) root->jointree);
+       add_base_rels_to_query(root, (Node *) parse->jointree);
 
        /*
         * Examine the targetlist and qualifications, adding entries to
@@ -133,7 +135,7 @@ query_planner(Query *root, List *tlist, double tuple_fraction,
         */
        build_base_rel_tlists(root, tlist);
 
-       (void) distribute_quals_to_rels(root, (Node *) root->jointree);
+       (void) distribute_quals_to_rels(root, (Node *) parse->jointree);
 
        /*
         * Use the completed lists of equijoined keys to deduce any implied
index 858f960aaf803ace960fc788cb445d253740cb82..76ffe04078fabfe7014f2a9fc28d9aa3189c92f3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.187 2005/05/30 01:04:44 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.188 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,18 +54,18 @@ ParamListInfo PlannerBoundParamList = NULL;         /* current boundParams */
 #define EXPRKIND_ININFO 4
 
 
-static Node *preprocess_expression(Query *parse, Node *expr, int kind);
-static void preprocess_qual_conditions(Query *parse, Node *jtnode);
-static Plan *inheritance_planner(Query *parse, List *inheritlist);
-static Plan *grouping_planner(Query *parse, double tuple_fraction);
-static bool choose_hashed_grouping(Query *parse, double tuple_fraction,
+static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
+static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
+static Plan *inheritance_planner(PlannerInfo *root, List *inheritlist);
+static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction);
+static bool choose_hashed_grouping(PlannerInfo *root, double tuple_fraction,
                                           Path *cheapest_path, Path *sorted_path,
                                           List *sort_pathkeys, List *group_pathkeys,
                                           double dNumGroups, AggClauseCounts *agg_counts);
-static bool hash_safe_grouping(Query *parse);
-static List *make_subplanTargetList(Query *parse, List *tlist,
+static bool hash_safe_grouping(PlannerInfo *root);
+static List *make_subplanTargetList(PlannerInfo *root, List *tlist,
                                           AttrNumber **groupColIdx, bool *need_tlist_eval);
-static void locate_grouping_columns(Query *parse,
+static void locate_grouping_columns(PlannerInfo *root,
                                                List *tlist,
                                                List *sub_tlist,
                                                AttrNumber *groupColIdx);
@@ -92,10 +92,10 @@ planner(Query *parse, bool isCursor, int cursorOptions,
         * 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 Query
-        * 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
+        * 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
@@ -130,8 +130,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
        }
 
        /* primary planning entry point (may recurse for subqueries) */
-       result_plan = subquery_planner(parse, tuple_fraction);
+       result_plan = subquery_planner(parse, tuple_fraction, NULL);
 
+       /* check we popped out the right number of levels */
        Assert(PlannerQueryLevel == 0);
 
        /*
@@ -168,6 +169,9 @@ planner(Query *parse, bool isCursor, int cursorOptions,
  * tuple_fraction is the fraction of tuples we expect will be retrieved.
  * tuple_fraction is interpreted as explained for grouping_planner, below.
  *
+ * If subquery_pathkeys isn't NULL, it receives a list of pathkeys indicating
+ * the output sort ordering of the completed plan.
+ *
  * Basically, this routine does the stuff that should only be done once
  * per Query object.  It then calls grouping_planner.  At one time,
  * grouping_planner could be invoked recursively on the same Query object;
@@ -181,12 +185,14 @@ planner(Query *parse, bool isCursor, int cursorOptions,
  *--------------------
  */
 Plan *
-subquery_planner(Query *parse, double tuple_fraction)
+subquery_planner(Query *parse, double tuple_fraction,
+                                List **subquery_pathkeys)
 {
        List       *saved_initplan = PlannerInitPlan;
        int                     saved_planid = PlannerPlanId;
-       bool            hasOuterJoins;
+       PlannerInfo *root;
        Plan       *plan;
+       bool            hasOuterJoins;
        List       *newHaving;
        List       *lst;
        ListCell   *l;
@@ -195,23 +201,27 @@ subquery_planner(Query *parse, double tuple_fraction)
        PlannerQueryLevel++;
        PlannerInitPlan = NIL;
 
+       /* Create a PlannerInfo data structure for this subquery */
+       root = makeNode(PlannerInfo);
+       root->parse = parse;
+
        /*
         * Look for IN clauses at the top level of WHERE, and transform them
         * into joins.  Note that this step only handles IN clauses originally
         * at top level of WHERE; if we pull up any subqueries in the next
         * step, their INs are processed just before pulling them up.
         */
-       parse->in_info_list = NIL;
+       root->in_info_list = NIL;
        if (parse->hasSubLinks)
-               parse->jointree->quals = pull_up_IN_clauses(parse,
-                                                                                                parse->jointree->quals);
+               parse->jointree->quals = pull_up_IN_clauses(root,
+                                                                                                       parse->jointree->quals);
 
        /*
         * Check to see if any subqueries in the rangetable can be merged into
         * this query.
         */
        parse->jointree = (FromExpr *)
-               pull_up_subqueries(parse, (Node *) parse->jointree, false);
+               pull_up_subqueries(root, (Node *) parse->jointree, false);
 
        /*
         * Detect whether any rangetable entries are RTE_JOIN kind; if not, we
@@ -220,7 +230,7 @@ subquery_planner(Query *parse, double tuple_fraction)
         * reduce_outer_joins(). This must be done after we have done
         * pull_up_subqueries, of course.
         */
-       parse->hasJoinRTEs = false;
+       root->hasJoinRTEs = false;
        hasOuterJoins = false;
        foreach(l, parse->rtable)
        {
@@ -228,7 +238,7 @@ subquery_planner(Query *parse, double tuple_fraction)
 
                if (rte->rtekind == RTE_JOIN)
                {
-                       parse->hasJoinRTEs = true;
+                       root->hasJoinRTEs = true;
                        if (IS_OUTER_JOIN(rte->jointype))
                        {
                                hasOuterJoins = true;
@@ -243,27 +253,27 @@ subquery_planner(Query *parse, double tuple_fraction)
         * because preprocess_expression will reduce a constant-true condition
         * to an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
         */
-       parse->hasHavingQual = (parse->havingQual != NULL);
+       root->hasHavingQual = (parse->havingQual != NULL);
 
        /*
         * Do expression preprocessing on targetlist and quals.
         */
        parse->targetList = (List *)
-               preprocess_expression(parse, (Node *) parse->targetList,
+               preprocess_expression(root, (Node *) parse->targetList,
                                                          EXPRKIND_TARGET);
 
-       preprocess_qual_conditions(parse, (Node *) parse->jointree);
+       preprocess_qual_conditions(root, (Node *) parse->jointree);
 
-       parse->havingQual = preprocess_expression(parse, parse->havingQual,
+       parse->havingQual = preprocess_expression(root, parse->havingQual,
                                                                                          EXPRKIND_QUAL);
 
-       parse->limitOffset = preprocess_expression(parse, parse->limitOffset,
+       parse->limitOffset = preprocess_expression(root, parse->limitOffset,
                                                                                           EXPRKIND_LIMIT);
-       parse->limitCount = preprocess_expression(parse, parse->limitCount,
+       parse->limitCount = preprocess_expression(root, parse->limitCount,
                                                                                          EXPRKIND_LIMIT);
 
-       parse->in_info_list = (List *)
-               preprocess_expression(parse, (Node *) parse->in_info_list,
+       root->in_info_list = (List *)
+               preprocess_expression(root, (Node *) root->in_info_list,
                                                          EXPRKIND_ININFO);
 
        /* Also need to preprocess expressions for function RTEs */
@@ -272,7 +282,7 @@ subquery_planner(Query *parse, double tuple_fraction)
                RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
 
                if (rte->rtekind == RTE_FUNCTION)
-                       rte->funcexpr = preprocess_expression(parse, rte->funcexpr,
+                       rte->funcexpr = preprocess_expression(root, rte->funcexpr,
                                                                                                  EXPRKIND_RTFUNC);
        }
 
@@ -336,7 +346,7 @@ subquery_planner(Query *parse, double tuple_fraction)
         * preprocessing.
         */
        if (hasOuterJoins)
-               reduce_outer_joins(parse);
+               reduce_outer_joins(root);
 
        /*
         * See if we can simplify the jointree; opportunities for this may
@@ -347,7 +357,7 @@ subquery_planner(Query *parse, double tuple_fraction)
         * after reduce_outer_joins, anyway.
         */
        parse->jointree = (FromExpr *)
-               simplify_jointree(parse, (Node *) parse->jointree);
+               simplify_jointree(root, (Node *) parse->jointree);
 
        /*
         * Do the main planning.  If we have an inherited target relation,
@@ -355,10 +365,10 @@ subquery_planner(Query *parse, double tuple_fraction)
         * grouping_planner.
         */
        if (parse->resultRelation &&
-               (lst = expand_inherited_rtentry(parse, parse->resultRelation)) != NIL)
-               plan = inheritance_planner(parse, lst);
+               (lst = expand_inherited_rtentry(root, parse->resultRelation)) != NIL)
+               plan = inheritance_planner(root, lst);
        else
-               plan = grouping_planner(parse, tuple_fraction);
+               plan = grouping_planner(root, tuple_fraction);
 
        /*
         * If any subplans were generated, or if we're inside a subplan, build
@@ -368,6 +378,10 @@ subquery_planner(Query *parse, double tuple_fraction)
        if (PlannerPlanId != saved_planid || PlannerQueryLevel > 1)
                SS_finalize_plan(plan, parse->rtable);
 
+       /* 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;
@@ -383,7 +397,7 @@ subquery_planner(Query *parse, double tuple_fraction)
  *             conditions), or a HAVING clause.
  */
 static Node *
-preprocess_expression(Query *parse, Node *expr, int kind)
+preprocess_expression(PlannerInfo *root, Node *expr, int kind)
 {
        /*
         * Fall out quickly if expression is empty.  This occurs often enough
@@ -399,8 +413,8 @@ preprocess_expression(Query *parse, Node *expr, int kind)
         * else sublinks expanded out from join aliases wouldn't get
         * processed.
         */
-       if (parse->hasJoinRTEs)
-               expr = flatten_join_alias_vars(parse, expr);
+       if (root->hasJoinRTEs)
+               expr = flatten_join_alias_vars(root, expr);
 
        /*
         * Simplify constant expressions.
@@ -418,7 +432,7 @@ preprocess_expression(Query *parse, Node *expr, int kind)
         * still must do it for quals (to get AND/OR flatness); and if we are
         * in a subquery we should not assume it will be done only once.
         */
-       if (parse->jointree->fromlist != NIL ||
+       if (root->parse->jointree->fromlist != NIL ||
                kind == EXPRKIND_QUAL ||
                PlannerQueryLevel > 1)
                expr = eval_const_expressions(expr);
@@ -437,7 +451,7 @@ preprocess_expression(Query *parse, Node *expr, int kind)
        }
 
        /* Expand SubLinks to SubPlans */
-       if (parse->hasSubLinks)
+       if (root->parse->hasSubLinks)
                expr = SS_process_sublinks(expr, (kind == EXPRKIND_QUAL));
 
        /*
@@ -467,7 +481,7 @@ preprocess_expression(Query *parse, Node *expr, int kind)
  *             preprocessing work on each qual condition found therein.
  */
 static void
-preprocess_qual_conditions(Query *parse, Node *jtnode)
+preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
 {
        if (jtnode == NULL)
                return;
@@ -481,18 +495,18 @@ preprocess_qual_conditions(Query *parse, Node *jtnode)
                ListCell   *l;
 
                foreach(l, f->fromlist)
-                       preprocess_qual_conditions(parse, lfirst(l));
+                       preprocess_qual_conditions(root, lfirst(l));
 
-               f->quals = preprocess_expression(parse, f->quals, EXPRKIND_QUAL);
+               f->quals = preprocess_expression(root, f->quals, EXPRKIND_QUAL);
        }
        else if (IsA(jtnode, JoinExpr))
        {
                JoinExpr   *j = (JoinExpr *) jtnode;
 
-               preprocess_qual_conditions(parse, j->larg);
-               preprocess_qual_conditions(parse, j->rarg);
+               preprocess_qual_conditions(root, j->larg);
+               preprocess_qual_conditions(root, j->rarg);
 
-               j->quals = preprocess_expression(parse, j->quals, EXPRKIND_QUAL);
+               j->quals = preprocess_expression(root, j->quals, EXPRKIND_QUAL);
        }
        else
                elog(ERROR, "unrecognized node type: %d",
@@ -514,15 +528,15 @@ preprocess_qual_conditions(Query *parse, Node *jtnode)
  * can never be the nullable side of an outer join, so it's OK to generate
  * the plan this way.
  *
- * parse is the querytree produced by the parser & rewriter.
  * inheritlist is an integer list of RT indexes for the result relation set.
  *
  * Returns a query plan.
  *--------------------
  */
 static Plan *
-inheritance_planner(Query *parse, List *inheritlist)
+inheritance_planner(PlannerInfo *root, List *inheritlist)
 {
+       Query      *parse = root->parse;
        int                     parentRTindex = parse->resultRelation;
        Oid                     parentOID = getrelid(parentRTindex, parse->rtable);
        int                     mainrtlength = list_length(parse->rtable);
@@ -534,15 +548,27 @@ inheritance_planner(Query *parse, List *inheritlist)
        {
                int                     childRTindex = lfirst_int(l);
                Oid                     childOID = getrelid(childRTindex, parse->rtable);
-               Query      *subquery;
+               PlannerInfo subroot;
                Plan       *subplan;
 
-               /* Generate modified query with this rel as target */
-               subquery = (Query *) adjust_inherited_attrs((Node *) parse,
-                                                                                               parentRTindex, parentOID,
-                                                                                                childRTindex, childOID);
+               /*
+                * Generate modified query with this rel as target.  We have to
+                * be prepared to translate varnos in in_info_list as well as in
+                * the Query proper.
+                */
+               memcpy(&subroot, root, sizeof(PlannerInfo));
+               subroot.parse = (Query *)
+                       adjust_inherited_attrs((Node *) parse,
+                                                                  parentRTindex, parentOID,
+                                                                  childRTindex, childOID);
+               subroot.in_info_list = (List *)
+                       adjust_inherited_attrs((Node *) root->in_info_list,
+                                                                  parentRTindex, parentOID,
+                                                                  childRTindex, childOID);
+
                /* Generate plan */
-               subplan = grouping_planner(subquery, 0.0 /* retrieve all tuples */ );
+               subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
+
                subplans = lappend(subplans, subplan);
 
                /*
@@ -565,16 +591,16 @@ inheritance_planner(Query *parse, List *inheritlist)
                 * rangetables will be the same each time.  Did I say this is ugly?)
                 */
                if (lnext(l) == NULL)
-                       parse->rtable = subquery->rtable;
+                       parse->rtable = subroot.parse->rtable;
                else
                {
-                       int             subrtlength = list_length(subquery->rtable);
+                       int             subrtlength = list_length(subroot.parse->rtable);
 
                        if (subrtlength > mainrtlength)
                        {
                                List       *subrt;
 
-                               subrt = list_copy_tail(subquery->rtable, mainrtlength);
+                               subrt = list_copy_tail(subroot.parse->rtable, mainrtlength);
                                parse->rtable = list_concat(parse->rtable, subrt);
                                mainrtlength = subrtlength;
                        }
@@ -589,7 +615,7 @@ inheritance_planner(Query *parse, List *inheritlist)
        parse->resultRelations = inheritlist;
 
        /* Mark result as unordered (probably unnecessary) */
-       parse->query_pathkeys = NIL;
+       root->query_pathkeys = NIL;
 
        return (Plan *) make_append(subplans, true, tlist);
 }
@@ -600,7 +626,6 @@ inheritance_planner(Query *parse, List *inheritlist)
  *       This primarily means adding top-level processing to the basic
  *       query plan produced by query_planner.
  *
- * parse is the querytree produced by the parser & rewriter.
  * tuple_fraction is the fraction of tuples we expect will be retrieved
  *
  * tuple_fraction is interpreted as follows:
@@ -610,13 +635,14 @@ inheritance_planner(Query *parse, List *inheritlist)
  *       tuple_fraction >= 1: tuple_fraction is the absolute number of tuples
  *             expected to be retrieved (ie, a LIMIT specification)
  *
- * Returns a query plan.  Also, parse->query_pathkeys is returned as the
+ * Returns a query plan.  Also, root->query_pathkeys is returned as the
  * actual output ordering of the plan (in pathkey format).
  *--------------------
  */
 static Plan *
-grouping_planner(Query *parse, double tuple_fraction)
+grouping_planner(PlannerInfo *root, double tuple_fraction)
 {
+       Query      *parse = root->parse;
        List       *tlist = parse->targetList;
        Plan       *result_plan;
        List       *current_pathkeys;
@@ -630,7 +656,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                 * Construct the plan for set operations.  The result will not
                 * need any work except perhaps a top-level sort and/or LIMIT.
                 */
-               result_plan = plan_set_operations(parse,
+               result_plan = plan_set_operations(root,
                                                                                  &set_sortclauses);
 
                /*
@@ -640,7 +666,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                 */
                current_pathkeys = make_pathkeys_for_sortclauses(set_sortclauses,
                                                                                                result_plan->targetlist);
-               current_pathkeys = canonicalize_pathkeys(parse, current_pathkeys);
+               current_pathkeys = canonicalize_pathkeys(root, current_pathkeys);
 
                /*
                 * We should not need to call preprocess_targetlist, since we must
@@ -667,7 +693,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                 */
                sort_pathkeys = make_pathkeys_for_sortclauses(parse->sortClause,
                                                                                                          tlist);
-               sort_pathkeys = canonicalize_pathkeys(parse, sort_pathkeys);
+               sort_pathkeys = canonicalize_pathkeys(root, sort_pathkeys);
        }
        else
        {
@@ -690,13 +716,13 @@ grouping_planner(Query *parse, double tuple_fraction)
                MemSet(&agg_counts, 0, sizeof(AggClauseCounts));
 
                /* Preprocess targetlist */
-               tlist = preprocess_targetlist(parse, tlist);
+               tlist = preprocess_targetlist(root, tlist);
 
                /*
                 * Generate appropriate target list for subplan; may be different
                 * from tlist if grouping or aggregation is needed.
                 */
-               sub_tlist = make_subplanTargetList(parse, tlist,
+               sub_tlist = make_subplanTargetList(root, tlist,
                                                                                 &groupColIdx, &need_tlist_eval);
 
                /*
@@ -737,11 +763,11 @@ grouping_planner(Query *parse, double tuple_fraction)
                 * Needs more thought...)
                 */
                if (parse->groupClause)
-                       parse->query_pathkeys = group_pathkeys;
+                       root->query_pathkeys = group_pathkeys;
                else if (parse->sortClause)
-                       parse->query_pathkeys = sort_pathkeys;
+                       root->query_pathkeys = sort_pathkeys;
                else
-                       parse->query_pathkeys = NIL;
+                       root->query_pathkeys = NIL;
 
                /*
                 * Adjust tuple_fraction if we see that we are going to apply
@@ -902,15 +928,15 @@ grouping_planner(Query *parse, double tuple_fraction)
                 * Generate the best unsorted and presorted paths for this Query
                 * (but note there may not be any presorted path).
                 */
-               query_planner(parse, sub_tlist, sub_tuple_fraction,
+               query_planner(root, sub_tlist, sub_tuple_fraction,
                                          &cheapest_path, &sorted_path);
 
                /*
                 * We couldn't canonicalize group_pathkeys and sort_pathkeys
                 * before running query_planner(), so do it now.
                 */
-               group_pathkeys = canonicalize_pathkeys(parse, group_pathkeys);
-               sort_pathkeys = canonicalize_pathkeys(parse, sort_pathkeys);
+               group_pathkeys = canonicalize_pathkeys(root, group_pathkeys);
+               sort_pathkeys = canonicalize_pathkeys(root, sort_pathkeys);
 
                /*
                 * If grouping, estimate the number of groups.  (We can't do this
@@ -934,14 +960,14 @@ grouping_planner(Query *parse, double tuple_fraction)
 
                        groupExprs = get_sortgrouplist_exprs(parse->groupClause,
                                                                                                 parse->targetList);
-                       dNumGroups = estimate_num_groups(parse,
+                       dNumGroups = estimate_num_groups(root,
                                                                                         groupExprs,
                                                                                         cheapest_path_rows);
                        /* Also want it as a long int --- but 'ware overflow! */
                        numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
 
                        use_hashed_grouping =
-                               choose_hashed_grouping(parse, tuple_fraction,
+                               choose_hashed_grouping(root, tuple_fraction,
                                                                           cheapest_path, sorted_path,
                                                                           sort_pathkeys, group_pathkeys,
                                                                           dNumGroups, &agg_counts);
@@ -963,7 +989,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                 * "regular" path ... but we had to do it anyway to be able to
                 * tell which way is cheaper.
                 */
-               result_plan = optimize_minmax_aggregates(parse,
+               result_plan = optimize_minmax_aggregates(root,
                                                                                                 tlist,
                                                                                                 best_path);
                if (result_plan != NULL)
@@ -980,7 +1006,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                         * Normal case --- create a plan according to query_planner's
                         * results.
                         */
-                       result_plan = create_plan(parse, best_path);
+                       result_plan = create_plan(root, best_path);
                        current_pathkeys = best_path->pathkeys;
 
                        /*
@@ -1042,7 +1068,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                                 * make_subplanTargetList calculated, we have to refigure any
                                 * grouping-column indexes make_subplanTargetList computed.
                                 */
-                               locate_grouping_columns(parse, tlist, result_plan->targetlist,
+                               locate_grouping_columns(root, tlist, result_plan->targetlist,
                                                                                groupColIdx);
                        }
 
@@ -1055,7 +1081,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                        if (use_hashed_grouping)
                        {
                                /* Hashed aggregate plan --- no sort needed */
-                               result_plan = (Plan *) make_agg(parse,
+                               result_plan = (Plan *) make_agg(root,
                                                                                                tlist,
                                                                                                (List *) parse->havingQual,
                                                                                                AGG_HASHED,
@@ -1078,7 +1104,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                                                                                           current_pathkeys))
                                        {
                                                result_plan = (Plan *)
-                                                       make_sort_from_groupcols(parse,
+                                                       make_sort_from_groupcols(root,
                                                                                                         parse->groupClause,
                                                                                                         groupColIdx,
                                                                                                         result_plan);
@@ -1098,7 +1124,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                                        current_pathkeys = NIL;
                                }
 
-                               result_plan = (Plan *) make_agg(parse,
+                               result_plan = (Plan *) make_agg(root,
                                                                                                tlist,
                                                                                                (List *) parse->havingQual,
                                                                                                aggstrategy,
@@ -1120,14 +1146,14 @@ grouping_planner(Query *parse, double tuple_fraction)
                                if (!pathkeys_contained_in(group_pathkeys, current_pathkeys))
                                {
                                        result_plan = (Plan *)
-                                               make_sort_from_groupcols(parse,
+                                               make_sort_from_groupcols(root,
                                                                                                 parse->groupClause,
                                                                                                 groupColIdx,
                                                                                                 result_plan);
                                        current_pathkeys = group_pathkeys;
                                }
 
-                               result_plan = (Plan *) make_group(parse,
+                               result_plan = (Plan *) make_group(root,
                                                                                                  tlist,
                                                                                                  (List *) parse->havingQual,
                                                                                                  numGroupCols,
@@ -1136,7 +1162,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                                                                                                  result_plan);
                                /* The Group node won't change sort ordering */
                        }
-                       else if (parse->hasHavingQual)
+                       else if (root->hasHavingQual)
                        {
                                /*
                                 * No aggregates, and no GROUP BY, but we have a HAVING qual.
@@ -1165,7 +1191,7 @@ grouping_planner(Query *parse, double tuple_fraction)
                if (!pathkeys_contained_in(sort_pathkeys, current_pathkeys))
                {
                        result_plan = (Plan *)
-                               make_sort_from_sortclauses(parse,
+                               make_sort_from_sortclauses(root,
                                                                                   parse->sortClause,
                                                                                   result_plan);
                        current_pathkeys = sort_pathkeys;
@@ -1185,13 +1211,13 @@ grouping_planner(Query *parse, double tuple_fraction)
                 * it's reasonable to assume the UNIQUE filter has effects
                 * comparable to GROUP BY.
                 */
-               if (!parse->groupClause && !parse->hasHavingQual && !parse->hasAggs)
+               if (!parse->groupClause && !root->hasHavingQual && !parse->hasAggs)
                {
                        List       *distinctExprs;
 
                        distinctExprs = get_sortgrouplist_exprs(parse->distinctClause,
                                                                                                        parse->targetList);
-                       result_plan->plan_rows = estimate_num_groups(parse,
+                       result_plan->plan_rows = estimate_num_groups(root,
                                                                                                                 distinctExprs,
                                                                                                 result_plan->plan_rows);
                }
@@ -1211,7 +1237,7 @@ grouping_planner(Query *parse, double tuple_fraction)
         * Return the actual output ordering in query_pathkeys for possible
         * use by an outer query level.
         */
-       parse->query_pathkeys = current_pathkeys;
+       root->query_pathkeys = current_pathkeys;
 
        return result_plan;
 }
@@ -1220,12 +1246,12 @@ grouping_planner(Query *parse, double tuple_fraction)
  * choose_hashed_grouping - should we use hashed grouping?
  */
 static bool
-choose_hashed_grouping(Query *parse, double tuple_fraction,
+choose_hashed_grouping(PlannerInfo *root, double tuple_fraction,
                                           Path *cheapest_path, Path *sorted_path,
                                           List *sort_pathkeys, List *group_pathkeys,
                                           double dNumGroups, AggClauseCounts *agg_counts)
 {
-       int                     numGroupCols = list_length(parse->groupClause);
+       int                     numGroupCols = list_length(root->parse->groupClause);
        double          cheapest_path_rows;
        int                     cheapest_path_width;
        Size            hashentrysize;
@@ -1245,7 +1271,7 @@ choose_hashed_grouping(Query *parse, double tuple_fraction,
                return false;
        if (agg_counts->numDistinctAggs != 0)
                return false;
-       if (!hash_safe_grouping(parse))
+       if (!hash_safe_grouping(root))
                return false;
 
        /*
@@ -1296,13 +1322,13 @@ choose_hashed_grouping(Query *parse, double tuple_fraction,
         * These path variables are dummies that just hold cost fields; we don't
         * make actual Paths for these steps.
         */
-       cost_agg(&hashed_p, parse, AGG_HASHED, agg_counts->numAggs,
+       cost_agg(&hashed_p, root, AGG_HASHED, agg_counts->numAggs,
                         numGroupCols, dNumGroups,
                         cheapest_path->startup_cost, cheapest_path->total_cost,
                         cheapest_path_rows);
        /* Result of hashed agg is always unsorted */
        if (sort_pathkeys)
-               cost_sort(&hashed_p, parse, sort_pathkeys, hashed_p.total_cost,
+               cost_sort(&hashed_p, root, sort_pathkeys, hashed_p.total_cost,
                                  dNumGroups, cheapest_path_width);
 
        if (sorted_path)
@@ -1320,24 +1346,24 @@ choose_hashed_grouping(Query *parse, double tuple_fraction,
        if (!pathkeys_contained_in(group_pathkeys,
                                                           current_pathkeys))
        {
-               cost_sort(&sorted_p, parse, group_pathkeys, sorted_p.total_cost,
+               cost_sort(&sorted_p, root, group_pathkeys, sorted_p.total_cost,
                                  cheapest_path_rows, cheapest_path_width);
                current_pathkeys = group_pathkeys;
        }
 
-       if (parse->hasAggs)
-               cost_agg(&sorted_p, parse, AGG_SORTED, agg_counts->numAggs,
+       if (root->parse->hasAggs)
+               cost_agg(&sorted_p, root, AGG_SORTED, agg_counts->numAggs,
                                 numGroupCols, dNumGroups,
                                 sorted_p.startup_cost, sorted_p.total_cost,
                                 cheapest_path_rows);
        else
-               cost_group(&sorted_p, parse, numGroupCols, dNumGroups,
+               cost_group(&sorted_p, root, numGroupCols, dNumGroups,
                                   sorted_p.startup_cost, sorted_p.total_cost,
                                   cheapest_path_rows);
        /* The Agg or Group node will preserve ordering */
        if (sort_pathkeys &&
                !pathkeys_contained_in(sort_pathkeys, current_pathkeys))
-               cost_sort(&sorted_p, parse, sort_pathkeys, sorted_p.total_cost,
+               cost_sort(&sorted_p, root, sort_pathkeys, sorted_p.total_cost,
                                  dNumGroups, cheapest_path_width);
 
        /*
@@ -1363,14 +1389,15 @@ choose_hashed_grouping(Query *parse, double tuple_fraction,
  * is marked hashjoinable.
  */
 static bool
-hash_safe_grouping(Query *parse)
+hash_safe_grouping(PlannerInfo *root)
 {
        ListCell   *gl;
 
-       foreach(gl, parse->groupClause)
+       foreach(gl, root->parse->groupClause)
        {
                GroupClause *grpcl = (GroupClause *) lfirst(gl);
-               TargetEntry *tle = get_sortgroupclause_tle(grpcl, parse->targetList);
+               TargetEntry *tle = get_sortgroupclause_tle(grpcl,
+                                                                                                  root->parse->targetList);
                Operator        optup;
                bool            oprcanhash;
 
@@ -1417,7 +1444,6 @@ hash_safe_grouping(Query *parse)
  * need to force it to be evaluated, because all the Vars it contains
  * should be present in the output of query_planner anyway.
  *
- * 'parse' is the query being processed.
  * 'tlist' is the query's target list.
  * 'groupColIdx' receives an array of column numbers for the GROUP BY
  *                     expressions (if there are any) in the subplan's target list.
@@ -1428,11 +1454,12 @@ hash_safe_grouping(Query *parse)
  *---------------
  */
 static List *
-make_subplanTargetList(Query *parse,
+make_subplanTargetList(PlannerInfo *root,
                                           List *tlist,
                                           AttrNumber **groupColIdx,
                                           bool *need_tlist_eval)
 {
+       Query      *parse = root->parse;
        List       *sub_tlist;
        List       *extravars;
        int                     numCols;
@@ -1443,7 +1470,7 @@ make_subplanTargetList(Query *parse,
         * If we're not grouping or aggregating, there's nothing to do here;
         * query_planner should receive the unmodified target list.
         */
-       if (!parse->hasAggs && !parse->groupClause && !parse->hasHavingQual)
+       if (!parse->hasAggs && !parse->groupClause && !root->hasHavingQual)
        {
                *need_tlist_eval = true;
                return tlist;
@@ -1517,7 +1544,7 @@ make_subplanTargetList(Query *parse,
  * by that routine and re-locate the grouping vars in the real sub_tlist.
  */
 static void
-locate_grouping_columns(Query *parse,
+locate_grouping_columns(PlannerInfo *root,
                                                List *tlist,
                                                List *sub_tlist,
                                                AttrNumber *groupColIdx)
@@ -1528,14 +1555,14 @@ locate_grouping_columns(Query *parse,
        /*
         * No work unless grouping.
         */
-       if (!parse->groupClause)
+       if (!root->parse->groupClause)
        {
                Assert(groupColIdx == NULL);
                return;
        }
        Assert(groupColIdx != NULL);
 
-       foreach(gl, parse->groupClause)
+       foreach(gl, root->parse->groupClause)
        {
                GroupClause *grpcl = (GroupClause *) lfirst(gl);
                Node       *groupexpr = get_sortgroupclause_expr(grpcl, tlist);
index 0865feae2640780239a63493cc86a931b01aa606..ec037db514cd4a16b8a9da9d86d663ffbe2d8cc8 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.98 2005/04/25 01:30:13 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.99 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -292,7 +292,7 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
        /*
         * Generate the plan for the subquery.
         */
-       node->plan = plan = subquery_planner(subquery, tuple_fraction);
+       node->plan = plan = subquery_planner(subquery, tuple_fraction, NULL);
 
        node->plan_id = PlannerPlanId++;        /* Assign unique ID to this
                                                                                 * SubPlan */
@@ -417,10 +417,8 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
                 * top of the subplan, to reduce the cost of reading it
                 * repeatedly.  This is pointless for a direct-correlated subplan,
                 * since we'd have to recompute its results each time anyway.  For
-                * uncorrelated/undirect correlated subplans, we add MATERIAL if
-                * the subplan's top plan node is anything more complicated than a
-                * plain sequential scan, and we do it even for seqscan if the
-                * qual appears selective enough to eliminate many tuples.
+                * uncorrelated/undirect correlated subplans, we add MATERIAL unless
+                * the subplan's top plan node would materialize its output anyway.
                 */
                else if (node->parParam == NIL)
                {
@@ -428,29 +426,9 @@ make_subplan(SubLink *slink, List *lefthand, bool isTopQual)
 
                        switch (nodeTag(plan))
                        {
-                               case T_SeqScan:
-                                       if (plan->initPlan)
-                                               use_material = true;
-                                       else
-                                       {
-                                               Selectivity qualsel;
-
-                                               qualsel = clauselist_selectivity(subquery,
-                                                                                                                plan->qual,
-                                                                                                                0, JOIN_INNER);
-                                               /* Is 10% selectivity a good threshold?? */
-                                               use_material = qualsel < 0.10;
-                                       }
-                                       break;
                                case T_Material:
                                case T_FunctionScan:
                                case T_Sort:
-
-                                       /*
-                                        * Don't add another Material node if there's one
-                                        * already, nor if the top node is any other type that
-                                        * materializes its output anyway.
-                                        */
                                        use_material = false;
                                        break;
                                default:
@@ -678,8 +656,9 @@ subplan_is_hashable(SubLink *slink, SubPlan *node)
  * its in_info_list.
  */
 Node *
-convert_IN_to_join(Query *parse, SubLink *sublink)
+convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
 {
+       Query      *parse = root->parse;
        Query      *subselect = (Query *) sublink->subselect;
        Relids          left_varnos;
        int                     rtindex;
@@ -746,7 +725,7 @@ convert_IN_to_join(Query *parse, SubLink *sublink)
        ininfo = makeNode(InClauseInfo);
        ininfo->lefthand = left_varnos;
        ininfo->righthand = bms_make_singleton(rtindex);
-       parse->in_info_list = lcons(ininfo, parse->in_info_list);
+       root->in_info_list = lappend(root->in_info_list, ininfo);
 
        /*
         * Build the result qual expressions.  As a side effect,
@@ -1252,7 +1231,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
  * We assume the plan hasn't been put through SS_finalize_plan.
  */
 Param *
-SS_make_initplan_from_plan(Query *root, Plan *plan,
+SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
                                                   Oid resulttype, int32 resulttypmod)
 {
        List       *saved_initplan = PlannerInitPlan;
@@ -1271,7 +1250,7 @@ SS_make_initplan_from_plan(Query *root, Plan *plan,
        /*
         * Build extParam/allParam sets for plan nodes.
         */
-       SS_finalize_plan(plan, root->rtable);
+       SS_finalize_plan(plan, root->parse->rtable);
 
        /* Return to outer subquery context */
        PlannerQueryLevel--;
@@ -1286,7 +1265,7 @@ SS_make_initplan_from_plan(Query *root, Plan *plan,
        node->plan_id = PlannerPlanId++;        /* Assign unique ID to this
                                                                                 * SubPlan */
 
-       node->rtable = root->rtable;
+       node->rtable = root->parse->rtable;
 
        PlannerInitPlan = lappend(PlannerInitPlan, node);
 
index 67f4e823d8654c3b41a538adb8d3b688f6c5d3f3..ba758528c7646641466c17508daf6343c7b20588 100644 (file)
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.28 2005/06/04 19:19:41 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.29 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,7 +50,7 @@ static void resolvenew_in_jointree(Node *jtnode, int varno,
 static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode);
 static void reduce_outer_joins_pass2(Node *jtnode,
                                                 reduce_outer_joins_state *state,
-                                                Query *parse,
+                                                PlannerInfo *root,
                                                 Relids nonnullable_rels);
 static Relids find_nonnullable_rels(Node *node, bool top_level);
 static void fix_in_clause_relids(List *in_info_list, int varno,
@@ -79,7 +79,7 @@ static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
  * Returns the possibly-modified version of the given qual-tree node.
  */
 Node *
-pull_up_IN_clauses(Query *parse, Node *node)
+pull_up_IN_clauses(PlannerInfo *root, Node *node)
 {
        if (node == NULL)
                return NULL;
@@ -89,7 +89,7 @@ pull_up_IN_clauses(Query *parse, Node *node)
                Node       *subst;
 
                /* Is it a convertible IN clause?  If not, return it as-is */
-               subst = convert_IN_to_join(parse, sublink);
+               subst = convert_IN_to_join(root, sublink);
                if (subst == NULL)
                        return node;
                return subst;
@@ -104,8 +104,7 @@ pull_up_IN_clauses(Query *parse, Node *node)
                        Node       *oldclause = (Node *) lfirst(l);
 
                        newclauses = lappend(newclauses,
-                                                                pull_up_IN_clauses(parse,
-                                                                                                       oldclause));
+                                                                pull_up_IN_clauses(root, oldclause));
                }
                return (Node *) make_andclause(newclauses);
        }
@@ -132,13 +131,14 @@ pull_up_IN_clauses(Query *parse, Node *node)
  * copy of the tree; we have to invoke it just on the quals, instead.
  */
 Node *
-pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
+pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
 {
        if (jtnode == NULL)
                return NULL;
        if (IsA(jtnode, RangeTblRef))
        {
                int                     varno = ((RangeTblRef *) jtnode)->rtindex;
+               Query      *parse = root->parse;
                RangeTblEntry *rte = rt_fetch(varno, parse->rtable);
                Query      *subquery = rte->subquery;
 
@@ -160,6 +160,7 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
                        is_simple_subquery(subquery) &&
                        (!below_outer_join || has_nullable_targetlist(subquery)))
                {
+                       PlannerInfo *subroot;
                        int                     rtoffset;
                        List       *subtlist;
                        ListCell   *rt;
@@ -173,12 +174,23 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
                         */
                        subquery = copyObject(subquery);
 
+                       /*
+                        * Create a PlannerInfo data structure for this subquery.
+                        *
+                        * NOTE: the next few steps should match the first processing
+                        * in subquery_planner().  Can we refactor to avoid code
+                        * duplication, or would that just make things uglier?
+                        */
+                       subroot = makeNode(PlannerInfo);
+                       subroot->parse = subquery;
+
                        /*
                         * Pull up any IN clauses within the subquery's WHERE, so that
                         * we don't leave unoptimized INs behind.
                         */
+                       subroot->in_info_list = NIL;
                        if (subquery->hasSubLinks)
-                               subquery->jointree->quals = pull_up_IN_clauses(subquery,
+                               subquery->jointree->quals = pull_up_IN_clauses(subroot,
                                                                                          subquery->jointree->quals);
 
                        /*
@@ -191,7 +203,7 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
                         * clean slate for outer-join semantics.
                         */
                        subquery->jointree = (FromExpr *)
-                               pull_up_subqueries(subquery, (Node *) subquery->jointree,
+                               pull_up_subqueries(subroot, (Node *) subquery->jointree,
                                                                   false);
 
                        /*
@@ -222,16 +234,19 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
 
                        /*
                         * Adjust level-0 varnos in subquery so that we can append its
-                        * rangetable to upper query's.
+                        * rangetable to upper query's.  We have to fix the subquery's
+                        * in_info_list, as well.
                         */
                        rtoffset = list_length(parse->rtable);
                        OffsetVarNodes((Node *) subquery, rtoffset, 0);
+                       OffsetVarNodes((Node *) subroot->in_info_list, rtoffset, 0);
 
                        /*
                         * Upper-level vars in subquery are now one level closer to
                         * their parent than before.
                         */
                        IncrementVarSublevelsUp((Node *) subquery, -1, 1);
+                       IncrementVarSublevelsUp((Node *) subroot->in_info_list, -1, 1);
 
                        /*
                         * Replace all of the top query's references to the subquery's
@@ -252,8 +267,8 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
                                ResolveNew(parse->havingQual,
                                                   varno, 0, rte,
                                                   subtlist, CMD_SELECT, 0);
-                       parse->in_info_list = (List *)
-                               ResolveNew((Node *) parse->in_info_list,
+                       root->in_info_list = (List *)
+                               ResolveNew((Node *) root->in_info_list,
                                                   varno, 0, rte,
                                                   subtlist, CMD_SELECT, 0);
 
@@ -299,19 +314,19 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
                         * ResolveNew, but it would clutter that routine's API
                         * unreasonably.)
                         */
-                       if (parse->in_info_list)
+                       if (root->in_info_list)
                        {
                                Relids          subrelids;
 
                                subrelids = get_relids_in_jointree((Node *) subquery->jointree);
-                               fix_in_clause_relids(parse->in_info_list, varno, subrelids);
+                               fix_in_clause_relids(root->in_info_list, varno, subrelids);
                        }
 
                        /*
                         * And now append any subquery InClauseInfos to our list.
                         */
-                       parse->in_info_list = list_concat(parse->in_info_list,
-                                                                                         subquery->in_info_list);
+                       root->in_info_list = list_concat(root->in_info_list,
+                                                                                        subroot->in_info_list);
 
                        /*
                         * Miscellaneous housekeeping.
@@ -332,7 +347,7 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
                ListCell   *l;
 
                foreach(l, f->fromlist)
-                       lfirst(l) = pull_up_subqueries(parse, lfirst(l),
+                       lfirst(l) = pull_up_subqueries(root, lfirst(l),
                                                                                   below_outer_join);
        }
        else if (IsA(jtnode, JoinExpr))
@@ -343,27 +358,27 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
                switch (j->jointype)
                {
                        case JOIN_INNER:
-                               j->larg = pull_up_subqueries(parse, j->larg,
+                               j->larg = pull_up_subqueries(root, j->larg,
                                                                                         below_outer_join);
-                               j->rarg = pull_up_subqueries(parse, j->rarg,
+                               j->rarg = pull_up_subqueries(root, j->rarg,
                                                                                         below_outer_join);
                                break;
                        case JOIN_LEFT:
-                               j->larg = pull_up_subqueries(parse, j->larg,
+                               j->larg = pull_up_subqueries(root, j->larg,
                                                                                         below_outer_join);
-                               j->rarg = pull_up_subqueries(parse, j->rarg,
+                               j->rarg = pull_up_subqueries(root, j->rarg,
                                                                                         true);
                                break;
                        case JOIN_FULL:
-                               j->larg = pull_up_subqueries(parse, j->larg,
+                               j->larg = pull_up_subqueries(root, j->larg,
                                                                                         true);
-                               j->rarg = pull_up_subqueries(parse, j->rarg,
+                               j->rarg = pull_up_subqueries(root, j->rarg,
                                                                                         true);
                                break;
                        case JOIN_RIGHT:
-                               j->larg = pull_up_subqueries(parse, j->larg,
+                               j->larg = pull_up_subqueries(root, j->larg,
                                                                                         true);
-                               j->rarg = pull_up_subqueries(parse, j->rarg,
+                               j->rarg = pull_up_subqueries(root, j->rarg,
                                                                                         below_outer_join);
                                break;
                        case JOIN_UNION:
@@ -555,7 +570,7 @@ resolvenew_in_jointree(Node *jtnode, int varno,
  * alias-var expansion).
  */
 void
-reduce_outer_joins(Query *parse)
+reduce_outer_joins(PlannerInfo *root)
 {
        reduce_outer_joins_state *state;
 
@@ -569,13 +584,14 @@ reduce_outer_joins(Query *parse)
         * clause. The second pass examines qual clauses and changes join
         * types as it descends the tree.
         */
-       state = reduce_outer_joins_pass1((Node *) parse->jointree);
+       state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
 
        /* planner.c shouldn't have called me if no outer joins */
        if (state == NULL || !state->contains_outer)
                elog(ERROR, "so where are the outer joins?");
 
-       reduce_outer_joins_pass2((Node *) parse->jointree, state, parse, NULL);
+       reduce_outer_joins_pass2((Node *) root->parse->jointree,
+                                                        state, root, NULL);
 }
 
 /*
@@ -650,13 +666,13 @@ reduce_outer_joins_pass1(Node *jtnode)
  *
  *     jtnode: current jointree node
  *     state: state data collected by phase 1 for this node
- *     parse: toplevel Query
+ *     root: toplevel planner state
  *     nonnullable_rels: set of base relids forced non-null by upper quals
  */
 static void
 reduce_outer_joins_pass2(Node *jtnode,
                                                 reduce_outer_joins_state *state,
-                                                Query *parse,
+                                                PlannerInfo *root,
                                                 Relids nonnullable_rels)
 {
        /*
@@ -685,7 +701,7 @@ reduce_outer_joins_pass2(Node *jtnode,
                        reduce_outer_joins_state *sub_state = lfirst(s);
 
                        if (sub_state->contains_outer)
-                               reduce_outer_joins_pass2(lfirst(l), sub_state, parse,
+                               reduce_outer_joins_pass2(lfirst(l), sub_state, root,
                                                                                 pass_nonnullable);
                }
                bms_free(pass_nonnullable);
@@ -729,7 +745,7 @@ reduce_outer_joins_pass2(Node *jtnode,
                if (jointype != j->jointype)
                {
                        /* apply the change to both jointree node and RTE */
-                       RangeTblEntry *rte = rt_fetch(rtindex, parse->rtable);
+                       RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
 
                        Assert(rte->rtekind == RTE_JOIN);
                        Assert(rte->jointype == j->jointype);
@@ -767,7 +783,7 @@ reduce_outer_joins_pass2(Node *jtnode,
                                        pass_nonnullable = local_nonnullable;
                                else
                                        pass_nonnullable = nonnullable_rels;
-                               reduce_outer_joins_pass2(j->larg, left_state, parse,
+                               reduce_outer_joins_pass2(j->larg, left_state, root,
                                                                                 pass_nonnullable);
                        }
                        if (right_state->contains_outer)
@@ -776,7 +792,7 @@ reduce_outer_joins_pass2(Node *jtnode,
                                        pass_nonnullable = local_nonnullable;
                                else
                                        pass_nonnullable = nonnullable_rels;
-                               reduce_outer_joins_pass2(j->rarg, right_state, parse,
+                               reduce_outer_joins_pass2(j->rarg, right_state, root,
                                                                                 pass_nonnullable);
                        }
                        bms_free(local_nonnullable);
@@ -909,7 +925,7 @@ find_nonnullable_rels(Node *node, bool top_level)
  * work reliably --- see comments for pull_up_subqueries().
  */
 Node *
-simplify_jointree(Query *parse, Node *jtnode)
+simplify_jointree(PlannerInfo *root, Node *jtnode)
 {
        if (jtnode == NULL)
                return NULL;
@@ -931,7 +947,7 @@ simplify_jointree(Query *parse, Node *jtnode)
 
                        children_remaining--;
                        /* Recursively simplify this child... */
-                       child = simplify_jointree(parse, child);
+                       child = simplify_jointree(root, child);
                        /* Now, is it a FromExpr? */
                        if (child && IsA(child, FromExpr))
                        {
@@ -972,8 +988,8 @@ simplify_jointree(Query *parse, Node *jtnode)
                JoinExpr   *j = (JoinExpr *) jtnode;
 
                /* Recursively simplify the children... */
-               j->larg = simplify_jointree(parse, j->larg);
-               j->rarg = simplify_jointree(parse, j->rarg);
+               j->larg = simplify_jointree(root, j->larg);
+               j->rarg = simplify_jointree(root, j->rarg);
 
                /*
                 * If it is an outer join, we must not flatten it.      An inner join
@@ -1115,11 +1131,12 @@ get_relids_in_jointree(Node *jtnode)
  * since that may eliminate join nodes from the jointree.
  */
 Relids
-get_relids_for_join(Query *parse, int joinrelid)
+get_relids_for_join(PlannerInfo *root, int joinrelid)
 {
        Node       *jtnode;
 
-       jtnode = find_jointree_node_for_rel((Node *) parse->jointree, joinrelid);
+       jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,
+                                                                               joinrelid);
        if (!jtnode)
                elog(ERROR, "could not find join node %d", joinrelid);
        return get_relids_in_jointree(jtnode);
index 22334e238f51c275539d773d8c1344a361e140ab..fa56c5fc29c5ab72ba93340b2b0017a9436d91f1 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.76 2005/05/23 03:01:13 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.77 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -43,8 +43,9 @@ static List *expand_targetlist(List *tlist, int command_type,
  *       Returns the new targetlist.
  */
 List *
-preprocess_targetlist(Query *parse, List *tlist)
+preprocess_targetlist(PlannerInfo *root, List *tlist)
 {
+       Query  *parse = root->parse;
        int             result_relation = parse->resultRelation;
        List   *range_table = parse->rtable;
        CmdType command_type = parse->commandType;
index 0f532a99453f1047f5fd4d1965d249154a6603df..e7aee1d52ab6f5639fe328256a45f2654541dc8c 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.121 2005/05/22 22:30:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.122 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -49,15 +49,15 @@ typedef struct
        char       *new_rel_name;
 } adjust_inherited_attrs_context;
 
-static Plan *recurse_set_operations(Node *setOp, Query *parse,
+static Plan *recurse_set_operations(Node *setOp, PlannerInfo *root,
                                           List *colTypes, bool junkOK,
                                           int flag, List *refnames_tlist,
                                           List **sortClauses);
-static Plan *generate_union_plan(SetOperationStmt *op, Query *parse,
+static Plan *generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
                                        List *refnames_tlist, List **sortClauses);
-static Plan *generate_nonunion_plan(SetOperationStmt *op, Query *parse,
+static Plan *generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
                                           List *refnames_tlist, List **sortClauses);
-static List *recurse_union_children(Node *setOp, Query *parse,
+static List *recurse_union_children(Node *setOp, PlannerInfo *root,
                                           SetOperationStmt *top_union,
                                           List *refnames_tlist);
 static List *generate_setop_tlist(List *colTypes, int flag,
@@ -82,15 +82,16 @@ static List *adjust_inherited_tlist(List *tlist,
  *       Plans the queries for a tree of set operations (UNION/INTERSECT/EXCEPT)
  *
  * This routine only deals with the setOperations tree of the given query.
- * Any top-level ORDER BY requested in parse->sortClause will be added
+ * Any top-level ORDER BY requested in root->parse->sortClause will be added
  * when we return to grouping_planner.
  *
  * *sortClauses is an output argument: it is set to a list of SortClauses
  * representing the result ordering of the topmost set operation.
  */
 Plan *
-plan_set_operations(Query *parse, List **sortClauses)
+plan_set_operations(PlannerInfo *root, List **sortClauses)
 {
+       Query      *parse = root->parse;
        SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
        Node       *node;
        Query      *leftmostQuery;
@@ -123,7 +124,7 @@ plan_set_operations(Query *parse, List **sortClauses)
         * output from the top-level node, plus possibly resjunk working
         * columns (we can rely on upper-level nodes to deal with that).
         */
-       return recurse_set_operations((Node *) topop, parse,
+       return recurse_set_operations((Node *) topop, root,
                                                                  topop->colTypes, true, -1,
                                                                  leftmostQuery->targetList,
                                                                  sortClauses);
@@ -140,7 +141,7 @@ plan_set_operations(Query *parse, List **sortClauses)
  * *sortClauses: receives list of SortClauses for result plan, if any
  */
 static Plan *
-recurse_set_operations(Node *setOp, Query *parse,
+recurse_set_operations(Node *setOp, PlannerInfo *root,
                                           List *colTypes, bool junkOK,
                                           int flag, List *refnames_tlist,
                                           List **sortClauses)
@@ -148,7 +149,7 @@ recurse_set_operations(Node *setOp, Query *parse,
        if (IsA(setOp, RangeTblRef))
        {
                RangeTblRef *rtr = (RangeTblRef *) setOp;
-               RangeTblEntry *rte = rt_fetch(rtr->rtindex, parse->rtable);
+               RangeTblEntry *rte = rt_fetch(rtr->rtindex, root->parse->rtable);
                Query      *subquery = rte->subquery;
                Plan       *subplan,
                                   *plan;
@@ -158,7 +159,7 @@ recurse_set_operations(Node *setOp, Query *parse,
                /*
                 * Generate plan for primitive subquery
                 */
-               subplan = subquery_planner(subquery, 0.0 /* default case */ );
+               subplan = subquery_planner(subquery, 0.0 /* default case */, NULL);
 
                /*
                 * Add a SubqueryScan with the caller-requested targetlist
@@ -188,10 +189,10 @@ recurse_set_operations(Node *setOp, Query *parse,
 
                /* UNIONs are much different from INTERSECT/EXCEPT */
                if (op->op == SETOP_UNION)
-                       plan = generate_union_plan(op, parse, refnames_tlist,
+                       plan = generate_union_plan(op, root, refnames_tlist,
                                                                           sortClauses);
                else
-                       plan = generate_nonunion_plan(op, parse, refnames_tlist,
+                       plan = generate_nonunion_plan(op, root, refnames_tlist,
                                                                                  sortClauses);
 
                /*
@@ -233,7 +234,7 @@ recurse_set_operations(Node *setOp, Query *parse,
  * Generate plan for a UNION or UNION ALL node
  */
 static Plan *
-generate_union_plan(SetOperationStmt *op, Query *parse,
+generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
                                        List *refnames_tlist,
                                        List **sortClauses)
 {
@@ -247,9 +248,9 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
         * generate only one Append and Sort for the lot.  Recurse to find
         * such nodes and compute their children's plans.
         */
-       planlist = list_concat(recurse_union_children(op->larg, parse,
+       planlist = list_concat(recurse_union_children(op->larg, root,
                                                                                                  op, refnames_tlist),
-                                                  recurse_union_children(op->rarg, parse,
+                                                  recurse_union_children(op->rarg, root,
                                                                                                  op, refnames_tlist));
 
        /*
@@ -278,7 +279,7 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
                sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
                if (sortList)
                {
-                       plan = (Plan *) make_sort_from_sortclauses(parse, sortList, plan);
+                       plan = (Plan *) make_sort_from_sortclauses(root, sortList, plan);
                        plan = (Plan *) make_unique(plan, sortList);
                }
                *sortClauses = sortList;
@@ -293,7 +294,7 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
  * Generate plan for an INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL node
  */
 static Plan *
-generate_nonunion_plan(SetOperationStmt *op, Query *parse,
+generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
                                           List *refnames_tlist,
                                           List **sortClauses)
 {
@@ -307,11 +308,11 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
        SetOpCmd        cmd;
 
        /* Recurse on children, ensuring their outputs are marked */
-       lplan = recurse_set_operations(op->larg, parse,
+       lplan = recurse_set_operations(op->larg, root,
                                                                   op->colTypes, false, 0,
                                                                   refnames_tlist,
                                                                   &child_sortclauses);
-       rplan = recurse_set_operations(op->rarg, parse,
+       rplan = recurse_set_operations(op->rarg, root,
                                                                   op->colTypes, false, 1,
                                                                   refnames_tlist,
                                                                   &child_sortclauses);
@@ -346,7 +347,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
                return plan;
        }
 
-       plan = (Plan *) make_sort_from_sortclauses(parse, sortList, plan);
+       plan = (Plan *) make_sort_from_sortclauses(root, sortList, plan);
        switch (op->op)
        {
                case SETOP_INTERSECT:
@@ -375,7 +376,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
  * output rows will be lost anyway.
  */
 static List *
-recurse_union_children(Node *setOp, Query *parse,
+recurse_union_children(Node *setOp, PlannerInfo *root,
                                           SetOperationStmt *top_union,
                                           List *refnames_tlist)
 {
@@ -390,10 +391,10 @@ recurse_union_children(Node *setOp, Query *parse,
                        equal(op->colTypes, top_union->colTypes))
                {
                        /* Same UNION, so fold children into parent's subplan list */
-                       return list_concat(recurse_union_children(op->larg, parse,
+                       return list_concat(recurse_union_children(op->larg, root,
                                                                                                          top_union,
                                                                                                          refnames_tlist),
-                                                          recurse_union_children(op->rarg, parse,
+                                                          recurse_union_children(op->rarg, root,
                                                                                                          top_union,
                                                                                                          refnames_tlist));
                }
@@ -409,7 +410,7 @@ recurse_union_children(Node *setOp, Query *parse,
         * we have an EXCEPT or INTERSECT as child, else there won't be
         * resjunk anyway.
         */
-       return list_make1(recurse_set_operations(setOp, parse,
+       return list_make1(recurse_set_operations(setOp, root,
                                                                                         top_union->colTypes, false,
                                                                                         -1, refnames_tlist,
                                                                                         &child_sortclauses));
@@ -724,8 +725,9 @@ find_all_inheritors(Oid parentrel)
  * trying to avoid.
  */
 List *
-expand_inherited_rtentry(Query *parse, Index rti)
+expand_inherited_rtentry(PlannerInfo *root, Index rti)
 {
+       Query      *parse = root->parse;
        RangeTblEntry *rte = rt_fetch(rti, parse->rtable);
        Oid                     parentOID;
        List       *inhOIDs;
index 429e5d2495cda6c3c06fd75ab6903c677f0b9e08..5663cce6e8d3c6ef39465d2962a8cd1f37147c15 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.197 2005/05/22 22:30:20 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.198 2005/06/05 22:32:56 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -3040,8 +3040,6 @@ query_tree_walker(Query *query,
                return true;
        if (walker(query->limitCount, context))
                return true;
-       if (walker(query->in_info_list, context))
-               return true;
        if (range_table_walker(query->rtable, walker, context, flags))
                return true;
        return false;
@@ -3564,7 +3562,6 @@ query_tree_mutator(Query *query,
        MUTATE(query->havingQual, query->havingQual, Node *);
        MUTATE(query->limitOffset, query->limitOffset, Node *);
        MUTATE(query->limitCount, query->limitCount, Node *);
-       MUTATE(query->in_info_list, query->in_info_list, List *);
        query->rtable = range_table_mutator(query->rtable,
                                                                                mutator, context, flags);
        return query;
index 8a19892750cf6eee7ae0dc3c8ae804208858681f..b49ead13163710aab472602758abb6cb644c8e90 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/joininfo.c,v 1.41 2004/12/31 22:00:23 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/joininfo.c,v 1.42 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -82,7 +82,7 @@ make_joininfo_node(RelOptInfo *this_rel, Relids join_relids)
  *                              (there must be more than one)
  */
 void
-add_join_clause_to_rels(Query *root,
+add_join_clause_to_rels(PlannerInfo *root,
                                                RestrictInfo *restrictinfo,
                                                Relids join_relids)
 {
@@ -131,7 +131,7 @@ add_join_clause_to_rels(Query *root,
  *                              (there must be more than one)
  */
 void
-remove_join_clause_from_rels(Query *root,
+remove_join_clause_from_rels(PlannerInfo *root,
                                                         RestrictInfo *restrictinfo,
                                                         Relids join_relids)
 {
index cf5438f06c5992225d42679f0b8a1d98465af065..4c52561521794e08b51fdbd073641e44e0cdb5ea 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.121 2005/06/03 19:00:12 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.122 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -415,7 +415,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
  *       pathnode.
  */
 Path *
-create_seqscan_path(Query *root, RelOptInfo *rel)
+create_seqscan_path(PlannerInfo *root, RelOptInfo *rel)
 {
        Path       *pathnode = makeNode(Path);
 
@@ -445,7 +445,7 @@ create_seqscan_path(Query *root, RelOptInfo *rel)
  * Returns the new path node.
  */
 IndexPath *
-create_index_path(Query *root,
+create_index_path(PlannerInfo *root,
                                  IndexOptInfo *index,
                                  List *clause_groups,
                                  List *pathkeys,
@@ -537,7 +537,7 @@ create_index_path(Query *root,
  * 'bitmapqual' is a tree of IndexPath, BitmapAndPath, and BitmapOrPath nodes.
  */
 BitmapHeapPath *
-create_bitmap_heap_path(Query *root,
+create_bitmap_heap_path(PlannerInfo *root,
                                                RelOptInfo *rel,
                                                Path *bitmapqual,
                                                bool isjoininner)
@@ -590,7 +590,7 @@ create_bitmap_heap_path(Query *root,
  *       Creates a path node representing a BitmapAnd.
  */
 BitmapAndPath *
-create_bitmap_and_path(Query *root,
+create_bitmap_and_path(PlannerInfo *root,
                                           RelOptInfo *rel,
                                           List *bitmapquals)
 {
@@ -613,7 +613,7 @@ create_bitmap_and_path(Query *root,
  *       Creates a path node representing a BitmapOr.
  */
 BitmapOrPath *
-create_bitmap_or_path(Query *root,
+create_bitmap_or_path(PlannerInfo *root,
                                          RelOptInfo *rel,
                                          List *bitmapquals)
 {
@@ -637,7 +637,7 @@ create_bitmap_or_path(Query *root,
  *       pathnode.
  */
 TidPath *
-create_tidscan_path(Query *root, RelOptInfo *rel, List *tideval)
+create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tideval)
 {
        TidPath    *pathnode = makeNode(TidPath);
 
@@ -759,7 +759,7 @@ create_material_path(RelOptInfo *rel, Path *subpath)
  * for the rel).  So we cache the result.
  */
 UniquePath *
-create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
+create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath)
 {
        UniquePath *pathnode;
        Path            sort_path;              /* dummy for result of cost_sort */
@@ -805,7 +805,7 @@ create_unique_path(Query *root, RelOptInfo *rel, Path *subpath)
         */
        if (rel->rtekind == RTE_SUBQUERY)
        {
-               RangeTblEntry *rte = rt_fetch(rel->relid, root->rtable);
+               RangeTblEntry *rte = rt_fetch(rel->relid, root->parse->rtable);
 
                if (is_distinct_query(rte->subquery))
                {
@@ -1029,7 +1029,7 @@ create_subqueryscan_path(RelOptInfo *rel, List *pathkeys)
  *       returning the pathnode.
  */
 Path *
-create_functionscan_path(Query *root, RelOptInfo *rel)
+create_functionscan_path(PlannerInfo *root, RelOptInfo *rel)
 {
        Path       *pathnode = makeNode(Path);
 
@@ -1057,7 +1057,7 @@ create_functionscan_path(Query *root, RelOptInfo *rel)
  * Returns the resulting path node.
  */
 NestPath *
-create_nestloop_path(Query *root,
+create_nestloop_path(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         JoinType jointype,
                                         Path *outer_path,
@@ -1097,7 +1097,7 @@ create_nestloop_path(Query *root,
  * 'innersortkeys' are the sort varkeys for the inner relation
  */
 MergePath *
-create_mergejoin_path(Query *root,
+create_mergejoin_path(PlannerInfo *root,
                                          RelOptInfo *joinrel,
                                          JoinType jointype,
                                          Path *outer_path,
@@ -1166,7 +1166,7 @@ create_mergejoin_path(Query *root,
  *             (this should be a subset of the restrict_clauses list)
  */
 HashPath *
-create_hashjoin_path(Query *root,
+create_hashjoin_path(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         JoinType jointype,
                                         Path *outer_path,
index a86bdbfb61dcff0956150a3a96c5c72058f7aca8..a8dcdae9a2ff828381dc0220d8ef73d1452c3ebd 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.110 2005/06/04 19:19:42 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.111 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -379,11 +379,11 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
  * nodes.
  */
 List *
-build_physical_tlist(Query *root, RelOptInfo *rel)
+build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
 {
        List       *tlist = NIL;
        Index           varno = rel->relid;
-       RangeTblEntry *rte = rt_fetch(varno, root->rtable);
+       RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
        Relation        relation;
        Query      *subquery;
        Var                *var;
@@ -494,7 +494,7 @@ build_physical_tlist(Query *root, RelOptInfo *rel)
  * See clause_selectivity() for the meaning of the additional parameters.
  */
 Selectivity
-restriction_selectivity(Query *root,
+restriction_selectivity(PlannerInfo *root,
                                                Oid operator,
                                                List *args,
                                                int varRelid)
@@ -529,7 +529,7 @@ restriction_selectivity(Query *root,
  * operator relation, by calling the function manager.
  */
 Selectivity
-join_selectivity(Query *root,
+join_selectivity(PlannerInfo *root,
                                 Oid operator,
                                 List *args,
                                 JoinType jointype)
index f679768cfe9c3f697fe85ab3023a444fceaa8b14..5a39bf3f05138a5bfbcb17e1960cd1228b9b5e7e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.66 2005/05/23 03:01:14 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.67 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "parser/parsetree.h"
 
 
-static RelOptInfo *make_reloptinfo(Query *root, int relid,
+static RelOptInfo *make_reloptinfo(PlannerInfo *root, int relid,
                                                                   RelOptKind reloptkind);
-static void build_joinrel_tlist(Query *root, RelOptInfo *joinrel);
-static List *build_joinrel_restrictlist(Query *root,
+static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel);
+static List *build_joinrel_restrictlist(PlannerInfo *root,
                                                   RelOptInfo *joinrel,
                                                   RelOptInfo *outer_rel,
                                                   RelOptInfo *inner_rel,
@@ -46,7 +46,7 @@ static void subbuild_joinrel_joinlist(RelOptInfo *joinrel,
  *       base_rel_list.
  */
 void
-build_base_rel(Query *root, int relid)
+build_base_rel(PlannerInfo *root, int relid)
 {
        ListCell   *l;
        RelOptInfo *rel;
@@ -81,7 +81,7 @@ build_base_rel(Query *root, int relid)
  *       base relations except that they live in a different list.
  */
 RelOptInfo *
-build_other_rel(Query *root, int relid)
+build_other_rel(PlannerInfo *root, int relid)
 {
        ListCell   *l;
        RelOptInfo *rel;
@@ -119,10 +119,10 @@ build_other_rel(Query *root, int relid)
  * Common code for build_base_rel and build_other_rel.
  */
 static RelOptInfo *
-make_reloptinfo(Query *root, int relid, RelOptKind reloptkind)
+make_reloptinfo(PlannerInfo *root, int relid, RelOptKind reloptkind)
 {
        RelOptInfo *rel = makeNode(RelOptInfo);
-       RangeTblEntry *rte = rt_fetch(relid, root->rtable);
+       RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
 
        rel->reloptkind = reloptkind;
        rel->relids = bms_make_singleton(relid);
@@ -181,7 +181,7 @@ make_reloptinfo(Query *root, int relid, RelOptKind reloptkind)
  *       (since we'd have no idea which list to add it to).
  */
 RelOptInfo *
-find_base_rel(Query *root, int relid)
+find_base_rel(PlannerInfo *root, int relid)
 {
        ListCell   *l;
        RelOptInfo *rel;
@@ -211,7 +211,7 @@ find_base_rel(Query *root, int relid)
  *       or NULL if none exists.  This is for join relations.
  */
 RelOptInfo *
-find_join_rel(Query *root, Relids relids)
+find_join_rel(PlannerInfo *root, Relids relids)
 {
        ListCell   *l;
 
@@ -243,7 +243,7 @@ find_join_rel(Query *root, Relids relids)
  * duplicated calculation of the restrictlist...
  */
 RelOptInfo *
-build_join_rel(Query *root,
+build_join_rel(PlannerInfo *root,
                           Relids joinrelids,
                           RelOptInfo *outer_rel,
                           RelOptInfo *inner_rel,
@@ -356,7 +356,7 @@ build_join_rel(Query *root,
  * of data that was cached at the baserel level by set_rel_width().
  */
 static void
-build_joinrel_tlist(Query *root, RelOptInfo *joinrel)
+build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel)
 {
        Relids          relids = joinrel->relids;
        ListCell   *rels;
@@ -433,7 +433,7 @@ build_joinrel_tlist(Query *root, RelOptInfo *joinrel)
  * the original nodes in the lists made for the join relation.
  */
 static List *
-build_joinrel_restrictlist(Query *root,
+build_joinrel_restrictlist(PlannerInfo *root,
                                                   RelOptInfo *joinrel,
                                                   RelOptInfo *outer_rel,
                                                   RelOptInfo *inner_rel,
index e19a308cdf43dbee2dc954e51f45906d5d355001..460ccc9546dc4efbbe39018613e4a113d31876d8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.35 2005/04/25 02:14:47 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.36 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,7 @@ static RestrictInfo *make_restrictinfo_internal(Expr *clause,
 static Expr *make_sub_restrictinfos(Expr *clause,
                                           bool is_pushed_down,
                                           bool valid_everywhere);
-static RestrictInfo *join_clause_is_redundant(Query *root,
+static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
                                                 RestrictInfo *rinfo,
                                                 List *reference_list,
                                                 bool isouterjoin);
@@ -354,7 +354,7 @@ get_actual_join_clauses(List *restrictinfo_list,
  * as were in the input.
  */
 List *
-remove_redundant_join_clauses(Query *root, List *restrictinfo_list,
+remove_redundant_join_clauses(PlannerInfo *root, List *restrictinfo_list,
                                                          bool isouterjoin)
 {
        List       *result = NIL;
@@ -415,7 +415,7 @@ remove_redundant_join_clauses(Query *root, List *restrictinfo_list,
  * for local redundancies, so we don't check again.
  */
 List *
-select_nonredundant_join_clauses(Query *root,
+select_nonredundant_join_clauses(PlannerInfo *root,
                                                                 List *restrictinfo_list,
                                                                 List *reference_list,
                                                                 bool isouterjoin)
@@ -467,7 +467,7 @@ select_nonredundant_join_clauses(Query *root,
  * joined rows after addition of null fill rows, and the other doesn't.
  */
 static RestrictInfo *
-join_clause_is_redundant(Query *root,
+join_clause_is_redundant(PlannerInfo *root,
                                                 RestrictInfo *rinfo,
                                                 List *reference_list,
                                                 bool isouterjoin)
index a95f7dcd76325889613937d3fa26d30939f729c5..abd01ca157af5d0a0824afe1486cc59de62b97e9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.64 2005/06/03 23:05:28 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.65 2005/06/05 22:32:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -49,7 +49,7 @@ typedef struct
 
 typedef struct
 {
-       Query      *root;
+       PlannerInfo *root;
        int                     sublevels_up;
 } flatten_join_alias_vars_context;
 
@@ -66,7 +66,7 @@ static bool pull_var_clause_walker(Node *node,
                                           pull_var_clause_context *context);
 static Node *flatten_join_alias_vars_mutator(Node *node,
                                                                flatten_join_alias_vars_context *context);
-static Relids alias_relid_set(Query *root, Relids relids);
+static Relids alias_relid_set(PlannerInfo *root, Relids relids);
 
 
 /*
@@ -482,7 +482,7 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
  * to be applied directly to a Query node.
  */
 Node *
-flatten_join_alias_vars(Query *root, Node *node)
+flatten_join_alias_vars(PlannerInfo *root, Node *node)
 {
        flatten_join_alias_vars_context context;
 
@@ -507,7 +507,7 @@ flatten_join_alias_vars_mutator(Node *node,
                /* No change unless Var belongs to a JOIN of the target level */
                if (var->varlevelsup != context->sublevels_up)
                        return node;            /* no need to copy, really */
-               rte = rt_fetch(var->varno, context->root->rtable);
+               rte = rt_fetch(var->varno, context->root->parse->rtable);
                if (rte->rtekind != RTE_JOIN)
                        return node;
                if (var->varattno == InvalidAttrNumber)
@@ -608,7 +608,7 @@ flatten_join_alias_vars_mutator(Node *node,
  * underlying base relids
  */
 static Relids
-alias_relid_set(Query *root, Relids relids)
+alias_relid_set(PlannerInfo *root, Relids relids)
 {
        Relids          result = NULL;
        Relids          tmprelids;
@@ -617,7 +617,7 @@ alias_relid_set(Query *root, Relids relids)
        tmprelids = bms_copy(relids);
        while ((rtindex = bms_first_member(tmprelids)) >= 0)
        {
-               RangeTblEntry *rte = rt_fetch(rtindex, root->rtable);
+               RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
 
                if (rte->rtekind == RTE_JOIN)
                        result = bms_join(result, get_relids_for_join(root, rtindex));
index 18a42c5742b2f6ab4b91833c675a5b3a1cd6f9db..799bacd233e27fc67f24abf6c6f10974b0f7cf4e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.68 2005/03/29 00:17:04 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.69 2005/06/05 22:32:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -101,6 +101,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
        bool            have_non_var_grouping;
        ListCell   *l;
        bool            hasJoinRTEs;
+       PlannerInfo *root;
        Node       *clause;
 
        /* This should only be called if we found aggregates or grouping */
@@ -162,9 +163,22 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
                }
        }
 
+       /*
+        * We use the planner's flatten_join_alias_vars routine to do the
+        * flattening; it wants a PlannerInfo root node, which fortunately
+        * can be mostly dummy.
+        */
        if (hasJoinRTEs)
-               groupClauses = (List *) flatten_join_alias_vars(qry,
+       {
+               root = makeNode(PlannerInfo);
+               root->parse = qry;
+               root->hasJoinRTEs = true;
+
+               groupClauses = (List *) flatten_join_alias_vars(root,
                                                                                                  (Node *) groupClauses);
+       }
+       else
+               root = NULL;                    /* keep compiler quiet */
 
        /*
         * Detect whether any of the grouping expressions aren't simple Vars;
@@ -186,13 +200,13 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
         */
        clause = (Node *) qry->targetList;
        if (hasJoinRTEs)
-               clause = flatten_join_alias_vars(qry, clause);
+               clause = flatten_join_alias_vars(root, clause);
        check_ungrouped_columns(clause, pstate,
                                                        groupClauses, have_non_var_grouping);
 
        clause = (Node *) qry->havingQual;
        if (hasJoinRTEs)
-               clause = flatten_join_alias_vars(qry, clause);
+               clause = flatten_join_alias_vars(root, clause);
        check_ungrouped_columns(clause, pstate,
                                                        groupClauses, have_non_var_grouping);
 }
index d2b22d30eb67cc0a59768f084a0587de173c2868..12157fb4d9dac387a68120a1efe9e62d5852eaf9 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.179 2005/06/01 17:05:11 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.180 2005/06/05 22:32:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,7 +38,7 @@
  *
  * The call convention for a restriction estimator (oprrest function) is
  *
- *             Selectivity oprrest (Query *root,
+ *             Selectivity oprrest (PlannerInfo *root,
  *                                                      Oid operator,
  *                                                      List *args,
  *                                                      int varRelid);
@@ -59,7 +59,7 @@
  * except that varRelid is not needed, and instead the join type is
  * supplied:
  *
- *             Selectivity oprjoin (Query *root,
+ *             Selectivity oprjoin (PlannerInfo *root,
  *                                                      Oid operator,
  *                                                      List *args,
  *                                                      JoinType jointype);
@@ -152,18 +152,18 @@ static double convert_one_bytea_to_scalar(unsigned char *value, int valuelen,
                                                        int rangelo, int rangehi);
 static unsigned char *convert_string_datum(Datum value, Oid typid);
 static double convert_timevalue_to_scalar(Datum value, Oid typid);
-static bool get_restriction_variable(Query *root, List *args, int varRelid,
+static bool get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
                                                 VariableStatData *vardata, Node **other,
                                                 bool *varonleft);
-static void get_join_variables(Query *root, List *args,
+static void get_join_variables(PlannerInfo *root, List *args,
                                   VariableStatData *vardata1,
                                   VariableStatData *vardata2);
-static void examine_variable(Query *root, Node *node, int varRelid,
+static void examine_variable(PlannerInfo *root, Node *node, int varRelid,
                                 VariableStatData *vardata);
 static double get_variable_numdistinct(VariableStatData *vardata);
-static bool get_variable_maximum(Query *root, VariableStatData *vardata,
+static bool get_variable_maximum(PlannerInfo *root, VariableStatData *vardata,
                                         Oid sortop, Datum *max);
-static Selectivity prefix_selectivity(Query *root, Node *variable,
+static Selectivity prefix_selectivity(PlannerInfo *root, Node *variable,
                                   Oid opclass, Const *prefix);
 static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
 static Datum string_to_datum(const char *str, Oid datatype);
@@ -182,7 +182,7 @@ static Const *string_to_bytea_const(const char *str, size_t str_len);
 Datum
 eqsel(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        Oid                     operator = PG_GETARG_OID(1);
        List       *args = (List *) PG_GETARG_POINTER(2);
        int                     varRelid = PG_GETARG_INT32(3);
@@ -377,7 +377,7 @@ eqsel(PG_FUNCTION_ARGS)
 Datum
 neqsel(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        Oid                     operator = PG_GETARG_OID(1);
        List       *args = (List *) PG_GETARG_POINTER(2);
        int                     varRelid = PG_GETARG_INT32(3);
@@ -420,7 +420,7 @@ neqsel(PG_FUNCTION_ARGS)
  * it will return a default estimate.
  */
 static double
-scalarineqsel(Query *root, Oid operator, bool isgt,
+scalarineqsel(PlannerInfo *root, Oid operator, bool isgt,
                          VariableStatData *vardata, Datum constval, Oid consttype)
 {
        Form_pg_statistic stats;
@@ -652,7 +652,7 @@ scalarineqsel(Query *root, Oid operator, bool isgt,
 Datum
 scalarltsel(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        Oid                     operator = PG_GETARG_OID(1);
        List       *args = (List *) PG_GETARG_POINTER(2);
        int                     varRelid = PG_GETARG_INT32(3);
@@ -728,7 +728,7 @@ scalarltsel(PG_FUNCTION_ARGS)
 Datum
 scalargtsel(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        Oid                     operator = PG_GETARG_OID(1);
        List       *args = (List *) PG_GETARG_POINTER(2);
        int                     varRelid = PG_GETARG_INT32(3);
@@ -804,7 +804,7 @@ scalargtsel(PG_FUNCTION_ARGS)
 static double
 patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
 
 #ifdef NOT_USED
        Oid                     operator = PG_GETARG_OID(1);
@@ -1073,7 +1073,7 @@ icnlikesel(PG_FUNCTION_ARGS)
  *             booltestsel             - Selectivity of BooleanTest Node.
  */
 Selectivity
-booltestsel(Query *root, BoolTestType booltesttype, Node *arg,
+booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg,
                        int varRelid, JoinType jointype)
 {
        VariableStatData vardata;
@@ -1238,7 +1238,8 @@ booltestsel(Query *root, BoolTestType booltesttype, Node *arg,
  *             nulltestsel             - Selectivity of NullTest Node.
  */
 Selectivity
-nulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid)
+nulltestsel(PlannerInfo *root, NullTestType nulltesttype,
+                       Node *arg, int varRelid)
 {
        VariableStatData vardata;
        double          selec;
@@ -1310,7 +1311,7 @@ nulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid)
 Datum
 eqjoinsel(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        Oid                     operator = PG_GETARG_OID(1);
        List       *args = (List *) PG_GETARG_POINTER(2);
        JoinType        jointype = (JoinType) PG_GETARG_INT16(3);
@@ -1570,7 +1571,7 @@ eqjoinsel(PG_FUNCTION_ARGS)
 Datum
 neqjoinsel(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        Oid                     operator = PG_GETARG_OID(1);
        List       *args = (List *) PG_GETARG_POINTER(2);
        JoinType        jointype = (JoinType) PG_GETARG_INT16(3);
@@ -1720,7 +1721,7 @@ icnlikejoinsel(PG_FUNCTION_ARGS)
  * variable.
  */
 void
-mergejoinscansel(Query *root, Node *clause,
+mergejoinscansel(PlannerInfo *root, Node *clause,
                                 Selectivity *leftscan,
                                 Selectivity *rightscan)
 {
@@ -1841,7 +1842,7 @@ typedef struct
 } GroupVarInfo;
 
 static List *
-add_unique_group_var(Query *root, List *varinfos,
+add_unique_group_var(PlannerInfo *root, List *varinfos,
                                         Node *var, VariableStatData *vardata)
 {
        GroupVarInfo *varinfo;
@@ -1953,7 +1954,7 @@ add_unique_group_var(Query *root, List *varinfos,
  * do better).
  */
 double
-estimate_num_groups(Query *root, List *groupExprs, double input_rows)
+estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows)
 {
        List       *varinfos = NIL;
        double          numdistinct;
@@ -2151,7 +2152,7 @@ estimate_num_groups(Query *root, List *groupExprs, double input_rows)
  * inner rel is well-dispersed (or the alternatives seem much worse).
  */
 Selectivity
-estimate_hash_bucketsize(Query *root, Node *hashkey, double nbuckets)
+estimate_hash_bucketsize(PlannerInfo *root, Node *hashkey, double nbuckets)
 {
        VariableStatData vardata;
        double          estfract,
@@ -2840,7 +2841,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
  *             and also indicate which side it was on and the other argument.
  *
  * Inputs:
- *     root: the Query
+ *     root: the planner info
  *     args: clause argument list
  *     varRelid: see specs for restriction selectivity functions
  *
@@ -2855,7 +2856,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
  * callers are expecting that the other side will act like a pseudoconstant.
  */
 static bool
-get_restriction_variable(Query *root, List *args, int varRelid,
+get_restriction_variable(PlannerInfo *root, List *args, int varRelid,
                                                 VariableStatData *vardata, Node **other,
                                                 bool *varonleft)
 {
@@ -2909,7 +2910,7 @@ get_restriction_variable(Query *root, List *args, int varRelid,
  *             Apply examine_variable() to each side of a join clause.
  */
 static void
-get_join_variables(Query *root, List *args,
+get_join_variables(PlannerInfo *root, List *args,
                                   VariableStatData *vardata1, VariableStatData *vardata2)
 {
        Node       *left,
@@ -2931,7 +2932,7 @@ get_join_variables(Query *root, List *args,
  *             Fill in a VariableStatData struct to describe the expression.
  *
  * Inputs:
- *     root: the Query
+ *     root: the planner info
  *     node: the expression tree to examine
  *     varRelid: see specs for restriction selectivity functions
  *
@@ -2952,7 +2953,7 @@ get_join_variables(Query *root, List *args,
  * Caller is responsible for doing ReleaseVariableStats() before exiting.
  */
 static void
-examine_variable(Query *root, Node *node, int varRelid,
+examine_variable(PlannerInfo *root, Node *node, int varRelid,
                                 VariableStatData *vardata)
 {
        Node       *basenode;
@@ -2985,7 +2986,7 @@ examine_variable(Query *root, Node *node, int varRelid,
                vardata->atttype = var->vartype;
                vardata->atttypmod = var->vartypmod;
 
-               relid = getrelid(var->varno, root->rtable);
+               relid = getrelid(var->varno, root->parse->rtable);
 
                if (OidIsValid(relid))
                {
@@ -3250,7 +3251,7 @@ get_variable_numdistinct(VariableStatData *vardata)
  * minimum instead of the maximum, just pass the ">" operator instead.)
  */
 static bool
-get_variable_maximum(Query *root, VariableStatData *vardata,
+get_variable_maximum(PlannerInfo *root, VariableStatData *vardata,
                                         Oid sortop, Datum *max)
 {
        Datum           tmax = 0;
@@ -3696,7 +3697,7 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
  * more useful to use the upper-bound code than not.
  */
 static Selectivity
-prefix_selectivity(Query *root, Node *variable,
+prefix_selectivity(PlannerInfo *root, Node *variable,
                                   Oid opclass, Const *prefixcon)
 {
        Selectivity prefixsel;
@@ -4198,7 +4199,7 @@ string_to_bytea_const(const char *str, size_t str_len)
  */
 
 static void
-genericcostestimate(Query *root,
+genericcostestimate(PlannerInfo *root,
                                        IndexOptInfo *index, List *indexQuals,
                                        Cost *indexStartupCost,
                                        Cost *indexTotalCost,
@@ -4327,7 +4328,7 @@ genericcostestimate(Query *root,
 Datum
 btcostestimate(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
        List       *indexQuals = (List *) PG_GETARG_POINTER(2);
        Cost       *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
@@ -4354,7 +4355,7 @@ btcostestimate(PG_FUNCTION_ARGS)
        if (index->indexkeys[0] != 0)
        {
                /* Simple variable --- look to stats for the underlying table */
-               relid = getrelid(index->rel->relid, root->rtable);
+               relid = getrelid(index->rel->relid, root->parse->rtable);
                Assert(relid != InvalidOid);
                colnum = index->indexkeys[0];
        }
@@ -4406,7 +4407,7 @@ btcostestimate(PG_FUNCTION_ARGS)
 Datum
 rtcostestimate(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
        List       *indexQuals = (List *) PG_GETARG_POINTER(2);
        Cost       *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
@@ -4424,7 +4425,7 @@ rtcostestimate(PG_FUNCTION_ARGS)
 Datum
 hashcostestimate(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
        List       *indexQuals = (List *) PG_GETARG_POINTER(2);
        Cost       *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
@@ -4442,7 +4443,7 @@ hashcostestimate(PG_FUNCTION_ARGS)
 Datum
 gistcostestimate(PG_FUNCTION_ARGS)
 {
-       Query      *root = (Query *) PG_GETARG_POINTER(0);
+       PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
        IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
        List       *indexQuals = (List *) PG_GETARG_POINTER(2);
        Cost       *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
index d69734f95e94a8689d274c90026e8b5c2a11ad1d..326e929d76fd6e26d0dc44552eace62293f9f686 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.168 2005/04/21 19:18:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.169 2005/06/05 22:32:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,7 +165,8 @@ typedef enum NodeTag
        /*
         * TAGS FOR PLANNER NODES (relation.h)
         */
-       T_RelOptInfo = 500,
+       T_PlannerInfo = 500,
+       T_RelOptInfo,
        T_IndexOptInfo,
        T_Path,
        T_IndexPath,
index 9a525eb1de0c86029aa2c44f799a7564b86a7bf0..04b32082ebf59fcd9c62b7f49215274a4827a542 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.280 2005/06/05 00:38:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.281 2005/06/05 22:32:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,8 +62,9 @@ typedef uint32 AclMode;                       /* a bitmask of privilege bits */
  * Query -
  *       all statements are turned into a Query tree (via transformStmt)
  *       for further processing by the optimizer
- *       utility statements (i.e. non-optimizable statements)
- *       have the *utilityStmt field set.
+ *
+ *       utility statements (i.e. non-optimizable statements) have the
+ *       utilityStmt field set, and the Query itself is mostly dummy.
  */
 typedef struct Query
 {
@@ -121,17 +122,6 @@ typedef struct Query
         * ought to go in some sort of TopPlan plan node, not in the Query.
         */
        List       *resultRelations;    /* integer list of RT indexes, or NIL */
-
-       /* internal to planner */
-       List       *base_rel_list;      /* list of base-relation RelOptInfos */
-       List       *other_rel_list; /* list of other 1-relation RelOptInfos */
-       List       *join_rel_list;      /* list of join-relation RelOptInfos */
-       List       *equi_key_list;      /* list of lists of equijoined
-                                                                * PathKeyItems */
-       List       *in_info_list;       /* list of InClauseInfos */
-       List       *query_pathkeys; /* desired pathkeys for query_planner() */
-       bool            hasJoinRTEs;    /* true if any RTEs are RTE_JOIN kind */
-       bool            hasHavingQual;  /* true if havingQual was non-null */
 } Query;
 
 
index 4618cf3a07e65d362b7ad06acacb6dbc5377b29a..4cbf285029c8f284e1d9805dbf4c69bbcb7d8368 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.109 2005/04/25 01:30:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.110 2005/06/05 22:32:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,6 +46,40 @@ typedef struct QualCost
        Cost            per_tuple;              /* per-evaluation cost */
 } QualCost;
 
+
+/*----------
+ * PlannerInfo
+ *             Per-query information for planning/optimization
+ *
+ * This struct is conventionally called "root" in all the planner routines.
+ * It holds links to all of the planner's working state, in addition to the
+ * original Query.  Note that at present the planner extensively manipulates
+ * the passed-in Query data structure; someday that should stop.
+ *----------
+ */
+typedef struct PlannerInfo
+{
+       NodeTag         type;
+
+       Query      *parse;                      /* the Query being planned */
+
+       List       *base_rel_list;      /* list of base-relation RelOptInfos */
+       List       *other_rel_list; /* list of other 1-relation RelOptInfos */
+       List       *join_rel_list;      /* list of join-relation RelOptInfos */
+
+       List       *equi_key_list;      /* list of lists of equijoined
+                                                                * PathKeyItems */
+
+       List       *in_info_list;       /* list of InClauseInfos */
+
+       List       *query_pathkeys; /* desired pathkeys for query_planner(),
+                                                                * and actual pathkeys afterwards */
+
+       bool            hasJoinRTEs;    /* true if any RTEs are RTE_JOIN kind */
+       bool            hasHavingQual;  /* true if havingQual was non-null */
+} PlannerInfo;
+
+
 /*----------
  * RelOptInfo
  *             Per-relation information for planning/optimization
@@ -55,7 +89,7 @@ typedef struct QualCost
  * In either case it is uniquely identified by an RT index.  A "joinrel"
  * is the joining of two or more base rels.  A joinrel is identified by
  * the set of RT indexes for its component baserels.  We create RelOptInfo
- * nodes for each baserel and joinrel, and store them in the Query's
+ * nodes for each baserel and joinrel, and store them in the PlannerInfo's
  * base_rel_list and join_rel_list respectively.
  *
  * Note that there is only one joinrel for any given set of component
@@ -778,7 +812,7 @@ typedef struct InnerIndexscanInfo
  * When we convert top-level IN quals into join operations, we must restrict
  * the order of joining and use special join methods at some join points.
  * We record information about each such IN clause in an InClauseInfo struct.
- * These structs are kept in the Query node's in_info_list.
+ * These structs are kept in the PlannerInfo node's in_info_list.
  */
 
 typedef struct InClauseInfo
index 0f9e56880d5f39b37d51d05cca9935fae6905d3c..5b6d28242538f6f3fe62657809ff938e96e6601f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.67 2005/04/22 21:58:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.68 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,53 +51,53 @@ extern bool enable_mergejoin;
 extern bool enable_hashjoin;
 
 extern double clamp_row_est(double nrows);
-extern void cost_seqscan(Path *path, Query *root, RelOptInfo *baserel);
-extern void cost_index(IndexPath *path, Query *root, IndexOptInfo *index,
+extern void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel);
+extern void cost_index(IndexPath *path, PlannerInfo *root, IndexOptInfo *index,
                   List *indexQuals, bool is_injoin);
-extern void cost_bitmap_heap_scan(Path *path, Query *root, RelOptInfo *baserel,
+extern void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
                                                                  Path *bitmapqual, bool is_injoin);
-extern void cost_bitmap_and_node(BitmapAndPath *path, Query *root);
-extern void cost_bitmap_or_node(BitmapOrPath *path, Query *root);
+extern void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root);
+extern void cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root);
 extern void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec);
-extern void cost_tidscan(Path *path, Query *root,
+extern void cost_tidscan(Path *path, PlannerInfo *root,
                         RelOptInfo *baserel, List *tideval);
 extern void cost_subqueryscan(Path *path, RelOptInfo *baserel);
-extern void cost_functionscan(Path *path, Query *root,
+extern void cost_functionscan(Path *path, PlannerInfo *root,
                                  RelOptInfo *baserel);
-extern void cost_sort(Path *path, Query *root,
+extern void cost_sort(Path *path, PlannerInfo *root,
                  List *pathkeys, Cost input_cost, double tuples, int width);
 extern void cost_material(Path *path,
                          Cost input_cost, double tuples, int width);
-extern void cost_agg(Path *path, Query *root,
+extern void cost_agg(Path *path, PlannerInfo *root,
                 AggStrategy aggstrategy, int numAggs,
                 int numGroupCols, double numGroups,
                 Cost input_startup_cost, Cost input_total_cost,
                 double input_tuples);
-extern void cost_group(Path *path, Query *root,
+extern void cost_group(Path *path, PlannerInfo *root,
                   int numGroupCols, double numGroups,
                   Cost input_startup_cost, Cost input_total_cost,
                   double input_tuples);
-extern void cost_nestloop(NestPath *path, Query *root);
-extern void cost_mergejoin(MergePath *path, Query *root);
-extern void cost_hashjoin(HashPath *path, Query *root);
+extern void cost_nestloop(NestPath *path, PlannerInfo *root);
+extern void cost_mergejoin(MergePath *path, PlannerInfo *root);
+extern void cost_hashjoin(HashPath *path, PlannerInfo *root);
 extern void cost_qual_eval(QualCost *cost, List *quals);
-extern void set_baserel_size_estimates(Query *root, RelOptInfo *rel);
-extern void set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
+extern void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
                                                   RelOptInfo *outer_rel,
                                                   RelOptInfo *inner_rel,
                                                   JoinType jointype,
                                                   List *restrictlist);
-extern void set_function_size_estimates(Query *root, RelOptInfo *rel);
+extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel);
 
 /*
  * prototypes for clausesel.c
  *       routines to compute clause selectivities
  */
-extern Selectivity clauselist_selectivity(Query *root,
+extern Selectivity clauselist_selectivity(PlannerInfo *root,
                                           List *clauses,
                                           int varRelid,
                                           JoinType jointype);
-extern Selectivity clause_selectivity(Query *root,
+extern Selectivity clause_selectivity(PlannerInfo *root,
                                   Node *clause,
                                   int varRelid,
                                   JoinType jointype);
index 53d0644c3896abeae0dbfb19d4208372c9dd6ca2..b67fc1aa496de91917d24c3f3765ffd53e5c820f 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.38 2004/12/31 22:03:36 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.39 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,13 +72,14 @@ extern double Geqo_selection_bias;
  */
 typedef struct
 {
-       Query      *root;                       /* the query we are planning */
+       PlannerInfo *root;                      /* the query we are planning */
        List       *initial_rels;       /* the base relations */
 } GeqoEvalData;
 
 
 /* routines in geqo_main.c */
-extern RelOptInfo *geqo(Query *root, int number_of_rels, List *initial_rels);
+extern RelOptInfo *geqo(PlannerInfo *root,
+                                               int number_of_rels, List *initial_rels);
 
 /* routines in geqo_eval.c */
 extern Cost geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata);
index fb1217cf6aa22d5714bf6c372f8885babba57cd0..b0f0f56fd9b18a3ffa8d7176f0d6bb936f121ab4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/joininfo.h,v 1.28 2004/12/31 22:03:36 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/joininfo.h,v 1.29 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 extern JoinInfo *find_joininfo_node(RelOptInfo *this_rel, Relids join_relids);
 extern JoinInfo *make_joininfo_node(RelOptInfo *this_rel, Relids join_relids);
 
-extern void add_join_clause_to_rels(Query *root,
+extern void add_join_clause_to_rels(PlannerInfo *root,
                                                RestrictInfo *restrictinfo,
                                                Relids join_relids);
-extern void remove_join_clause_from_rels(Query *root,
+extern void remove_join_clause_from_rels(PlannerInfo *root,
                                                         RestrictInfo *restrictinfo,
                                                         Relids join_relids);
 
index f5c11ff58e3548977a4d736466a034f409dc92c7..009ada29da7b0f0a551c6d694531eb6f7cc207ab 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.60 2005/04/22 21:58:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.61 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,35 +27,35 @@ extern int compare_fractional_path_costs(Path *path1, Path *path2,
 extern void set_cheapest(RelOptInfo *parent_rel);
 extern void add_path(RelOptInfo *parent_rel, Path *new_path);
 
-extern Path *create_seqscan_path(Query *root, RelOptInfo *rel);
-extern IndexPath *create_index_path(Query *root,
+extern Path *create_seqscan_path(PlannerInfo *root, RelOptInfo *rel);
+extern IndexPath *create_index_path(PlannerInfo *root,
                                  IndexOptInfo *index,
                                  List *clause_groups,
                                  List *pathkeys,
                                  ScanDirection indexscandir,
                                  bool isjoininner);
-extern BitmapHeapPath *create_bitmap_heap_path(Query *root,
+extern BitmapHeapPath *create_bitmap_heap_path(PlannerInfo *root,
                                                                                           RelOptInfo *rel,
                                                                                           Path *bitmapqual,
                                                                                           bool isjoininner);
-extern BitmapAndPath *create_bitmap_and_path(Query *root,
+extern BitmapAndPath *create_bitmap_and_path(PlannerInfo *root,
                                                                                         RelOptInfo *rel,
                                                                                         List *bitmapquals);
-extern BitmapOrPath *create_bitmap_or_path(Query *root,
+extern BitmapOrPath *create_bitmap_or_path(PlannerInfo *root,
                                                                                   RelOptInfo *rel,
                                                                                   List *bitmapquals);
-extern TidPath *create_tidscan_path(Query *root, RelOptInfo *rel,
+extern TidPath *create_tidscan_path(PlannerInfo *root, RelOptInfo *rel,
                                        List *tideval);
 extern AppendPath *create_append_path(RelOptInfo *rel, List *subpaths);
 extern ResultPath *create_result_path(RelOptInfo *rel, Path *subpath,
                                   List *constantqual);
 extern MaterialPath *create_material_path(RelOptInfo *rel, Path *subpath);
-extern UniquePath *create_unique_path(Query *root, RelOptInfo *rel,
+extern UniquePath *create_unique_path(PlannerInfo *root, RelOptInfo *rel,
                                   Path *subpath);
 extern Path *create_subqueryscan_path(RelOptInfo *rel, List *pathkeys);
-extern Path *create_functionscan_path(Query *root, RelOptInfo *rel);
+extern Path *create_functionscan_path(PlannerInfo *root, RelOptInfo *rel);
 
-extern NestPath *create_nestloop_path(Query *root,
+extern NestPath *create_nestloop_path(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         JoinType jointype,
                                         Path *outer_path,
@@ -63,7 +63,7 @@ extern NestPath *create_nestloop_path(Query *root,
                                         List *restrict_clauses,
                                         List *pathkeys);
 
-extern MergePath *create_mergejoin_path(Query *root,
+extern MergePath *create_mergejoin_path(PlannerInfo *root,
                                          RelOptInfo *joinrel,
                                          JoinType jointype,
                                          Path *outer_path,
@@ -74,7 +74,7 @@ extern MergePath *create_mergejoin_path(Query *root,
                                          List *outersortkeys,
                                          List *innersortkeys);
 
-extern HashPath *create_hashjoin_path(Query *root,
+extern HashPath *create_hashjoin_path(PlannerInfo *root,
                                         RelOptInfo *joinrel,
                                         JoinType jointype,
                                         Path *outer_path,
@@ -85,11 +85,11 @@ extern HashPath *create_hashjoin_path(Query *root,
 /*
  * prototypes for relnode.c
  */
-extern void build_base_rel(Query *root, int relid);
-extern RelOptInfo *build_other_rel(Query *root, int relid);
-extern RelOptInfo *find_base_rel(Query *root, int relid);
-extern RelOptInfo *find_join_rel(Query *root, Relids relids);
-extern RelOptInfo *build_join_rel(Query *root,
+extern void build_base_rel(PlannerInfo *root, int relid);
+extern RelOptInfo *build_other_rel(PlannerInfo *root, int relid);
+extern RelOptInfo *find_base_rel(PlannerInfo *root, int relid);
+extern RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids);
+extern RelOptInfo *build_join_rel(PlannerInfo *root,
                           Relids joinrelids,
                           RelOptInfo *outer_rel,
                           RelOptInfo *inner_rel,
index 3b90cd7f7c8cf2e48867b9a8f8f472d3dc01fc41..f0c2e64599f348677be09fcb0298298b3eeb132b 100644 (file)
@@ -1,14 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * paths.h
- *       prototypes for various files in optimizer/path (were separate
- *       header files)
+ *       prototypes for various files in optimizer/path
  *
  *
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.83 2005/04/25 01:30:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.84 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 extern bool enable_geqo;
 extern int     geqo_threshold;
 
-extern RelOptInfo *make_one_rel(Query *root);
-extern RelOptInfo *make_fromexpr_rel(Query *root, FromExpr *from);
+extern RelOptInfo *make_one_rel(PlannerInfo *root);
+extern RelOptInfo *make_fromexpr_rel(PlannerInfo *root, FromExpr *from);
 
 #ifdef OPTIMIZER_DEBUG
-extern void debug_print_rel(Query *root, RelOptInfo *rel);
+extern void debug_print_rel(PlannerInfo *root, RelOptInfo *rel);
 #endif
 
 /*
  * indxpath.c
  *       routines to generate index paths
  */
-extern void create_index_paths(Query *root, RelOptInfo *rel);
-extern List *generate_bitmap_or_paths(Query *root, RelOptInfo *rel,
+extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel);
+extern List *generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
                                                 List *clauses, List *outer_clauses,
                                                 bool isjoininner,
                                                 Relids outer_relids);
-extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel,
+extern Path *best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
                                         Relids outer_relids, JoinType jointype);
 extern List *group_clauses_by_indexkey(IndexOptInfo *index,
                                                                           List *clauses, List *outer_clauses,
@@ -49,7 +48,7 @@ extern bool match_index_to_operand(Node *operand, int indexcol,
                                           IndexOptInfo *index);
 extern List *expand_indexqual_conditions(IndexOptInfo *index,
                                                                                 List *clausegroups);
-extern void check_partial_indexes(Query *root, RelOptInfo *rel);
+extern void check_partial_indexes(PlannerInfo *root, RelOptInfo *rel);
 extern bool pred_test(List *predicate_list, List *restrictinfo_list);
 extern List *flatten_clausegroups_list(List *clausegroups);
 
@@ -57,19 +56,19 @@ extern List *flatten_clausegroups_list(List *clausegroups);
  * orindxpath.c
  *       additional routines for indexable OR clauses
  */
-extern bool create_or_index_quals(Query *root, RelOptInfo *rel);
+extern bool create_or_index_quals(PlannerInfo *root, RelOptInfo *rel);
 
 /*
  * tidpath.h
  *       routines to generate tid paths
  */
-extern void create_tidscan_paths(Query *root, RelOptInfo *rel);
+extern void create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel);
 
 /*
  * joinpath.c
  *        routines to create join paths
  */
-extern void add_paths_to_joinrel(Query *root, RelOptInfo *joinrel,
+extern void add_paths_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
                                         RelOptInfo *outerrel,
                                         RelOptInfo *innerrel,
                                         JoinType jointype,
@@ -79,9 +78,9 @@ extern void add_paths_to_joinrel(Query *root, RelOptInfo *joinrel,
  * joinrels.c
  *       routines to determine which relations to join
  */
-extern List *make_rels_by_joins(Query *root, int level, List **joinrels);
-extern RelOptInfo *make_jointree_rel(Query *root, Node *jtnode);
-extern RelOptInfo *make_join_rel(Query *root,
+extern List *make_rels_by_joins(PlannerInfo *root, int level, List **joinrels);
+extern RelOptInfo *make_jointree_rel(PlannerInfo *root, Node *jtnode);
+extern RelOptInfo *make_join_rel(PlannerInfo *root,
                          RelOptInfo *rel1, RelOptInfo *rel2,
                          JoinType jointype);
 
@@ -97,10 +96,10 @@ typedef enum
        PATHKEYS_DIFFERENT                      /* neither pathkey includes the other */
 } PathKeysComparison;
 
-extern void add_equijoined_keys(Query *root, RestrictInfo *restrictinfo);
-extern bool exprs_known_equal(Query *root, Node *item1, Node *item2);
-extern void generate_implied_equalities(Query *root);
-extern List *canonicalize_pathkeys(Query *root, List *pathkeys);
+extern void add_equijoined_keys(PlannerInfo *root, RestrictInfo *restrictinfo);
+extern bool exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2);
+extern void generate_implied_equalities(PlannerInfo *root);
+extern List *canonicalize_pathkeys(PlannerInfo *root, List *pathkeys);
 extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2);
 extern bool pathkeys_contained_in(List *keys1, List *keys2);
 extern PathKeysComparison compare_noncanonical_pathkeys(List *keys1,
@@ -111,29 +110,29 @@ extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
 extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
                                                                                  List *pathkeys,
                                                                                  double fraction);
-extern List *build_index_pathkeys(Query *root, IndexOptInfo *index,
+extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
                                         ScanDirection scandir);
-extern List *build_subquery_pathkeys(Query *root, RelOptInfo *rel,
-                                               Query *subquery);
-extern List *build_join_pathkeys(Query *root,
+extern List *convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
+                                                                          List *subquery_pathkeys);
+extern List *build_join_pathkeys(PlannerInfo *root,
                                        RelOptInfo *joinrel,
                                        JoinType jointype,
                                        List *outer_pathkeys);
 extern List *make_pathkeys_for_sortclauses(List *sortclauses,
                                                          List *tlist);
-extern void cache_mergeclause_pathkeys(Query *root,
+extern void cache_mergeclause_pathkeys(PlannerInfo *root,
                                                   RestrictInfo *restrictinfo);
-extern List *find_mergeclauses_for_pathkeys(Query *root,
+extern List *find_mergeclauses_for_pathkeys(PlannerInfo *root,
                                                           List *pathkeys,
                                                           List *restrictinfos);
-extern List *make_pathkeys_for_mergeclauses(Query *root,
+extern List *make_pathkeys_for_mergeclauses(PlannerInfo *root,
                                                           List *mergeclauses,
                                                           RelOptInfo *rel);
-extern int pathkeys_useful_for_merging(Query *root,
+extern int pathkeys_useful_for_merging(PlannerInfo *root,
                                                        RelOptInfo *rel,
                                                        List *pathkeys);
-extern int     pathkeys_useful_for_ordering(Query *root, List *pathkeys);
-extern List *truncate_useless_pathkeys(Query *root,
+extern int     pathkeys_useful_for_ordering(PlannerInfo *root, List *pathkeys);
+extern List *truncate_useless_pathkeys(PlannerInfo *root,
                                                  RelOptInfo *rel,
                                                  List *pathkeys);
 
index 2f254016efcece518ab081a50d29363ff4991c0d..f8ecd36110d471e9340cf03c893e7a5e3d68d678 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.35 2004/12/31 22:03:36 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.36 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,7 @@
 
 extern void get_relation_info(Oid relationObjectId, RelOptInfo *rel);
 
-extern List *build_physical_tlist(Query *root, RelOptInfo *rel);
+extern List *build_physical_tlist(PlannerInfo *root, RelOptInfo *rel);
 
 extern List *find_inheritance_children(Oid inhparent);
 
@@ -27,12 +27,12 @@ extern bool has_subclass(Oid relationId);
 
 extern bool has_unique_index(RelOptInfo *rel, AttrNumber attno);
 
-extern Selectivity restriction_selectivity(Query *root,
+extern Selectivity restriction_selectivity(PlannerInfo *root,
                                                Oid operator,
                                                List *args,
                                                int varRelid);
 
-extern Selectivity join_selectivity(Query *root,
+extern Selectivity join_selectivity(PlannerInfo *root,
                                 Oid operator,
                                 List *args,
                                 JoinType jointype);
index bb27bf01d57ca3a0d4f786e424170a6c185c53ad..451863518605953bf8f0303ee9ac48bec4bc69f4 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.85 2005/05/22 22:30:20 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/planmain.h,v 1.86 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /*
  * prototypes for plan/planmain.c
  */
-extern void query_planner(Query *root, List *tlist, double tuple_fraction,
-                         Path **cheapest_path, Path **sorted_path);
+extern void query_planner(PlannerInfo *root, List *tlist,
+                                                 double tuple_fraction,
+                                                 Path **cheapest_path, Path **sorted_path);
 
 /*
  * prototypes for plan/planagg.c
  */
-extern Plan *optimize_minmax_aggregates(Query *root, List *tlist,
+extern Plan *optimize_minmax_aggregates(PlannerInfo *root, List *tlist,
                                                                                Path *best_path);
 
 /*
  * prototypes for plan/createplan.c
  */
-extern Plan *create_plan(Query *root, Path *best_path);
+extern Plan *create_plan(PlannerInfo *root, Path *best_path);
 extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual,
                                  Index scanrelid, Plan *subplan);
 extern Append *make_append(List *appendplans, bool isTarget, List *tlist);
-extern Sort *make_sort_from_sortclauses(Query *root, List *sortcls,
+extern Sort *make_sort_from_sortclauses(PlannerInfo *root, List *sortcls,
                                                   Plan *lefttree);
-extern Sort *make_sort_from_groupcols(Query *root, List *groupcls,
+extern Sort *make_sort_from_groupcols(PlannerInfo *root, List *groupcls,
                                                 AttrNumber *grpColIdx, Plan *lefttree);
-extern List *order_qual_clauses(Query *root, List *clauses);
-extern Agg *make_agg(Query *root, List *tlist, List *qual,
+extern List *order_qual_clauses(PlannerInfo *root, List *clauses);
+extern Agg *make_agg(PlannerInfo *root, List *tlist, List *qual,
                 AggStrategy aggstrategy,
                 int numGroupCols, AttrNumber *grpColIdx,
                 long numGroups, int numAggs,
                 Plan *lefttree);
-extern Group *make_group(Query *root, List *tlist, List *qual,
+extern Group *make_group(PlannerInfo *root, List *tlist, List *qual,
                   int numGroupCols, AttrNumber *grpColIdx,
                   double numGroups,
                   Plan *lefttree);
@@ -62,10 +63,10 @@ extern bool is_projection_capable_plan(Plan *plan);
 /*
  * prototypes for plan/initsplan.c
  */
-extern void add_base_rels_to_query(Query *root, Node *jtnode);
-extern void build_base_rel_tlists(Query *root, List *final_tlist);
-extern Relids distribute_quals_to_rels(Query *root, Node *jtnode);
-extern void process_implied_equality(Query *root,
+extern void add_base_rels_to_query(PlannerInfo *root, Node *jtnode);
+extern void build_base_rel_tlists(PlannerInfo *root, List *final_tlist);
+extern Relids distribute_quals_to_rels(PlannerInfo *root, Node *jtnode);
+extern void process_implied_equality(PlannerInfo *root,
                                                 Node *item1, Node *item2,
                                                 Oid sortop1, Oid sortop2,
                                                 Relids item1_relids, Relids item2_relids,
index 1f1a6b91c2d5fbe1194ed621e5cf1481bf313ac8..37091c9f57e3613f3a8ad8141583b09ec338541d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.32 2004/12/31 22:03:36 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.33 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@ 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);
+extern Plan *subquery_planner(Query *parse, double tuple_fraction,
+                                                         List **subquery_pathkeys);
 
 #endif   /* PLANNER_H */
index 6a86b2e174f7c06b4d0e28c6440901f4b4fbc544..e4b9cb2f45c20f98fbbeb13eb8fa034aaca80500 100644 (file)
@@ -7,14 +7,13 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/prep.h,v 1.49 2005/03/28 00:58:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/prep.h,v 1.50 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef PREP_H
 #define PREP_H
 
-#include "nodes/parsenodes.h"
 #include "nodes/plannodes.h"
 #include "nodes/relation.h"
 
 extern int     from_collapse_limit;
 extern int     join_collapse_limit;
 
-extern Node *pull_up_IN_clauses(Query *parse, Node *node);
-extern Node *pull_up_subqueries(Query *parse, Node *jtnode,
+extern Node *pull_up_IN_clauses(PlannerInfo *root, Node *node);
+extern Node *pull_up_subqueries(PlannerInfo *root, Node *jtnode,
                                   bool below_outer_join);
-extern void reduce_outer_joins(Query *parse);
-extern Node *simplify_jointree(Query *parse, Node *jtnode);
+extern void reduce_outer_joins(PlannerInfo *root);
+extern Node *simplify_jointree(PlannerInfo *root, Node *jtnode);
 extern Relids get_relids_in_jointree(Node *jtnode);
-extern Relids get_relids_for_join(Query *parse, int joinrelid);
+extern Relids get_relids_for_join(PlannerInfo *root, int joinrelid);
 
 /*
  * prototypes for prepqual.c
@@ -41,16 +40,16 @@ extern Expr *canonicalize_qual(Expr *qual);
 /*
  * prototypes for preptlist.c
  */
-extern List *preprocess_targetlist(Query *parse, List *tlist);
+extern List *preprocess_targetlist(PlannerInfo *root, List *tlist);
 
 /*
  * prototypes for prepunion.c
  */
-extern Plan *plan_set_operations(Query *parse, List **sortClauses);
+extern Plan *plan_set_operations(PlannerInfo *root, List **sortClauses);
 
 extern List *find_all_inheritors(Oid parentrel);
 
-extern List *expand_inherited_rtentry(Query *parse, Index rti);
+extern List *expand_inherited_rtentry(PlannerInfo *root, Index rti);
 
 extern Node *adjust_inherited_attrs(Node *node,
                                           Index old_rt_index, Oid old_relid,
index 3760a65669b50e43cc8b9d877d71e2e7c560e37a..4fa6ace6aee30c928bbfa17d2d802daff3551fb9 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.29 2005/04/25 02:14:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.30 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "nodes/relation.h"
 
+
 extern RestrictInfo *make_restrictinfo(Expr *clause, bool is_pushed_down,
                                  bool valid_everywhere);
 extern List *make_restrictinfo_from_bitmapqual(Path *bitmapqual,
@@ -25,10 +26,10 @@ extern bool restriction_is_or_clause(RestrictInfo *restrictinfo);
 extern List *get_actual_clauses(List *restrictinfo_list);
 extern void get_actual_join_clauses(List *restrictinfo_list,
                                                List **joinquals, List **otherquals);
-extern List *remove_redundant_join_clauses(Query *root,
+extern List *remove_redundant_join_clauses(PlannerInfo *root,
                                                          List *restrictinfo_list,
                                                          bool isouterjoin);
-extern List *select_nonredundant_join_clauses(Query *root,
+extern List *select_nonredundant_join_clauses(PlannerInfo *root,
                                                                 List *restrictinfo_list,
                                                                 List *reference_list,
                                                                 bool isouterjoin);
index 9381321a46fa7bbc01a327a148dbe8e04ba52882..ccad3cd91b1ad1afde04352a6bd04f5887943d69 100644 (file)
@@ -5,26 +5,27 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.24 2005/04/11 23:06:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/subselect.h,v 1.25 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef SUBSELECT_H
 #define SUBSELECT_H
 
-#include "nodes/parsenodes.h"
 #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(Query *parse, SubLink *sublink);
+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 Param *SS_make_initplan_from_plan(Query *root, Plan *plan,
+extern Param *SS_make_initplan_from_plan(PlannerInfo *root, Plan *plan,
                                                                                 Oid resulttype, int32 resulttypmod);
 
 #endif   /* SUBSELECT_H */
index 4c21c1274501b70f66ba9c93c4ebebf9cba5c19f..5ba6406ab048f719cb050a6467c6881d3d2473ff 100644 (file)
@@ -1,13 +1,13 @@
 /*-------------------------------------------------------------------------
  *
  * var.h
- *       prototypes for var.c.
+ *       prototypes for optimizer/util/var.c.
  *
  *
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/var.h,v 1.32 2004/12/31 22:03:36 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/var.h,v 1.33 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,6 @@ extern bool contain_vars_of_level(Node *node, int levelsup);
 extern bool contain_vars_above_level(Node *node, int levelsup);
 extern int     find_minimum_var_level(Node *node);
 extern List *pull_var_clause(Node *node, bool includeUpperVars);
-extern Node *flatten_join_alias_vars(Query *root, Node *node);
+extern Node *flatten_join_alias_vars(PlannerInfo *root, Node *node);
 
 #endif   /* VAR_H */
index 5fbc9d3ae6bff839df01e15ec1f6bb15ca41b1aa..e54c11df3613dca81e8e486b0c47d565290c93ba 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.22 2005/03/06 22:15:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.23 2005/06/05 22:32:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,7 +16,7 @@
 #define SELFUNCS_H
 
 #include "fmgr.h"
-#include "nodes/parsenodes.h"
+#include "nodes/relation.h"
 
 
 /*
@@ -108,19 +108,19 @@ extern Datum icregexnejoinsel(PG_FUNCTION_ARGS);
 extern Datum nlikejoinsel(PG_FUNCTION_ARGS);
 extern Datum icnlikejoinsel(PG_FUNCTION_ARGS);
 
-extern Selectivity booltestsel(Query *root, BoolTestType booltesttype,
+extern Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype,
                        Node *arg, int varRelid, JoinType jointype);
-extern Selectivity nulltestsel(Query *root, NullTestType nulltesttype,
+extern Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype,
                        Node *arg, int varRelid);
 
-extern void mergejoinscansel(Query *root, Node *clause,
+extern void mergejoinscansel(PlannerInfo *root, Node *clause,
                                 Selectivity *leftscan,
                                 Selectivity *rightscan);
 
-extern double estimate_num_groups(Query *root, List *groupExprs,
+extern double estimate_num_groups(PlannerInfo *root, List *groupExprs,
                                        double input_rows);
 
-extern Selectivity estimate_hash_bucketsize(Query *root, Node *hashkey,
+extern Selectivity estimate_hash_bucketsize(PlannerInfo *root, Node *hashkey,
                                                 double nbuckets);
 
 extern Datum btcostestimate(PG_FUNCTION_ARGS);