Header And Logo

PostgreSQL
| The world's most advanced open source database.

allpaths.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * allpaths.c
00004  *    Routines to find possible search paths for processing a query
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/optimizer/path/allpaths.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #include "postgres.h"
00017 
00018 #include <math.h>
00019 
00020 #include "catalog/pg_class.h"
00021 #include "foreign/fdwapi.h"
00022 #include "nodes/nodeFuncs.h"
00023 #ifdef OPTIMIZER_DEBUG
00024 #include "nodes/print.h"
00025 #endif
00026 #include "optimizer/clauses.h"
00027 #include "optimizer/cost.h"
00028 #include "optimizer/geqo.h"
00029 #include "optimizer/pathnode.h"
00030 #include "optimizer/paths.h"
00031 #include "optimizer/plancat.h"
00032 #include "optimizer/planner.h"
00033 #include "optimizer/prep.h"
00034 #include "optimizer/restrictinfo.h"
00035 #include "optimizer/var.h"
00036 #include "parser/parse_clause.h"
00037 #include "parser/parsetree.h"
00038 #include "rewrite/rewriteManip.h"
00039 #include "utils/lsyscache.h"
00040 
00041 
00042 /* These parameters are set by GUC */
00043 bool        enable_geqo = false;    /* just in case GUC doesn't set it */
00044 int         geqo_threshold;
00045 
00046 /* Hook for plugins to replace standard_join_search() */
00047 join_search_hook_type join_search_hook = NULL;
00048 
00049 
00050 static void set_base_rel_sizes(PlannerInfo *root);
00051 static void set_base_rel_pathlists(PlannerInfo *root);
00052 static void set_rel_size(PlannerInfo *root, RelOptInfo *rel,
00053              Index rti, RangeTblEntry *rte);
00054 static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00055                  Index rti, RangeTblEntry *rte);
00056 static void set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel,
00057                    RangeTblEntry *rte);
00058 static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00059                        RangeTblEntry *rte);
00060 static void set_foreign_size(PlannerInfo *root, RelOptInfo *rel,
00061                  RangeTblEntry *rte);
00062 static void set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel,
00063                      RangeTblEntry *rte);
00064 static void set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
00065                     Index rti, RangeTblEntry *rte);
00066 static void set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00067                         Index rti, RangeTblEntry *rte);
00068 static void generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
00069                            List *live_childrels,
00070                            List *all_child_pathkeys);
00071 static List *accumulate_append_subpath(List *subpaths, Path *path);
00072 static void set_dummy_rel_pathlist(RelOptInfo *rel);
00073 static void set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
00074                       Index rti, RangeTblEntry *rte);
00075 static void set_function_pathlist(PlannerInfo *root, RelOptInfo *rel,
00076                       RangeTblEntry *rte);
00077 static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
00078                     RangeTblEntry *rte);
00079 static void set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel,
00080                  RangeTblEntry *rte);
00081 static void set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel,
00082                        RangeTblEntry *rte);
00083 static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
00084 static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
00085                           bool *differentTypes);
00086 static bool recurse_pushdown_safe(Node *setOp, Query *topquery,
00087                       bool *differentTypes);
00088 static void compare_tlist_datatypes(List *tlist, List *colTypes,
00089                         bool *differentTypes);
00090 static bool qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
00091                       bool *differentTypes);
00092 static void subquery_push_qual(Query *subquery,
00093                    RangeTblEntry *rte, Index rti, Node *qual);
00094 static void recurse_push_qual(Node *setOp, Query *topquery,
00095                   RangeTblEntry *rte, Index rti, Node *qual);
00096 
00097 
00098 /*
00099  * make_one_rel
00100  *    Finds all possible access paths for executing a query, returning a
00101  *    single rel that represents the join of all base rels in the query.
00102  */
00103 RelOptInfo *
00104 make_one_rel(PlannerInfo *root, List *joinlist)
00105 {
00106     RelOptInfo *rel;
00107     Index       rti;
00108 
00109     /*
00110      * Construct the all_baserels Relids set.
00111      */
00112     root->all_baserels = NULL;
00113     for (rti = 1; rti < root->simple_rel_array_size; rti++)
00114     {
00115         RelOptInfo *brel = root->simple_rel_array[rti];
00116 
00117         /* there may be empty slots corresponding to non-baserel RTEs */
00118         if (brel == NULL)
00119             continue;
00120 
00121         Assert(brel->relid == rti);     /* sanity check on array */
00122 
00123         /* ignore RTEs that are "other rels" */
00124         if (brel->reloptkind != RELOPT_BASEREL)
00125             continue;
00126 
00127         root->all_baserels = bms_add_member(root->all_baserels, brel->relid);
00128     }
00129 
00130     /*
00131      * Generate access paths for the base rels.
00132      */
00133     set_base_rel_sizes(root);
00134     set_base_rel_pathlists(root);
00135 
00136     /*
00137      * Generate access paths for the entire join tree.
00138      */
00139     rel = make_rel_from_joinlist(root, joinlist);
00140 
00141     /*
00142      * The result should join all and only the query's base rels.
00143      */
00144     Assert(bms_equal(rel->relids, root->all_baserels));
00145 
00146     return rel;
00147 }
00148 
00149 /*
00150  * set_base_rel_sizes
00151  *    Set the size estimates (rows and widths) for each base-relation entry.
00152  *
00153  * We do this in a separate pass over the base rels so that rowcount
00154  * estimates are available for parameterized path generation.
00155  */
00156 static void
00157 set_base_rel_sizes(PlannerInfo *root)
00158 {
00159     Index       rti;
00160 
00161     for (rti = 1; rti < root->simple_rel_array_size; rti++)
00162     {
00163         RelOptInfo *rel = root->simple_rel_array[rti];
00164 
00165         /* there may be empty slots corresponding to non-baserel RTEs */
00166         if (rel == NULL)
00167             continue;
00168 
00169         Assert(rel->relid == rti);      /* sanity check on array */
00170 
00171         /* ignore RTEs that are "other rels" */
00172         if (rel->reloptkind != RELOPT_BASEREL)
00173             continue;
00174 
00175         set_rel_size(root, rel, rti, root->simple_rte_array[rti]);
00176     }
00177 }
00178 
00179 /*
00180  * set_base_rel_pathlists
00181  *    Finds all paths available for scanning each base-relation entry.
00182  *    Sequential scan and any available indices are considered.
00183  *    Each useful path is attached to its relation's 'pathlist' field.
00184  */
00185 static void
00186 set_base_rel_pathlists(PlannerInfo *root)
00187 {
00188     Index       rti;
00189 
00190     for (rti = 1; rti < root->simple_rel_array_size; rti++)
00191     {
00192         RelOptInfo *rel = root->simple_rel_array[rti];
00193 
00194         /* there may be empty slots corresponding to non-baserel RTEs */
00195         if (rel == NULL)
00196             continue;
00197 
00198         Assert(rel->relid == rti);      /* sanity check on array */
00199 
00200         /* ignore RTEs that are "other rels" */
00201         if (rel->reloptkind != RELOPT_BASEREL)
00202             continue;
00203 
00204         set_rel_pathlist(root, rel, rti, root->simple_rte_array[rti]);
00205     }
00206 }
00207 
00208 /*
00209  * set_rel_size
00210  *    Set size estimates for a base relation
00211  */
00212 static void
00213 set_rel_size(PlannerInfo *root, RelOptInfo *rel,
00214              Index rti, RangeTblEntry *rte)
00215 {
00216     if (rel->reloptkind == RELOPT_BASEREL &&
00217         relation_excluded_by_constraints(root, rel, rte))
00218     {
00219         /*
00220          * We proved we don't need to scan the rel via constraint exclusion,
00221          * so set up a single dummy path for it.  Here we only check this for
00222          * regular baserels; if it's an otherrel, CE was already checked in
00223          * set_append_rel_pathlist().
00224          *
00225          * In this case, we go ahead and set up the relation's path right away
00226          * instead of leaving it for set_rel_pathlist to do.  This is because
00227          * we don't have a convention for marking a rel as dummy except by
00228          * assigning a dummy path to it.
00229          */
00230         set_dummy_rel_pathlist(rel);
00231     }
00232     else if (rte->inh)
00233     {
00234         /* It's an "append relation", process accordingly */
00235         set_append_rel_size(root, rel, rti, rte);
00236     }
00237     else
00238     {
00239         switch (rel->rtekind)
00240         {
00241             case RTE_RELATION:
00242                 if (rte->relkind == RELKIND_FOREIGN_TABLE)
00243                 {
00244                     /* Foreign table */
00245                     set_foreign_size(root, rel, rte);
00246                 }
00247                 else
00248                 {
00249                     /* Plain relation */
00250                     set_plain_rel_size(root, rel, rte);
00251                 }
00252                 break;
00253             case RTE_SUBQUERY:
00254 
00255                 /*
00256                  * Subqueries don't support making a choice between
00257                  * parameterized and unparameterized paths, so just go ahead
00258                  * and build their paths immediately.
00259                  */
00260                 set_subquery_pathlist(root, rel, rti, rte);
00261                 break;
00262             case RTE_FUNCTION:
00263                 set_function_size_estimates(root, rel);
00264                 break;
00265             case RTE_VALUES:
00266                 set_values_size_estimates(root, rel);
00267                 break;
00268             case RTE_CTE:
00269 
00270                 /*
00271                  * CTEs don't support making a choice between parameterized
00272                  * and unparameterized paths, so just go ahead and build their
00273                  * paths immediately.
00274                  */
00275                 if (rte->self_reference)
00276                     set_worktable_pathlist(root, rel, rte);
00277                 else
00278                     set_cte_pathlist(root, rel, rte);
00279                 break;
00280             default:
00281                 elog(ERROR, "unexpected rtekind: %d", (int) rel->rtekind);
00282                 break;
00283         }
00284     }
00285 }
00286 
00287 /*
00288  * set_rel_pathlist
00289  *    Build access paths for a base relation
00290  */
00291 static void
00292 set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00293                  Index rti, RangeTblEntry *rte)
00294 {
00295     if (IS_DUMMY_REL(rel))
00296     {
00297         /* We already proved the relation empty, so nothing more to do */
00298     }
00299     else if (rte->inh)
00300     {
00301         /* It's an "append relation", process accordingly */
00302         set_append_rel_pathlist(root, rel, rti, rte);
00303     }
00304     else
00305     {
00306         switch (rel->rtekind)
00307         {
00308             case RTE_RELATION:
00309                 if (rte->relkind == RELKIND_FOREIGN_TABLE)
00310                 {
00311                     /* Foreign table */
00312                     set_foreign_pathlist(root, rel, rte);
00313                 }
00314                 else
00315                 {
00316                     /* Plain relation */
00317                     set_plain_rel_pathlist(root, rel, rte);
00318                 }
00319                 break;
00320             case RTE_SUBQUERY:
00321                 /* Subquery --- fully handled during set_rel_size */
00322                 break;
00323             case RTE_FUNCTION:
00324                 /* RangeFunction */
00325                 set_function_pathlist(root, rel, rte);
00326                 break;
00327             case RTE_VALUES:
00328                 /* Values list */
00329                 set_values_pathlist(root, rel, rte);
00330                 break;
00331             case RTE_CTE:
00332                 /* CTE reference --- fully handled during set_rel_size */
00333                 break;
00334             default:
00335                 elog(ERROR, "unexpected rtekind: %d", (int) rel->rtekind);
00336                 break;
00337         }
00338     }
00339 
00340 #ifdef OPTIMIZER_DEBUG
00341     debug_print_rel(root, rel);
00342 #endif
00343 }
00344 
00345 /*
00346  * set_plain_rel_size
00347  *    Set size estimates for a plain relation (no subquery, no inheritance)
00348  */
00349 static void
00350 set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00351 {
00352     /*
00353      * Test any partial indexes of rel for applicability.  We must do this
00354      * first since partial unique indexes can affect size estimates.
00355      */
00356     check_partial_indexes(root, rel);
00357 
00358     /* Mark rel with estimated output rows, width, etc */
00359     set_baserel_size_estimates(root, rel);
00360 
00361     /*
00362      * Check to see if we can extract any restriction conditions from join
00363      * quals that are OR-of-AND structures.  If so, add them to the rel's
00364      * restriction list, and redo the above steps.
00365      */
00366     if (create_or_index_quals(root, rel))
00367     {
00368         check_partial_indexes(root, rel);
00369         set_baserel_size_estimates(root, rel);
00370     }
00371 }
00372 
00373 /*
00374  * set_plain_rel_pathlist
00375  *    Build access paths for a plain relation (no subquery, no inheritance)
00376  */
00377 static void
00378 set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00379 {
00380     Relids      required_outer;
00381 
00382     /*
00383      * We don't support pushing join clauses into the quals of a seqscan, but
00384      * it could still have required parameterization due to LATERAL refs in
00385      * its tlist.  (That can only happen if the seqscan is on a relation
00386      * pulled up out of a UNION ALL appendrel.)
00387      */
00388     required_outer = rel->lateral_relids;
00389 
00390     /* Consider sequential scan */
00391     add_path(rel, create_seqscan_path(root, rel, required_outer));
00392 
00393     /* Consider index scans */
00394     create_index_paths(root, rel);
00395 
00396     /* Consider TID scans */
00397     create_tidscan_paths(root, rel);
00398 
00399     /* Now find the cheapest of the paths for this rel */
00400     set_cheapest(rel);
00401 }
00402 
00403 /*
00404  * set_foreign_size
00405  *      Set size estimates for a foreign table RTE
00406  */
00407 static void
00408 set_foreign_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00409 {
00410     /* Mark rel with estimated output rows, width, etc */
00411     set_foreign_size_estimates(root, rel);
00412 
00413     /* Let FDW adjust the size estimates, if it can */
00414     rel->fdwroutine->GetForeignRelSize(root, rel, rte->relid);
00415 }
00416 
00417 /*
00418  * set_foreign_pathlist
00419  *      Build access paths for a foreign table RTE
00420  */
00421 static void
00422 set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
00423 {
00424     /* Call the FDW's GetForeignPaths function to generate path(s) */
00425     rel->fdwroutine->GetForeignPaths(root, rel, rte->relid);
00426 
00427     /* Select cheapest path */
00428     set_cheapest(rel);
00429 }
00430 
00431 /*
00432  * set_append_rel_size
00433  *    Set size estimates for an "append relation"
00434  *
00435  * The passed-in rel and RTE represent the entire append relation.  The
00436  * relation's contents are computed by appending together the output of
00437  * the individual member relations.  Note that in the inheritance case,
00438  * the first member relation is actually the same table as is mentioned in
00439  * the parent RTE ... but it has a different RTE and RelOptInfo.  This is
00440  * a good thing because their outputs are not the same size.
00441  */
00442 static void
00443 set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
00444                     Index rti, RangeTblEntry *rte)
00445 {
00446     int         parentRTindex = rti;
00447     double      parent_rows;
00448     double      parent_size;
00449     double     *parent_attrsizes;
00450     int         nattrs;
00451     ListCell   *l;
00452 
00453     /*
00454      * Initialize to compute size estimates for whole append relation.
00455      *
00456      * We handle width estimates by weighting the widths of different child
00457      * rels proportionally to their number of rows.  This is sensible because
00458      * the use of width estimates is mainly to compute the total relation
00459      * "footprint" if we have to sort or hash it.  To do this, we sum the
00460      * total equivalent size (in "double" arithmetic) and then divide by the
00461      * total rowcount estimate.  This is done separately for the total rel
00462      * width and each attribute.
00463      *
00464      * Note: if you consider changing this logic, beware that child rels could
00465      * have zero rows and/or width, if they were excluded by constraints.
00466      */
00467     parent_rows = 0;
00468     parent_size = 0;
00469     nattrs = rel->max_attr - rel->min_attr + 1;
00470     parent_attrsizes = (double *) palloc0(nattrs * sizeof(double));
00471 
00472     foreach(l, root->append_rel_list)
00473     {
00474         AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
00475         int         childRTindex;
00476         RangeTblEntry *childRTE;
00477         RelOptInfo *childrel;
00478         List       *childquals;
00479         Node       *childqual;
00480         ListCell   *parentvars;
00481         ListCell   *childvars;
00482 
00483         /* append_rel_list contains all append rels; ignore others */
00484         if (appinfo->parent_relid != parentRTindex)
00485             continue;
00486 
00487         childRTindex = appinfo->child_relid;
00488         childRTE = root->simple_rte_array[childRTindex];
00489 
00490         /*
00491          * The child rel's RelOptInfo was already created during
00492          * add_base_rels_to_query.
00493          */
00494         childrel = find_base_rel(root, childRTindex);
00495         Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
00496 
00497         /*
00498          * We have to copy the parent's targetlist and quals to the child,
00499          * with appropriate substitution of variables.  However, only the
00500          * baserestrictinfo quals are needed before we can check for
00501          * constraint exclusion; so do that first and then check to see if we
00502          * can disregard this child.
00503          *
00504          * As of 8.4, the child rel's targetlist might contain non-Var
00505          * expressions, which means that substitution into the quals could
00506          * produce opportunities for const-simplification, and perhaps even
00507          * pseudoconstant quals.  To deal with this, we strip the RestrictInfo
00508          * nodes, do the substitution, do const-simplification, and then
00509          * reconstitute the RestrictInfo layer.
00510          */
00511         childquals = get_all_actual_clauses(rel->baserestrictinfo);
00512         childquals = (List *) adjust_appendrel_attrs(root,
00513                                                      (Node *) childquals,
00514                                                      appinfo);
00515         childqual = eval_const_expressions(root, (Node *)
00516                                            make_ands_explicit(childquals));
00517         if (childqual && IsA(childqual, Const) &&
00518             (((Const *) childqual)->constisnull ||
00519              !DatumGetBool(((Const *) childqual)->constvalue)))
00520         {
00521             /*
00522              * Restriction reduces to constant FALSE or constant NULL after
00523              * substitution, so this child need not be scanned.
00524              */
00525             set_dummy_rel_pathlist(childrel);
00526             continue;
00527         }
00528         childquals = make_ands_implicit((Expr *) childqual);
00529         childquals = make_restrictinfos_from_actual_clauses(root,
00530                                                             childquals);
00531         childrel->baserestrictinfo = childquals;
00532 
00533         if (relation_excluded_by_constraints(root, childrel, childRTE))
00534         {
00535             /*
00536              * This child need not be scanned, so we can omit it from the
00537              * appendrel.
00538              */
00539             set_dummy_rel_pathlist(childrel);
00540             continue;
00541         }
00542 
00543         /*
00544          * CE failed, so finish copying/modifying targetlist and join quals.
00545          *
00546          * Note: the resulting childrel->reltargetlist may contain arbitrary
00547          * expressions, which otherwise would not occur in a reltargetlist.
00548          * Code that might be looking at an appendrel child must cope with
00549          * such.  Note in particular that "arbitrary expression" can include
00550          * "Var belonging to another relation", due to LATERAL references.
00551          */
00552         childrel->joininfo = (List *)
00553             adjust_appendrel_attrs(root,
00554                                    (Node *) rel->joininfo,
00555                                    appinfo);
00556         childrel->reltargetlist = (List *)
00557             adjust_appendrel_attrs(root,
00558                                    (Node *) rel->reltargetlist,
00559                                    appinfo);
00560 
00561         /*
00562          * We have to make child entries in the EquivalenceClass data
00563          * structures as well.  This is needed either if the parent
00564          * participates in some eclass joins (because we will want to consider
00565          * inner-indexscan joins on the individual children) or if the parent
00566          * has useful pathkeys (because we should try to build MergeAppend
00567          * paths that produce those sort orderings).
00568          */
00569         if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
00570             add_child_rel_equivalences(root, appinfo, rel, childrel);
00571         childrel->has_eclass_joins = rel->has_eclass_joins;
00572 
00573         /*
00574          * Note: we could compute appropriate attr_needed data for the child's
00575          * variables, by transforming the parent's attr_needed through the
00576          * translated_vars mapping.  However, currently there's no need
00577          * because attr_needed is only examined for base relations not
00578          * otherrels.  So we just leave the child's attr_needed empty.
00579          */
00580 
00581         /*
00582          * Compute the child's size.
00583          */
00584         set_rel_size(root, childrel, childRTindex, childRTE);
00585 
00586         /*
00587          * It is possible that constraint exclusion detected a contradiction
00588          * within a child subquery, even though we didn't prove one above. If
00589          * so, we can skip this child.
00590          */
00591         if (IS_DUMMY_REL(childrel))
00592             continue;
00593 
00594         /*
00595          * Accumulate size information from each live child.
00596          */
00597         if (childrel->rows > 0)
00598         {
00599             parent_rows += childrel->rows;
00600             parent_size += childrel->width * childrel->rows;
00601 
00602             /*
00603              * Accumulate per-column estimates too.  We need not do anything
00604              * for PlaceHolderVars in the parent list.  If child expression
00605              * isn't a Var, or we didn't record a width estimate for it, we
00606              * have to fall back on a datatype-based estimate.
00607              *
00608              * By construction, child's reltargetlist is 1-to-1 with parent's.
00609              */
00610             forboth(parentvars, rel->reltargetlist,
00611                     childvars, childrel->reltargetlist)
00612             {
00613                 Var        *parentvar = (Var *) lfirst(parentvars);
00614                 Node       *childvar = (Node *) lfirst(childvars);
00615 
00616                 if (IsA(parentvar, Var))
00617                 {
00618                     int         pndx = parentvar->varattno - rel->min_attr;
00619                     int32       child_width = 0;
00620 
00621                     if (IsA(childvar, Var) &&
00622                         ((Var *) childvar)->varno == childrel->relid)
00623                     {
00624                         int         cndx = ((Var *) childvar)->varattno - childrel->min_attr;
00625 
00626                         child_width = childrel->attr_widths[cndx];
00627                     }
00628                     if (child_width <= 0)
00629                         child_width = get_typavgwidth(exprType(childvar),
00630                                                       exprTypmod(childvar));
00631                     Assert(child_width > 0);
00632                     parent_attrsizes[pndx] += child_width * childrel->rows;
00633                 }
00634             }
00635         }
00636     }
00637 
00638     /*
00639      * Save the finished size estimates.
00640      */
00641     rel->rows = parent_rows;
00642     if (parent_rows > 0)
00643     {
00644         int         i;
00645 
00646         rel->width = rint(parent_size / parent_rows);
00647         for (i = 0; i < nattrs; i++)
00648             rel->attr_widths[i] = rint(parent_attrsizes[i] / parent_rows);
00649     }
00650     else
00651         rel->width = 0;         /* attr_widths should be zero already */
00652 
00653     /*
00654      * Set "raw tuples" count equal to "rows" for the appendrel; needed
00655      * because some places assume rel->tuples is valid for any baserel.
00656      */
00657     rel->tuples = parent_rows;
00658 
00659     pfree(parent_attrsizes);
00660 }
00661 
00662 /*
00663  * set_append_rel_pathlist
00664  *    Build access paths for an "append relation"
00665  */
00666 static void
00667 set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
00668                         Index rti, RangeTblEntry *rte)
00669 {
00670     int         parentRTindex = rti;
00671     List       *live_childrels = NIL;
00672     List       *subpaths = NIL;
00673     bool        subpaths_valid = true;
00674     List       *all_child_pathkeys = NIL;
00675     List       *all_child_outers = NIL;
00676     ListCell   *l;
00677 
00678     /*
00679      * Generate access paths for each member relation, and remember the
00680      * cheapest path for each one.  Also, identify all pathkeys (orderings)
00681      * and parameterizations (required_outer sets) available for the member
00682      * relations.
00683      */
00684     foreach(l, root->append_rel_list)
00685     {
00686         AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
00687         int         childRTindex;
00688         RangeTblEntry *childRTE;
00689         RelOptInfo *childrel;
00690         ListCell   *lcp;
00691 
00692         /* append_rel_list contains all append rels; ignore others */
00693         if (appinfo->parent_relid != parentRTindex)
00694             continue;
00695 
00696         /* Re-locate the child RTE and RelOptInfo */
00697         childRTindex = appinfo->child_relid;
00698         childRTE = root->simple_rte_array[childRTindex];
00699         childrel = root->simple_rel_array[childRTindex];
00700 
00701         /*
00702          * Compute the child's access paths.
00703          */
00704         set_rel_pathlist(root, childrel, childRTindex, childRTE);
00705 
00706         /*
00707          * If child is dummy, ignore it.
00708          */
00709         if (IS_DUMMY_REL(childrel))
00710             continue;
00711 
00712         /*
00713          * Child is live, so add it to the live_childrels list for use below.
00714          */
00715         live_childrels = lappend(live_childrels, childrel);
00716 
00717         /*
00718          * If child has an unparameterized cheapest-total path, add that to
00719          * the unparameterized Append path we are constructing for the parent.
00720          * If not, there's no workable unparameterized path.
00721          */
00722         if (childrel->cheapest_total_path->param_info == NULL)
00723             subpaths = accumulate_append_subpath(subpaths,
00724                                              childrel->cheapest_total_path);
00725         else
00726             subpaths_valid = false;
00727 
00728         /*
00729          * Collect lists of all the available path orderings and
00730          * parameterizations for all the children.  We use these as a
00731          * heuristic to indicate which sort orderings and parameterizations we
00732          * should build Append and MergeAppend paths for.
00733          */
00734         foreach(lcp, childrel->pathlist)
00735         {
00736             Path       *childpath = (Path *) lfirst(lcp);
00737             List       *childkeys = childpath->pathkeys;
00738             Relids      childouter = PATH_REQ_OUTER(childpath);
00739 
00740             /* Unsorted paths don't contribute to pathkey list */
00741             if (childkeys != NIL)
00742             {
00743                 ListCell   *lpk;
00744                 bool        found = false;
00745 
00746                 /* Have we already seen this ordering? */
00747                 foreach(lpk, all_child_pathkeys)
00748                 {
00749                     List       *existing_pathkeys = (List *) lfirst(lpk);
00750 
00751                     if (compare_pathkeys(existing_pathkeys,
00752                                          childkeys) == PATHKEYS_EQUAL)
00753                     {
00754                         found = true;
00755                         break;
00756                     }
00757                 }
00758                 if (!found)
00759                 {
00760                     /* No, so add it to all_child_pathkeys */
00761                     all_child_pathkeys = lappend(all_child_pathkeys,
00762                                                  childkeys);
00763                 }
00764             }
00765 
00766             /* Unparameterized paths don't contribute to param-set list */
00767             if (childouter)
00768             {
00769                 ListCell   *lco;
00770                 bool        found = false;
00771 
00772                 /* Have we already seen this param set? */
00773                 foreach(lco, all_child_outers)
00774                 {
00775                     Relids      existing_outers = (Relids) lfirst(lco);
00776 
00777                     if (bms_equal(existing_outers, childouter))
00778                     {
00779                         found = true;
00780                         break;
00781                     }
00782                 }
00783                 if (!found)
00784                 {
00785                     /* No, so add it to all_child_outers */
00786                     all_child_outers = lappend(all_child_outers,
00787                                                childouter);
00788                 }
00789             }
00790         }
00791     }
00792 
00793     /*
00794      * If we found unparameterized paths for all children, build an unordered,
00795      * unparameterized Append path for the rel.  (Note: this is correct even
00796      * if we have zero or one live subpath due to constraint exclusion.)
00797      */
00798     if (subpaths_valid)
00799         add_path(rel, (Path *) create_append_path(rel, subpaths, NULL));
00800 
00801     /*
00802      * Also build unparameterized MergeAppend paths based on the collected
00803      * list of child pathkeys.
00804      */
00805     if (subpaths_valid)
00806         generate_mergeappend_paths(root, rel, live_childrels,
00807                                    all_child_pathkeys);
00808 
00809     /*
00810      * Build Append paths for each parameterization seen among the child rels.
00811      * (This may look pretty expensive, but in most cases of practical
00812      * interest, the child rels will expose mostly the same parameterizations,
00813      * so that not that many cases actually get considered here.)
00814      *
00815      * The Append node itself cannot enforce quals, so all qual checking must
00816      * be done in the child paths.  This means that to have a parameterized
00817      * Append path, we must have the exact same parameterization for each
00818      * child path; otherwise some children might be failing to check the
00819      * moved-down quals.  To make them match up, we can try to increase the
00820      * parameterization of lesser-parameterized paths.
00821      */
00822     foreach(l, all_child_outers)
00823     {
00824         Relids      required_outer = (Relids) lfirst(l);
00825         ListCell   *lcr;
00826 
00827         /* Select the child paths for an Append with this parameterization */
00828         subpaths = NIL;
00829         subpaths_valid = true;
00830         foreach(lcr, live_childrels)
00831         {
00832             RelOptInfo *childrel = (RelOptInfo *) lfirst(lcr);
00833             Path       *cheapest_total;
00834 
00835             cheapest_total =
00836                 get_cheapest_path_for_pathkeys(childrel->pathlist,
00837                                                NIL,
00838                                                required_outer,
00839                                                TOTAL_COST);
00840             Assert(cheapest_total != NULL);
00841 
00842             /* Children must have exactly the desired parameterization */
00843             if (!bms_equal(PATH_REQ_OUTER(cheapest_total), required_outer))
00844             {
00845                 cheapest_total = reparameterize_path(root, cheapest_total,
00846                                                      required_outer, 1.0);
00847                 if (cheapest_total == NULL)
00848                 {
00849                     subpaths_valid = false;
00850                     break;
00851                 }
00852             }
00853 
00854             subpaths = accumulate_append_subpath(subpaths, cheapest_total);
00855         }
00856 
00857         if (subpaths_valid)
00858             add_path(rel, (Path *)
00859                      create_append_path(rel, subpaths, required_outer));
00860     }
00861 
00862     /* Select cheapest paths */
00863     set_cheapest(rel);
00864 }
00865 
00866 /*
00867  * generate_mergeappend_paths
00868  *      Generate MergeAppend paths for an append relation
00869  *
00870  * Generate a path for each ordering (pathkey list) appearing in
00871  * all_child_pathkeys.
00872  *
00873  * We consider both cheapest-startup and cheapest-total cases, ie, for each
00874  * interesting ordering, collect all the cheapest startup subpaths and all the
00875  * cheapest total paths, and build a MergeAppend path for each case.
00876  *
00877  * We don't currently generate any parameterized MergeAppend paths.  While
00878  * it would not take much more code here to do so, it's very unclear that it
00879  * is worth the planning cycles to investigate such paths: there's little
00880  * use for an ordered path on the inside of a nestloop.  In fact, it's likely
00881  * that the current coding of add_path would reject such paths out of hand,
00882  * because add_path gives no credit for sort ordering of parameterized paths,
00883  * and a parameterized MergeAppend is going to be more expensive than the
00884  * corresponding parameterized Append path.  If we ever try harder to support
00885  * parameterized mergejoin plans, it might be worth adding support for
00886  * parameterized MergeAppends to feed such joins.  (See notes in
00887  * optimizer/README for why that might not ever happen, though.)
00888  */
00889 static void
00890 generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
00891                            List *live_childrels,
00892                            List *all_child_pathkeys)
00893 {
00894     ListCell   *lcp;
00895 
00896     foreach(lcp, all_child_pathkeys)
00897     {
00898         List       *pathkeys = (List *) lfirst(lcp);
00899         List       *startup_subpaths = NIL;
00900         List       *total_subpaths = NIL;
00901         bool        startup_neq_total = false;
00902         ListCell   *lcr;
00903 
00904         /* Select the child paths for this ordering... */
00905         foreach(lcr, live_childrels)
00906         {
00907             RelOptInfo *childrel = (RelOptInfo *) lfirst(lcr);
00908             Path       *cheapest_startup,
00909                        *cheapest_total;
00910 
00911             /* Locate the right paths, if they are available. */
00912             cheapest_startup =
00913                 get_cheapest_path_for_pathkeys(childrel->pathlist,
00914                                                pathkeys,
00915                                                NULL,
00916                                                STARTUP_COST);
00917             cheapest_total =
00918                 get_cheapest_path_for_pathkeys(childrel->pathlist,
00919                                                pathkeys,
00920                                                NULL,
00921                                                TOTAL_COST);
00922 
00923             /*
00924              * If we can't find any paths with the right order just use the
00925              * cheapest-total path; we'll have to sort it later.
00926              */
00927             if (cheapest_startup == NULL || cheapest_total == NULL)
00928             {
00929                 cheapest_startup = cheapest_total =
00930                     childrel->cheapest_total_path;
00931                 /* Assert we do have an unparameterized path for this child */
00932                 Assert(cheapest_total->param_info == NULL);
00933             }
00934 
00935             /*
00936              * Notice whether we actually have different paths for the
00937              * "cheapest" and "total" cases; frequently there will be no point
00938              * in two create_merge_append_path() calls.
00939              */
00940             if (cheapest_startup != cheapest_total)
00941                 startup_neq_total = true;
00942 
00943             startup_subpaths =
00944                 accumulate_append_subpath(startup_subpaths, cheapest_startup);
00945             total_subpaths =
00946                 accumulate_append_subpath(total_subpaths, cheapest_total);
00947         }
00948 
00949         /* ... and build the MergeAppend paths */
00950         add_path(rel, (Path *) create_merge_append_path(root,
00951                                                         rel,
00952                                                         startup_subpaths,
00953                                                         pathkeys,
00954                                                         NULL));
00955         if (startup_neq_total)
00956             add_path(rel, (Path *) create_merge_append_path(root,
00957                                                             rel,
00958                                                             total_subpaths,
00959                                                             pathkeys,
00960                                                             NULL));
00961     }
00962 }
00963 
00964 /*
00965  * accumulate_append_subpath
00966  *      Add a subpath to the list being built for an Append or MergeAppend
00967  *
00968  * It's possible that the child is itself an Append path, in which case
00969  * we can "cut out the middleman" and just add its child paths to our
00970  * own list.  (We don't try to do this earlier because we need to
00971  * apply both levels of transformation to the quals.)
00972  */
00973 static List *
00974 accumulate_append_subpath(List *subpaths, Path *path)
00975 {
00976     if (IsA(path, AppendPath))
00977     {
00978         AppendPath *apath = (AppendPath *) path;
00979 
00980         /* list_copy is important here to avoid sharing list substructure */
00981         return list_concat(subpaths, list_copy(apath->subpaths));
00982     }
00983     else
00984         return lappend(subpaths, path);
00985 }
00986 
00987 /*
00988  * set_dummy_rel_pathlist
00989  *    Build a dummy path for a relation that's been excluded by constraints
00990  *
00991  * Rather than inventing a special "dummy" path type, we represent this as an
00992  * AppendPath with no members (see also IS_DUMMY_PATH/IS_DUMMY_REL macros).
00993  */
00994 static void
00995 set_dummy_rel_pathlist(RelOptInfo *rel)
00996 {
00997     /* Set dummy size estimates --- we leave attr_widths[] as zeroes */
00998     rel->rows = 0;
00999     rel->width = 0;
01000 
01001     /* Discard any pre-existing paths; no further need for them */
01002     rel->pathlist = NIL;
01003 
01004     add_path(rel, (Path *) create_append_path(rel, NIL, NULL));
01005 
01006     /* Select cheapest path (pretty easy in this case...) */
01007     set_cheapest(rel);
01008 }
01009 
01010 /* quick-and-dirty test to see if any joining is needed */
01011 static bool
01012 has_multiple_baserels(PlannerInfo *root)
01013 {
01014     int         num_base_rels = 0;
01015     Index       rti;
01016 
01017     for (rti = 1; rti < root->simple_rel_array_size; rti++)
01018     {
01019         RelOptInfo *brel = root->simple_rel_array[rti];
01020 
01021         if (brel == NULL)
01022             continue;
01023 
01024         /* ignore RTEs that are "other rels" */
01025         if (brel->reloptkind == RELOPT_BASEREL)
01026             if (++num_base_rels > 1)
01027                 return true;
01028     }
01029     return false;
01030 }
01031 
01032 /*
01033  * set_subquery_pathlist
01034  *      Build the (single) access path for a subquery RTE
01035  *
01036  * We don't currently support generating parameterized paths for subqueries
01037  * by pushing join clauses down into them; it seems too expensive to re-plan
01038  * the subquery multiple times to consider different alternatives.  So the
01039  * subquery will have exactly one path.  (The path will be parameterized
01040  * if the subquery contains LATERAL references, otherwise not.)  Since there's
01041  * no freedom of action here, there's no need for a separate set_subquery_size
01042  * phase: we just make the path right away.
01043  */
01044 static void
01045 set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
01046                       Index rti, RangeTblEntry *rte)
01047 {
01048     Query      *parse = root->parse;
01049     Query      *subquery = rte->subquery;
01050     Relids      required_outer;
01051     bool       *differentTypes;
01052     double      tuple_fraction;
01053     PlannerInfo *subroot;
01054     List       *pathkeys;
01055 
01056     /*
01057      * Must copy the Query so that planning doesn't mess up the RTE contents
01058      * (really really need to fix the planner to not scribble on its input,
01059      * someday).
01060      */
01061     subquery = copyObject(subquery);
01062 
01063     /*
01064      * If it's a LATERAL subquery, it might contain some Vars of the current
01065      * query level, requiring it to be treated as parameterized, even though
01066      * we don't support pushing down join quals into subqueries.
01067      */
01068     required_outer = rel->lateral_relids;
01069 
01070     /* We need a workspace for keeping track of set-op type coercions */
01071     differentTypes = (bool *)
01072         palloc0((list_length(subquery->targetList) + 1) * sizeof(bool));
01073 
01074     /*
01075      * If there are any restriction clauses that have been attached to the
01076      * subquery relation, consider pushing them down to become WHERE or HAVING
01077      * quals of the subquery itself.  This transformation is useful because it
01078      * may allow us to generate a better plan for the subquery than evaluating
01079      * all the subquery output rows and then filtering them.
01080      *
01081      * There are several cases where we cannot push down clauses. Restrictions
01082      * involving the subquery are checked by subquery_is_pushdown_safe().
01083      * Restrictions on individual clauses are checked by
01084      * qual_is_pushdown_safe().  Also, we don't want to push down
01085      * pseudoconstant clauses; better to have the gating node above the
01086      * subquery.
01087      *
01088      * Also, if the sub-query has the "security_barrier" flag, it means the
01089      * sub-query originated from a view that must enforce row-level security.
01090      * Then we must not push down quals that contain leaky functions.
01091      *
01092      * Non-pushed-down clauses will get evaluated as qpquals of the
01093      * SubqueryScan node.
01094      *
01095      * XXX Are there any cases where we want to make a policy decision not to
01096      * push down a pushable qual, because it'd result in a worse plan?
01097      */
01098     if (rel->baserestrictinfo != NIL &&
01099         subquery_is_pushdown_safe(subquery, subquery, differentTypes))
01100     {
01101         /* OK to consider pushing down individual quals */
01102         List       *upperrestrictlist = NIL;
01103         ListCell   *l;
01104 
01105         foreach(l, rel->baserestrictinfo)
01106         {
01107             RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
01108             Node       *clause = (Node *) rinfo->clause;
01109 
01110             if (!rinfo->pseudoconstant &&
01111                 (!rte->security_barrier ||
01112                  !contain_leaky_functions(clause)) &&
01113                 qual_is_pushdown_safe(subquery, rti, clause, differentTypes))
01114             {
01115                 /* Push it down */
01116                 subquery_push_qual(subquery, rte, rti, clause);
01117             }
01118             else
01119             {
01120                 /* Keep it in the upper query */
01121                 upperrestrictlist = lappend(upperrestrictlist, rinfo);
01122             }
01123         }
01124         rel->baserestrictinfo = upperrestrictlist;
01125     }
01126 
01127     pfree(differentTypes);
01128 
01129     /*
01130      * We can safely pass the outer tuple_fraction down to the subquery if the
01131      * outer level has no joining, aggregation, or sorting to do. Otherwise
01132      * we'd better tell the subquery to plan for full retrieval. (XXX This
01133      * could probably be made more intelligent ...)
01134      */
01135     if (parse->hasAggs ||
01136         parse->groupClause ||
01137         parse->havingQual ||
01138         parse->distinctClause ||
01139         parse->sortClause ||
01140         has_multiple_baserels(root))
01141         tuple_fraction = 0.0;   /* default case */
01142     else
01143         tuple_fraction = root->tuple_fraction;
01144 
01145     /* plan_params should not be in use in current query level */
01146     Assert(root->plan_params == NIL);
01147 
01148     /* Generate the plan for the subquery */
01149     rel->subplan = subquery_planner(root->glob, subquery,
01150                                     root,
01151                                     false, tuple_fraction,
01152                                     &subroot);
01153     rel->subroot = subroot;
01154 
01155     /* Isolate the params needed by this specific subplan */
01156     rel->subplan_params = root->plan_params;
01157     root->plan_params = NIL;
01158 
01159     /*
01160      * It's possible that constraint exclusion proved the subquery empty. If
01161      * so, it's convenient to turn it back into a dummy path so that we will
01162      * recognize appropriate optimizations at this query level.  (But see
01163      * create_append_plan in createplan.c, which has to reverse this
01164      * substitution.)
01165      */
01166     if (is_dummy_plan(rel->subplan))
01167     {
01168         set_dummy_rel_pathlist(rel);
01169         return;
01170     }
01171 
01172     /* Mark rel with estimated output rows, width, etc */
01173     set_subquery_size_estimates(root, rel);
01174 
01175     /* Convert subquery pathkeys to outer representation */
01176     pathkeys = convert_subquery_pathkeys(root, rel, subroot->query_pathkeys);
01177 
01178     /* Generate appropriate path */
01179     add_path(rel, create_subqueryscan_path(root, rel, pathkeys, required_outer));
01180 
01181     /* Select cheapest path (pretty easy in this case...) */
01182     set_cheapest(rel);
01183 }
01184 
01185 /*
01186  * set_function_pathlist
01187  *      Build the (single) access path for a function RTE
01188  */
01189 static void
01190 set_function_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01191 {
01192     Relids      required_outer;
01193 
01194     /*
01195      * We don't support pushing join clauses into the quals of a function
01196      * scan, but it could still have required parameterization due to LATERAL
01197      * refs in the function expression.
01198      */
01199     required_outer = rel->lateral_relids;
01200 
01201     /* Generate appropriate path */
01202     add_path(rel, create_functionscan_path(root, rel, required_outer));
01203 
01204     /* Select cheapest path (pretty easy in this case...) */
01205     set_cheapest(rel);
01206 }
01207 
01208 /*
01209  * set_values_pathlist
01210  *      Build the (single) access path for a VALUES RTE
01211  */
01212 static void
01213 set_values_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01214 {
01215     Relids      required_outer;
01216 
01217     /*
01218      * We don't support pushing join clauses into the quals of a values scan,
01219      * but it could still have required parameterization due to LATERAL refs
01220      * in the values expressions.
01221      */
01222     required_outer = rel->lateral_relids;
01223 
01224     /* Generate appropriate path */
01225     add_path(rel, create_valuesscan_path(root, rel, required_outer));
01226 
01227     /* Select cheapest path (pretty easy in this case...) */
01228     set_cheapest(rel);
01229 }
01230 
01231 /*
01232  * set_cte_pathlist
01233  *      Build the (single) access path for a non-self-reference CTE RTE
01234  *
01235  * There's no need for a separate set_cte_size phase, since we don't
01236  * support join-qual-parameterized paths for CTEs.
01237  */
01238 static void
01239 set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01240 {
01241     Plan       *cteplan;
01242     PlannerInfo *cteroot;
01243     Index       levelsup;
01244     int         ndx;
01245     ListCell   *lc;
01246     int         plan_id;
01247     Relids      required_outer;
01248 
01249     /*
01250      * Find the referenced CTE, and locate the plan previously made for it.
01251      */
01252     levelsup = rte->ctelevelsup;
01253     cteroot = root;
01254     while (levelsup-- > 0)
01255     {
01256         cteroot = cteroot->parent_root;
01257         if (!cteroot)           /* shouldn't happen */
01258             elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01259     }
01260 
01261     /*
01262      * Note: cte_plan_ids can be shorter than cteList, if we are still working
01263      * on planning the CTEs (ie, this is a side-reference from another CTE).
01264      * So we mustn't use forboth here.
01265      */
01266     ndx = 0;
01267     foreach(lc, cteroot->parse->cteList)
01268     {
01269         CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
01270 
01271         if (strcmp(cte->ctename, rte->ctename) == 0)
01272             break;
01273         ndx++;
01274     }
01275     if (lc == NULL)             /* shouldn't happen */
01276         elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
01277     if (ndx >= list_length(cteroot->cte_plan_ids))
01278         elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
01279     plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
01280     Assert(plan_id > 0);
01281     cteplan = (Plan *) list_nth(root->glob->subplans, plan_id - 1);
01282 
01283     /* Mark rel with estimated output rows, width, etc */
01284     set_cte_size_estimates(root, rel, cteplan);
01285 
01286     /*
01287      * We don't support pushing join clauses into the quals of a CTE scan, but
01288      * it could still have required parameterization due to LATERAL refs in
01289      * its tlist.  (That can only happen if the CTE scan is on a relation
01290      * pulled up out of a UNION ALL appendrel.)
01291      */
01292     required_outer = rel->lateral_relids;
01293 
01294     /* Generate appropriate path */
01295     add_path(rel, create_ctescan_path(root, rel, required_outer));
01296 
01297     /* Select cheapest path (pretty easy in this case...) */
01298     set_cheapest(rel);
01299 }
01300 
01301 /*
01302  * set_worktable_pathlist
01303  *      Build the (single) access path for a self-reference CTE RTE
01304  *
01305  * There's no need for a separate set_worktable_size phase, since we don't
01306  * support join-qual-parameterized paths for CTEs.
01307  */
01308 static void
01309 set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
01310 {
01311     Plan       *cteplan;
01312     PlannerInfo *cteroot;
01313     Index       levelsup;
01314     Relids      required_outer;
01315 
01316     /*
01317      * We need to find the non-recursive term's plan, which is in the plan
01318      * level that's processing the recursive UNION, which is one level *below*
01319      * where the CTE comes from.
01320      */
01321     levelsup = rte->ctelevelsup;
01322     if (levelsup == 0)          /* shouldn't happen */
01323         elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01324     levelsup--;
01325     cteroot = root;
01326     while (levelsup-- > 0)
01327     {
01328         cteroot = cteroot->parent_root;
01329         if (!cteroot)           /* shouldn't happen */
01330             elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
01331     }
01332     cteplan = cteroot->non_recursive_plan;
01333     if (!cteplan)               /* shouldn't happen */
01334         elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
01335 
01336     /* Mark rel with estimated output rows, width, etc */
01337     set_cte_size_estimates(root, rel, cteplan);
01338 
01339     /*
01340      * We don't support pushing join clauses into the quals of a worktable
01341      * scan, but it could still have required parameterization due to LATERAL
01342      * refs in its tlist.  (That can only happen if the worktable scan is on a
01343      * relation pulled up out of a UNION ALL appendrel.  I'm not sure this is
01344      * actually possible given the restrictions on recursive references, but
01345      * it's easy enough to support.)
01346      */
01347     required_outer = rel->lateral_relids;
01348 
01349     /* Generate appropriate path */
01350     add_path(rel, create_worktablescan_path(root, rel, required_outer));
01351 
01352     /* Select cheapest path (pretty easy in this case...) */
01353     set_cheapest(rel);
01354 }
01355 
01356 /*
01357  * make_rel_from_joinlist
01358  *    Build access paths using a "joinlist" to guide the join path search.
01359  *
01360  * See comments for deconstruct_jointree() for definition of the joinlist
01361  * data structure.
01362  */
01363 static RelOptInfo *
01364 make_rel_from_joinlist(PlannerInfo *root, List *joinlist)
01365 {
01366     int         levels_needed;
01367     List       *initial_rels;
01368     ListCell   *jl;
01369 
01370     /*
01371      * Count the number of child joinlist nodes.  This is the depth of the
01372      * dynamic-programming algorithm we must employ to consider all ways of
01373      * joining the child nodes.
01374      */
01375     levels_needed = list_length(joinlist);
01376 
01377     if (levels_needed <= 0)
01378         return NULL;            /* nothing to do? */
01379 
01380     /*
01381      * Construct a list of rels corresponding to the child joinlist nodes.
01382      * This may contain both base rels and rels constructed according to
01383      * sub-joinlists.
01384      */
01385     initial_rels = NIL;
01386     foreach(jl, joinlist)
01387     {
01388         Node       *jlnode = (Node *) lfirst(jl);
01389         RelOptInfo *thisrel;
01390 
01391         if (IsA(jlnode, RangeTblRef))
01392         {
01393             int         varno = ((RangeTblRef *) jlnode)->rtindex;
01394 
01395             thisrel = find_base_rel(root, varno);
01396         }
01397         else if (IsA(jlnode, List))
01398         {
01399             /* Recurse to handle subproblem */
01400             thisrel = make_rel_from_joinlist(root, (List *) jlnode);
01401         }
01402         else
01403         {
01404             elog(ERROR, "unrecognized joinlist node type: %d",
01405                  (int) nodeTag(jlnode));
01406             thisrel = NULL;     /* keep compiler quiet */
01407         }
01408 
01409         initial_rels = lappend(initial_rels, thisrel);
01410     }
01411 
01412     if (levels_needed == 1)
01413     {
01414         /*
01415          * Single joinlist node, so we're done.
01416          */
01417         return (RelOptInfo *) linitial(initial_rels);
01418     }
01419     else
01420     {
01421         /*
01422          * Consider the different orders in which we could join the rels,
01423          * using a plugin, GEQO, or the regular join search code.
01424          *
01425          * We put the initial_rels list into a PlannerInfo field because
01426          * has_legal_joinclause() needs to look at it (ugly :-().
01427          */
01428         root->initial_rels = initial_rels;
01429 
01430         if (join_search_hook)
01431             return (*join_search_hook) (root, levels_needed, initial_rels);
01432         else if (enable_geqo && levels_needed >= geqo_threshold)
01433             return geqo(root, levels_needed, initial_rels);
01434         else
01435             return standard_join_search(root, levels_needed, initial_rels);
01436     }
01437 }
01438 
01439 /*
01440  * standard_join_search
01441  *    Find possible joinpaths for a query by successively finding ways
01442  *    to join component relations into join relations.
01443  *
01444  * 'levels_needed' is the number of iterations needed, ie, the number of
01445  *      independent jointree items in the query.  This is > 1.
01446  *
01447  * 'initial_rels' is a list of RelOptInfo nodes for each independent
01448  *      jointree item.  These are the components to be joined together.
01449  *      Note that levels_needed == list_length(initial_rels).
01450  *
01451  * Returns the final level of join relations, i.e., the relation that is
01452  * the result of joining all the original relations together.
01453  * At least one implementation path must be provided for this relation and
01454  * all required sub-relations.
01455  *
01456  * To support loadable plugins that modify planner behavior by changing the
01457  * join searching algorithm, we provide a hook variable that lets a plugin
01458  * replace or supplement this function.  Any such hook must return the same
01459  * final join relation as the standard code would, but it might have a
01460  * different set of implementation paths attached, and only the sub-joinrels
01461  * needed for these paths need have been instantiated.
01462  *
01463  * Note to plugin authors: the functions invoked during standard_join_search()
01464  * modify root->join_rel_list and root->join_rel_hash.  If you want to do more
01465  * than one join-order search, you'll probably need to save and restore the
01466  * original states of those data structures.  See geqo_eval() for an example.
01467  */
01468 RelOptInfo *
01469 standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
01470 {
01471     int         lev;
01472     RelOptInfo *rel;
01473 
01474     /*
01475      * This function cannot be invoked recursively within any one planning
01476      * problem, so join_rel_level[] can't be in use already.
01477      */
01478     Assert(root->join_rel_level == NULL);
01479 
01480     /*
01481      * We employ a simple "dynamic programming" algorithm: we first find all
01482      * ways to build joins of two jointree items, then all ways to build joins
01483      * of three items (from two-item joins and single items), then four-item
01484      * joins, and so on until we have considered all ways to join all the
01485      * items into one rel.
01486      *
01487      * root->join_rel_level[j] is a list of all the j-item rels.  Initially we
01488      * set root->join_rel_level[1] to represent all the single-jointree-item
01489      * relations.
01490      */
01491     root->join_rel_level = (List **) palloc0((levels_needed + 1) * sizeof(List *));
01492 
01493     root->join_rel_level[1] = initial_rels;
01494 
01495     for (lev = 2; lev <= levels_needed; lev++)
01496     {
01497         ListCell   *lc;
01498 
01499         /*
01500          * Determine all possible pairs of relations to be joined at this
01501          * level, and build paths for making each one from every available
01502          * pair of lower-level relations.
01503          */
01504         join_search_one_level(root, lev);
01505 
01506         /*
01507          * Do cleanup work on each just-processed rel.
01508          */
01509         foreach(lc, root->join_rel_level[lev])
01510         {
01511             rel = (RelOptInfo *) lfirst(lc);
01512 
01513             /* Find and save the cheapest paths for this rel */
01514             set_cheapest(rel);
01515 
01516 #ifdef OPTIMIZER_DEBUG
01517             debug_print_rel(root, rel);
01518 #endif
01519         }
01520     }
01521 
01522     /*
01523      * We should have a single rel at the final level.
01524      */
01525     if (root->join_rel_level[levels_needed] == NIL)
01526         elog(ERROR, "failed to build any %d-way joins", levels_needed);
01527     Assert(list_length(root->join_rel_level[levels_needed]) == 1);
01528 
01529     rel = (RelOptInfo *) linitial(root->join_rel_level[levels_needed]);
01530 
01531     root->join_rel_level = NULL;
01532 
01533     return rel;
01534 }
01535 
01536 /*****************************************************************************
01537  *          PUSHING QUALS DOWN INTO SUBQUERIES
01538  *****************************************************************************/
01539 
01540 /*
01541  * subquery_is_pushdown_safe - is a subquery safe for pushing down quals?
01542  *
01543  * subquery is the particular component query being checked.  topquery
01544  * is the top component of a set-operations tree (the same Query if no
01545  * set-op is involved).
01546  *
01547  * Conditions checked here:
01548  *
01549  * 1. If the subquery has a LIMIT clause, we must not push down any quals,
01550  * since that could change the set of rows returned.
01551  *
01552  * 2. If the subquery contains any window functions, we can't push quals
01553  * into it, because that could change the results.
01554  *
01555  * 3. If the subquery contains EXCEPT or EXCEPT ALL set ops we cannot push
01556  * quals into it, because that could change the results.
01557  *
01558  * 4. For subqueries using UNION/UNION ALL/INTERSECT/INTERSECT ALL, we can
01559  * push quals into each component query, but the quals can only reference
01560  * subquery columns that suffer no type coercions in the set operation.
01561  * Otherwise there are possible semantic gotchas.  So, we check the
01562  * component queries to see if any of them have different output types;
01563  * differentTypes[k] is set true if column k has different type in any
01564  * component.
01565  */
01566 static bool
01567 subquery_is_pushdown_safe(Query *subquery, Query *topquery,
01568                           bool *differentTypes)
01569 {
01570     SetOperationStmt *topop;
01571 
01572     /* Check point 1 */
01573     if (subquery->limitOffset != NULL || subquery->limitCount != NULL)
01574         return false;
01575 
01576     /* Check point 2 */
01577     if (subquery->hasWindowFuncs)
01578         return false;
01579 
01580     /* Are we at top level, or looking at a setop component? */
01581     if (subquery == topquery)
01582     {
01583         /* Top level, so check any component queries */
01584         if (subquery->setOperations != NULL)
01585             if (!recurse_pushdown_safe(subquery->setOperations, topquery,
01586                                        differentTypes))
01587                 return false;
01588     }
01589     else
01590     {
01591         /* Setop component must not have more components (too weird) */
01592         if (subquery->setOperations != NULL)
01593             return false;
01594         /* Check whether setop component output types match top level */
01595         topop = (SetOperationStmt *) topquery->setOperations;
01596         Assert(topop && IsA(topop, SetOperationStmt));
01597         compare_tlist_datatypes(subquery->targetList,
01598                                 topop->colTypes,
01599                                 differentTypes);
01600     }
01601     return true;
01602 }
01603 
01604 /*
01605  * Helper routine to recurse through setOperations tree
01606  */
01607 static bool
01608 recurse_pushdown_safe(Node *setOp, Query *topquery,
01609                       bool *differentTypes)
01610 {
01611     if (IsA(setOp, RangeTblRef))
01612     {
01613         RangeTblRef *rtr = (RangeTblRef *) setOp;
01614         RangeTblEntry *rte = rt_fetch(rtr->rtindex, topquery->rtable);
01615         Query      *subquery = rte->subquery;
01616 
01617         Assert(subquery != NULL);
01618         return subquery_is_pushdown_safe(subquery, topquery, differentTypes);
01619     }
01620     else if (IsA(setOp, SetOperationStmt))
01621     {
01622         SetOperationStmt *op = (SetOperationStmt *) setOp;
01623 
01624         /* EXCEPT is no good */
01625         if (op->op == SETOP_EXCEPT)
01626             return false;
01627         /* Else recurse */
01628         if (!recurse_pushdown_safe(op->larg, topquery, differentTypes))
01629             return false;
01630         if (!recurse_pushdown_safe(op->rarg, topquery, differentTypes))
01631             return false;
01632     }
01633     else
01634     {
01635         elog(ERROR, "unrecognized node type: %d",
01636              (int) nodeTag(setOp));
01637     }
01638     return true;
01639 }
01640 
01641 /*
01642  * Compare tlist's datatypes against the list of set-operation result types.
01643  * For any items that are different, mark the appropriate element of
01644  * differentTypes[] to show that this column will have type conversions.
01645  *
01646  * We don't have to care about typmods here: the only allowed difference
01647  * between set-op input and output typmods is input is a specific typmod
01648  * and output is -1, and that does not require a coercion.
01649  */
01650 static void
01651 compare_tlist_datatypes(List *tlist, List *colTypes,
01652                         bool *differentTypes)
01653 {
01654     ListCell   *l;
01655     ListCell   *colType = list_head(colTypes);
01656 
01657     foreach(l, tlist)
01658     {
01659         TargetEntry *tle = (TargetEntry *) lfirst(l);
01660 
01661         if (tle->resjunk)
01662             continue;           /* ignore resjunk columns */
01663         if (colType == NULL)
01664             elog(ERROR, "wrong number of tlist entries");
01665         if (exprType((Node *) tle->expr) != lfirst_oid(colType))
01666             differentTypes[tle->resno] = true;
01667         colType = lnext(colType);
01668     }
01669     if (colType != NULL)
01670         elog(ERROR, "wrong number of tlist entries");
01671 }
01672 
01673 /*
01674  * qual_is_pushdown_safe - is a particular qual safe to push down?
01675  *
01676  * qual is a restriction clause applying to the given subquery (whose RTE
01677  * has index rti in the parent query).
01678  *
01679  * Conditions checked here:
01680  *
01681  * 1. The qual must not contain any subselects (mainly because I'm not sure
01682  * it will work correctly: sublinks will already have been transformed into
01683  * subplans in the qual, but not in the subquery).
01684  *
01685  * 2. The qual must not refer to the whole-row output of the subquery
01686  * (since there is no easy way to name that within the subquery itself).
01687  *
01688  * 3. The qual must not refer to any subquery output columns that were
01689  * found to have inconsistent types across a set operation tree by
01690  * subquery_is_pushdown_safe().
01691  *
01692  * 4. If the subquery uses DISTINCT ON, we must not push down any quals that
01693  * refer to non-DISTINCT output columns, because that could change the set
01694  * of rows returned.  (This condition is vacuous for DISTINCT, because then
01695  * there are no non-DISTINCT output columns, so we needn't check.  But note
01696  * we are assuming that the qual can't distinguish values that the DISTINCT
01697  * operator sees as equal.  This is a bit shaky but we have no way to test
01698  * for the case, and it's unlikely enough that we shouldn't refuse the
01699  * optimization just because it could theoretically happen.)
01700  *
01701  * 5. We must not push down any quals that refer to subselect outputs that
01702  * return sets, else we'd introduce functions-returning-sets into the
01703  * subquery's WHERE/HAVING quals.
01704  *
01705  * 6. We must not push down any quals that refer to subselect outputs that
01706  * contain volatile functions, for fear of introducing strange results due
01707  * to multiple evaluation of a volatile function.
01708  */
01709 static bool
01710 qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
01711                       bool *differentTypes)
01712 {
01713     bool        safe = true;
01714     List       *vars;
01715     ListCell   *vl;
01716     Bitmapset  *tested = NULL;
01717 
01718     /* Refuse subselects (point 1) */
01719     if (contain_subplans(qual))
01720         return false;
01721 
01722     /*
01723      * It would be unsafe to push down window function calls, but at least for
01724      * the moment we could never see any in a qual anyhow.  (The same applies
01725      * to aggregates, which we check for in pull_var_clause below.)
01726      */
01727     Assert(!contain_window_function(qual));
01728 
01729     /*
01730      * Examine all Vars used in clause; since it's a restriction clause, all
01731      * such Vars must refer to subselect output columns.
01732      */
01733     vars = pull_var_clause(qual,
01734                            PVC_REJECT_AGGREGATES,
01735                            PVC_INCLUDE_PLACEHOLDERS);
01736     foreach(vl, vars)
01737     {
01738         Var        *var = (Var *) lfirst(vl);
01739         TargetEntry *tle;
01740 
01741         /*
01742          * XXX Punt if we find any PlaceHolderVars in the restriction clause.
01743          * It's not clear whether a PHV could safely be pushed down, and even
01744          * less clear whether such a situation could arise in any cases of
01745          * practical interest anyway.  So for the moment, just refuse to push
01746          * down.
01747          */
01748         if (!IsA(var, Var))
01749         {
01750             safe = false;
01751             break;
01752         }
01753 
01754         Assert(var->varno == rti);
01755 
01756         /* Check point 2 */
01757         if (var->varattno == 0)
01758         {
01759             safe = false;
01760             break;
01761         }
01762 
01763         /*
01764          * We use a bitmapset to avoid testing the same attno more than once.
01765          * (NB: this only works because subquery outputs can't have negative
01766          * attnos.)
01767          */
01768         if (bms_is_member(var->varattno, tested))
01769             continue;
01770         tested = bms_add_member(tested, var->varattno);
01771 
01772         /* Check point 3 */
01773         if (differentTypes[var->varattno])
01774         {
01775             safe = false;
01776             break;
01777         }
01778 
01779         /* Must find the tlist element referenced by the Var */
01780         tle = get_tle_by_resno(subquery->targetList, var->varattno);
01781         Assert(tle != NULL);
01782         Assert(!tle->resjunk);
01783 
01784         /* If subquery uses DISTINCT ON, check point 4 */
01785         if (subquery->hasDistinctOn &&
01786             !targetIsInSortList(tle, InvalidOid, subquery->distinctClause))
01787         {
01788             /* non-DISTINCT column, so fail */
01789             safe = false;
01790             break;
01791         }
01792 
01793         /* Refuse functions returning sets (point 5) */
01794         if (expression_returns_set((Node *) tle->expr))
01795         {
01796             safe = false;
01797             break;
01798         }
01799 
01800         /* Refuse volatile functions (point 6) */
01801         if (contain_volatile_functions((Node *) tle->expr))
01802         {
01803             safe = false;
01804             break;
01805         }
01806     }
01807 
01808     list_free(vars);
01809     bms_free(tested);
01810 
01811     return safe;
01812 }
01813 
01814 /*
01815  * subquery_push_qual - push down a qual that we have determined is safe
01816  */
01817 static void
01818 subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
01819 {
01820     if (subquery->setOperations != NULL)
01821     {
01822         /* Recurse to push it separately to each component query */
01823         recurse_push_qual(subquery->setOperations, subquery,
01824                           rte, rti, qual);
01825     }
01826     else
01827     {
01828         /*
01829          * We need to replace Vars in the qual (which must refer to outputs of
01830          * the subquery) with copies of the subquery's targetlist expressions.
01831          * Note that at this point, any uplevel Vars in the qual should have
01832          * been replaced with Params, so they need no work.
01833          *
01834          * This step also ensures that when we are pushing into a setop tree,
01835          * each component query gets its own copy of the qual.
01836          */
01837         qual = ReplaceVarsFromTargetList(qual, rti, 0, rte,
01838                                          subquery->targetList,
01839                                          REPLACEVARS_REPORT_ERROR, 0,
01840                                          &subquery->hasSubLinks);
01841 
01842         /*
01843          * Now attach the qual to the proper place: normally WHERE, but if the
01844          * subquery uses grouping or aggregation, put it in HAVING (since the
01845          * qual really refers to the group-result rows).
01846          */
01847         if (subquery->hasAggs || subquery->groupClause || subquery->havingQual)
01848             subquery->havingQual = make_and_qual(subquery->havingQual, qual);
01849         else
01850             subquery->jointree->quals =
01851                 make_and_qual(subquery->jointree->quals, qual);
01852 
01853         /*
01854          * We need not change the subquery's hasAggs or hasSublinks flags,
01855          * since we can't be pushing down any aggregates that weren't there
01856          * before, and we don't push down subselects at all.
01857          */
01858     }
01859 }
01860 
01861 /*
01862  * Helper routine to recurse through setOperations tree
01863  */
01864 static void
01865 recurse_push_qual(Node *setOp, Query *topquery,
01866                   RangeTblEntry *rte, Index rti, Node *qual)
01867 {
01868     if (IsA(setOp, RangeTblRef))
01869     {
01870         RangeTblRef *rtr = (RangeTblRef *) setOp;
01871         RangeTblEntry *subrte = rt_fetch(rtr->rtindex, topquery->rtable);
01872         Query      *subquery = subrte->subquery;
01873 
01874         Assert(subquery != NULL);
01875         subquery_push_qual(subquery, rte, rti, qual);
01876     }
01877     else if (IsA(setOp, SetOperationStmt))
01878     {
01879         SetOperationStmt *op = (SetOperationStmt *) setOp;
01880 
01881         recurse_push_qual(op->larg, topquery, rte, rti, qual);
01882         recurse_push_qual(op->rarg, topquery, rte, rti, qual);
01883     }
01884     else
01885     {
01886         elog(ERROR, "unrecognized node type: %d",
01887              (int) nodeTag(setOp));
01888     }
01889 }
01890 
01891 /*****************************************************************************
01892  *          DEBUG SUPPORT
01893  *****************************************************************************/
01894 
01895 #ifdef OPTIMIZER_DEBUG
01896 
01897 static void
01898 print_relids(Relids relids)
01899 {
01900     Relids      tmprelids;
01901     int         x;
01902     bool        first = true;
01903 
01904     tmprelids = bms_copy(relids);
01905     while ((x = bms_first_member(tmprelids)) >= 0)
01906     {
01907         if (!first)
01908             printf(" ");
01909         printf("%d", x);
01910         first = false;
01911     }
01912     bms_free(tmprelids);
01913 }
01914 
01915 static void
01916 print_restrictclauses(PlannerInfo *root, List *clauses)
01917 {
01918     ListCell   *l;
01919 
01920     foreach(l, clauses)
01921     {
01922         RestrictInfo *c = lfirst(l);
01923 
01924         print_expr((Node *) c->clause, root->parse->rtable);
01925         if (lnext(l))
01926             printf(", ");
01927     }
01928 }
01929 
01930 static void
01931 print_path(PlannerInfo *root, Path *path, int indent)
01932 {
01933     const char *ptype;
01934     bool        join = false;
01935     Path       *subpath = NULL;
01936     int         i;
01937 
01938     switch (nodeTag(path))
01939     {
01940         case T_Path:
01941             ptype = "SeqScan";
01942             break;
01943         case T_IndexPath:
01944             ptype = "IdxScan";
01945             break;
01946         case T_BitmapHeapPath:
01947             ptype = "BitmapHeapScan";
01948             break;
01949         case T_BitmapAndPath:
01950             ptype = "BitmapAndPath";
01951             break;
01952         case T_BitmapOrPath:
01953             ptype = "BitmapOrPath";
01954             break;
01955         case T_TidPath:
01956             ptype = "TidScan";
01957             break;
01958         case T_ForeignPath:
01959             ptype = "ForeignScan";
01960             break;
01961         case T_AppendPath:
01962             ptype = "Append";
01963             break;
01964         case T_MergeAppendPath:
01965             ptype = "MergeAppend";
01966             break;
01967         case T_ResultPath:
01968             ptype = "Result";
01969             break;
01970         case T_MaterialPath:
01971             ptype = "Material";
01972             subpath = ((MaterialPath *) path)->subpath;
01973             break;
01974         case T_UniquePath:
01975             ptype = "Unique";
01976             subpath = ((UniquePath *) path)->subpath;
01977             break;
01978         case T_NestPath:
01979             ptype = "NestLoop";
01980             join = true;
01981             break;
01982         case T_MergePath:
01983             ptype = "MergeJoin";
01984             join = true;
01985             break;
01986         case T_HashPath:
01987             ptype = "HashJoin";
01988             join = true;
01989             break;
01990         default:
01991             ptype = "???Path";
01992             break;
01993     }
01994 
01995     for (i = 0; i < indent; i++)
01996         printf("\t");
01997     printf("%s", ptype);
01998 
01999     if (path->parent)
02000     {
02001         printf("(");
02002         print_relids(path->parent->relids);
02003         printf(") rows=%.0f", path->parent->rows);
02004     }
02005     printf(" cost=%.2f..%.2f\n", path->startup_cost, path->total_cost);
02006 
02007     if (path->pathkeys)
02008     {
02009         for (i = 0; i < indent; i++)
02010             printf("\t");
02011         printf("  pathkeys: ");
02012         print_pathkeys(path->pathkeys, root->parse->rtable);
02013     }
02014 
02015     if (join)
02016     {
02017         JoinPath   *jp = (JoinPath *) path;
02018 
02019         for (i = 0; i < indent; i++)
02020             printf("\t");
02021         printf("  clauses: ");
02022         print_restrictclauses(root, jp->joinrestrictinfo);
02023         printf("\n");
02024 
02025         if (IsA(path, MergePath))
02026         {
02027             MergePath  *mp = (MergePath *) path;
02028 
02029             for (i = 0; i < indent; i++)
02030                 printf("\t");
02031             printf("  sortouter=%d sortinner=%d materializeinner=%d\n",
02032                    ((mp->outersortkeys) ? 1 : 0),
02033                    ((mp->innersortkeys) ? 1 : 0),
02034                    ((mp->materialize_inner) ? 1 : 0));
02035         }
02036 
02037         print_path(root, jp->outerjoinpath, indent + 1);
02038         print_path(root, jp->innerjoinpath, indent + 1);
02039     }
02040 
02041     if (subpath)
02042         print_path(root, subpath, indent + 1);
02043 }
02044 
02045 void
02046 debug_print_rel(PlannerInfo *root, RelOptInfo *rel)
02047 {
02048     ListCell   *l;
02049 
02050     printf("RELOPTINFO (");
02051     print_relids(rel->relids);
02052     printf("): rows=%.0f width=%d\n", rel->rows, rel->width);
02053 
02054     if (rel->baserestrictinfo)
02055     {
02056         printf("\tbaserestrictinfo: ");
02057         print_restrictclauses(root, rel->baserestrictinfo);
02058         printf("\n");
02059     }
02060 
02061     if (rel->joininfo)
02062     {
02063         printf("\tjoininfo: ");
02064         print_restrictclauses(root, rel->joininfo);
02065         printf("\n");
02066     }
02067 
02068     printf("\tpath list:\n");
02069     foreach(l, rel->pathlist)
02070         print_path(root, lfirst(l), 1);
02071     if (rel->cheapest_startup_path)
02072     {
02073         printf("\n\tcheapest startup path:\n");
02074         print_path(root, rel->cheapest_startup_path, 1);
02075     }
02076     if (rel->cheapest_total_path)
02077     {
02078         printf("\n\tcheapest total path:\n");
02079         print_path(root, rel->cheapest_total_path, 1);
02080     }
02081     printf("\n");
02082     fflush(stdout);
02083 }
02084 
02085 #endif   /* OPTIMIZER_DEBUG */