LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/path - tidpath.c (source / functions) Coverage Total Hit LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 95.8 % 144 138 4 2 1 79 4 54 5 79 1
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 12 12 11 1 11
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (180,240] days: 100.0 % 3 3 3
(240..) days: 95.7 % 140 134 4 2 1 79 54 5 78
Function coverage date bins:
(240..) days: 52.2 % 23 12 11 1 11

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * tidpath.c
                                  4                 :  *    Routines to determine which TID conditions are usable for scanning
                                  5                 :  *    a given relation, and create TidPaths and TidRangePaths accordingly.
                                  6                 :  *
                                  7                 :  * For TidPaths, we look for WHERE conditions of the form
                                  8                 :  * "CTID = pseudoconstant", which can be implemented by just fetching
                                  9                 :  * the tuple directly via heap_fetch().  We can also handle OR'd conditions
                                 10                 :  * such as (CTID = const1) OR (CTID = const2), as well as ScalarArrayOpExpr
                                 11                 :  * conditions of the form CTID = ANY(pseudoconstant_array).  In particular
                                 12                 :  * this allows
                                 13                 :  *      WHERE ctid IN (tid1, tid2, ...)
                                 14                 :  *
                                 15                 :  * As with indexscans, our definition of "pseudoconstant" is pretty liberal:
                                 16                 :  * we allow anything that doesn't involve a volatile function or a Var of
                                 17                 :  * the relation under consideration.  Vars belonging to other relations of
                                 18                 :  * the query are allowed, giving rise to parameterized TID scans.
                                 19                 :  *
                                 20                 :  * We also support "WHERE CURRENT OF cursor" conditions (CurrentOfExpr),
                                 21                 :  * which amount to "CTID = run-time-determined-TID".  These could in
                                 22                 :  * theory be translated to a simple comparison of CTID to the result of
                                 23                 :  * a function, but in practice it works better to keep the special node
                                 24                 :  * representation all the way through to execution.
                                 25                 :  *
                                 26                 :  * Additionally, TidRangePaths may be created for conditions of the form
                                 27                 :  * "CTID relop pseudoconstant", where relop is one of >,>=,<,<=, and
                                 28                 :  * AND-clauses composed of such conditions.
                                 29                 :  *
                                 30                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 31                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 32                 :  *
                                 33                 :  *
                                 34                 :  * IDENTIFICATION
                                 35                 :  *    src/backend/optimizer/path/tidpath.c
                                 36                 :  *
                                 37                 :  *-------------------------------------------------------------------------
                                 38                 :  */
                                 39                 : #include "postgres.h"
                                 40                 : 
                                 41                 : #include "access/sysattr.h"
                                 42                 : #include "catalog/pg_operator.h"
                                 43                 : #include "catalog/pg_type.h"
                                 44                 : #include "nodes/nodeFuncs.h"
                                 45                 : #include "optimizer/clauses.h"
                                 46                 : #include "optimizer/optimizer.h"
                                 47                 : #include "optimizer/pathnode.h"
                                 48                 : #include "optimizer/paths.h"
                                 49                 : #include "optimizer/restrictinfo.h"
                                 50                 : 
                                 51                 : 
                                 52                 : /*
                                 53                 :  * Does this Var represent the CTID column of the specified baserel?
                                 54                 :  */
                                 55                 : static inline bool
 1561 tgl                        56 CBC      340363 : IsCTIDVar(Var *var, RelOptInfo *rel)
                                 57                 : {
                                 58                 :     /* The vartype check is strictly paranoia */
                                 59          340363 :     if (var->varattno == SelfItemPointerAttributeNumber &&
                                 60             710 :         var->vartype == TIDOID &&
                                 61             710 :         var->varno == rel->relid &&
   69 tgl                        62 GNC         653 :         var->varnullingrels == NULL &&
 1561 tgl                        63 CBC         653 :         var->varlevelsup == 0)
                                 64             653 :         return true;
                                 65          339710 :     return false;
 1561 tgl                        66 ECB             : }
                                 67                 : 
                                 68                 : /*
                                 69                 :  * Check to see if a RestrictInfo is of the form
                                 70                 :  *      CTID OP pseudoconstant
                                 71                 :  * or
                                 72                 :  *      pseudoconstant OP CTID
                                 73                 :  * where OP is a binary operation, the CTID Var belongs to relation "rel",
                                 74                 :  * and nothing on the other side of the clause does.
                                 75                 :  */
                                 76                 : static bool
  771 drowley                    77 GIC      340427 : IsBinaryTidClause(RestrictInfo *rinfo, RelOptInfo *rel)
 8538 bruce                      78 ECB             : {
                                 79                 :     OpExpr     *node;
                                 80                 :     Node       *arg1,
                                 81                 :                *arg2,
                                 82                 :                *other;
                                 83                 :     Relids      other_relids;
                                 84                 : 
                                 85                 :     /* Must be an OpExpr */
 1561 tgl                        86 GIC      340427 :     if (!is_opclause(rinfo->clause))
 1561 tgl                        87 CBC       70386 :         return false;
                                 88          270041 :     node = (OpExpr *) rinfo->clause;
 8538 bruce                      89 ECB             : 
                                 90                 :     /* OpExpr must have two arguments */
  771 drowley                    91 GIC      270041 :     if (list_length(node->args) != 2)
 6343 tgl                        92 CBC          24 :         return false;
 6892 neilc                      93          270017 :     arg1 = linitial(node->args);
 8538 bruce                      94          270017 :     arg2 = lsecond(node->args);
 8538 bruce                      95 ECB             : 
                                 96                 :     /* Look for CTID as either argument */
 6438 tgl                        97 GIC      270017 :     other = NULL;
 1561 tgl                        98 CBC      270017 :     other_relids = NULL;
                                 99          525563 :     if (arg1 && IsA(arg1, Var) &&
                                100          255546 :         IsCTIDVar((Var *) arg1, rel))
 8538 bruce                     101 ECB             :     {
 1561 tgl                       102 GIC         461 :         other = arg2;
 1561 tgl                       103 CBC         461 :         other_relids = rinfo->right_relids;
 8538 bruce                     104 ECB             :     }
 1561 tgl                       105 GIC      315483 :     if (!other && arg2 && IsA(arg2, Var) &&
 1561 tgl                       106 CBC       45466 :         IsCTIDVar((Var *) arg2, rel))
 8538 bruce                     107 ECB             :     {
 1561 tgl                       108 GIC         111 :         other = arg1;
 1561 tgl                       109 CBC         111 :         other_relids = rinfo->left_relids;
 8538 bruce                     110 ECB             :     }
 6438 tgl                       111 GIC      270017 :     if (!other)
 6343 tgl                       112 CBC      269445 :         return false;
 6438 tgl                       113 ECB             : 
                                114                 :     /* The other argument must be a pseudoconstant */
 1561 tgl                       115 GIC        1144 :     if (bms_is_member(rel->relid, other_relids) ||
 1561 tgl                       116 CBC         572 :         contain_volatile_functions(other))
 6343 tgl                       117 LBC           0 :         return false;
 6343 tgl                       118 EUB             : 
 6343 tgl                       119 GIC         572 :     return true;                /* success */
 6343 tgl                       120 ECB             : }
                                121                 : 
                                122                 : /*
                                123                 :  * Check to see if a RestrictInfo is of the form
                                124                 :  *      CTID = pseudoconstant
                                125                 :  * or
                                126                 :  *      pseudoconstant = CTID
                                127                 :  * where the CTID Var belongs to relation "rel", and nothing on the
                                128                 :  * other side of the clause does.
                                129                 :  */
                                130                 : static bool
  771 drowley                   131 GIC      191925 : IsTidEqualClause(RestrictInfo *rinfo, RelOptInfo *rel)
  771 drowley                   132 ECB             : {
  771 drowley                   133 GIC      191925 :     if (!IsBinaryTidClause(rinfo, rel))
  771 drowley                   134 CBC      191558 :         return false;
  771 drowley                   135 ECB             : 
  771 drowley                   136 GIC         367 :     if (((OpExpr *) rinfo->clause)->opno == TIDEqualOperator)
  771 drowley                   137 CBC         185 :         return true;
  771 drowley                   138 ECB             : 
  771 drowley                   139 GIC         182 :     return false;
  771 drowley                   140 ECB             : }
                                141                 : 
                                142                 : /*
                                143                 :  * Check to see if a RestrictInfo is of the form
                                144                 :  *      CTID OP pseudoconstant
                                145                 :  * or
                                146                 :  *      pseudoconstant OP CTID
                                147                 :  * where OP is a range operator such as <, <=, >, or >=, the CTID Var belongs
                                148                 :  * to relation "rel", and nothing on the other side of the clause does.
                                149                 :  */
                                150                 : static bool
  771 drowley                   151 GIC      148502 : IsTidRangeClause(RestrictInfo *rinfo, RelOptInfo *rel)
  771 drowley                   152 ECB             : {
                                153                 :     Oid         opno;
                                154                 : 
  771 drowley                   155 GIC      148502 :     if (!IsBinaryTidClause(rinfo, rel))
  771 drowley                   156 CBC      148297 :         return false;
                                157             205 :     opno = ((OpExpr *) rinfo->clause)->opno;
  771 drowley                   158 ECB             : 
  771 drowley                   159 GIC         205 :     if (opno == TIDLessOperator || opno == TIDLessEqOperator ||
  771 drowley                   160 CBC         116 :         opno == TIDGreaterOperator || opno == TIDGreaterEqOperator)
                                161             116 :         return true;
  771 drowley                   162 ECB             : 
  771 drowley                   163 GIC          89 :     return false;
  771 drowley                   164 ECB             : }
                                165                 : 
                                166                 : /*
                                167                 :  * Check to see if a RestrictInfo is of the form
                                168                 :  *      CTID = ANY (pseudoconstant_array)
                                169                 :  * where the CTID Var belongs to relation "rel", and nothing on the
                                170                 :  * other side of the clause does.
                                171                 :  */
                                172                 : static bool
  808 tgl                       173 GIC      145416 : IsTidEqualAnyClause(PlannerInfo *root, RestrictInfo *rinfo, RelOptInfo *rel)
 6343 tgl                       174 ECB             : {
                                175                 :     ScalarArrayOpExpr *node;
                                176                 :     Node       *arg1,
                                177                 :                *arg2;
                                178                 : 
                                179                 :     /* Must be a ScalarArrayOpExpr */
 1561 tgl                       180 GIC      145416 :     if (!(rinfo->clause && IsA(rinfo->clause, ScalarArrayOpExpr)))
 1561 tgl                       181 CBC      138250 :         return false;
                                182            7166 :     node = (ScalarArrayOpExpr *) rinfo->clause;
 1561 tgl                       183 ECB             : 
                                184                 :     /* Operator must be tideq */
 6343 tgl                       185 GIC        7166 :     if (node->opno != TIDEqualOperator)
 6343 tgl                       186 CBC        7151 :         return false;
                                187              15 :     if (!node->useOr)
 6343 tgl                       188 LBC           0 :         return false;
 6343 tgl                       189 GBC          15 :     Assert(list_length(node->args) == 2);
 6343 tgl                       190 CBC          15 :     arg1 = linitial(node->args);
                                191              15 :     arg2 = lsecond(node->args);
 6343 tgl                       192 ECB             : 
                                193                 :     /* CTID must be first argument */
 1561 tgl                       194 GIC          30 :     if (arg1 && IsA(arg1, Var) &&
 1561 tgl                       195 CBC          15 :         IsCTIDVar((Var *) arg1, rel))
 6343 tgl                       196 ECB             :     {
                                197                 :         /* The other argument must be a pseudoconstant */
  808 tgl                       198 GIC          30 :         if (bms_is_member(rel->relid, pull_varnos(root, arg2)) ||
 1561 tgl                       199 CBC          15 :             contain_volatile_functions(arg2))
 1561 tgl                       200 LBC           0 :             return false;
 6438 tgl                       201 EUB             : 
 1561 tgl                       202 GIC          15 :         return true;            /* success */
 6343 tgl                       203 ECB             :     }
                                204                 : 
 6343 tgl                       205 UIC           0 :     return false;
 8538 bruce                     206 EUB             : }
                                207                 : 
                                208                 : /*
                                209                 :  * Check to see if a RestrictInfo is a CurrentOfExpr referencing "rel".
                                210                 :  */
                                211                 : static bool
 1561 tgl                       212 GIC      145401 : IsCurrentOfClause(RestrictInfo *rinfo, RelOptInfo *rel)
 1561 tgl                       213 ECB             : {
                                214                 :     CurrentOfExpr *node;
                                215                 : 
                                216                 :     /* Must be a CurrentOfExpr */
 1561 tgl                       217 GIC      145401 :     if (!(rinfo->clause && IsA(rinfo->clause, CurrentOfExpr)))
 1561 tgl                       218 CBC      145205 :         return false;
                                219             196 :     node = (CurrentOfExpr *) rinfo->clause;
 1561 tgl                       220 ECB             : 
                                221                 :     /* If it references this rel, we're good */
 1561 tgl                       222 GIC         196 :     if (node->cvarno == rel->relid)
 1561 tgl                       223 CBC         196 :         return true;
 1561 tgl                       224 ECB             : 
 1561 tgl                       225 UIC           0 :     return false;
 1561 tgl                       226 EUB             : }
                                227                 : 
                                228                 : /*
                                229                 :  * Extract a set of CTID conditions from the given RestrictInfo
                                230                 :  *
                                231                 :  * Returns a List of CTID qual RestrictInfos for the specified rel (with
                                232                 :  * implicit OR semantics across the list), or NIL if there are no usable
                                233                 :  * conditions.
                                234                 :  *
                                235                 :  * This function considers only base cases; AND/OR combination is handled
                                236                 :  * below.  Therefore the returned List never has more than one element.
                                237                 :  * (Using a List may seem a bit weird, but it simplifies the caller.)
                                238                 :  */
                                239                 : static List *
  808 tgl                       240 GIC      148878 : TidQualFromRestrictInfo(PlannerInfo *root, RestrictInfo *rinfo, RelOptInfo *rel)
 1561 tgl                       241 ECB             : {
                                242                 :     /*
                                243                 :      * We may ignore pseudoconstant clauses (they can't contain Vars, so could
                                244                 :      * not match anyway).
                                245                 :      */
 1561 tgl                       246 GIC      148878 :     if (rinfo->pseudoconstant)
 1561 tgl                       247 CBC        2541 :         return NIL;
 1561 tgl                       248 ECB             : 
                                249                 :     /*
                                250                 :      * If clause must wait till after some lower-security-level restriction
                                251                 :      * clause, reject it.
                                252                 :      */
 1561 tgl                       253 GIC      146337 :     if (!restriction_is_securely_promotable(rinfo, rel))
 1561 tgl                       254 CBC         814 :         return NIL;
 1561 tgl                       255 ECB             : 
                                256                 :     /*
                                257                 :      * Check all base cases.  If we get a match, return the clause.
                                258                 :      */
 1561 tgl                       259 GIC      290939 :     if (IsTidEqualClause(rinfo, rel) ||
  808 tgl                       260 CBC      290817 :         IsTidEqualAnyClause(root, rinfo, rel) ||
 1561                           261          145401 :         IsCurrentOfClause(rinfo, rel))
                                262             318 :         return list_make1(rinfo);
 1561 tgl                       263 ECB             : 
 1561 tgl                       264 GIC      145205 :     return NIL;
 1561 tgl                       265 ECB             : }
                                266                 : 
                                267                 : /*
                                268                 :  * Extract a set of CTID conditions from implicit-AND List of RestrictInfos
                                269                 :  *
                                270                 :  * Returns a List of CTID qual RestrictInfos for the specified rel (with
                                271                 :  * implicit OR semantics across the list), or NIL if there are no usable
                                272                 :  * equality conditions.
                                273                 :  *
                                274                 :  * This function is just concerned with handling AND/OR recursion.
                                275                 :  */
                                276                 : static List *
  808 tgl                       277 GIC      157672 : TidQualFromRestrictInfoList(PlannerInfo *root, List *rlist, RelOptInfo *rel)
 8538 bruce                     278 ECB             : {
 6343 tgl                       279 GIC      157672 :     List       *rlst = NIL;
 6892 neilc                     280 ECB             :     ListCell   *l;
                                281                 : 
 1561 tgl                       282 GIC      306541 :     foreach(l, rlist)
 8538 bruce                     283 ECB             :     {
 1561 tgl                       284 GIC      149187 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
 1561 tgl                       285 ECB             : 
 1561 tgl                       286 GIC      149187 :         if (restriction_is_or_clause(rinfo))
 8538 bruce                     287 ECB             :         {
                                288                 :             ListCell   *j;
                                289                 : 
                                290                 :             /*
                                291                 :              * We must be able to extract a CTID condition from every
                                292                 :              * sub-clause of an OR, or we can't use it.
                                293                 :              */
 1561 tgl                       294 GIC        1647 :             foreach(j, ((BoolExpr *) rinfo->orclause)->args)
 8538 bruce                     295 ECB             :             {
 1561 tgl                       296 GIC        1635 :                 Node       *orarg = (Node *) lfirst(j);
 1561 tgl                       297 ECB             :                 List       *sublist;
                                298                 : 
                                299                 :                 /* OR arguments should be ANDs or sub-RestrictInfos */
 1531 tgl                       300 GIC        1635 :                 if (is_andclause(orarg))
 1561 tgl                       301 ECB             :                 {
 1561 tgl                       302 GIC         321 :                     List       *andargs = ((BoolExpr *) orarg)->args;
 1561 tgl                       303 ECB             : 
                                304                 :                     /* Recurse in case there are sub-ORs */
  808 tgl                       305 GIC         321 :                     sublist = TidQualFromRestrictInfoList(root, andargs, rel);
 1561 tgl                       306 ECB             :                 }
                                307                 :                 else
                                308                 :                 {
  186 drowley                   309 GNC        1314 :                     RestrictInfo *ri = castNode(RestrictInfo, orarg);
 1561 tgl                       310 ECB             : 
  186 drowley                   311 GNC        1314 :                     Assert(!restriction_is_or_clause(ri));
                                312            1314 :                     sublist = TidQualFromRestrictInfo(root, ri, rel);
 1561 tgl                       313 ECB             :                 }
                                314                 : 
                                315                 :                 /*
                                316                 :                  * If nothing found in this arm, we can't do anything with
                                317                 :                  * this OR clause.
                                318                 :                  */
 1561 tgl                       319 GIC        1635 :                 if (sublist == NIL)
 1561 tgl                       320 ECB             :                 {
 1561 tgl                       321 GIC        1611 :                     rlst = NIL; /* forget anything we had */
 1561 tgl                       322 CBC        1611 :                     break;      /* out of loop over OR args */
 1561 tgl                       323 ECB             :                 }
                                324                 : 
                                325                 :                 /*
                                326                 :                  * OK, continue constructing implicitly-OR'ed result list.
                                327                 :                  */
 1561 tgl                       328 GIC          24 :                 rlst = list_concat(rlst, sublist);
 8538 bruce                     329 ECB             :             }
                                330                 :         }
                                331                 :         else
                                332                 :         {
                                333                 :             /* Not an OR clause, so handle base cases */
  808 tgl                       334 GIC      147564 :             rlst = TidQualFromRestrictInfo(root, rinfo, rel);
 1561 tgl                       335 ECB             :         }
                                336                 : 
                                337                 :         /*
                                338                 :          * Stop as soon as we find any usable CTID condition.  In theory we
                                339                 :          * could get CTID equality conditions from different AND'ed clauses,
                                340                 :          * in which case we could try to pick the most efficient one.  In
                                341                 :          * practice, such usage seems very unlikely, so we don't bother; we
                                342                 :          * just exit as soon as we find the first candidate.
                                343                 :          */
 1561 tgl                       344 GIC      149187 :         if (rlst)
 1561 tgl                       345 CBC         318 :             break;
 8538 bruce                     346 ECB             :     }
                                347                 : 
 8538 bruce                     348 GIC      157672 :     return rlst;
 8397 bruce                     349 ECB             : }
                                350                 : 
                                351                 : /*
                                352                 :  * Extract a set of CTID range conditions from implicit-AND List of RestrictInfos
                                353                 :  *
                                354                 :  * Returns a List of CTID range qual RestrictInfos for the specified rel
                                355                 :  * (with implicit AND semantics across the list), or NIL if there are no
                                356                 :  * usable range conditions or if the rel's table AM does not support TID range
                                357                 :  * scans.
                                358                 :  */
                                359                 : static List *
  771 drowley                   360 GIC      157351 : TidRangeQualFromRestrictInfoList(List *rlist, RelOptInfo *rel)
  771 drowley                   361 ECB             : {
  771 drowley                   362 GIC      157351 :     List       *rlst = NIL;
  771 drowley                   363 ECB             :     ListCell   *l;
                                364                 : 
  771 drowley                   365 GIC      157351 :     if ((rel->amflags & AMFLAG_HAS_TID_RANGE) == 0)
  771 drowley                   366 LBC           0 :         return NIL;
  771 drowley                   367 EUB             : 
  771 drowley                   368 GIC      305853 :     foreach(l, rlist)
  771 drowley                   369 ECB             :     {
  771 drowley                   370 GIC      148502 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
  771 drowley                   371 ECB             : 
  771 drowley                   372 GIC      148502 :         if (IsTidRangeClause(rinfo, rel))
  771 drowley                   373 CBC         116 :             rlst = lappend(rlst, rinfo);
  771 drowley                   374 ECB             :     }
                                375                 : 
  771 drowley                   376 GIC      157351 :     return rlst;
  771 drowley                   377 ECB             : }
                                378                 : 
                                379                 : /*
                                380                 :  * Given a list of join clauses involving our rel, create a parameterized
                                381                 :  * TidPath for each one that is a suitable TidEqual clause.
                                382                 :  *
                                383                 :  * In principle we could combine clauses that reference the same outer rels,
                                384                 :  * but it doesn't seem like such cases would arise often enough to be worth
                                385                 :  * troubling over.
                                386                 :  */
                                387                 : static void
 1561 tgl                       388 GIC      201481 : BuildParameterizedTidPaths(PlannerInfo *root, RelOptInfo *rel, List *clauses)
 8538 bruce                     389 ECB             : {
                                390                 :     ListCell   *l;
                                391                 : 
 1561 tgl                       392 GIC      251546 :     foreach(l, clauses)
 8538 bruce                     393 ECB             :     {
 1561 tgl                       394 GIC       50065 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
 1561 tgl                       395 ECB             :         List       *tidquals;
                                396                 :         Relids      required_outer;
                                397                 : 
                                398                 :         /*
                                399                 :          * Validate whether each clause is actually usable; we must check this
                                400                 :          * even when examining clauses generated from an EquivalenceClass,
                                401                 :          * since they might not satisfy the restriction on not having Vars of
                                402                 :          * our rel on the other side, or somebody might've built an operator
                                403                 :          * class that accepts type "tid" but has other operators in it.
                                404                 :          *
                                405                 :          * We currently consider only TidEqual join clauses.  In principle we
                                406                 :          * might find a suitable ScalarArrayOpExpr in the rel's joininfo list,
                                407                 :          * but it seems unlikely to be worth expending the cycles to check.
                                408                 :          * And we definitely won't find a CurrentOfExpr here.  Hence, we don't
                                409                 :          * use TidQualFromRestrictInfo; but this must match that function
                                410                 :          * otherwise.
                                411                 :          */
 1560 tgl                       412 GIC       50065 :         if (rinfo->pseudoconstant ||
 1560 tgl                       413 CBC       46402 :             !restriction_is_securely_promotable(rinfo, rel) ||
                                414           46402 :             !IsTidEqualClause(rinfo, rel))
 2272                           415           49993 :             continue;
 2272 tgl                       416 ECB             : 
                                417                 :         /*
                                418                 :          * Check if clause can be moved to this rel; this is probably
                                419                 :          * redundant when considering EC-derived clauses, but we must check it
                                420                 :          * for "loose" join clauses.
                                421                 :          */
 1561 tgl                       422 GIC          78 :         if (!join_clause_is_movable_to(rinfo, rel))
 1561 tgl                       423 CBC           6 :             continue;
 1561 tgl                       424 ECB             : 
                                425                 :         /* OK, make list of clauses for this path */
 1561 tgl                       426 GIC          72 :         tidquals = list_make1(rinfo);
 1561 tgl                       427 ECB             : 
                                428                 :         /* Compute required outer rels for this path */
 1561 tgl                       429 GIC          72 :         required_outer = bms_union(rinfo->required_relids, rel->lateral_relids);
 1561 tgl                       430 CBC          72 :         required_outer = bms_del_member(required_outer, rel->relid);
 1561 tgl                       431 ECB             : 
 1561 tgl                       432 GIC          72 :         add_path(rel, (Path *) create_tidscan_path(root, rel, tidquals,
 1561 tgl                       433 ECB             :                                                    required_outer));
                                434                 :     }
 1561 tgl                       435 GIC      201481 : }
 1561 tgl                       436 ECB             : 
                                437                 : /*
                                438                 :  * Test whether an EquivalenceClass member matches our rel's CTID Var.
                                439                 :  *
                                440                 :  * This is a callback for use by generate_implied_equalities_for_column.
                                441                 :  */
                                442                 : static bool
 1561 tgl                       443 GIC       40534 : ec_member_matches_ctid(PlannerInfo *root, RelOptInfo *rel,
 1561 tgl                       444 ECB             :                        EquivalenceClass *ec, EquivalenceMember *em,
                                445                 :                        void *arg)
                                446                 : {
 1561 tgl                       447 GIC       79870 :     if (em->em_expr && IsA(em->em_expr, Var) &&
 1561 tgl                       448 CBC       39336 :         IsCTIDVar((Var *) em->em_expr, rel))
                                449              66 :         return true;
                                450           40468 :     return false;
 8538 bruce                     451 ECB             : }
                                452                 : 
                                453                 : /*
                                454                 :  * create_tidscan_paths
                                455                 :  *    Create paths corresponding to direct TID scans of the given rel.
                                456                 :  *
                                457                 :  *    Candidate paths are added to the rel's pathlist (using add_path).
                                458                 :  */
                                459                 : void
 6517 tgl                       460 GIC      157351 : create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel)
 8538 bruce                     461 ECB             : {
                                462                 :     List       *tidquals;
                                463                 :     List       *tidrangequals;
                                464                 : 
                                465                 :     /*
                                466                 :      * If any suitable quals exist in the rel's baserestrict list, generate a
                                467                 :      * plain (unparameterized) TidPath with them.
                                468                 :      */
  808 tgl                       469 GIC      157351 :     tidquals = TidQualFromRestrictInfoList(root, rel->baserestrictinfo, rel);
 8397 bruce                     470 ECB             : 
  771 drowley                   471 GIC      157351 :     if (tidquals != NIL)
 1561 tgl                       472 ECB             :     {
                                473                 :         /*
                                474                 :          * This path uses no join clauses, but it could still have required
                                475                 :          * parameterization due to LATERAL refs in its tlist.
                                476                 :          */
 1561 tgl                       477 GIC         306 :         Relids      required_outer = rel->lateral_relids;
 1561 tgl                       478 ECB             : 
 3878 tgl                       479 GIC         306 :         add_path(rel, (Path *) create_tidscan_path(root, rel, tidquals,
 3878 tgl                       480 ECB             :                                                    required_outer));
                                481                 :     }
                                482                 : 
                                483                 :     /*
                                484                 :      * If there are range quals in the baserestrict list, generate a
                                485                 :      * TidRangePath.
                                486                 :      */
  771 drowley                   487 GIC      157351 :     tidrangequals = TidRangeQualFromRestrictInfoList(rel->baserestrictinfo,
  771 drowley                   488 ECB             :                                                      rel);
                                489                 : 
  771 drowley                   490 GIC      157351 :     if (tidrangequals != NIL)
  771 drowley                   491 ECB             :     {
                                492                 :         /*
                                493                 :          * This path uses no join clauses, but it could still have required
                                494                 :          * parameterization due to LATERAL refs in its tlist.
                                495                 :          */
  771 drowley                   496 GIC         101 :         Relids      required_outer = rel->lateral_relids;
  771 drowley                   497 ECB             : 
  771 drowley                   498 GIC         101 :         add_path(rel, (Path *) create_tidrangescan_path(root, rel,
  771 drowley                   499 ECB             :                                                         tidrangequals,
                                500                 :                                                         required_outer));
                                501                 :     }
                                502                 : 
                                503                 :     /*
                                504                 :      * Try to generate parameterized TidPaths using equality clauses extracted
                                505                 :      * from EquivalenceClasses.  (This is important since simple "t1.ctid =
                                506                 :      * t2.ctid" clauses will turn into ECs.)
                                507                 :      */
 1561 tgl                       508 GIC      157351 :     if (rel->has_eclass_joins)
 1561 tgl                       509 ECB             :     {
                                510                 :         List       *clauses;
                                511                 : 
                                512                 :         /* Generate clauses, skipping any that join to lateral_referencers */
 1561 tgl                       513 GIC       44130 :         clauses = generate_implied_equalities_for_column(root,
 1561 tgl                       514 ECB             :                                                          rel,
                                515                 :                                                          ec_member_matches_ctid,
                                516                 :                                                          NULL,
                                517                 :                                                          rel->lateral_referencers);
                                518                 : 
                                519                 :         /* Generate a path for each usable join clause */
 1561 tgl                       520 GIC       44130 :         BuildParameterizedTidPaths(root, rel, clauses);
 1561 tgl                       521 ECB             :     }
                                522                 : 
                                523                 :     /*
                                524                 :      * Also consider parameterized TidPaths using "loose" join quals.  Quals
                                525                 :      * of the form "t1.ctid = t2.ctid" would turn into these if they are outer
                                526                 :      * join quals, for example.
                                527                 :      */
 1561 tgl                       528 GIC      157351 :     BuildParameterizedTidPaths(root, rel, rel->joininfo);
 8538 bruce                     529 CBC      157351 : }
        

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