Header And Logo

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

restrictinfo.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * restrictinfo.c
00004  *    RestrictInfo node manipulation 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/restrictinfo.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "optimizer/clauses.h"
00018 #include "optimizer/predtest.h"
00019 #include "optimizer/restrictinfo.h"
00020 #include "optimizer/var.h"
00021 
00022 
00023 static RestrictInfo *make_restrictinfo_internal(Expr *clause,
00024                            Expr *orclause,
00025                            bool is_pushed_down,
00026                            bool outerjoin_delayed,
00027                            bool pseudoconstant,
00028                            Relids required_relids,
00029                            Relids outer_relids,
00030                            Relids nullable_relids);
00031 static Expr *make_sub_restrictinfos(Expr *clause,
00032                        bool is_pushed_down,
00033                        bool outerjoin_delayed,
00034                        bool pseudoconstant,
00035                        Relids required_relids,
00036                        Relids outer_relids,
00037                        Relids nullable_relids);
00038 
00039 
00040 /*
00041  * make_restrictinfo
00042  *
00043  * Build a RestrictInfo node containing the given subexpression.
00044  *
00045  * The is_pushed_down, outerjoin_delayed, and pseudoconstant flags for the
00046  * RestrictInfo must be supplied by the caller, as well as the correct values
00047  * for outer_relids and nullable_relids.
00048  * required_relids can be NULL, in which case it defaults to the actual clause
00049  * contents (i.e., clause_relids).
00050  *
00051  * We initialize fields that depend only on the given subexpression, leaving
00052  * others that depend on context (or may never be needed at all) to be filled
00053  * later.
00054  */
00055 RestrictInfo *
00056 make_restrictinfo(Expr *clause,
00057                   bool is_pushed_down,
00058                   bool outerjoin_delayed,
00059                   bool pseudoconstant,
00060                   Relids required_relids,
00061                   Relids outer_relids,
00062                   Relids nullable_relids)
00063 {
00064     /*
00065      * If it's an OR clause, build a modified copy with RestrictInfos inserted
00066      * above each subclause of the top-level AND/OR structure.
00067      */
00068     if (or_clause((Node *) clause))
00069         return (RestrictInfo *) make_sub_restrictinfos(clause,
00070                                                        is_pushed_down,
00071                                                        outerjoin_delayed,
00072                                                        pseudoconstant,
00073                                                        required_relids,
00074                                                        outer_relids,
00075                                                        nullable_relids);
00076 
00077     /* Shouldn't be an AND clause, else AND/OR flattening messed up */
00078     Assert(!and_clause((Node *) clause));
00079 
00080     return make_restrictinfo_internal(clause,
00081                                       NULL,
00082                                       is_pushed_down,
00083                                       outerjoin_delayed,
00084                                       pseudoconstant,
00085                                       required_relids,
00086                                       outer_relids,
00087                                       nullable_relids);
00088 }
00089 
00090 /*
00091  * make_restrictinfo_from_bitmapqual
00092  *
00093  * Given the bitmapqual Path structure for a bitmap indexscan, generate
00094  * RestrictInfo node(s) equivalent to the condition represented by the
00095  * indexclauses of the Path structure.
00096  *
00097  * The result is a List (effectively, implicit-AND representation) of
00098  * RestrictInfos.
00099  *
00100  * The caller must pass is_pushed_down, but we assume outerjoin_delayed
00101  * and pseudoconstant are false while outer_relids and nullable_relids
00102  * are NULL (no other kind of qual should ever get into a bitmapqual).
00103  *
00104  * If include_predicates is true, we add any partial index predicates to
00105  * the explicit index quals.  When this is not true, we return a condition
00106  * that might be weaker than the actual scan represents.
00107  *
00108  * To do this through the normal make_restrictinfo() API, callers would have
00109  * to strip off the RestrictInfo nodes present in the indexclauses lists, and
00110  * then make_restrictinfo() would have to build new ones.  It's better to have
00111  * a specialized routine to allow sharing of RestrictInfos.
00112  *
00113  * The qual manipulations here are much the same as in create_bitmap_subplan;
00114  * keep the two routines in sync!
00115  */
00116 List *
00117 make_restrictinfo_from_bitmapqual(Path *bitmapqual,
00118                                   bool is_pushed_down,
00119                                   bool include_predicates)
00120 {
00121     List       *result;
00122     ListCell   *l;
00123 
00124     if (IsA(bitmapqual, BitmapAndPath))
00125     {
00126         BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
00127 
00128         /*
00129          * There may well be redundant quals among the subplans, since a
00130          * top-level WHERE qual might have gotten used to form several
00131          * different index quals.  We don't try exceedingly hard to eliminate
00132          * redundancies, but we do eliminate obvious duplicates by using
00133          * list_concat_unique.
00134          */
00135         result = NIL;
00136         foreach(l, apath->bitmapquals)
00137         {
00138             List       *sublist;
00139 
00140             sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
00141                                                         is_pushed_down,
00142                                                         include_predicates);
00143             result = list_concat_unique(result, sublist);
00144         }
00145     }
00146     else if (IsA(bitmapqual, BitmapOrPath))
00147     {
00148         BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
00149         List       *withris = NIL;
00150         List       *withoutris = NIL;
00151 
00152         /*
00153          * Here, we only detect qual-free subplans.  A qual-free subplan would
00154          * cause us to generate "... OR true ..."  which we may as well reduce
00155          * to just "true".  We do not try to eliminate redundant subclauses
00156          * because (a) it's not as likely as in the AND case, and (b) we might
00157          * well be working with hundreds or even thousands of OR conditions,
00158          * perhaps from a long IN list.  The performance of list_append_unique
00159          * would be unacceptable.
00160          */
00161         foreach(l, opath->bitmapquals)
00162         {
00163             List       *sublist;
00164 
00165             sublist = make_restrictinfo_from_bitmapqual((Path *) lfirst(l),
00166                                                         is_pushed_down,
00167                                                         include_predicates);
00168             if (sublist == NIL)
00169             {
00170                 /*
00171                  * If we find a qual-less subscan, it represents a constant
00172                  * TRUE, and hence the OR result is also constant TRUE, so we
00173                  * can stop here.
00174                  */
00175                 return NIL;
00176             }
00177 
00178             /*
00179              * If the sublist contains multiple RestrictInfos, we create an
00180              * AND subclause.  If there's just one, we have to check if it's
00181              * an OR clause, and if so flatten it to preserve AND/OR flatness
00182              * of our output.
00183              *
00184              * We construct lists with and without sub-RestrictInfos, so as
00185              * not to have to regenerate duplicate RestrictInfos below.
00186              */
00187             if (list_length(sublist) > 1)
00188             {
00189                 withris = lappend(withris, make_andclause(sublist));
00190                 sublist = get_actual_clauses(sublist);
00191                 withoutris = lappend(withoutris, make_andclause(sublist));
00192             }
00193             else
00194             {
00195                 RestrictInfo *subri = (RestrictInfo *) linitial(sublist);
00196 
00197                 Assert(IsA(subri, RestrictInfo));
00198                 if (restriction_is_or_clause(subri))
00199                 {
00200                     BoolExpr   *subor = (BoolExpr *) subri->orclause;
00201 
00202                     Assert(or_clause((Node *) subor));
00203                     withris = list_concat(withris,
00204                                           list_copy(subor->args));
00205                     subor = (BoolExpr *) subri->clause;
00206                     Assert(or_clause((Node *) subor));
00207                     withoutris = list_concat(withoutris,
00208                                              list_copy(subor->args));
00209                 }
00210                 else
00211                 {
00212                     withris = lappend(withris, subri);
00213                     withoutris = lappend(withoutris, subri->clause);
00214                 }
00215             }
00216         }
00217 
00218         /*
00219          * Avoid generating one-element ORs, which could happen due to
00220          * redundancy elimination or ScalarArrayOpExpr quals.
00221          */
00222         if (list_length(withris) <= 1)
00223             result = withris;
00224         else
00225         {
00226             /* Here's the magic part not available to outside callers */
00227             result =
00228                 list_make1(make_restrictinfo_internal(make_orclause(withoutris),
00229                                                       make_orclause(withris),
00230                                                       is_pushed_down,
00231                                                       false,
00232                                                       false,
00233                                                       NULL,
00234                                                       NULL,
00235                                                       NULL));
00236         }
00237     }
00238     else if (IsA(bitmapqual, IndexPath))
00239     {
00240         IndexPath  *ipath = (IndexPath *) bitmapqual;
00241 
00242         result = list_copy(ipath->indexclauses);
00243         if (include_predicates && ipath->indexinfo->indpred != NIL)
00244         {
00245             foreach(l, ipath->indexinfo->indpred)
00246             {
00247                 Expr       *pred = (Expr *) lfirst(l);
00248 
00249                 /*
00250                  * We know that the index predicate must have been implied by
00251                  * the query condition as a whole, but it may or may not be
00252                  * implied by the conditions that got pushed into the
00253                  * bitmapqual.  Avoid generating redundant conditions.
00254                  */
00255                 if (!predicate_implied_by(list_make1(pred), result))
00256                     result = lappend(result,
00257                                      make_restrictinfo(pred,
00258                                                        is_pushed_down,
00259                                                        false,
00260                                                        false,
00261                                                        NULL,
00262                                                        NULL,
00263                                                        NULL));
00264             }
00265         }
00266     }
00267     else
00268     {
00269         elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
00270         result = NIL;           /* keep compiler quiet */
00271     }
00272 
00273     return result;
00274 }
00275 
00276 /*
00277  * make_restrictinfos_from_actual_clauses
00278  *
00279  * Given a list of implicitly-ANDed restriction clauses, produce a list
00280  * of RestrictInfo nodes.  This is used to reconstitute the RestrictInfo
00281  * representation after doing transformations of a list of clauses.
00282  *
00283  * We assume that the clauses are relation-level restrictions and therefore
00284  * we don't have to worry about is_pushed_down, outerjoin_delayed,
00285  * outer_relids, and nullable_relids (these can be assumed true, false,
00286  * NULL, and NULL, respectively).
00287  * We do take care to recognize pseudoconstant clauses properly.
00288  */
00289 List *
00290 make_restrictinfos_from_actual_clauses(PlannerInfo *root,
00291                                        List *clause_list)
00292 {
00293     List       *result = NIL;
00294     ListCell   *l;
00295 
00296     foreach(l, clause_list)
00297     {
00298         Expr       *clause = (Expr *) lfirst(l);
00299         bool        pseudoconstant;
00300         RestrictInfo *rinfo;
00301 
00302         /*
00303          * It's pseudoconstant if it contains no Vars and no volatile
00304          * functions.  We probably can't see any sublinks here, so
00305          * contain_var_clause() would likely be enough, but for safety use
00306          * contain_vars_of_level() instead.
00307          */
00308         pseudoconstant =
00309             !contain_vars_of_level((Node *) clause, 0) &&
00310             !contain_volatile_functions((Node *) clause);
00311         if (pseudoconstant)
00312         {
00313             /* tell createplan.c to check for gating quals */
00314             root->hasPseudoConstantQuals = true;
00315         }
00316 
00317         rinfo = make_restrictinfo(clause,
00318                                   true,
00319                                   false,
00320                                   pseudoconstant,
00321                                   NULL,
00322                                   NULL,
00323                                   NULL);
00324         result = lappend(result, rinfo);
00325     }
00326     return result;
00327 }
00328 
00329 /*
00330  * make_restrictinfo_internal
00331  *
00332  * Common code for the main entry points and the recursive cases.
00333  */
00334 static RestrictInfo *
00335 make_restrictinfo_internal(Expr *clause,
00336                            Expr *orclause,
00337                            bool is_pushed_down,
00338                            bool outerjoin_delayed,
00339                            bool pseudoconstant,
00340                            Relids required_relids,
00341                            Relids outer_relids,
00342                            Relids nullable_relids)
00343 {
00344     RestrictInfo *restrictinfo = makeNode(RestrictInfo);
00345 
00346     restrictinfo->clause = clause;
00347     restrictinfo->orclause = orclause;
00348     restrictinfo->is_pushed_down = is_pushed_down;
00349     restrictinfo->outerjoin_delayed = outerjoin_delayed;
00350     restrictinfo->pseudoconstant = pseudoconstant;
00351     restrictinfo->can_join = false;     /* may get set below */
00352     restrictinfo->outer_relids = outer_relids;
00353     restrictinfo->nullable_relids = nullable_relids;
00354 
00355     /*
00356      * If it's a binary opclause, set up left/right relids info. In any case
00357      * set up the total clause relids info.
00358      */
00359     if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
00360     {
00361         restrictinfo->left_relids = pull_varnos(get_leftop(clause));
00362         restrictinfo->right_relids = pull_varnos(get_rightop(clause));
00363 
00364         restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
00365                                                 restrictinfo->right_relids);
00366 
00367         /*
00368          * Does it look like a normal join clause, i.e., a binary operator
00369          * relating expressions that come from distinct relations? If so we
00370          * might be able to use it in a join algorithm.  Note that this is a
00371          * purely syntactic test that is made regardless of context.
00372          */
00373         if (!bms_is_empty(restrictinfo->left_relids) &&
00374             !bms_is_empty(restrictinfo->right_relids) &&
00375             !bms_overlap(restrictinfo->left_relids,
00376                          restrictinfo->right_relids))
00377         {
00378             restrictinfo->can_join = true;
00379             /* pseudoconstant should certainly not be true */
00380             Assert(!restrictinfo->pseudoconstant);
00381         }
00382     }
00383     else
00384     {
00385         /* Not a binary opclause, so mark left/right relid sets as empty */
00386         restrictinfo->left_relids = NULL;
00387         restrictinfo->right_relids = NULL;
00388         /* and get the total relid set the hard way */
00389         restrictinfo->clause_relids = pull_varnos((Node *) clause);
00390     }
00391 
00392     /* required_relids defaults to clause_relids */
00393     if (required_relids != NULL)
00394         restrictinfo->required_relids = required_relids;
00395     else
00396         restrictinfo->required_relids = restrictinfo->clause_relids;
00397 
00398     /*
00399      * Fill in all the cacheable fields with "not yet set" markers. None of
00400      * these will be computed until/unless needed.  Note in particular that we
00401      * don't mark a binary opclause as mergejoinable or hashjoinable here;
00402      * that happens only if it appears in the right context (top level of a
00403      * joinclause list).
00404      */
00405     restrictinfo->parent_ec = NULL;
00406 
00407     restrictinfo->eval_cost.startup = -1;
00408     restrictinfo->norm_selec = -1;
00409     restrictinfo->outer_selec = -1;
00410 
00411     restrictinfo->mergeopfamilies = NIL;
00412 
00413     restrictinfo->left_ec = NULL;
00414     restrictinfo->right_ec = NULL;
00415     restrictinfo->left_em = NULL;
00416     restrictinfo->right_em = NULL;
00417     restrictinfo->scansel_cache = NIL;
00418 
00419     restrictinfo->outer_is_left = false;
00420 
00421     restrictinfo->hashjoinoperator = InvalidOid;
00422 
00423     restrictinfo->left_bucketsize = -1;
00424     restrictinfo->right_bucketsize = -1;
00425 
00426     return restrictinfo;
00427 }
00428 
00429 /*
00430  * Recursively insert sub-RestrictInfo nodes into a boolean expression.
00431  *
00432  * We put RestrictInfos above simple (non-AND/OR) clauses and above
00433  * sub-OR clauses, but not above sub-AND clauses, because there's no need.
00434  * This may seem odd but it is closely related to the fact that we use
00435  * implicit-AND lists at top level of RestrictInfo lists.  Only ORs and
00436  * simple clauses are valid RestrictInfos.
00437  *
00438  * The same is_pushed_down, outerjoin_delayed, and pseudoconstant flag
00439  * values can be applied to all RestrictInfo nodes in the result.  Likewise
00440  * for outer_relids and nullable_relids.
00441  *
00442  * The given required_relids are attached to our top-level output,
00443  * but any OR-clause constituents are allowed to default to just the
00444  * contained rels.
00445  */
00446 static Expr *
00447 make_sub_restrictinfos(Expr *clause,
00448                        bool is_pushed_down,
00449                        bool outerjoin_delayed,
00450                        bool pseudoconstant,
00451                        Relids required_relids,
00452                        Relids outer_relids,
00453                        Relids nullable_relids)
00454 {
00455     if (or_clause((Node *) clause))
00456     {
00457         List       *orlist = NIL;
00458         ListCell   *temp;
00459 
00460         foreach(temp, ((BoolExpr *) clause)->args)
00461             orlist = lappend(orlist,
00462                              make_sub_restrictinfos(lfirst(temp),
00463                                                     is_pushed_down,
00464                                                     outerjoin_delayed,
00465                                                     pseudoconstant,
00466                                                     NULL,
00467                                                     outer_relids,
00468                                                     nullable_relids));
00469         return (Expr *) make_restrictinfo_internal(clause,
00470                                                    make_orclause(orlist),
00471                                                    is_pushed_down,
00472                                                    outerjoin_delayed,
00473                                                    pseudoconstant,
00474                                                    required_relids,
00475                                                    outer_relids,
00476                                                    nullable_relids);
00477     }
00478     else if (and_clause((Node *) clause))
00479     {
00480         List       *andlist = NIL;
00481         ListCell   *temp;
00482 
00483         foreach(temp, ((BoolExpr *) clause)->args)
00484             andlist = lappend(andlist,
00485                               make_sub_restrictinfos(lfirst(temp),
00486                                                      is_pushed_down,
00487                                                      outerjoin_delayed,
00488                                                      pseudoconstant,
00489                                                      required_relids,
00490                                                      outer_relids,
00491                                                      nullable_relids));
00492         return make_andclause(andlist);
00493     }
00494     else
00495         return (Expr *) make_restrictinfo_internal(clause,
00496                                                    NULL,
00497                                                    is_pushed_down,
00498                                                    outerjoin_delayed,
00499                                                    pseudoconstant,
00500                                                    required_relids,
00501                                                    outer_relids,
00502                                                    nullable_relids);
00503 }
00504 
00505 /*
00506  * restriction_is_or_clause
00507  *
00508  * Returns t iff the restrictinfo node contains an 'or' clause.
00509  */
00510 bool
00511 restriction_is_or_clause(RestrictInfo *restrictinfo)
00512 {
00513     if (restrictinfo->orclause != NULL)
00514         return true;
00515     else
00516         return false;
00517 }
00518 
00519 /*
00520  * get_actual_clauses
00521  *
00522  * Returns a list containing the bare clauses from 'restrictinfo_list'.
00523  *
00524  * This is only to be used in cases where none of the RestrictInfos can
00525  * be pseudoconstant clauses (for instance, it's OK on indexqual lists).
00526  */
00527 List *
00528 get_actual_clauses(List *restrictinfo_list)
00529 {
00530     List       *result = NIL;
00531     ListCell   *l;
00532 
00533     foreach(l, restrictinfo_list)
00534     {
00535         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00536 
00537         Assert(IsA(rinfo, RestrictInfo));
00538 
00539         Assert(!rinfo->pseudoconstant);
00540 
00541         result = lappend(result, rinfo->clause);
00542     }
00543     return result;
00544 }
00545 
00546 /*
00547  * get_all_actual_clauses
00548  *
00549  * Returns a list containing the bare clauses from 'restrictinfo_list'.
00550  *
00551  * This loses the distinction between regular and pseudoconstant clauses,
00552  * so be careful what you use it for.
00553  */
00554 List *
00555 get_all_actual_clauses(List *restrictinfo_list)
00556 {
00557     List       *result = NIL;
00558     ListCell   *l;
00559 
00560     foreach(l, restrictinfo_list)
00561     {
00562         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00563 
00564         Assert(IsA(rinfo, RestrictInfo));
00565 
00566         result = lappend(result, rinfo->clause);
00567     }
00568     return result;
00569 }
00570 
00571 /*
00572  * extract_actual_clauses
00573  *
00574  * Extract bare clauses from 'restrictinfo_list', returning either the
00575  * regular ones or the pseudoconstant ones per 'pseudoconstant'.
00576  */
00577 List *
00578 extract_actual_clauses(List *restrictinfo_list,
00579                        bool pseudoconstant)
00580 {
00581     List       *result = NIL;
00582     ListCell   *l;
00583 
00584     foreach(l, restrictinfo_list)
00585     {
00586         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00587 
00588         Assert(IsA(rinfo, RestrictInfo));
00589 
00590         if (rinfo->pseudoconstant == pseudoconstant)
00591             result = lappend(result, rinfo->clause);
00592     }
00593     return result;
00594 }
00595 
00596 /*
00597  * extract_actual_join_clauses
00598  *
00599  * Extract bare clauses from 'restrictinfo_list', separating those that
00600  * syntactically match the join level from those that were pushed down.
00601  * Pseudoconstant clauses are excluded from the results.
00602  *
00603  * This is only used at outer joins, since for plain joins we don't care
00604  * about pushed-down-ness.
00605  */
00606 void
00607 extract_actual_join_clauses(List *restrictinfo_list,
00608                             List **joinquals,
00609                             List **otherquals)
00610 {
00611     ListCell   *l;
00612 
00613     *joinquals = NIL;
00614     *otherquals = NIL;
00615 
00616     foreach(l, restrictinfo_list)
00617     {
00618         RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
00619 
00620         Assert(IsA(rinfo, RestrictInfo));
00621 
00622         if (rinfo->is_pushed_down)
00623         {
00624             if (!rinfo->pseudoconstant)
00625                 *otherquals = lappend(*otherquals, rinfo->clause);
00626         }
00627         else
00628         {
00629             /* joinquals shouldn't have been marked pseudoconstant */
00630             Assert(!rinfo->pseudoconstant);
00631             *joinquals = lappend(*joinquals, rinfo->clause);
00632         }
00633     }
00634 }
00635 
00636 
00637 /*
00638  * join_clause_is_movable_to
00639  *      Test whether a join clause is a safe candidate for parameterization
00640  *      of a scan on the specified base relation.
00641  *
00642  * A movable join clause is one that can safely be evaluated at a rel below
00643  * its normal semantic level (ie, its required_relids), if the values of
00644  * variables that it would need from other rels are provided.
00645  *
00646  * We insist that the clause actually reference the target relation; this
00647  * prevents undesirable movement of degenerate join clauses, and ensures
00648  * that there is a unique place that a clause can be moved down to.
00649  *
00650  * We cannot move an outer-join clause into the non-nullable side of its
00651  * outer join, as that would change the results (rows would be suppressed
00652  * rather than being null-extended).
00653  *
00654  * And the target relation must not be in the clause's nullable_relids, i.e.,
00655  * there must not be an outer join below the clause that would null the Vars
00656  * coming from the target relation.  Otherwise the clause might give results
00657  * different from what it would give at its normal semantic level.
00658  */
00659 bool
00660 join_clause_is_movable_to(RestrictInfo *rinfo, Index baserelid)
00661 {
00662     /* Clause must physically reference target rel */
00663     if (!bms_is_member(baserelid, rinfo->clause_relids))
00664         return false;
00665 
00666     /* Cannot move an outer-join clause into the join's outer side */
00667     if (bms_is_member(baserelid, rinfo->outer_relids))
00668         return false;
00669 
00670     /* Target rel must not be nullable below the clause */
00671     if (bms_is_member(baserelid, rinfo->nullable_relids))
00672         return false;
00673 
00674     return true;
00675 }
00676 
00677 /*
00678  * join_clause_is_movable_into
00679  *      Test whether a join clause is movable and can be evaluated within
00680  *      the current join context.
00681  *
00682  * currentrelids: the relids of the proposed evaluation location
00683  * current_and_outer: the union of currentrelids and the required_outer
00684  *      relids (parameterization's outer relations)
00685  *
00686  * The API would be a bit clearer if we passed the current relids and the
00687  * outer relids separately and did bms_union internally; but since most
00688  * callers need to apply this function to multiple clauses, we make the
00689  * caller perform the union.
00690  *
00691  * Obviously, the clause must only refer to Vars available from the current
00692  * relation plus the outer rels.  We also check that it does reference at
00693  * least one current Var, ensuring that the clause will be pushed down to
00694  * a unique place in a parameterized join tree.  And we check that we're
00695  * not pushing the clause into its outer-join outer side, nor down into
00696  * a lower outer join's inner side.
00697  *
00698  * Note: get_joinrel_parampathinfo depends on the fact that if
00699  * current_and_outer is NULL, this function will always return false
00700  * (since one or the other of the first two tests must fail).
00701  */
00702 bool
00703 join_clause_is_movable_into(RestrictInfo *rinfo,
00704                             Relids currentrelids,
00705                             Relids current_and_outer)
00706 {
00707     /* Clause must be evaluatable given available context */
00708     if (!bms_is_subset(rinfo->clause_relids, current_and_outer))
00709         return false;
00710 
00711     /* Clause must physically reference target rel(s) */
00712     if (!bms_overlap(currentrelids, rinfo->clause_relids))
00713         return false;
00714 
00715     /* Cannot move an outer-join clause into the join's outer side */
00716     if (bms_overlap(currentrelids, rinfo->outer_relids))
00717         return false;
00718 
00719     /* Target rel(s) must not be nullable below the clause */
00720     if (bms_overlap(currentrelids, rinfo->nullable_relids))
00721         return false;
00722 
00723     return true;
00724 }