LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/util - restrictinfo.c (source / functions) Coverage Total Hit GIC GNC CBC ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 100.0 % 182 182 94 34 54 114 14
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 13 13 10 3 12
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * restrictinfo.c
       4                 :  *    RestrictInfo node manipulation routines.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/backend/optimizer/util/restrictinfo.c
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : #include "postgres.h"
      16                 : 
      17                 : #include "nodes/makefuncs.h"
      18                 : #include "nodes/nodeFuncs.h"
      19                 : #include "optimizer/clauses.h"
      20                 : #include "optimizer/optimizer.h"
      21                 : #include "optimizer/restrictinfo.h"
      22                 : 
      23                 : 
      24                 : static RestrictInfo *make_restrictinfo_internal(PlannerInfo *root,
      25                 :                                                 Expr *clause,
      26                 :                                                 Expr *orclause,
      27                 :                                                 bool is_pushed_down,
      28                 :                                                 bool pseudoconstant,
      29                 :                                                 Index security_level,
      30                 :                                                 Relids required_relids,
      31                 :                                                 Relids outer_relids);
      32                 : static Expr *make_sub_restrictinfos(PlannerInfo *root,
      33                 :                                     Expr *clause,
      34                 :                                     bool is_pushed_down,
      35                 :                                     bool pseudoconstant,
      36                 :                                     Index security_level,
      37                 :                                     Relids required_relids,
      38                 :                                     Relids outer_relids);
      39                 : 
      40                 : 
      41                 : /*
      42                 :  * make_restrictinfo
      43                 :  *
      44                 :  * Build a RestrictInfo node containing the given subexpression.
      45                 :  *
      46                 :  * The is_pushed_down and pseudoconstant flags for the
      47                 :  * RestrictInfo must be supplied by the caller, as well as the correct values
      48                 :  * for security_level and outer_relids.
      49                 :  * required_relids can be NULL, in which case it defaults to the actual clause
      50                 :  * contents (i.e., clause_relids).
      51                 :  *
      52                 :  * Note that there aren't options to set the has_clone and is_clone flags:
      53                 :  * we always initialize those to false.  There's just one place that wants
      54                 :  * something different, so making all callers pass them seems inconvenient.
      55                 :  *
      56                 :  * We initialize fields that depend only on the given subexpression, leaving
      57                 :  * others that depend on context (or may never be needed at all) to be filled
      58                 :  * later.
      59                 :  */
      60                 : RestrictInfo *
      61 CBC      250946 : make_restrictinfo(PlannerInfo *root,
      62                 :                   Expr *clause,
      63                 :                   bool is_pushed_down,
      64                 :                   bool pseudoconstant,
      65                 :                   Index security_level,
      66                 :                   Relids required_relids,
      67                 :                   Relids outer_relids)
      68                 : {
      69                 :     /*
      70                 :      * If it's an OR clause, build a modified copy with RestrictInfos inserted
      71 ECB             :      * above each subclause of the top-level AND/OR structure.
      72                 :      */
      73 GIC      250946 :     if (is_orclause(clause))
      74            3475 :         return (RestrictInfo *) make_sub_restrictinfos(root,
      75                 :                                                        clause,
      76                 :                                                        is_pushed_down,
      77                 :                                                        pseudoconstant,
      78                 :                                                        security_level,
      79                 :                                                        required_relids,
      80                 :                                                        outer_relids);
      81 ECB             : 
      82                 :     /* Shouldn't be an AND clause, else AND/OR flattening messed up */
      83 GIC      247471 :     Assert(!is_andclause(clause));
      84                 : 
      85          247471 :     return make_restrictinfo_internal(root,
      86                 :                                       clause,
      87                 :                                       NULL,
      88                 :                                       is_pushed_down,
      89                 :                                       pseudoconstant,
      90                 :                                       security_level,
      91                 :                                       required_relids,
      92                 :                                       outer_relids);
      93                 : }
      94                 : 
      95 ECB             : /*
      96                 :  * make_restrictinfo_internal
      97                 :  *
      98                 :  * Common code for the main entry points and the recursive cases.
      99                 :  */
     100                 : static RestrictInfo *
     101 GIC      260725 : make_restrictinfo_internal(PlannerInfo *root,
     102                 :                            Expr *clause,
     103                 :                            Expr *orclause,
     104 ECB             :                            bool is_pushed_down,
     105                 :                            bool pseudoconstant,
     106                 :                            Index security_level,
     107                 :                            Relids required_relids,
     108                 :                            Relids outer_relids)
     109                 : {
     110 CBC      260725 :     RestrictInfo *restrictinfo = makeNode(RestrictInfo);
     111                 :     Relids      baserels;
     112 ECB             : 
     113 CBC      260725 :     restrictinfo->clause = clause;
     114          260725 :     restrictinfo->orclause = orclause;
     115 GIC      260725 :     restrictinfo->is_pushed_down = is_pushed_down;
     116          260725 :     restrictinfo->pseudoconstant = pseudoconstant;
     117 GNC      260725 :     restrictinfo->has_clone = false; /* may get set by caller */
     118          260725 :     restrictinfo->is_clone = false; /* may get set by caller */
     119 GIC      260725 :     restrictinfo->can_join = false; /* may get set below */
     120          260725 :     restrictinfo->security_level = security_level;
     121          260725 :     restrictinfo->outer_relids = outer_relids;
     122 ECB             : 
     123                 :     /*
     124                 :      * If it's potentially delayable by lower-level security quals, figure out
     125                 :      * whether it's leakproof.  We can skip testing this for level-zero quals,
     126                 :      * since they would never get delayed on security grounds anyway.
     127                 :      */
     128 GIC      260725 :     if (security_level > 0)
     129            2026 :         restrictinfo->leakproof = !contain_leaked_vars((Node *) clause);
     130                 :     else
     131 CBC      258699 :         restrictinfo->leakproof = false; /* really, "don't know" */
     132                 : 
     133                 :     /*
     134                 :      * Mark volatility as unknown.  The contain_volatile_functions function
     135                 :      * will determine if there are any volatile functions when called for the
     136                 :      * first time with this RestrictInfo.
     137 ECB             :      */
     138 GIC      260725 :     restrictinfo->has_volatile = VOLATILITY_UNKNOWN;
     139 ECB             : 
     140                 :     /*
     141                 :      * If it's a binary opclause, set up left/right relids info. In any case
     142                 :      * set up the total clause relids info.
     143                 :      */
     144 GIC      260725 :     if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
     145                 :     {
     146          216494 :         restrictinfo->left_relids = pull_varnos(root, get_leftop(clause));
     147          216494 :         restrictinfo->right_relids = pull_varnos(root, get_rightop(clause));
     148                 : 
     149          432988 :         restrictinfo->clause_relids = bms_union(restrictinfo->left_relids,
     150          216494 :                                                 restrictinfo->right_relids);
     151 ECB             : 
     152                 :         /*
     153                 :          * Does it look like a normal join clause, i.e., a binary operator
     154                 :          * relating expressions that come from distinct relations? If so we
     155                 :          * might be able to use it in a join algorithm.  Note that this is a
     156                 :          * purely syntactic test that is made regardless of context.
     157                 :          */
     158 CBC      216494 :         if (!bms_is_empty(restrictinfo->left_relids) &&
     159 GIC      212677 :             !bms_is_empty(restrictinfo->right_relids) &&
     160           75853 :             !bms_overlap(restrictinfo->left_relids,
     161           75853 :                          restrictinfo->right_relids))
     162                 :         {
     163           75064 :             restrictinfo->can_join = true;
     164 ECB             :             /* pseudoconstant should certainly not be true */
     165 CBC       75064 :             Assert(!restrictinfo->pseudoconstant);
     166                 :         }
     167 ECB             :     }
     168                 :     else
     169                 :     {
     170                 :         /* Not a binary opclause, so mark left/right relid sets as empty */
     171 CBC       44231 :         restrictinfo->left_relids = NULL;
     172           44231 :         restrictinfo->right_relids = NULL;
     173                 :         /* and get the total relid set the hard way */
     174           44231 :         restrictinfo->clause_relids = pull_varnos(root, (Node *) clause);
     175                 :     }
     176                 : 
     177                 :     /* required_relids defaults to clause_relids */
     178 GIC      260725 :     if (required_relids != NULL)
     179          234403 :         restrictinfo->required_relids = required_relids;
     180                 :     else
     181           26322 :         restrictinfo->required_relids = restrictinfo->clause_relids;
     182                 : 
     183                 :     /*
     184                 :      * Count the number of base rels appearing in clause_relids.  To do this,
     185                 :      * we just delete rels mentioned in root->outer_join_rels and count the
     186                 :      * survivors.  Because we are called during deconstruct_jointree which is
     187                 :      * the same tree walk that populates outer_join_rels, this is a little bit
     188                 :      * unsafe-looking; but it should be fine because the recursion in
     189                 :      * deconstruct_jointree should already have visited any outer join that
     190                 :      * could be mentioned in this clause.
     191                 :      */
     192 GNC      260725 :     baserels = bms_difference(restrictinfo->clause_relids,
     193          260725 :                               root->outer_join_rels);
     194          260725 :     restrictinfo->num_base_rels = bms_num_members(baserels);
     195          260725 :     bms_free(baserels);
     196                 : 
     197                 :     /*
     198                 :      * Label this RestrictInfo with a fresh serial number.
     199                 :      */
     200          260725 :     restrictinfo->rinfo_serial = ++(root->last_rinfo_serial);
     201                 : 
     202                 :     /*
     203                 :      * Fill in all the cacheable fields with "not yet set" markers. None of
     204 ECB             :      * these will be computed until/unless needed.  Note in particular that we
     205                 :      * don't mark a binary opclause as mergejoinable or hashjoinable here;
     206                 :      * that happens only if it appears in the right context (top level of a
     207                 :      * joinclause list).
     208                 :      */
     209 GIC      260725 :     restrictinfo->parent_ec = NULL;
     210                 : 
     211          260725 :     restrictinfo->eval_cost.startup = -1;
     212 CBC      260725 :     restrictinfo->norm_selec = -1;
     213 GIC      260725 :     restrictinfo->outer_selec = -1;
     214                 : 
     215          260725 :     restrictinfo->mergeopfamilies = NIL;
     216                 : 
     217          260725 :     restrictinfo->left_ec = NULL;
     218          260725 :     restrictinfo->right_ec = NULL;
     219          260725 :     restrictinfo->left_em = NULL;
     220          260725 :     restrictinfo->right_em = NULL;
     221 CBC      260725 :     restrictinfo->scansel_cache = NIL;
     222                 : 
     223          260725 :     restrictinfo->outer_is_left = false;
     224 ECB             : 
     225 CBC      260725 :     restrictinfo->hashjoinoperator = InvalidOid;
     226                 : 
     227          260725 :     restrictinfo->left_bucketsize = -1;
     228 GIC      260725 :     restrictinfo->right_bucketsize = -1;
     229 CBC      260725 :     restrictinfo->left_mcvfreq = -1;
     230          260725 :     restrictinfo->right_mcvfreq = -1;
     231 ECB             : 
     232 CBC      260725 :     restrictinfo->left_hasheqoperator = InvalidOid;
     233          260725 :     restrictinfo->right_hasheqoperator = InvalidOid;
     234                 : 
     235          260725 :     return restrictinfo;
     236                 : }
     237 ECB             : 
     238                 : /*
     239                 :  * Recursively insert sub-RestrictInfo nodes into a boolean expression.
     240                 :  *
     241                 :  * We put RestrictInfos above simple (non-AND/OR) clauses and above
     242                 :  * sub-OR clauses, but not above sub-AND clauses, because there's no need.
     243                 :  * This may seem odd but it is closely related to the fact that we use
     244                 :  * implicit-AND lists at top level of RestrictInfo lists.  Only ORs and
     245                 :  * simple clauses are valid RestrictInfos.
     246                 :  *
     247                 :  * The same is_pushed_down and pseudoconstant flag
     248                 :  * values can be applied to all RestrictInfo nodes in the result.  Likewise
     249                 :  * for security_level and outer_relids.
     250                 :  *
     251                 :  * The given required_relids are attached to our top-level output,
     252                 :  * but any OR-clause constituents are allowed to default to just the
     253                 :  * contained rels.
     254                 :  */
     255                 : static Expr *
     256 GIC       14536 : make_sub_restrictinfos(PlannerInfo *root,
     257                 :                        Expr *clause,
     258                 :                        bool is_pushed_down,
     259                 :                        bool pseudoconstant,
     260                 :                        Index security_level,
     261                 :                        Relids required_relids,
     262                 :                        Relids outer_relids)
     263                 : {
     264           14536 :     if (is_orclause(clause))
     265                 :     {
     266 CBC        3514 :         List       *orlist = NIL;
     267                 :         ListCell   *temp;
     268                 : 
     269 GIC       11821 :         foreach(temp, ((BoolExpr *) clause)->args)
     270            8307 :             orlist = lappend(orlist,
     271            8307 :                              make_sub_restrictinfos(root,
     272            8307 :                                                     lfirst(temp),
     273                 :                                                     is_pushed_down,
     274                 :                                                     pseudoconstant,
     275 ECB             :                                                     security_level,
     276                 :                                                     NULL,
     277                 :                                                     outer_relids));
     278 CBC        3514 :         return (Expr *) make_restrictinfo_internal(root,
     279 ECB             :                                                    clause,
     280                 :                                                    make_orclause(orlist),
     281                 :                                                    is_pushed_down,
     282                 :                                                    pseudoconstant,
     283                 :                                                    security_level,
     284                 :                                                    required_relids,
     285                 :                                                    outer_relids);
     286                 :     }
     287 GIC       11022 :     else if (is_andclause(clause))
     288                 :     {
     289            1282 :         List       *andlist = NIL;
     290                 :         ListCell   *temp;
     291                 : 
     292            4036 :         foreach(temp, ((BoolExpr *) clause)->args)
     293 CBC        2754 :             andlist = lappend(andlist,
     294 GIC        2754 :                               make_sub_restrictinfos(root,
     295 CBC        2754 :                                                      lfirst(temp),
     296                 :                                                      is_pushed_down,
     297 ECB             :                                                      pseudoconstant,
     298                 :                                                      security_level,
     299                 :                                                      required_relids,
     300                 :                                                      outer_relids));
     301 GIC        1282 :         return make_andclause(andlist);
     302                 :     }
     303                 :     else
     304            9740 :         return (Expr *) make_restrictinfo_internal(root,
     305 ECB             :                                                    clause,
     306                 :                                                    NULL,
     307                 :                                                    is_pushed_down,
     308                 :                                                    pseudoconstant,
     309                 :                                                    security_level,
     310                 :                                                    required_relids,
     311                 :                                                    outer_relids);
     312                 : }
     313                 : 
     314                 : /*
     315                 :  * commute_restrictinfo
     316                 :  *
     317                 :  * Given a RestrictInfo containing a binary opclause, produce a RestrictInfo
     318                 :  * representing the commutation of that clause.  The caller must pass the
     319                 :  * OID of the commutator operator (which it's presumably looked up, else
     320                 :  * it would not know this is valid).
     321                 :  *
     322                 :  * Beware that the result shares sub-structure with the given RestrictInfo.
     323                 :  * That's okay for the intended usage with derived index quals, but might
     324                 :  * be hazardous if the source is subject to change.  Also notice that we
     325                 :  * assume without checking that the commutator op is a member of the same
     326                 :  * btree and hash opclasses as the original op.
     327                 :  */
     328                 : RestrictInfo *
     329 GIC       23039 : commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op)
     330                 : {
     331 ECB             :     RestrictInfo *result;
     332                 :     OpExpr     *newclause;
     333 GIC       23039 :     OpExpr     *clause = castNode(OpExpr, rinfo->clause);
     334                 : 
     335 CBC       23039 :     Assert(list_length(clause->args) == 2);
     336                 : 
     337 ECB             :     /* flat-copy all the fields of clause ... */
     338 GIC       23039 :     newclause = makeNode(OpExpr);
     339           23039 :     memcpy(newclause, clause, sizeof(OpExpr));
     340 ECB             : 
     341                 :     /* ... and adjust those we need to change to commute it */
     342 GIC       23039 :     newclause->opno = comm_op;
     343           23039 :     newclause->opfuncid = InvalidOid;
     344 CBC       23039 :     newclause->args = list_make2(lsecond(clause->args),
     345 ECB             :                                  linitial(clause->args));
     346                 : 
     347                 :     /* likewise, flat-copy all the fields of rinfo ... */
     348 GIC       23039 :     result = makeNode(RestrictInfo);
     349           23039 :     memcpy(result, rinfo, sizeof(RestrictInfo));
     350 ECB             : 
     351                 :     /*
     352                 :      * ... and adjust those we need to change.  Note in particular that we can
     353                 :      * preserve any cached selectivity or cost estimates, since those ought to
     354                 :      * be the same for the new clause.  Likewise we can keep the source's
     355                 :      * parent_ec.  It's also important that we keep the same rinfo_serial.
     356                 :      */
     357 GIC       23039 :     result->clause = (Expr *) newclause;
     358           23039 :     result->left_relids = rinfo->right_relids;
     359 CBC       23039 :     result->right_relids = rinfo->left_relids;
     360           23039 :     Assert(result->orclause == NULL);
     361           23039 :     result->left_ec = rinfo->right_ec;
     362           23039 :     result->right_ec = rinfo->left_ec;
     363           23039 :     result->left_em = rinfo->right_em;
     364           23039 :     result->right_em = rinfo->left_em;
     365           23039 :     result->scansel_cache = NIL; /* not worth updating this */
     366           23039 :     if (rinfo->hashjoinoperator == clause->opno)
     367           22537 :         result->hashjoinoperator = comm_op;
     368 ECB             :     else
     369 CBC         502 :         result->hashjoinoperator = InvalidOid;
     370 GIC       23039 :     result->left_bucketsize = rinfo->right_bucketsize;
     371 CBC       23039 :     result->right_bucketsize = rinfo->left_bucketsize;
     372           23039 :     result->left_mcvfreq = rinfo->right_mcvfreq;
     373           23039 :     result->right_mcvfreq = rinfo->left_mcvfreq;
     374           23039 :     result->left_hasheqoperator = InvalidOid;
     375           23039 :     result->right_hasheqoperator = InvalidOid;
     376 ECB             : 
     377 CBC       23039 :     return result;
     378                 : }
     379 ECB             : 
     380                 : /*
     381                 :  * restriction_is_or_clause
     382                 :  *
     383                 :  * Returns t iff the restrictinfo node contains an 'or' clause.
     384                 :  */
     385                 : bool
     386 GIC      386446 : restriction_is_or_clause(RestrictInfo *restrictinfo)
     387                 : {
     388 CBC      386446 :     if (restrictinfo->orclause != NULL)
     389 GIC       14268 :         return true;
     390 ECB             :     else
     391 CBC      372178 :         return false;
     392                 : }
     393 ECB             : 
     394                 : /*
     395                 :  * restriction_is_securely_promotable
     396                 :  *
     397                 :  * Returns true if it's okay to evaluate this clause "early", that is before
     398                 :  * other restriction clauses attached to the specified relation.
     399                 :  */
     400                 : bool
     401 GIC      569087 : restriction_is_securely_promotable(RestrictInfo *restrictinfo,
     402                 :                                    RelOptInfo *rel)
     403 ECB             : {
     404                 :     /*
     405                 :      * It's okay if there are no baserestrictinfo clauses for the rel that
     406                 :      * would need to go before this one, *or* if this one is leakproof.
     407                 :      */
     408 GIC      569087 :     if (restrictinfo->security_level <= rel->baserestrict_min_security ||
     409            2095 :         restrictinfo->leakproof)
     410 CBC      568036 :         return true;
     411 ECB             :     else
     412 CBC        1051 :         return false;
     413                 : }
     414 ECB             : 
     415                 : /*
     416                 :  * Detect whether a RestrictInfo's clause is constant TRUE (note that it's
     417                 :  * surely of type boolean).  No such WHERE clause could survive qual
     418                 :  * canonicalization, but equivclass.c may generate such RestrictInfos for
     419                 :  * reasons discussed therein.  We should drop them again when creating
     420                 :  * the finished plan, which is handled by the next few functions.
     421                 :  */
     422                 : static inline bool
     423 GNC      157289 : rinfo_is_constant_true(RestrictInfo *rinfo)
     424                 : {
     425          158035 :     return IsA(rinfo->clause, Const) &&
     426          158008 :         !((Const *) rinfo->clause)->constisnull &&
     427             719 :         DatumGetBool(((Const *) rinfo->clause)->constvalue);
     428                 : }
     429                 : 
     430                 : /*
     431                 :  * get_actual_clauses
     432                 :  *
     433                 :  * Returns a list containing the bare clauses from 'restrictinfo_list'.
     434                 :  *
     435                 :  * This is only to be used in cases where none of the RestrictInfos can
     436                 :  * be pseudoconstant clauses (for instance, it's OK on indexqual lists).
     437                 :  */
     438                 : List *
     439 GIC       27541 : get_actual_clauses(List *restrictinfo_list)
     440 ECB             : {
     441 GIC       27541 :     List       *result = NIL;
     442 ECB             :     ListCell   *l;
     443                 : 
     444 CBC       56547 :     foreach(l, restrictinfo_list)
     445                 :     {
     446 GIC       29006 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
     447                 : 
     448           29006 :         Assert(!rinfo->pseudoconstant);
     449 GNC       29006 :         Assert(!rinfo_is_constant_true(rinfo));
     450                 : 
     451 GIC       29006 :         result = lappend(result, rinfo->clause);
     452                 :     }
     453           27541 :     return result;
     454                 : }
     455                 : 
     456                 : /*
     457 ECB             :  * extract_actual_clauses
     458                 :  *
     459                 :  * Extract bare clauses from 'restrictinfo_list', returning either the
     460                 :  * regular ones or the pseudoconstant ones per 'pseudoconstant'.
     461                 :  * Constant-TRUE clauses are dropped in any case.
     462                 :  */
     463                 : List *
     464 GIC      252629 : extract_actual_clauses(List *restrictinfo_list,
     465 ECB             :                        bool pseudoconstant)
     466                 : {
     467 CBC      252629 :     List       *result = NIL;
     468 ECB             :     ListCell   *l;
     469                 : 
     470 CBC      377522 :     foreach(l, restrictinfo_list)
     471                 :     {
     472          124893 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
     473                 : 
     474 GNC      124893 :         if (rinfo->pseudoconstant == pseudoconstant &&
     475          114408 :             !rinfo_is_constant_true(rinfo))
     476 GIC      114408 :             result = lappend(result, rinfo->clause);
     477                 :     }
     478          252629 :     return result;
     479                 : }
     480                 : 
     481                 : /*
     482                 :  * extract_actual_join_clauses
     483                 :  *
     484 ECB             :  * Extract bare clauses from 'restrictinfo_list', separating those that
     485                 :  * semantically match the join level from those that were pushed down.
     486                 :  * Pseudoconstant and constant-TRUE clauses are excluded from the results.
     487                 :  *
     488                 :  * This is only used at outer joins, since for plain joins we don't care
     489                 :  * about pushed-down-ness.
     490                 :  */
     491                 : void
     492 CBC       16047 : extract_actual_join_clauses(List *restrictinfo_list,
     493                 :                             Relids joinrelids,
     494 ECB             :                             List **joinquals,
     495                 :                             List **otherquals)
     496                 : {
     497                 :     ListCell   *l;
     498                 : 
     499 GIC       16047 :     *joinquals = NIL;
     500           16047 :     *otherquals = NIL;
     501                 : 
     502           29925 :     foreach(l, restrictinfo_list)
     503                 :     {
     504           13878 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
     505                 : 
     506           13878 :         if (RINFO_IS_PUSHED_DOWN(rinfo, joinrelids))
     507                 :         {
     508 GNC        1874 :             if (!rinfo->pseudoconstant &&
     509            1871 :                 !rinfo_is_constant_true(rinfo))
     510 GIC        1221 :                 *otherquals = lappend(*otherquals, rinfo->clause);
     511                 :         }
     512                 :         else
     513 ECB             :         {
     514                 :             /* joinquals shouldn't have been marked pseudoconstant */
     515 GIC       12004 :             Assert(!rinfo->pseudoconstant);
     516 GNC       12004 :             Assert(!rinfo_is_constant_true(rinfo));
     517 GIC       12004 :             *joinquals = lappend(*joinquals, rinfo->clause);
     518                 :         }
     519                 :     }
     520           16047 : }
     521 ECB             : 
     522                 : /*
     523                 :  * clause_is_computable_at
     524                 :  *      Test whether a clause is computable at a given evaluation level.
     525                 :  *
     526                 :  * There are two conditions for whether an expression can actually be
     527                 :  * evaluated at a given join level: the evaluation context must include
     528                 :  * all the relids (both base and OJ) used by the expression, and we must
     529                 :  * not have already evaluated any outer joins that null Vars/PHVs of the
     530                 :  * expression and are not listed in their nullingrels.
     531                 :  *
     532                 :  * This function checks the second condition; we assume the caller already
     533                 :  * saw to the first one.
     534                 :  *
     535                 :  * For speed reasons, we don't individually examine each Var/PHV of the
     536                 :  * expression, but just look at the overall clause_relids (the union of the
     537                 :  * varnos and varnullingrels).  This could give a misleading answer if the
     538                 :  * Vars of a given varno don't all have the same varnullingrels; but that
     539                 :  * really shouldn't happen within a single scalar expression or RestrictInfo
     540                 :  * clause.  Despite that, this is still annoyingly expensive :-(
     541                 :  */
     542                 : bool
     543 GNC      125738 : clause_is_computable_at(PlannerInfo *root,
     544                 :                         Relids clause_relids,
     545                 :                         Relids eval_relids)
     546                 : {
     547                 :     ListCell   *lc;
     548                 : 
     549                 :     /* Nothing to do if no outer joins have been performed yet. */
     550          125738 :     if (!bms_overlap(eval_relids, root->outer_join_rels))
     551           66602 :         return true;
     552                 : 
     553          202403 :     foreach(lc, root->join_info_list)
     554                 :     {
     555          149437 :         SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
     556                 : 
     557                 :         /* Ignore outer joins that are not yet performed. */
     558          149437 :         if (!bms_is_member(sjinfo->ojrelid, eval_relids))
     559           71872 :             continue;
     560                 : 
     561                 :         /* OK if clause lists it (we assume all Vars in it agree). */
     562           77565 :         if (bms_is_member(sjinfo->ojrelid, clause_relids))
     563            9853 :             continue;
     564                 : 
     565                 :         /* Else, trouble if clause mentions any nullable Vars. */
     566           67712 :         if (bms_overlap(clause_relids, sjinfo->min_righthand) ||
     567           61548 :             (sjinfo->jointype == JOIN_FULL &&
     568               6 :              bms_overlap(clause_relids, sjinfo->min_lefthand)))
     569            6170 :             return false;       /* doesn't work */
     570                 :     }
     571                 : 
     572           52966 :     return true;                /* OK */
     573                 : }
     574 ECB             : 
     575                 : /*
     576                 :  * join_clause_is_movable_to
     577                 :  *      Test whether a join clause is a safe candidate for parameterization
     578                 :  *      of a scan on the specified base relation.
     579                 :  *
     580                 :  * A movable join clause is one that can safely be evaluated at a rel below
     581                 :  * its normal semantic level (ie, its required_relids), if the values of
     582                 :  * variables that it would need from other rels are provided.
     583                 :  *
     584                 :  * We insist that the clause actually reference the target relation; this
     585                 :  * prevents undesirable movement of degenerate join clauses, and ensures
     586                 :  * that there is a unique place that a clause can be moved down to.
     587                 :  *
     588                 :  * We cannot move an outer-join clause into the non-nullable side of its
     589                 :  * outer join, as that would change the results (rows would be suppressed
     590                 :  * rather than being null-extended).
     591                 :  *
     592                 :  * Also there must not be an outer join below the clause that would null the
     593                 :  * Vars coming from the target relation.  Otherwise the clause might give
     594                 :  * results different from what it would give at its normal semantic level.
     595                 :  *
     596                 :  * Also, the join clause must not use any relations that have LATERAL
     597                 :  * references to the target relation, since we could not put such rels on
     598                 :  * the outer side of a nestloop with the target relation.
     599                 :  *
     600                 :  * Also, we reject is_clone versions of outer-join clauses.  This has the
     601                 :  * effect of preventing us from generating variant parameterized paths
     602                 :  * that differ only in which outer joins null the parameterization rel(s).
     603                 :  * Generating one path from the minimally-parameterized has_clone version
     604                 :  * is sufficient.
     605                 :  */
     606                 : bool
     607 GIC      103556 : join_clause_is_movable_to(RestrictInfo *rinfo, RelOptInfo *baserel)
     608                 : {
     609                 :     /* Clause must physically reference target rel */
     610          103556 :     if (!bms_is_member(baserel->relid, rinfo->clause_relids))
     611           15375 :         return false;
     612                 : 
     613                 :     /* Cannot move an outer-join clause into the join's outer side */
     614           88181 :     if (bms_is_member(baserel->relid, rinfo->outer_relids))
     615           39989 :         return false;
     616                 : 
     617                 :     /*
     618                 :      * Target rel's Vars must not be nulled by any outer join.  We can check
     619                 :      * this without groveling through the individual Vars by seeing whether
     620                 :      * clause_relids (which includes all such Vars' varnullingrels) includes
     621                 :      * any outer join that can null the target rel.  You might object that
     622                 :      * this could reject the clause on the basis of an OJ relid that came from
     623                 :      * some other rel's Var.  However, that would still mean that the clause
     624                 :      * came from above that outer join and shouldn't be pushed down; so there
     625                 :      * should be no false positives.
     626                 :      */
     627 GNC       48192 :     if (bms_overlap(rinfo->clause_relids, baserel->nulling_relids))
     628 GIC        2140 :         return false;
     629                 : 
     630                 :     /* Clause must not use any rels with LATERAL references to this rel */
     631           46052 :     if (bms_overlap(baserel->lateral_referencers, rinfo->clause_relids))
     632 CBC           9 :         return false;
     633                 : 
     634                 :     /* Ignore clones, too */
     635 GNC       46043 :     if (rinfo->is_clone)
     636            4021 :         return false;
     637                 : 
     638 GIC       42022 :     return true;
     639                 : }
     640                 : 
     641                 : /*
     642                 :  * join_clause_is_movable_into
     643 ECB             :  *      Test whether a join clause is movable and can be evaluated within
     644                 :  *      the current join context.
     645                 :  *
     646                 :  * currentrelids: the relids of the proposed evaluation location
     647                 :  * current_and_outer: the union of currentrelids and the required_outer
     648                 :  *      relids (parameterization's outer relations)
     649                 :  *
     650                 :  * The API would be a bit clearer if we passed the current relids and the
     651                 :  * outer relids separately and did bms_union internally; but since most
     652                 :  * callers need to apply this function to multiple clauses, we make the
     653                 :  * caller perform the union.
     654                 :  *
     655                 :  * Obviously, the clause must only refer to Vars available from the current
     656                 :  * relation plus the outer rels.  We also check that it does reference at
     657                 :  * least one current Var, ensuring that the clause will be pushed down to
     658                 :  * a unique place in a parameterized join tree.  And we check that we're
     659                 :  * not pushing the clause into its outer-join outer side.
     660                 :  *
     661                 :  * We used to need to check that we're not pushing the clause into a lower
     662                 :  * outer join's inner side.  However, now that clause_relids includes
     663                 :  * references to potentially-nulling outer joins, the other tests handle that
     664                 :  * concern.  If the clause references any Var coming from the inside of a
     665                 :  * lower outer join, its clause_relids will mention that outer join, causing
     666                 :  * the evaluability check to fail; while if it references no such Vars, the
     667                 :  * references-a-target-rel check will fail.
     668                 :  *
     669                 :  * There's no check here equivalent to join_clause_is_movable_to's test on
     670                 :  * lateral_referencers.  We assume the caller wouldn't be inquiring unless
     671                 :  * it'd verified that the proposed outer rels don't have lateral references
     672                 :  * to the current rel(s).  (If we are considering join paths with the outer
     673                 :  * rels on the outside and the current rels on the inside, then this should
     674                 :  * have been checked at the outset of such consideration; see join_is_legal
     675                 :  * and the path parameterization checks in joinpath.c.)  On the other hand,
     676                 :  * in join_clause_is_movable_to we are asking whether the clause could be
     677                 :  * moved for some valid set of outer rels, so we don't have the benefit of
     678                 :  * relying on prior checks for lateral-reference validity.
     679                 :  *
     680                 :  * Likewise, we don't check is_clone here: rejecting the inappropriate
     681                 :  * variants of a cloned clause must be handled upstream.
     682                 :  *
     683                 :  * Note: if this returns true, it means that the clause could be moved to
     684                 :  * this join relation, but that doesn't mean that this is the lowest join
     685                 :  * it could be moved to.  Caller may need to make additional calls to verify
     686                 :  * that this doesn't succeed on either of the inputs of a proposed join.
     687                 :  *
     688                 :  * Note: get_joinrel_parampathinfo depends on the fact that if
     689                 :  * current_and_outer is NULL, this function will always return false
     690                 :  * (since one or the other of the first two tests must fail).
     691                 :  */
     692                 : bool
     693 GIC      121022 : join_clause_is_movable_into(RestrictInfo *rinfo,
     694                 :                             Relids currentrelids,
     695                 :                             Relids current_and_outer)
     696                 : {
     697                 :     /* Clause must be evaluable given available context */
     698          121022 :     if (!bms_is_subset(rinfo->clause_relids, current_and_outer))
     699           22085 :         return false;
     700 ECB             : 
     701                 :     /* Clause must physically reference at least one target rel */
     702 GIC       98937 :     if (!bms_overlap(currentrelids, rinfo->clause_relids))
     703 CBC        7069 :         return false;
     704 ECB             : 
     705                 :     /* Cannot move an outer-join clause into the join's outer side */
     706 GIC       91868 :     if (bms_overlap(currentrelids, rinfo->outer_relids))
     707 CBC         314 :         return false;
     708 ECB             : 
     709 GIC       91554 :     return true;
     710                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a