Header And Logo

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

relnode.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * relnode.c
00004  *    Relation-node lookup/construction routines
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/util/relnode.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "optimizer/cost.h"
00018 #include "optimizer/pathnode.h"
00019 #include "optimizer/paths.h"
00020 #include "optimizer/placeholder.h"
00021 #include "optimizer/plancat.h"
00022 #include "optimizer/restrictinfo.h"
00023 #include "utils/hsearch.h"
00024 
00025 
00026 typedef struct JoinHashEntry
00027 {
00028     Relids      join_relids;    /* hash key --- MUST BE FIRST */
00029     RelOptInfo *join_rel;
00030 } JoinHashEntry;
00031 
00032 static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
00033                     RelOptInfo *input_rel);
00034 static List *build_joinrel_restrictlist(PlannerInfo *root,
00035                            RelOptInfo *joinrel,
00036                            RelOptInfo *outer_rel,
00037                            RelOptInfo *inner_rel);
00038 static void build_joinrel_joinlist(RelOptInfo *joinrel,
00039                        RelOptInfo *outer_rel,
00040                        RelOptInfo *inner_rel);
00041 static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
00042                               List *joininfo_list,
00043                               List *new_restrictlist);
00044 static List *subbuild_joinrel_joinlist(RelOptInfo *joinrel,
00045                           List *joininfo_list,
00046                           List *new_joininfo);
00047 
00048 
00049 /*
00050  * setup_simple_rel_arrays
00051  *    Prepare the arrays we use for quickly accessing base relations.
00052  */
00053 void
00054 setup_simple_rel_arrays(PlannerInfo *root)
00055 {
00056     Index       rti;
00057     ListCell   *lc;
00058 
00059     /* Arrays are accessed using RT indexes (1..N) */
00060     root->simple_rel_array_size = list_length(root->parse->rtable) + 1;
00061 
00062     /* simple_rel_array is initialized to all NULLs */
00063     root->simple_rel_array = (RelOptInfo **)
00064         palloc0(root->simple_rel_array_size * sizeof(RelOptInfo *));
00065 
00066     /* simple_rte_array is an array equivalent of the rtable list */
00067     root->simple_rte_array = (RangeTblEntry **)
00068         palloc0(root->simple_rel_array_size * sizeof(RangeTblEntry *));
00069     rti = 1;
00070     foreach(lc, root->parse->rtable)
00071     {
00072         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
00073 
00074         root->simple_rte_array[rti++] = rte;
00075     }
00076 }
00077 
00078 /*
00079  * build_simple_rel
00080  *    Construct a new RelOptInfo for a base relation or 'other' relation.
00081  */
00082 RelOptInfo *
00083 build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
00084 {
00085     RelOptInfo *rel;
00086     RangeTblEntry *rte;
00087 
00088     /* Rel should not exist already */
00089     Assert(relid > 0 && relid < root->simple_rel_array_size);
00090     if (root->simple_rel_array[relid] != NULL)
00091         elog(ERROR, "rel %d already exists", relid);
00092 
00093     /* Fetch RTE for relation */
00094     rte = root->simple_rte_array[relid];
00095     Assert(rte != NULL);
00096 
00097     rel = makeNode(RelOptInfo);
00098     rel->reloptkind = reloptkind;
00099     rel->relids = bms_make_singleton(relid);
00100     rel->rows = 0;
00101     rel->width = 0;
00102     /* cheap startup cost is interesting iff not all tuples to be retrieved */
00103     rel->consider_startup = (root->tuple_fraction > 0);
00104     rel->reltargetlist = NIL;
00105     rel->pathlist = NIL;
00106     rel->ppilist = NIL;
00107     rel->cheapest_startup_path = NULL;
00108     rel->cheapest_total_path = NULL;
00109     rel->cheapest_unique_path = NULL;
00110     rel->cheapest_parameterized_paths = NIL;
00111     rel->relid = relid;
00112     rel->rtekind = rte->rtekind;
00113     /* min_attr, max_attr, attr_needed, attr_widths are set below */
00114     rel->lateral_vars = NIL;
00115     rel->lateral_relids = NULL;
00116     rel->indexlist = NIL;
00117     rel->pages = 0;
00118     rel->tuples = 0;
00119     rel->allvisfrac = 0;
00120     rel->subplan = NULL;
00121     rel->subroot = NULL;
00122     rel->subplan_params = NIL;
00123     rel->fdwroutine = NULL;
00124     rel->fdw_private = NULL;
00125     rel->baserestrictinfo = NIL;
00126     rel->baserestrictcost.startup = 0;
00127     rel->baserestrictcost.per_tuple = 0;
00128     rel->joininfo = NIL;
00129     rel->has_eclass_joins = false;
00130 
00131     /* Check type of rtable entry */
00132     switch (rte->rtekind)
00133     {
00134         case RTE_RELATION:
00135             /* Table --- retrieve statistics from the system catalogs */
00136             get_relation_info(root, rte->relid, rte->inh, rel);
00137             break;
00138         case RTE_SUBQUERY:
00139         case RTE_FUNCTION:
00140         case RTE_VALUES:
00141         case RTE_CTE:
00142 
00143             /*
00144              * Subquery, function, or values list --- set up attr range and
00145              * arrays
00146              *
00147              * Note: 0 is included in range to support whole-row Vars
00148              */
00149             rel->min_attr = 0;
00150             rel->max_attr = list_length(rte->eref->colnames);
00151             rel->attr_needed = (Relids *)
00152                 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
00153             rel->attr_widths = (int32 *)
00154                 palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));
00155             break;
00156         default:
00157             elog(ERROR, "unrecognized RTE kind: %d",
00158                  (int) rte->rtekind);
00159             break;
00160     }
00161 
00162     /* Save the finished struct in the query's simple_rel_array */
00163     root->simple_rel_array[relid] = rel;
00164 
00165     /*
00166      * If this rel is an appendrel parent, recurse to build "other rel"
00167      * RelOptInfos for its children.  They are "other rels" because they are
00168      * not in the main join tree, but we will need RelOptInfos to plan access
00169      * to them.
00170      */
00171     if (rte->inh)
00172     {
00173         ListCell   *l;
00174 
00175         foreach(l, root->append_rel_list)
00176         {
00177             AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
00178 
00179             /* append_rel_list contains all append rels; ignore others */
00180             if (appinfo->parent_relid != relid)
00181                 continue;
00182 
00183             (void) build_simple_rel(root, appinfo->child_relid,
00184                                     RELOPT_OTHER_MEMBER_REL);
00185         }
00186     }
00187 
00188     return rel;
00189 }
00190 
00191 /*
00192  * find_base_rel
00193  *    Find a base or other relation entry, which must already exist.
00194  */
00195 RelOptInfo *
00196 find_base_rel(PlannerInfo *root, int relid)
00197 {
00198     RelOptInfo *rel;
00199 
00200     Assert(relid > 0);
00201 
00202     if (relid < root->simple_rel_array_size)
00203     {
00204         rel = root->simple_rel_array[relid];
00205         if (rel)
00206             return rel;
00207     }
00208 
00209     elog(ERROR, "no relation entry for relid %d", relid);
00210 
00211     return NULL;                /* keep compiler quiet */
00212 }
00213 
00214 /*
00215  * build_join_rel_hash
00216  *    Construct the auxiliary hash table for join relations.
00217  */
00218 static void
00219 build_join_rel_hash(PlannerInfo *root)
00220 {
00221     HTAB       *hashtab;
00222     HASHCTL     hash_ctl;
00223     ListCell   *l;
00224 
00225     /* Create the hash table */
00226     MemSet(&hash_ctl, 0, sizeof(hash_ctl));
00227     hash_ctl.keysize = sizeof(Relids);
00228     hash_ctl.entrysize = sizeof(JoinHashEntry);
00229     hash_ctl.hash = bitmap_hash;
00230     hash_ctl.match = bitmap_match;
00231     hash_ctl.hcxt = CurrentMemoryContext;
00232     hashtab = hash_create("JoinRelHashTable",
00233                           256L,
00234                           &hash_ctl,
00235                     HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
00236 
00237     /* Insert all the already-existing joinrels */
00238     foreach(l, root->join_rel_list)
00239     {
00240         RelOptInfo *rel = (RelOptInfo *) lfirst(l);
00241         JoinHashEntry *hentry;
00242         bool        found;
00243 
00244         hentry = (JoinHashEntry *) hash_search(hashtab,
00245                                                &(rel->relids),
00246                                                HASH_ENTER,
00247                                                &found);
00248         Assert(!found);
00249         hentry->join_rel = rel;
00250     }
00251 
00252     root->join_rel_hash = hashtab;
00253 }
00254 
00255 /*
00256  * find_join_rel
00257  *    Returns relation entry corresponding to 'relids' (a set of RT indexes),
00258  *    or NULL if none exists.  This is for join relations.
00259  */
00260 RelOptInfo *
00261 find_join_rel(PlannerInfo *root, Relids relids)
00262 {
00263     /*
00264      * Switch to using hash lookup when list grows "too long".  The threshold
00265      * is arbitrary and is known only here.
00266      */
00267     if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)
00268         build_join_rel_hash(root);
00269 
00270     /*
00271      * Use either hashtable lookup or linear search, as appropriate.
00272      *
00273      * Note: the seemingly redundant hashkey variable is used to avoid taking
00274      * the address of relids; unless the compiler is exceedingly smart, doing
00275      * so would force relids out of a register and thus probably slow down the
00276      * list-search case.
00277      */
00278     if (root->join_rel_hash)
00279     {
00280         Relids      hashkey = relids;
00281         JoinHashEntry *hentry;
00282 
00283         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
00284                                                &hashkey,
00285                                                HASH_FIND,
00286                                                NULL);
00287         if (hentry)
00288             return hentry->join_rel;
00289     }
00290     else
00291     {
00292         ListCell   *l;
00293 
00294         foreach(l, root->join_rel_list)
00295         {
00296             RelOptInfo *rel = (RelOptInfo *) lfirst(l);
00297 
00298             if (bms_equal(rel->relids, relids))
00299                 return rel;
00300         }
00301     }
00302 
00303     return NULL;
00304 }
00305 
00306 /*
00307  * build_join_rel
00308  *    Returns relation entry corresponding to the union of two given rels,
00309  *    creating a new relation entry if none already exists.
00310  *
00311  * 'joinrelids' is the Relids set that uniquely identifies the join
00312  * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
00313  *      joined
00314  * 'sjinfo': join context info
00315  * 'restrictlist_ptr': result variable.  If not NULL, *restrictlist_ptr
00316  *      receives the list of RestrictInfo nodes that apply to this
00317  *      particular pair of joinable relations.
00318  *
00319  * restrictlist_ptr makes the routine's API a little grotty, but it saves
00320  * duplicated calculation of the restrictlist...
00321  */
00322 RelOptInfo *
00323 build_join_rel(PlannerInfo *root,
00324                Relids joinrelids,
00325                RelOptInfo *outer_rel,
00326                RelOptInfo *inner_rel,
00327                SpecialJoinInfo *sjinfo,
00328                List **restrictlist_ptr)
00329 {
00330     RelOptInfo *joinrel;
00331     List       *restrictlist;
00332 
00333     /*
00334      * See if we already have a joinrel for this set of base rels.
00335      */
00336     joinrel = find_join_rel(root, joinrelids);
00337 
00338     if (joinrel)
00339     {
00340         /*
00341          * Yes, so we only need to figure the restrictlist for this particular
00342          * pair of component relations.
00343          */
00344         if (restrictlist_ptr)
00345             *restrictlist_ptr = build_joinrel_restrictlist(root,
00346                                                            joinrel,
00347                                                            outer_rel,
00348                                                            inner_rel);
00349         return joinrel;
00350     }
00351 
00352     /*
00353      * Nope, so make one.
00354      */
00355     joinrel = makeNode(RelOptInfo);
00356     joinrel->reloptkind = RELOPT_JOINREL;
00357     joinrel->relids = bms_copy(joinrelids);
00358     joinrel->rows = 0;
00359     joinrel->width = 0;
00360     /* cheap startup cost is interesting iff not all tuples to be retrieved */
00361     joinrel->consider_startup = (root->tuple_fraction > 0);
00362     joinrel->reltargetlist = NIL;
00363     joinrel->pathlist = NIL;
00364     joinrel->ppilist = NIL;
00365     joinrel->cheapest_startup_path = NULL;
00366     joinrel->cheapest_total_path = NULL;
00367     joinrel->cheapest_unique_path = NULL;
00368     joinrel->cheapest_parameterized_paths = NIL;
00369     joinrel->relid = 0;         /* indicates not a baserel */
00370     joinrel->rtekind = RTE_JOIN;
00371     joinrel->min_attr = 0;
00372     joinrel->max_attr = 0;
00373     joinrel->attr_needed = NULL;
00374     joinrel->attr_widths = NULL;
00375     joinrel->lateral_vars = NIL;
00376     joinrel->lateral_relids = NULL;
00377     joinrel->indexlist = NIL;
00378     joinrel->pages = 0;
00379     joinrel->tuples = 0;
00380     joinrel->allvisfrac = 0;
00381     joinrel->subplan = NULL;
00382     joinrel->subroot = NULL;
00383     joinrel->subplan_params = NIL;
00384     joinrel->fdwroutine = NULL;
00385     joinrel->fdw_private = NULL;
00386     joinrel->baserestrictinfo = NIL;
00387     joinrel->baserestrictcost.startup = 0;
00388     joinrel->baserestrictcost.per_tuple = 0;
00389     joinrel->joininfo = NIL;
00390     joinrel->has_eclass_joins = false;
00391 
00392     /*
00393      * Create a new tlist containing just the vars that need to be output from
00394      * this join (ie, are needed for higher joinclauses or final output).
00395      *
00396      * NOTE: the tlist order for a join rel will depend on which pair of outer
00397      * and inner rels we first try to build it from.  But the contents should
00398      * be the same regardless.
00399      */
00400     build_joinrel_tlist(root, joinrel, outer_rel);
00401     build_joinrel_tlist(root, joinrel, inner_rel);
00402     add_placeholders_to_joinrel(root, joinrel);
00403 
00404     /*
00405      * Construct restrict and join clause lists for the new joinrel. (The
00406      * caller might or might not need the restrictlist, but I need it anyway
00407      * for set_joinrel_size_estimates().)
00408      */
00409     restrictlist = build_joinrel_restrictlist(root, joinrel,
00410                                               outer_rel, inner_rel);
00411     if (restrictlist_ptr)
00412         *restrictlist_ptr = restrictlist;
00413     build_joinrel_joinlist(joinrel, outer_rel, inner_rel);
00414 
00415     /*
00416      * This is also the right place to check whether the joinrel has any
00417      * pending EquivalenceClass joins.
00418      */
00419     joinrel->has_eclass_joins = has_relevant_eclass_joinclause(root, joinrel);
00420 
00421     /*
00422      * Set estimates of the joinrel's size.
00423      */
00424     set_joinrel_size_estimates(root, joinrel, outer_rel, inner_rel,
00425                                sjinfo, restrictlist);
00426 
00427     /*
00428      * Add the joinrel to the query's joinrel list, and store it into the
00429      * auxiliary hashtable if there is one.  NB: GEQO requires us to append
00430      * the new joinrel to the end of the list!
00431      */
00432     root->join_rel_list = lappend(root->join_rel_list, joinrel);
00433 
00434     if (root->join_rel_hash)
00435     {
00436         JoinHashEntry *hentry;
00437         bool        found;
00438 
00439         hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,
00440                                                &(joinrel->relids),
00441                                                HASH_ENTER,
00442                                                &found);
00443         Assert(!found);
00444         hentry->join_rel = joinrel;
00445     }
00446 
00447     /*
00448      * Also, if dynamic-programming join search is active, add the new joinrel
00449      * to the appropriate sublist.  Note: you might think the Assert on number
00450      * of members should be for equality, but some of the level 1 rels might
00451      * have been joinrels already, so we can only assert <=.
00452      */
00453     if (root->join_rel_level)
00454     {
00455         Assert(root->join_cur_level > 0);
00456         Assert(root->join_cur_level <= bms_num_members(joinrel->relids));
00457         root->join_rel_level[root->join_cur_level] =
00458             lappend(root->join_rel_level[root->join_cur_level], joinrel);
00459     }
00460 
00461     return joinrel;
00462 }
00463 
00464 /*
00465  * build_joinrel_tlist
00466  *    Builds a join relation's target list from an input relation.
00467  *    (This is invoked twice to handle the two input relations.)
00468  *
00469  * The join's targetlist includes all Vars of its member relations that
00470  * will still be needed above the join.  This subroutine adds all such
00471  * Vars from the specified input rel's tlist to the join rel's tlist.
00472  *
00473  * We also compute the expected width of the join's output, making use
00474  * of data that was cached at the baserel level by set_rel_width().
00475  */
00476 static void
00477 build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
00478                     RelOptInfo *input_rel)
00479 {
00480     Relids      relids = joinrel->relids;
00481     ListCell   *vars;
00482 
00483     foreach(vars, input_rel->reltargetlist)
00484     {
00485         Var        *var = (Var *) lfirst(vars);
00486         RelOptInfo *baserel;
00487         int         ndx;
00488 
00489         /*
00490          * Ignore PlaceHolderVars in the input tlists; we'll make our own
00491          * decisions about whether to copy them.
00492          */
00493         if (IsA(var, PlaceHolderVar))
00494             continue;
00495 
00496         /*
00497          * Otherwise, anything in a baserel or joinrel targetlist ought to be
00498          * a Var.  (More general cases can only appear in appendrel child
00499          * rels, which will never be seen here.)
00500          */
00501         if (!IsA(var, Var))
00502             elog(ERROR, "unexpected node type in reltargetlist: %d",
00503                  (int) nodeTag(var));
00504 
00505         /* Get the Var's original base rel */
00506         baserel = find_base_rel(root, var->varno);
00507 
00508         /* Is it still needed above this joinrel? */
00509         ndx = var->varattno - baserel->min_attr;
00510         if (bms_nonempty_difference(baserel->attr_needed[ndx], relids))
00511         {
00512             /* Yup, add it to the output */
00513             joinrel->reltargetlist = lappend(joinrel->reltargetlist, var);
00514             joinrel->width += baserel->attr_widths[ndx];
00515         }
00516     }
00517 }
00518 
00519 /*
00520  * build_joinrel_restrictlist
00521  * build_joinrel_joinlist
00522  *    These routines build lists of restriction and join clauses for a
00523  *    join relation from the joininfo lists of the relations it joins.
00524  *
00525  *    These routines are separate because the restriction list must be
00526  *    built afresh for each pair of input sub-relations we consider, whereas
00527  *    the join list need only be computed once for any join RelOptInfo.
00528  *    The join list is fully determined by the set of rels making up the
00529  *    joinrel, so we should get the same results (up to ordering) from any
00530  *    candidate pair of sub-relations.  But the restriction list is whatever
00531  *    is not handled in the sub-relations, so it depends on which
00532  *    sub-relations are considered.
00533  *
00534  *    If a join clause from an input relation refers to base rels still not
00535  *    present in the joinrel, then it is still a join clause for the joinrel;
00536  *    we put it into the joininfo list for the joinrel.  Otherwise,
00537  *    the clause is now a restrict clause for the joined relation, and we
00538  *    return it to the caller of build_joinrel_restrictlist() to be stored in
00539  *    join paths made from this pair of sub-relations.  (It will not need to
00540  *    be considered further up the join tree.)
00541  *
00542  *    In many case we will find the same RestrictInfos in both input
00543  *    relations' joinlists, so be careful to eliminate duplicates.
00544  *    Pointer equality should be a sufficient test for dups, since all
00545  *    the various joinlist entries ultimately refer to RestrictInfos
00546  *    pushed into them by distribute_restrictinfo_to_rels().
00547  *
00548  * 'joinrel' is a join relation node
00549  * 'outer_rel' and 'inner_rel' are a pair of relations that can be joined
00550  *      to form joinrel.
00551  *
00552  * build_joinrel_restrictlist() returns a list of relevant restrictinfos,
00553  * whereas build_joinrel_joinlist() stores its results in the joinrel's
00554  * joininfo list.  One or the other must accept each given clause!
00555  *
00556  * NB: Formerly, we made deep(!) copies of each input RestrictInfo to pass
00557  * up to the join relation.  I believe this is no longer necessary, because
00558  * RestrictInfo nodes are no longer context-dependent.  Instead, just include
00559  * the original nodes in the lists made for the join relation.
00560  */
00561 static List *
00562 build_joinrel_restrictlist(PlannerInfo *root,
00563                            RelOptInfo *joinrel,
00564                            RelOptInfo *outer_rel,
00565                            RelOptInfo *inner_rel)
00566 {
00567     List       *result;
00568 
00569     /*
00570      * Collect all the clauses that syntactically belong at this level,
00571      * eliminating any duplicates (important since we will see many of the
00572      * same clauses arriving from both input relations).
00573      */
00574     result = subbuild_joinrel_restrictlist(joinrel, outer_rel->joininfo, NIL);
00575     result = subbuild_joinrel_restrictlist(joinrel, inner_rel->joininfo, result);
00576 
00577     /*
00578      * Add on any clauses derived from EquivalenceClasses.  These cannot be
00579      * redundant with the clauses in the joininfo lists, so don't bother
00580      * checking.
00581      */
00582     result = list_concat(result,
00583                          generate_join_implied_equalities(root,
00584                                                           joinrel->relids,
00585                                                           outer_rel->relids,
00586                                                           inner_rel));
00587 
00588     return result;
00589 }
00590 
00591 static void
00592 build_joinrel_joinlist(RelOptInfo *joinrel,
00593                        RelOptInfo *outer_rel,
00594                        RelOptInfo *inner_rel)
00595 {
00596     List       *result;
00597 
00598     /*
00599      * Collect all the clauses that syntactically belong above this level,
00600      * eliminating any duplicates (important since we will see many of the
00601      * same clauses arriving from both input relations).
00602      */
00603     result = subbuild_joinrel_joinlist(joinrel, outer_rel->joininfo, NIL);
00604     result = subbuild_joinrel_joinlist(joinrel, inner_rel->joininfo, result);
00605 
00606     joinrel->joininfo = result;
00607 }
00608 
00609 static List *
00610 subbuild_joinrel_restrictlist(RelOptInfo *joinrel,
00611                               List *joininfo_list,
00612                               List *new_restrictlist)
00613 {
00614     ListCell   *l;
00615 
00616     foreach(l, joininfo_list)
00617     {
00618         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00619 
00620         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
00621         {
00622             /*
00623              * This clause becomes a restriction clause for the joinrel, since
00624              * it refers to no outside rels.  Add it to the list, being
00625              * careful to eliminate duplicates. (Since RestrictInfo nodes in
00626              * different joinlists will have been multiply-linked rather than
00627              * copied, pointer equality should be a sufficient test.)
00628              */
00629             new_restrictlist = list_append_unique_ptr(new_restrictlist, rinfo);
00630         }
00631         else
00632         {
00633             /*
00634              * This clause is still a join clause at this level, so we ignore
00635              * it in this routine.
00636              */
00637         }
00638     }
00639 
00640     return new_restrictlist;
00641 }
00642 
00643 static List *
00644 subbuild_joinrel_joinlist(RelOptInfo *joinrel,
00645                           List *joininfo_list,
00646                           List *new_joininfo)
00647 {
00648     ListCell   *l;
00649 
00650     foreach(l, joininfo_list)
00651     {
00652         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00653 
00654         if (bms_is_subset(rinfo->required_relids, joinrel->relids))
00655         {
00656             /*
00657              * This clause becomes a restriction clause for the joinrel, since
00658              * it refers to no outside rels.  So we can ignore it in this
00659              * routine.
00660              */
00661         }
00662         else
00663         {
00664             /*
00665              * This clause is still a join clause at this level, so add it to
00666              * the new joininfo list, being careful to eliminate duplicates.
00667              * (Since RestrictInfo nodes in different joinlists will have been
00668              * multiply-linked rather than copied, pointer equality should be
00669              * a sufficient test.)
00670              */
00671             new_joininfo = list_append_unique_ptr(new_joininfo, rinfo);
00672         }
00673     }
00674 
00675     return new_joininfo;
00676 }
00677 
00678 
00679 /*
00680  * find_childrel_appendrelinfo
00681  *      Get the AppendRelInfo associated with an appendrel child rel.
00682  *
00683  * This search could be eliminated by storing a link in child RelOptInfos,
00684  * but for now it doesn't seem performance-critical.
00685  */
00686 AppendRelInfo *
00687 find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel)
00688 {
00689     Index       relid = rel->relid;
00690     ListCell   *lc;
00691 
00692     /* Should only be called on child rels */
00693     Assert(rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
00694 
00695     foreach(lc, root->append_rel_list)
00696     {
00697         AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
00698 
00699         if (appinfo->child_relid == relid)
00700             return appinfo;
00701     }
00702     /* should have found the entry ... */
00703     elog(ERROR, "child rel %d not found in append_rel_list", relid);
00704     return NULL;                /* not reached */
00705 }
00706 
00707 
00708 /*
00709  * get_baserel_parampathinfo
00710  *      Get the ParamPathInfo for a parameterized path for a base relation,
00711  *      constructing one if we don't have one already.
00712  *
00713  * This centralizes estimating the rowcounts for parameterized paths.
00714  * We need to cache those to be sure we use the same rowcount for all paths
00715  * of the same parameterization for a given rel.  This is also a convenient
00716  * place to determine which movable join clauses the parameterized path will
00717  * be responsible for evaluating.
00718  */
00719 ParamPathInfo *
00720 get_baserel_parampathinfo(PlannerInfo *root, RelOptInfo *baserel,
00721                           Relids required_outer)
00722 {
00723     ParamPathInfo *ppi;
00724     Relids      joinrelids;
00725     List       *pclauses;
00726     double      rows;
00727     ListCell   *lc;
00728 
00729     /* Unparameterized paths have no ParamPathInfo */
00730     if (bms_is_empty(required_outer))
00731         return NULL;
00732 
00733     Assert(!bms_overlap(baserel->relids, required_outer));
00734 
00735     /* If we already have a PPI for this parameterization, just return it */
00736     foreach(lc, baserel->ppilist)
00737     {
00738         ppi = (ParamPathInfo *) lfirst(lc);
00739         if (bms_equal(ppi->ppi_req_outer, required_outer))
00740             return ppi;
00741     }
00742 
00743     /*
00744      * Identify all joinclauses that are movable to this base rel given this
00745      * parameterization.
00746      */
00747     joinrelids = bms_union(baserel->relids, required_outer);
00748     pclauses = NIL;
00749     foreach(lc, baserel->joininfo)
00750     {
00751         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00752 
00753         if (join_clause_is_movable_into(rinfo,
00754                                         baserel->relids,
00755                                         joinrelids))
00756             pclauses = lappend(pclauses, rinfo);
00757     }
00758 
00759     /*
00760      * Add in joinclauses generated by EquivalenceClasses, too.  (These
00761      * necessarily satisfy join_clause_is_movable_into.)
00762      */
00763     pclauses = list_concat(pclauses,
00764                            generate_join_implied_equalities(root,
00765                                                             joinrelids,
00766                                                             required_outer,
00767                                                             baserel));
00768 
00769     /* Estimate the number of rows returned by the parameterized scan */
00770     rows = get_parameterized_baserel_size(root, baserel, pclauses);
00771 
00772     /* And now we can build the ParamPathInfo */
00773     ppi = makeNode(ParamPathInfo);
00774     ppi->ppi_req_outer = required_outer;
00775     ppi->ppi_rows = rows;
00776     ppi->ppi_clauses = pclauses;
00777     baserel->ppilist = lappend(baserel->ppilist, ppi);
00778 
00779     return ppi;
00780 }
00781 
00782 /*
00783  * get_joinrel_parampathinfo
00784  *      Get the ParamPathInfo for a parameterized path for a join relation,
00785  *      constructing one if we don't have one already.
00786  *
00787  * This centralizes estimating the rowcounts for parameterized paths.
00788  * We need to cache those to be sure we use the same rowcount for all paths
00789  * of the same parameterization for a given rel.  This is also a convenient
00790  * place to determine which movable join clauses the parameterized path will
00791  * be responsible for evaluating.
00792  *
00793  * outer_path and inner_path are a pair of input paths that can be used to
00794  * construct the join, and restrict_clauses is the list of regular join
00795  * clauses (including clauses derived from EquivalenceClasses) that must be
00796  * applied at the join node when using these inputs.
00797  *
00798  * Unlike the situation for base rels, the set of movable join clauses to be
00799  * enforced at a join varies with the selected pair of input paths, so we
00800  * must calculate that and pass it back, even if we already have a matching
00801  * ParamPathInfo.  We handle this by adding any clauses moved down to this
00802  * join to *restrict_clauses, which is an in/out parameter.  (The addition
00803  * is done in such a way as to not modify the passed-in List structure.)
00804  *
00805  * Note: when considering a nestloop join, the caller must have removed from
00806  * restrict_clauses any movable clauses that are themselves scheduled to be
00807  * pushed into the right-hand path.  We do not do that here since it's
00808  * unnecessary for other join types.
00809  */
00810 ParamPathInfo *
00811 get_joinrel_parampathinfo(PlannerInfo *root, RelOptInfo *joinrel,
00812                           Path *outer_path,
00813                           Path *inner_path,
00814                           SpecialJoinInfo *sjinfo,
00815                           Relids required_outer,
00816                           List **restrict_clauses)
00817 {
00818     ParamPathInfo *ppi;
00819     Relids      join_and_req;
00820     Relids      outer_and_req;
00821     Relids      inner_and_req;
00822     List       *pclauses;
00823     List       *eclauses;
00824     double      rows;
00825     ListCell   *lc;
00826 
00827     /* Unparameterized paths have no ParamPathInfo or extra join clauses */
00828     if (bms_is_empty(required_outer))
00829         return NULL;
00830 
00831     Assert(!bms_overlap(joinrel->relids, required_outer));
00832 
00833     /*
00834      * Identify all joinclauses that are movable to this join rel given this
00835      * parameterization.  These are the clauses that are movable into this
00836      * join, but not movable into either input path.  Treat an unparameterized
00837      * input path as not accepting parameterized clauses (because it won't,
00838      * per the shortcut exit above), even though the joinclause movement rules
00839      * might allow the same clauses to be moved into a parameterized path for
00840      * that rel.
00841      */
00842     join_and_req = bms_union(joinrel->relids, required_outer);
00843     if (outer_path->param_info)
00844         outer_and_req = bms_union(outer_path->parent->relids,
00845                                   PATH_REQ_OUTER(outer_path));
00846     else
00847         outer_and_req = NULL;   /* outer path does not accept parameters */
00848     if (inner_path->param_info)
00849         inner_and_req = bms_union(inner_path->parent->relids,
00850                                   PATH_REQ_OUTER(inner_path));
00851     else
00852         inner_and_req = NULL;   /* inner path does not accept parameters */
00853 
00854     pclauses = NIL;
00855     foreach(lc, joinrel->joininfo)
00856     {
00857         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00858 
00859         if (join_clause_is_movable_into(rinfo,
00860                                         joinrel->relids,
00861                                         join_and_req) &&
00862             !join_clause_is_movable_into(rinfo,
00863                                          outer_path->parent->relids,
00864                                          outer_and_req) &&
00865             !join_clause_is_movable_into(rinfo,
00866                                          inner_path->parent->relids,
00867                                          inner_and_req))
00868             pclauses = lappend(pclauses, rinfo);
00869     }
00870 
00871     /* Consider joinclauses generated by EquivalenceClasses, too */
00872     eclauses = generate_join_implied_equalities(root,
00873                                                 join_and_req,
00874                                                 required_outer,
00875                                                 joinrel);
00876     /* We only want ones that aren't movable to lower levels */
00877     foreach(lc, eclauses)
00878     {
00879         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
00880 
00881         Assert(join_clause_is_movable_into(rinfo,
00882                                            joinrel->relids,
00883                                            join_and_req));
00884         if (!join_clause_is_movable_into(rinfo,
00885                                          outer_path->parent->relids,
00886                                          outer_and_req) &&
00887             !join_clause_is_movable_into(rinfo,
00888                                          inner_path->parent->relids,
00889                                          inner_and_req))
00890             pclauses = lappend(pclauses, rinfo);
00891     }
00892 
00893     /*
00894      * Now, attach the identified moved-down clauses to the caller's
00895      * restrict_clauses list.  By using list_concat in this order, we leave
00896      * the original list structure of restrict_clauses undamaged.
00897      */
00898     *restrict_clauses = list_concat(pclauses, *restrict_clauses);
00899 
00900     /* If we already have a PPI for this parameterization, just return it */
00901     foreach(lc, joinrel->ppilist)
00902     {
00903         ppi = (ParamPathInfo *) lfirst(lc);
00904         if (bms_equal(ppi->ppi_req_outer, required_outer))
00905             return ppi;
00906     }
00907 
00908     /* Estimate the number of rows returned by the parameterized join */
00909     rows = get_parameterized_joinrel_size(root, joinrel,
00910                                           outer_path->rows,
00911                                           inner_path->rows,
00912                                           sjinfo,
00913                                           *restrict_clauses);
00914 
00915     /*
00916      * And now we can build the ParamPathInfo.  No point in saving the
00917      * input-pair-dependent clause list, though.
00918      *
00919      * Note: in GEQO mode, we'll be called in a temporary memory context, but
00920      * the joinrel structure is there too, so no problem.
00921      */
00922     ppi = makeNode(ParamPathInfo);
00923     ppi->ppi_req_outer = required_outer;
00924     ppi->ppi_rows = rows;
00925     ppi->ppi_clauses = NIL;
00926     joinrel->ppilist = lappend(joinrel->ppilist, ppi);
00927 
00928     return ppi;
00929 }
00930 
00931 /*
00932  * get_appendrel_parampathinfo
00933  *      Get the ParamPathInfo for a parameterized path for an append relation.
00934  *
00935  * For an append relation, the rowcount estimate will just be the sum of
00936  * the estimates for its children.  However, we still need a ParamPathInfo
00937  * to flag the fact that the path requires parameters.  So this just creates
00938  * a suitable struct with zero ppi_rows (and no ppi_clauses either, since
00939  * the Append node isn't responsible for checking quals).
00940  */
00941 ParamPathInfo *
00942 get_appendrel_parampathinfo(RelOptInfo *appendrel, Relids required_outer)
00943 {
00944     ParamPathInfo *ppi;
00945     ListCell   *lc;
00946 
00947     /* Unparameterized paths have no ParamPathInfo */
00948     if (bms_is_empty(required_outer))
00949         return NULL;
00950 
00951     Assert(!bms_overlap(appendrel->relids, required_outer));
00952 
00953     /* If we already have a PPI for this parameterization, just return it */
00954     foreach(lc, appendrel->ppilist)
00955     {
00956         ppi = (ParamPathInfo *) lfirst(lc);
00957         if (bms_equal(ppi->ppi_req_outer, required_outer))
00958             return ppi;
00959     }
00960 
00961     /* Else build the ParamPathInfo */
00962     ppi = makeNode(ParamPathInfo);
00963     ppi->ppi_req_outer = required_outer;
00964     ppi->ppi_rows = 0;
00965     ppi->ppi_clauses = NIL;
00966     appendrel->ppilist = lappend(appendrel->ppilist, ppi);
00967 
00968     return ppi;
00969 }