LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/util - var.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 88.1 % 371 327 21 10 12 1 9 155 74 89 33 219 1 9
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 21 21 17 4 21
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 77.4 % 93 72 21 72
Legend: Lines: hit not hit (180,240] days: 100.0 % 2 2 2
(240..) days: 91.7 % 276 253 10 12 1 9 155 89 12 147
Function coverage date bins:
(60,120] days: 100.0 % 4 4 4
(240..) days: 50.0 % 34 17 17 17

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * var.c
                                  4                 :  *    Var node manipulation routines
                                  5                 :  *
                                  6                 :  * Note: for most purposes, PlaceHolderVar is considered a Var too,
                                  7                 :  * even if its contained expression is variable-free.  Also, CurrentOfExpr
                                  8                 :  * is treated as a Var for purposes of determining whether an expression
                                  9                 :  * contains variables.
                                 10                 :  *
                                 11                 :  *
                                 12                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 13                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 14                 :  *
                                 15                 :  *
                                 16                 :  * IDENTIFICATION
                                 17                 :  *    src/backend/optimizer/util/var.c
                                 18                 :  *
                                 19                 :  *-------------------------------------------------------------------------
                                 20                 :  */
                                 21                 : #include "postgres.h"
                                 22                 : 
                                 23                 : #include "access/sysattr.h"
                                 24                 : #include "nodes/nodeFuncs.h"
                                 25                 : #include "optimizer/optimizer.h"
                                 26                 : #include "optimizer/placeholder.h"
                                 27                 : #include "optimizer/prep.h"
                                 28                 : #include "parser/parsetree.h"
                                 29                 : #include "rewrite/rewriteManip.h"
                                 30                 : 
                                 31                 : 
                                 32                 : typedef struct
                                 33                 : {
                                 34                 :     Relids      varnos;
                                 35                 :     PlannerInfo *root;
                                 36                 :     int         sublevels_up;
                                 37                 : } pull_varnos_context;
                                 38                 : 
                                 39                 : typedef struct
                                 40                 : {
                                 41                 :     Bitmapset  *varattnos;
                                 42                 :     Index       varno;
                                 43                 : } pull_varattnos_context;
                                 44                 : 
                                 45                 : typedef struct
                                 46                 : {
                                 47                 :     List       *vars;
                                 48                 :     int         sublevels_up;
                                 49                 : } pull_vars_context;
                                 50                 : 
                                 51                 : typedef struct
                                 52                 : {
                                 53                 :     int         var_location;
                                 54                 :     int         sublevels_up;
                                 55                 : } locate_var_of_level_context;
                                 56                 : 
                                 57                 : typedef struct
                                 58                 : {
                                 59                 :     List       *varlist;
                                 60                 :     int         flags;
                                 61                 : } pull_var_clause_context;
                                 62                 : 
                                 63                 : typedef struct
                                 64                 : {
                                 65                 :     PlannerInfo *root;          /* could be NULL! */
                                 66                 :     Query      *query;          /* outer Query */
                                 67                 :     int         sublevels_up;
                                 68                 :     bool        possible_sublink;   /* could aliases include a SubLink? */
                                 69                 :     bool        inserted_sublink;   /* have we inserted a SubLink? */
                                 70                 : } flatten_join_alias_vars_context;
                                 71                 : 
                                 72                 : static bool pull_varnos_walker(Node *node,
                                 73                 :                                pull_varnos_context *context);
                                 74                 : static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context);
                                 75                 : static bool pull_vars_walker(Node *node, pull_vars_context *context);
                                 76                 : static bool contain_var_clause_walker(Node *node, void *context);
                                 77                 : static bool contain_vars_of_level_walker(Node *node, int *sublevels_up);
                                 78                 : static bool locate_var_of_level_walker(Node *node,
                                 79                 :                                        locate_var_of_level_context *context);
                                 80                 : static bool pull_var_clause_walker(Node *node,
                                 81                 :                                    pull_var_clause_context *context);
                                 82                 : static Node *flatten_join_alias_vars_mutator(Node *node,
                                 83                 :                                              flatten_join_alias_vars_context *context);
                                 84                 : static Node *add_nullingrels_if_needed(PlannerInfo *root, Node *newnode,
                                 85                 :                                        Var *oldvar);
                                 86                 : static bool is_standard_join_alias_expression(Node *newnode, Var *oldvar);
                                 87                 : static void adjust_standard_join_alias_expression(Node *newnode, Var *oldvar);
                                 88                 : static Relids alias_relid_set(Query *query, Relids relids);
                                 89                 : 
                                 90                 : 
                                 91                 : /*
                                 92                 :  * pull_varnos
                                 93                 :  *      Create a set of all the distinct varnos present in a parsetree.
                                 94                 :  *      Only varnos that reference level-zero rtable entries are considered.
                                 95                 :  *
                                 96                 :  * The result includes outer-join relids mentioned in Var.varnullingrels and
                                 97                 :  * PlaceHolderVar.phnullingrels fields in the parsetree.
                                 98                 :  *
                                 99                 :  * "root" can be passed as NULL if it is not necessary to process
                                100                 :  * PlaceHolderVars.
                                101                 :  *
                                102                 :  * NOTE: this is used on not-yet-planned expressions.  It may therefore find
                                103                 :  * bare SubLinks, and if so it needs to recurse into them to look for uplevel
                                104                 :  * references to the desired rtable level!  But when we find a completed
                                105                 :  * SubPlan, we only need to look at the parameters passed to the subplan.
                                106                 :  */
                                107                 : Relids
  808 tgl                       108 GIC     1145028 : pull_varnos(PlannerInfo *root, Node *node)
                                109                 : {
                                110                 :     pull_varnos_context context;
                                111                 : 
 7365                           112         1145028 :     context.varnos = NULL;
  808                           113         1145028 :     context.root = root;
 8244                           114         1145028 :     context.sublevels_up = 0;
                                115                 : 
 8244 tgl                       116 ECB             :     /*
                                117                 :      * Must be prepared to start with a Query or a bare expression tree; if
                                118                 :      * it's a Query, we don't want to increment sublevels_up.
                                119                 :      */
 7387 tgl                       120 CBC     1145028 :     query_or_expression_tree_walker(node,
 7387 tgl                       121 ECB             :                                     pull_varnos_walker,
                                122                 :                                     (void *) &context,
                                123                 :                                     0);
                                124                 : 
 7365 tgl                       125 GIC     1145028 :     return context.varnos;
                                126                 : }
                                127                 : 
 3897 tgl                       128 ECB             : /*
                                129                 :  * pull_varnos_of_level
                                130                 :  *      Create a set of all the distinct varnos present in a parsetree.
                                131                 :  *      Only Vars of the specified level are considered.
                                132                 :  */
                                133                 : Relids
  808 tgl                       134 GIC         517 : pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup)
                                135                 : {
                                136                 :     pull_varnos_context context;
                                137                 : 
 3897                           138             517 :     context.varnos = NULL;
  808                           139             517 :     context.root = root;
 3897                           140             517 :     context.sublevels_up = levelsup;
                                141                 : 
 3897 tgl                       142 ECB             :     /*
                                143                 :      * Must be prepared to start with a Query or a bare expression tree; if
                                144                 :      * it's a Query, we don't want to increment sublevels_up.
                                145                 :      */
 3897 tgl                       146 CBC         517 :     query_or_expression_tree_walker(node,
 3897 tgl                       147 ECB             :                                     pull_varnos_walker,
                                148                 :                                     (void *) &context,
                                149                 :                                     0);
                                150                 : 
 3897 tgl                       151 GIC         517 :     return context.varnos;
                                152                 : }
                                153                 : 
 8695 tgl                       154 ECB             : static bool
 8244 tgl                       155 GIC     1924780 : pull_varnos_walker(Node *node, pull_varnos_context *context)
                                156                 : {
 8695                           157         1924780 :     if (node == NULL)
                                158           24511 :         return false;
 8695 tgl                       159 CBC     1900269 :     if (IsA(node, Var))
                                160                 :     {
 8397 bruce                     161 GIC      932637 :         Var        *var = (Var *) node;
                                162                 : 
 7365 tgl                       163 CBC      932637 :         if (var->varlevelsup == context->sublevels_up)
                                164                 :         {
 7365 tgl                       165 GIC      931912 :             context->varnos = bms_add_member(context->varnos, var->varno);
   69 tgl                       166 GNC      931912 :             context->varnos = bms_add_members(context->varnos,
                                167          931912 :                                               var->varnullingrels);
                                168                 :         }
 8695 tgl                       169 CBC      932637 :         return false;
 9770 scrappy                   170 ECB             :     }
 5781 tgl                       171 CBC      967632 :     if (IsA(node, CurrentOfExpr))
                                172                 :     {
                                173             388 :         CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
                                174                 : 
                                175             388 :         if (context->sublevels_up == 0)
 5781 tgl                       176 GIC         388 :             context->varnos = bms_add_member(context->varnos, cexpr->cvarno);
 5781 tgl                       177 CBC         388 :         return false;
 5781 tgl                       178 ECB             :     }
 5283 tgl                       179 CBC      967244 :     if (IsA(node, PlaceHolderVar))
                                180                 :     {
                                181            1756 :         PlaceHolderVar *phv = (PlaceHolderVar *) node;
                                182                 : 
  808 tgl                       183 ECB             :         /*
                                184                 :          * If a PlaceHolderVar is not of the target query level, ignore it,
                                185                 :          * instead recursing into its expression to see if it contains any
                                186                 :          * vars that are of the target level.  We'll also do that when the
  455                           187                 :          * caller doesn't pass a "root" pointer.  (We probably shouldn't see
                                188                 :          * PlaceHolderVars at all in such cases, but if we do, this is a
                                189                 :          * reasonable behavior.)
                                190                 :          */
  455 tgl                       191 CBC        1756 :         if (phv->phlevelsup == context->sublevels_up &&
  455 tgl                       192 GIC        1756 :             context->root != NULL)
 3522 tgl                       193 ECB             :         {
                                194                 :             /*
                                195                 :              * Ideally, the PHV's contribution to context->varnos is its
                                196                 :              * ph_eval_at set.  However, this code can be invoked before
                                197                 :              * that's been computed.  If we cannot find a PlaceHolderInfo,
                                198                 :              * fall back to the conservative assumption that the PHV will be
                                199                 :              * evaluated at its syntactic level (phv->phrels).
                                200                 :              *
                                201                 :              * Another problem is that a PlaceHolderVar can appear in quals or
                                202                 :              * tlists that have been translated for use in a child appendrel.
                                203                 :              * Typically such a PHV is a parameter expression sourced by some
                                204                 :              * other relation, so that the translation from parent appendrel
                                205                 :              * to child doesn't change its phrels, and we should still take
                                206                 :              * ph_eval_at at face value.  But in corner cases, the PHV's
                                207                 :              * original phrels can include the parent appendrel itself, in
                                208                 :              * which case the translated PHV will have the child appendrel in
                                209                 :              * phrels, and we must translate ph_eval_at to match.
                                210                 :              */
  808 tgl                       211 GIC        1756 :             PlaceHolderInfo *phinfo = NULL;
                                212                 : 
  808 tgl                       213 CBC        1756 :             if (phv->phlevelsup == 0)
                                214                 :             {
  235 tgl                       215 GNC        1744 :                 if (phv->phid < context->root->placeholder_array_size)
                                216            1617 :                     phinfo = context->root->placeholder_array[phv->phid];
  808 tgl                       217 ECB             :             }
  569 tgl                       218 GIC        1756 :             if (phinfo == NULL)
  569 tgl                       219 ECB             :             {
                                220                 :                 /* No PlaceHolderInfo yet, use phrels */
  569 tgl                       221 GIC         145 :                 context->varnos = bms_add_members(context->varnos,
  569 tgl                       222 CBC         145 :                                                   phv->phrels);
  569 tgl                       223 ECB             :             }
  569 tgl                       224 GIC        1611 :             else if (bms_equal(phv->phrels, phinfo->ph_var->phrels))
                                225                 :             {
                                226                 :                 /* Normal case: use ph_eval_at */
  808                           227            1389 :                 context->varnos = bms_add_members(context->varnos,
                                228            1389 :                                                   phinfo->ph_eval_at);
                                229                 :             }
                                230                 :             else
                                231                 :             {
  569 tgl                       232 ECB             :                 /* Translated PlaceHolderVar: translate ph_eval_at to match */
                                233                 :                 Relids      newevalat,
                                234                 :                             delta;
                                235                 : 
                                236                 :                 /* remove what was removed from phv->phrels ... */
  569 tgl                       237 GIC         222 :                 delta = bms_difference(phinfo->ph_var->phrels, phv->phrels);
  569 tgl                       238 CBC         222 :                 newevalat = bms_difference(phinfo->ph_eval_at, delta);
  569 tgl                       239 ECB             :                 /* ... then if that was in fact part of ph_eval_at ... */
  569 tgl                       240 GIC         222 :                 if (!bms_equal(newevalat, phinfo->ph_eval_at))
  569 tgl                       241 ECB             :                 {
                                242                 :                     /* ... add what was added */
  569 tgl                       243 GIC         156 :                     delta = bms_difference(phv->phrels, phinfo->ph_var->phrels);
                                244             156 :                     newevalat = bms_join(newevalat, delta);
                                245                 :                 }
                                246             222 :                 context->varnos = bms_join(context->varnos,
                                247                 :                                            newevalat);
                                248                 :             }
                                249                 : 
                                250                 :             /*
                                251                 :              * In all three cases, include phnullingrels in the result.  We
                                252                 :              * don't worry about possibly needing to translate it, because
                                253                 :              * appendrels only translate varnos of baserels, not outer joins.
                                254                 :              */
   69 tgl                       255 GNC        3512 :             context->varnos = bms_add_members(context->varnos,
                                256            1756 :                                               phv->phnullingrels);
  808 tgl                       257 GIC        1756 :             return false;       /* don't recurse into expression */
 3522 tgl                       258 ECB             :         }
 5283                           259                 :     }
  808 tgl                       260 CBC      965488 :     else if (IsA(node, Query))
                                261                 :     {
                                262                 :         /* Recurse into RTE subquery or not-yet-planned sublink subquery */
 8244 tgl                       263 ECB             :         bool        result;
                                264                 : 
 8244 tgl                       265 GIC          33 :         context->sublevels_up++;
                                266              33 :         result = query_tree_walker((Query *) node, pull_varnos_walker,
                                267                 :                                    (void *) context, 0);
 8244 tgl                       268 CBC          33 :         context->sublevels_up--;
                                269              33 :         return result;
                                270                 :     }
                                271          965455 :     return expression_tree_walker(node, pull_varnos_walker,
 8244 tgl                       272 ECB             :                                   (void *) context);
                                273                 : }
 9770 scrappy                   274                 : 
                                275                 : 
                                276                 : /*
                                277                 :  * pull_varattnos
                                278                 :  *      Find all the distinct attribute numbers present in an expression tree,
                                279                 :  *      and add them to the initial contents of *varattnos.
                                280                 :  *      Only Vars of the given varno and rtable level zero are considered.
                                281                 :  *
                                282                 :  * Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
                                283                 :  * we can include system attributes (e.g., OID) in the bitmap representation.
                                284                 :  *
                                285                 :  * Currently, this does not support unplanned subqueries; that is not needed
                                286                 :  * for current uses.  It will handle already-planned SubPlan nodes, though,
                                287                 :  * looking into only the "testexpr" and the "args" list.  (The subplan cannot
                                288                 :  * contain any other references to Vars of the current level.)
                                289                 :  */
                                290                 : void
 4202 tgl                       291 GIC      668803 : pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
                                292                 : {
                                293                 :     pull_varattnos_context context;
 4202 tgl                       294 ECB             : 
 4202 tgl                       295 GIC      668803 :     context.varattnos = *varattnos;
                                296          668803 :     context.varno = varno;
                                297                 : 
 4202 tgl                       298 CBC      668803 :     (void) pull_varattnos_walker(node, &context);
 4202 tgl                       299 ECB             : 
 4202 tgl                       300 GIC      668803 :     *varattnos = context.varattnos;
 5680 tgl                       301 CBC      668803 : }
                                302                 : 
 5680 tgl                       303 ECB             : static bool
 4202 tgl                       304 CBC     2130140 : pull_varattnos_walker(Node *node, pull_varattnos_context *context)
                                305                 : {
 5680 tgl                       306 GIC     2130140 :     if (node == NULL)
 5680 tgl                       307 CBC       40868 :         return false;
 5680 tgl                       308 GIC     2089272 :     if (IsA(node, Var))
 5680 tgl                       309 ECB             :     {
 5680 tgl                       310 CBC     1189340 :         Var        *var = (Var *) node;
 5680 tgl                       311 ECB             : 
 4202 tgl                       312 GIC     1189340 :         if (var->varno == context->varno && var->varlevelsup == 0)
 4202 tgl                       313 CBC     1189304 :             context->varattnos =
 4202 tgl                       314 GIC     1189304 :                 bms_add_member(context->varattnos,
 2118 tgl                       315 CBC     1189304 :                                var->varattno - FirstLowInvalidHeapAttributeNumber);
 5680                           316         1189340 :         return false;
 5680 tgl                       317 ECB             :     }
 4202                           318                 : 
                                319                 :     /* Should not find an unplanned subquery */
 5680 tgl                       320 GIC      899932 :     Assert(!IsA(node, Query));
                                321                 : 
                                322          899932 :     return expression_tree_walker(node, pull_varattnos_walker,
 4202 tgl                       323 ECB             :                                   (void *) context);
                                324                 : }
 5680                           325                 : 
                                326                 : 
                                327                 : /*
                                328                 :  * pull_vars_of_level
                                329                 :  *      Create a list of all Vars (and PlaceHolderVars) referencing the
                                330                 :  *      specified query level in the given parsetree.
                                331                 :  *
                                332                 :  * Caution: the Vars are not copied, only linked into the list.
                                333                 :  */
                                334                 : List *
 3897 tgl                       335 GIC        3444 : pull_vars_of_level(Node *node, int levelsup)
                                336                 : {
                                337                 :     pull_vars_context context;
 3897 tgl                       338 ECB             : 
 3897 tgl                       339 GIC        3444 :     context.vars = NIL;
                                340            3444 :     context.sublevels_up = levelsup;
                                341                 : 
 3897 tgl                       342 ECB             :     /*
                                343                 :      * Must be prepared to start with a Query or a bare expression tree; if
                                344                 :      * it's a Query, we don't want to increment sublevels_up.
                                345                 :      */
 3897 tgl                       346 GIC        3444 :     query_or_expression_tree_walker(node,
                                347                 :                                     pull_vars_walker,
                                348                 :                                     (void *) &context,
 3897 tgl                       349 ECB             :                                     0);
                                350                 : 
 3897 tgl                       351 GIC        3444 :     return context.vars;
                                352                 : }
                                353                 : 
 3897 tgl                       354 ECB             : static bool
 3897 tgl                       355 GIC       39042 : pull_vars_walker(Node *node, pull_vars_context *context)
                                356                 : {
                                357           39042 :     if (node == NULL)
 3897 tgl                       358 CBC        4669 :         return false;
 3897 tgl                       359 GIC       34373 :     if (IsA(node, Var))
 3897 tgl                       360 ECB             :     {
 3897 tgl                       361 CBC        4502 :         Var        *var = (Var *) node;
 3897 tgl                       362 ECB             : 
 3897 tgl                       363 GIC        4502 :         if (var->varlevelsup == context->sublevels_up)
 3897 tgl                       364 CBC        3645 :             context->vars = lappend(context->vars, var);
 3897 tgl                       365 GIC        4502 :         return false;
 3897 tgl                       366 ECB             :     }
 3886 tgl                       367 CBC       29871 :     if (IsA(node, PlaceHolderVar))
 3886 tgl                       368 ECB             :     {
 3886 tgl                       369 GIC          36 :         PlaceHolderVar *phv = (PlaceHolderVar *) node;
 3886 tgl                       370 ECB             : 
 3886 tgl                       371 GIC          36 :         if (phv->phlevelsup == context->sublevels_up)
 3886 tgl                       372 CBC          36 :             context->vars = lappend(context->vars, phv);
                                373                 :         /* we don't want to look into the contained expression */
                                374              36 :         return false;
 3886 tgl                       375 ECB             :     }
 3897 tgl                       376 GIC       29835 :     if (IsA(node, Query))
 3897 tgl                       377 ECB             :     {
                                378                 :         /* Recurse into RTE subquery or not-yet-planned sublink subquery */
                                379                 :         bool        result;
                                380                 : 
 3897 tgl                       381 GIC         141 :         context->sublevels_up++;
                                382             141 :         result = query_tree_walker((Query *) node, pull_vars_walker,
                                383                 :                                    (void *) context, 0);
 3897 tgl                       384 CBC         141 :         context->sublevels_up--;
                                385             141 :         return result;
                                386                 :     }
                                387           29694 :     return expression_tree_walker(node, pull_vars_walker,
 3897 tgl                       388 ECB             :                                   (void *) context);
                                389                 : }
                                390                 : 
                                391                 : 
                                392                 : /*
                                393                 :  * contain_var_clause
                                394                 :  *    Recursively scan a clause to discover whether it contains any Var nodes
                                395                 :  *    (of the current query level).
                                396                 :  *
                                397                 :  *    Returns true if any varnode found.
                                398                 :  *
                                399                 :  * Does not examine subqueries, therefore must only be used after reduction
                                400                 :  * of sublinks to subplans!
                                401                 :  */
                                402                 : bool
 8026 tgl                       403 GIC       32240 : contain_var_clause(Node *node)
                                404                 : {
                                405           32240 :     return contain_var_clause_walker(node, NULL);
 8695 tgl                       406 ECB             : }
                                407                 : 
                                408                 : static bool
 8695 tgl                       409 GIC       39753 : contain_var_clause_walker(Node *node, void *context)
                                410                 : {
                                411           39753 :     if (node == NULL)
 8695 tgl                       412 CBC          41 :         return false;
 8695 tgl                       413 GIC       39712 :     if (IsA(node, Var))
 8627 tgl                       414 ECB             :     {
 8627 tgl                       415 CBC        1084 :         if (((Var *) node)->varlevelsup == 0)
 6385 bruce                     416            1084 :             return true;        /* abort the tree traversal and return true */
 8627 tgl                       417 UIC           0 :         return false;
 8627 tgl                       418 ECB             :     }
 5781 tgl                       419 CBC       38628 :     if (IsA(node, CurrentOfExpr))
 5781 tgl                       420 UBC           0 :         return true;
 5283 tgl                       421 GIC       38628 :     if (IsA(node, PlaceHolderVar))
 5283 tgl                       422 ECB             :     {
 5283 tgl                       423 GBC           6 :         if (((PlaceHolderVar *) node)->phlevelsup == 0)
 5283 tgl                       424 CBC           6 :             return true;        /* abort the tree traversal and return true */
                                425                 :         /* else fall through to check the contained expr */
 5283 tgl                       426 ECB             :     }
 8695 tgl                       427 CBC       38622 :     return expression_tree_walker(node, contain_var_clause_walker, context);
                                428                 : }
                                429                 : 
 5333 tgl                       430 ECB             : 
                                431                 : /*
                                432                 :  * contain_vars_of_level
                                433                 :  *    Recursively scan a clause to discover whether it contains any Var nodes
                                434                 :  *    of the specified query level.
                                435                 :  *
                                436                 :  *    Returns true if any such Var found.
                                437                 :  *
                                438                 :  * Will recurse into sublinks.  Also, may be invoked directly on a Query.
                                439                 :  */
                                440                 : bool
 7384 tgl                       441 GIC      130186 : contain_vars_of_level(Node *node, int levelsup)
                                442                 : {
 7188 bruce                     443          130186 :     int         sublevels_up = levelsup;
 7384 tgl                       444 ECB             : 
 7384 tgl                       445 GIC      130186 :     return query_or_expression_tree_walker(node,
 7384 tgl                       446 ECB             :                                            contain_vars_of_level_walker,
                                447                 :                                            (void *) &sublevels_up,
                                448                 :                                            0);
                                449                 : }
                                450                 : 
                                451                 : static bool
 7384 tgl                       452 GIC      330574 : contain_vars_of_level_walker(Node *node, int *sublevels_up)
                                453                 : {
                                454          330574 :     if (node == NULL)
 7384 tgl                       455 CBC       67335 :         return false;
 7384 tgl                       456 GIC      263239 :     if (IsA(node, Var))
 7384 tgl                       457 ECB             :     {
 7384 tgl                       458 CBC       33585 :         if (((Var *) node)->varlevelsup == *sublevels_up)
                                459           18462 :             return true;        /* abort tree traversal and return true */
 5781 tgl                       460 GIC       15123 :         return false;
 5781 tgl                       461 ECB             :     }
 5781 tgl                       462 CBC      229654 :     if (IsA(node, CurrentOfExpr))
 5781 tgl                       463 ECB             :     {
 5781 tgl                       464 GIC          92 :         if (*sublevels_up == 0)
 5781 tgl                       465 CBC          92 :             return true;
 5781 tgl                       466 UIC           0 :         return false;
 7384 tgl                       467 ECB             :     }
 5283 tgl                       468 CBC      229562 :     if (IsA(node, PlaceHolderVar))
 5283 tgl                       469 EUB             :     {
 5283 tgl                       470 GIC           9 :         if (((PlaceHolderVar *) node)->phlevelsup == *sublevels_up)
 5283 tgl                       471 CBC           6 :             return true;        /* abort the tree traversal and return true */
                                472                 :         /* else fall through to check the contained expr */
 5283 tgl                       473 ECB             :     }
 7384 tgl                       474 CBC      229556 :     if (IsA(node, Query))
                                475                 :     {
                                476                 :         /* Recurse into subselects */
 7384 tgl                       477 ECB             :         bool        result;
                                478                 : 
 7384 tgl                       479 GIC        2196 :         (*sublevels_up)++;
                                480            2196 :         result = query_tree_walker((Query *) node,
                                481                 :                                    contain_vars_of_level_walker,
 7384 tgl                       482 ECB             :                                    (void *) sublevels_up,
                                483                 :                                    0);
 7384 tgl                       484 GIC        2196 :         (*sublevels_up)--;
                                485            2196 :         return result;
                                486                 :     }
 7384 tgl                       487 CBC      227360 :     return expression_tree_walker(node,
 7384 tgl                       488 ECB             :                                   contain_vars_of_level_walker,
                                489                 :                                   (void *) sublevels_up);
                                490                 : }
                                491                 : 
                                492                 : 
                                493                 : /*
                                494                 :  * locate_var_of_level
                                495                 :  *    Find the parse location of any Var of the specified query level.
                                496                 :  *
                                497                 :  * Returns -1 if no such Var is in the querytree, or if they all have
                                498                 :  * unknown parse location.  (The former case is probably caller error,
                                499                 :  * but we don't bother to distinguish it from the latter case.)
                                500                 :  *
                                501                 :  * Will recurse into sublinks.  Also, may be invoked directly on a Query.
                                502                 :  *
                                503                 :  * Note: it might seem appropriate to merge this functionality into
                                504                 :  * contain_vars_of_level, but that would complicate that function's API.
                                505                 :  * Currently, the only uses of this function are for error reporting,
                                506                 :  * and so shaving cycles probably isn't very important.
                                507                 :  */
                                508                 : int
 5333 tgl                       509 GIC           6 : locate_var_of_level(Node *node, int levelsup)
                                510                 : {
                                511                 :     locate_var_of_level_context context;
 7384 tgl                       512 ECB             : 
 5050 bruce                     513 GIC           6 :     context.var_location = -1;  /* in case we find nothing */
 5333 tgl                       514               6 :     context.sublevels_up = levelsup;
                                515                 : 
 5333 tgl                       516 CBC           6 :     (void) query_or_expression_tree_walker(node,
 5333 tgl                       517 ECB             :                                            locate_var_of_level_walker,
                                518                 :                                            (void *) &context,
 7384                           519                 :                                            0);
                                520                 : 
 5333 tgl                       521 GIC           6 :     return context.var_location;
                                522                 : }
                                523                 : 
 7384 tgl                       524 ECB             : static bool
 5333 tgl                       525 GIC          15 : locate_var_of_level_walker(Node *node,
                                526                 :                            locate_var_of_level_context *context)
                                527                 : {
 7384 tgl                       528 CBC          15 :     if (node == NULL)
 7384 tgl                       529 UIC           0 :         return false;
 7384 tgl                       530 GIC          15 :     if (IsA(node, Var))
 7384 tgl                       531 ECB             :     {
 5050 bruce                     532 GBC           6 :         Var        *var = (Var *) node;
 5333 tgl                       533 ECB             : 
 5333 tgl                       534 GIC           6 :         if (var->varlevelsup == context->sublevels_up &&
 5333 tgl                       535 CBC           6 :             var->location >= 0)
                                536                 :         {
                                537               6 :             context->var_location = var->location;
 7384                           538               6 :             return true;        /* abort tree traversal and return true */
                                539                 :         }
 5333 tgl                       540 LBC           0 :         return false;
 5333 tgl                       541 ECB             :     }
 5333 tgl                       542 GIC           9 :     if (IsA(node, CurrentOfExpr))
 5333 tgl                       543 EUB             :     {
                                544                 :         /* since CurrentOfExpr doesn't carry location, nothing we can do */
 5333 tgl                       545 LBC           0 :         return false;
                                546                 :     }
                                547                 :     /* No extra code needed for PlaceHolderVar; just look in contained expr */
 7384 tgl                       548 GBC           9 :     if (IsA(node, Query))
                                549                 :     {
                                550                 :         /* Recurse into subselects */
 7384 tgl                       551 ECB             :         bool        result;
                                552                 : 
 5333 tgl                       553 UIC           0 :         context->sublevels_up++;
 7384                           554               0 :         result = query_tree_walker((Query *) node,
                                555                 :                                    locate_var_of_level_walker,
 5333 tgl                       556 EUB             :                                    (void *) context,
 7384                           557                 :                                    0);
 5333 tgl                       558 UIC           0 :         context->sublevels_up--;
 7384                           559               0 :         return result;
                                560                 :     }
 7384 tgl                       561 GBC           9 :     return expression_tree_walker(node,
 5333 tgl                       562 EUB             :                                   locate_var_of_level_walker,
                                563                 :                                   (void *) context);
 5333 tgl                       564 ECB             : }
                                565                 : 
                                566                 : 
                                567                 : /*
                                568                 :  * pull_var_clause
                                569                 :  *    Recursively pulls all Var nodes from an expression clause.
                                570                 :  *
                                571                 :  *    Aggrefs are handled according to these bits in 'flags':
                                572                 :  *      PVC_INCLUDE_AGGREGATES      include Aggrefs in output list
                                573                 :  *      PVC_RECURSE_AGGREGATES      recurse into Aggref arguments
                                574                 :  *      neither flag                throw error if Aggref found
                                575                 :  *    Vars within an Aggref's expression are included in the result only
                                576                 :  *    when PVC_RECURSE_AGGREGATES is specified.
                                577                 :  *
                                578                 :  *    WindowFuncs are handled according to these bits in 'flags':
                                579                 :  *      PVC_INCLUDE_WINDOWFUNCS     include WindowFuncs in output list
                                580                 :  *      PVC_RECURSE_WINDOWFUNCS     recurse into WindowFunc arguments
                                581                 :  *      neither flag                throw error if WindowFunc found
                                582                 :  *    Vars within a WindowFunc's expression are included in the result only
                                583                 :  *    when PVC_RECURSE_WINDOWFUNCS is specified.
                                584                 :  *
                                585                 :  *    PlaceHolderVars are handled according to these bits in 'flags':
                                586                 :  *      PVC_INCLUDE_PLACEHOLDERS    include PlaceHolderVars in output list
                                587                 :  *      PVC_RECURSE_PLACEHOLDERS    recurse into PlaceHolderVar arguments
                                588                 :  *      neither flag                throw error if PlaceHolderVar found
                                589                 :  *    Vars within a PHV's expression are included in the result only
                                590                 :  *    when PVC_RECURSE_PLACEHOLDERS is specified.
                                591                 :  *
                                592                 :  *    GroupingFuncs are treated exactly like Aggrefs, and so do not need
                                593                 :  *    their own flag bits.
                                594                 :  *
                                595                 :  *    CurrentOfExpr nodes are ignored in all cases.
                                596                 :  *
                                597                 :  *    Upper-level vars (with varlevelsup > 0) should not be seen here,
                                598                 :  *    likewise for upper-level Aggrefs and PlaceHolderVars.
                                599                 :  *
                                600                 :  *    Returns list of nodes found.  Note the nodes themselves are not
                                601                 :  *    copied, only referenced.
                                602                 :  *
                                603                 :  * Does not examine subqueries, therefore must only be used after reduction
                                604                 :  * of sublinks to subplans!
                                605                 :  */
                                606                 : List *
 2586 tgl                       607 GIC      270950 : pull_var_clause(Node *node, int flags)
                                608                 : {
                                609                 :     pull_var_clause_context context;
 9345 bruce                     610 ECB             : 
                                611                 :     /* Assert that caller has not specified inconsistent flags */
 2586 tgl                       612 GIC      270950 :     Assert((flags & (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES))
                                613                 :            != (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES));
                                614          270950 :     Assert((flags & (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS))
 2586 tgl                       615 ECB             :            != (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS));
 2586 tgl                       616 GIC      270950 :     Assert((flags & (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS))
 2586 tgl                       617 ECB             :            != (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS));
                                618                 : 
 6886 tgl                       619 CBC      270950 :     context.varlist = NIL;
 2586 tgl                       620 GIC      270950 :     context.flags = flags;
                                621                 : 
 8026 tgl                       622 CBC      270950 :     pull_var_clause_walker(node, &context);
 6886                           623          270950 :     return context.varlist;
                                624                 : }
 8720 bruce                     625 ECB             : 
 8695 tgl                       626                 : static bool
 8627 tgl                       627 GIC     1636963 : pull_var_clause_walker(Node *node, pull_var_clause_context *context)
                                628                 : {
 8695                           629         1636963 :     if (node == NULL)
 8695 tgl                       630 CBC       65135 :         return false;
 8695 tgl                       631 GIC     1571828 :     if (IsA(node, Var))
 8742 tgl                       632 ECB             :     {
 4289 tgl                       633 CBC      587095 :         if (((Var *) node)->varlevelsup != 0)
 4289 tgl                       634 LBC           0 :             elog(ERROR, "Upper-level Var found where not expected");
 4289 tgl                       635 GIC      587095 :         context->varlist = lappend(context->varlist, node);
 8695 tgl                       636 CBC      587095 :         return false;
 8742 tgl                       637 EUB             :     }
 4289 tgl                       638 CBC      984733 :     else if (IsA(node, Aggref))
 4289 tgl                       639 ECB             :     {
 4289 tgl                       640 GIC       39165 :         if (((Aggref *) node)->agglevelsup != 0)
 4289 tgl                       641 LBC           0 :             elog(ERROR, "Upper-level Aggref found where not expected");
 2586 tgl                       642 GIC       39165 :         if (context->flags & PVC_INCLUDE_AGGREGATES)
 2586 tgl                       643 ECB             :         {
 2586 tgl                       644 GBC        2307 :             context->varlist = lappend(context->varlist, node);
 2586 tgl                       645 ECB             :             /* we do NOT descend into the contained expression */
 2586 tgl                       646 GIC        2307 :             return false;
 2586 tgl                       647 ECB             :         }
 2586 tgl                       648 GIC       36858 :         else if (context->flags & PVC_RECURSE_AGGREGATES)
 4289 tgl                       649 ECB             :         {
                                650                 :             /* fall through to recurse into the aggregate's arguments */
                                651                 :         }
                                652                 :         else
 2586 tgl                       653 UIC           0 :             elog(ERROR, "Aggref found where not expected");
                                654                 :     }
 2885 andres                    655 GIC      945568 :     else if (IsA(node, GroupingFunc))
 2885 andres                    656 EUB             :     {
 2885 andres                    657 GIC         275 :         if (((GroupingFunc *) node)->agglevelsup != 0)
 2885 andres                    658 LBC           0 :             elog(ERROR, "Upper-level GROUPING found where not expected");
 2586 tgl                       659 GIC         275 :         if (context->flags & PVC_INCLUDE_AGGREGATES)
 2885 andres                    660 ECB             :         {
 2586 tgl                       661 GBC           2 :             context->varlist = lappend(context->varlist, node);
 2586 tgl                       662 ECB             :             /* we do NOT descend into the contained expression */
 2586 tgl                       663 GIC           2 :             return false;
 2885 andres                    664 ECB             :         }
 2586 tgl                       665 GIC         273 :         else if (context->flags & PVC_RECURSE_AGGREGATES)
 2586 tgl                       666 ECB             :         {
                                667                 :             /* fall through to recurse into the GroupingFunc's arguments */
                                668                 :         }
                                669                 :         else
 2586 tgl                       670 UIC           0 :             elog(ERROR, "GROUPING found where not expected");
                                671                 :     }
 2586 tgl                       672 GIC      945293 :     else if (IsA(node, WindowFunc))
 2586 tgl                       673 EUB             :     {
                                674                 :         /* WindowFuncs have no levelsup field to check ... */
 2586 tgl                       675 CBC        2769 :         if (context->flags & PVC_INCLUDE_WINDOWFUNCS)
                                676                 :         {
 2586 tgl                       677 GIC           6 :             context->varlist = lappend(context->varlist, node);
 2586 tgl                       678 ECB             :             /* we do NOT descend into the contained expressions */
 2586 tgl                       679 GIC           6 :             return false;
 2586 tgl                       680 ECB             :         }
 2586 tgl                       681 GIC        2763 :         else if (context->flags & PVC_RECURSE_WINDOWFUNCS)
 2586 tgl                       682 ECB             :         {
                                683                 :             /* fall through to recurse into the windowfunc's arguments */
                                684                 :         }
                                685                 :         else
 2586 tgl                       686 UIC           0 :             elog(ERROR, "WindowFunc found where not expected");
                                687                 :     }
 4289 tgl                       688 GIC      942524 :     else if (IsA(node, PlaceHolderVar))
 5283 tgl                       689 EUB             :     {
 4289 tgl                       690 GIC        1102 :         if (((PlaceHolderVar *) node)->phlevelsup != 0)
 4289 tgl                       691 LBC           0 :             elog(ERROR, "Upper-level PlaceHolderVar found where not expected");
 2586 tgl                       692 GIC        1102 :         if (context->flags & PVC_INCLUDE_PLACEHOLDERS)
 2586 tgl                       693 ECB             :         {
 2586 tgl                       694 GBC         912 :             context->varlist = lappend(context->varlist, node);
 2586 tgl                       695 ECB             :             /* we do NOT descend into the contained expression */
 2586 tgl                       696 GIC         912 :             return false;
 2586 tgl                       697 ECB             :         }
 2586 tgl                       698 GIC         190 :         else if (context->flags & PVC_RECURSE_PLACEHOLDERS)
 5103 tgl                       699 ECB             :         {
                                700                 :             /* fall through to recurse into the placeholder's expression */
                                701                 :         }
                                702                 :         else
 2586 tgl                       703 UIC           0 :             elog(ERROR, "PlaceHolderVar found where not expected");
                                704                 :     }
 8695 tgl                       705 GIC      981506 :     return expression_tree_walker(node, pull_var_clause_walker,
 8627 tgl                       706 EUB             :                                   (void *) context);
                                707                 : }
 7698 tgl                       708 ECB             : 
                                709                 : 
                                710                 : /*
                                711                 :  * flatten_join_alias_vars
                                712                 :  *    Replace Vars that reference JOIN outputs with references to the original
                                713                 :  *    relation variables instead.  This allows quals involving such vars to be
                                714                 :  *    pushed down.  Whole-row Vars that reference JOIN relations are expanded
                                715                 :  *    into RowExpr constructs that name the individual output Vars.  This
                                716                 :  *    is necessary since we will not scan the JOIN as a base relation, which
                                717                 :  *    is the only way that the executor can directly handle whole-row Vars.
                                718                 :  *
                                719                 :  * This also adjusts relid sets found in some expression node types to
                                720                 :  * substitute the contained base+OJ rels for any join relid.
                                721                 :  *
                                722                 :  * If a JOIN contains sub-selects that have been flattened, its join alias
                                723                 :  * entries might now be arbitrary expressions, not just Vars.  This affects
                                724                 :  * this function in two important ways.  First, we might find ourselves
                                725                 :  * inserting SubLink expressions into subqueries, and we must make sure that
                                726                 :  * their Query.hasSubLinks fields get set to true if so.  If there are any
                                727                 :  * SubLinks in the join alias lists, the outer Query should already have
                                728                 :  * hasSubLinks = true, so this is only relevant to un-flattened subqueries.
                                729                 :  * Second, we have to preserve any varnullingrels info attached to the
                                730                 :  * alias Vars we're replacing.  If the replacement expression is a Var or
                                731                 :  * PlaceHolderVar or constructed from those, we can just add the
                                732                 :  * varnullingrels bits to the existing nullingrels field(s); otherwise
                                733                 :  * we have to add a PlaceHolderVar wrapper.
                                734                 :  *
                                735                 :  * NOTE: this is also used by the parser, to expand join alias Vars before
                                736                 :  * checking GROUP BY validity.  For that use-case, root will be NULL, which
                                737                 :  * is why we have to pass the Query separately.  We need the root itself only
                                738                 :  * for making PlaceHolderVars.  We can avoid making PlaceHolderVars in the
                                739                 :  * parser's usage because it won't be dealing with arbitrary expressions:
                                740                 :  * so long as adjust_standard_join_alias_expression can handle everything
                                741                 :  * the parser would make as a join alias expression, we're OK.
                                742                 :  */
                                743                 : Node *
   69 tgl                       744 GNC       90090 : flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node)
                                745                 : {
                                746                 :     flatten_join_alias_vars_context context;
                                747                 : 
                                748                 :     /*
                                749                 :      * We do not expect this to be applied to the whole Query, only to
                                750                 :      * expressions or LATERAL subqueries.  Hence, if the top node is a Query,
                                751                 :      * it's okay to immediately increment sublevels_up.
                                752                 :      */
                                753           90090 :     Assert(node != (Node *) query);
                                754                 : 
                                755           90090 :     context.root = root;
 1531 tgl                       756 GIC       90090 :     context.query = query;
 7389                           757           90090 :     context.sublevels_up = 0;
                                758                 :     /* flag whether join aliases could possibly contain SubLinks */
 1531                           759           90090 :     context.possible_sublink = query->hasSubLinks;
                                760                 :     /* if hasSubLinks is already true, no need to work hard */
                                761           90090 :     context.inserted_sublink = query->hasSubLinks;
                                762                 : 
 7698 tgl                       763 CBC       90090 :     return flatten_join_alias_vars_mutator(node, &context);
                                764                 : }
                                765                 : 
                                766                 : static Node *
 7698 tgl                       767 GIC     1237744 : flatten_join_alias_vars_mutator(Node *node,
                                768                 :                                 flatten_join_alias_vars_context *context)
                                769                 : {
                                770         1237744 :     if (node == NULL)
                                771          125601 :         return NULL;
 7698 tgl                       772 CBC     1112143 :     if (IsA(node, Var))
                                773                 :     {
 7522 bruce                     774          324467 :         Var        *var = (Var *) node;
 7651 tgl                       775 ECB             :         RangeTblEntry *rte;
 7522 bruce                     776                 :         Node       *newvar;
                                777                 : 
 7367 tgl                       778                 :         /* No change unless Var belongs to a JOIN of the target level */
 7389 tgl                       779 GIC      324467 :         if (var->varlevelsup != context->sublevels_up)
 7698 tgl                       780 CBC       22497 :             return node;        /* no need to copy, really */
 1531 tgl                       781 GIC      301970 :         rte = rt_fetch(var->varno, context->query->rtable);
 7698 tgl                       782 CBC      301970 :         if (rte->rtekind != RTE_JOIN)
 7651 tgl                       783 GIC      301703 :             return node;
 6908                           784             267 :         if (var->varattno == InvalidAttrNumber)
                                785                 :         {
 6908 tgl                       786 ECB             :             /* Must expand whole-row reference */
                                787                 :             RowExpr    *rowexpr;
 6797 bruce                     788 GIC           3 :             List       *fields = NIL;
 4072 tgl                       789 CBC           3 :             List       *colnames = NIL;
 4072 tgl                       790 ECB             :             ListCell   *lv;
                                791                 :             ListCell   *ln;
                                792                 : 
 4072 tgl                       793 CBC           3 :             Assert(list_length(rte->joinaliasvars) == list_length(rte->eref->colnames));
 4072 tgl                       794 GIC          24 :             forboth(lv, rte->joinaliasvars, ln, rte->eref->colnames)
                                795                 :             {
                                796              21 :                 newvar = (Node *) lfirst(lv);
                                797                 :                 /* Ignore dropped columns */
 3547 tgl                       798 CBC          21 :                 if (newvar == NULL)
 6807 tgl                       799 LBC           0 :                     continue;
 4177 tgl                       800 CBC          21 :                 newvar = copyObject(newvar);
 6797 bruce                     801 ECB             : 
 6908 tgl                       802                 :                 /*
                                803                 :                  * If we are expanding an alias carried down from an upper
                                804                 :                  * query, must adjust its varlevelsup fields.
                                805                 :                  */
 6908 tgl                       806 GIC          21 :                 if (context->sublevels_up != 0)
 6908 tgl                       807 LBC           0 :                     IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
 4177 tgl                       808 ECB             :                 /* Preserve original Var's location, if possible */
 4177 tgl                       809 GIC          21 :                 if (IsA(newvar, Var))
                                810              21 :                     ((Var *) newvar)->location = var->location;
                                811                 :                 /* Recurse in case join input is itself a join */
 4658 tgl                       812 ECB             :                 /* (also takes care of setting inserted_sublink if needed) */
 6908 tgl                       813 CBC          21 :                 newvar = flatten_join_alias_vars_mutator(newvar, context);
 6908 tgl                       814 GIC          21 :                 fields = lappend(fields, newvar);
 4072 tgl                       815 ECB             :                 /* We need the names of non-dropped columns, too */
 4072 tgl                       816 GIC          21 :                 colnames = lappend(colnames, copyObject((Node *) lfirst(ln)));
 6908 tgl                       817 ECB             :             }
 6908 tgl                       818 GBC           3 :             rowexpr = makeNode(RowExpr);
 6908 tgl                       819 CBC           3 :             rowexpr->args = fields;
 6908 tgl                       820 GIC           3 :             rowexpr->row_typeid = var->vartype;
                                821               3 :             rowexpr->row_format = COERCE_IMPLICIT_CAST;
                                822                 :             /* vartype will always be RECORDOID, so we always need colnames */
 4072                           823               3 :             rowexpr->colnames = colnames;
 4177                           824               3 :             rowexpr->location = var->location;
 6908 tgl                       825 ECB             : 
                                826                 :             /* Lastly, add any varnullingrels to the replacement expression */
   69 tgl                       827 GNC           3 :             return add_nullingrels_if_needed(context->root, (Node *) rowexpr,
                                828                 :                                              var);
                                829                 :         }
 6908 tgl                       830 ECB             : 
                                831                 :         /* Expand join alias reference */
 7651 tgl                       832 GIC         264 :         Assert(var->varattno > 0);
 6888 neilc                     833             264 :         newvar = (Node *) list_nth(rte->joinaliasvars, var->varattno - 1);
 3547 tgl                       834 CBC         264 :         Assert(newvar != NULL);
 4177                           835             264 :         newvar = copyObject(newvar);
                                836                 : 
 7367 tgl                       837 ECB             :         /*
                                838                 :          * If we are expanding an alias carried down from an upper query, must
 6385 bruce                     839                 :          * adjust its varlevelsup fields.
 7367 tgl                       840                 :          */
 7367 tgl                       841 CBC         264 :         if (context->sublevels_up != 0)
 7367 tgl                       842 LBC           0 :             IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
                                843                 : 
 4177 tgl                       844 ECB             :         /* Preserve original Var's location, if possible */
 4177 tgl                       845 CBC         264 :         if (IsA(newvar, Var))
 4177 tgl                       846 UIC           0 :             ((Var *) newvar)->location = var->location;
                                847                 : 
 7367 tgl                       848 ECB             :         /* Recurse in case join input is itself a join */
 4658 tgl                       849 GIC         264 :         newvar = flatten_join_alias_vars_mutator(newvar, context);
                                850                 : 
                                851                 :         /* Detect if we are adding a sublink to query */
                                852             264 :         if (context->possible_sublink && !context->inserted_sublink)
 4658 tgl                       853 LBC           0 :             context->inserted_sublink = checkExprHasSubLink(newvar);
 4658 tgl                       854 ECB             : 
                                855                 :         /* Lastly, add any varnullingrels to the replacement expression */
   69 tgl                       856 GNC         264 :         return add_nullingrels_if_needed(context->root, newvar, var);
 7389 tgl                       857 ECB             :     }
 5283 tgl                       858 GIC      787676 :     if (IsA(node, PlaceHolderVar))
                                859                 :     {
                                860                 :         /* Copy the PlaceHolderVar node with correct mutation of subnodes */
                                861                 :         PlaceHolderVar *phv;
                                862                 : 
 5283 tgl                       863 CBC         705 :         phv = (PlaceHolderVar *) expression_tree_mutator(node,
 2118 tgl                       864 EUB             :                                                          flatten_join_alias_vars_mutator,
                                865                 :                                                          (void *) context);
                                866                 :         /* now fix PlaceHolderVar's relid sets */
 5283 tgl                       867 CBC         705 :         if (phv->phlevelsup == context->sublevels_up)
 5283 tgl                       868 EUB             :         {
 1531 tgl                       869 GIC         675 :             phv->phrels = alias_relid_set(context->query,
                                870                 :                                           phv->phrels);
                                871                 :             /* we *don't* change phnullingrels */
 5283 tgl                       872 ECB             :         }
 5283 tgl                       873 GIC         705 :         return (Node *) phv;
                                874                 :     }
 7388 tgl                       875 ECB             : 
 7389 tgl                       876 GBC      786971 :     if (IsA(node, Query))
                                877                 :     {
                                878                 :         /* Recurse into RTE subquery or not-yet-planned sublink subquery */
 7389 tgl                       879 ECB             :         Query      *newnode;
                                880                 :         bool        save_inserted_sublink;
                                881                 : 
 7389 tgl                       882 GIC        7692 :         context->sublevels_up++;
 4658                           883            7692 :         save_inserted_sublink = context->inserted_sublink;
                                884            7692 :         context->inserted_sublink = ((Query *) node)->hasSubLinks;
 7387                           885            7692 :         newnode = query_tree_mutator((Query *) node,
 7387 tgl                       886 ECB             :                                      flatten_join_alias_vars_mutator,
                                887                 :                                      (void *) context,
                                888                 :                                      QTW_IGNORE_JOINALIASES);
 4658 tgl                       889 GIC        7692 :         newnode->hasSubLinks |= context->inserted_sublink;
 4658 tgl                       890 CBC        7692 :         context->inserted_sublink = save_inserted_sublink;
 7389 tgl                       891 GIC        7692 :         context->sublevels_up--;
 7389 tgl                       892 CBC        7692 :         return (Node *) newnode;
                                893                 :     }
                                894                 :     /* Already-planned tree not supported */
 5343 tgl                       895 GIC      779279 :     Assert(!IsA(node, SubPlan));
 5282 tgl                       896 ECB             :     /* Shouldn't need to handle these planner auxiliary nodes here */
 5282 tgl                       897 GIC      779279 :     Assert(!IsA(node, SpecialJoinInfo));
                                898          779279 :     Assert(!IsA(node, PlaceHolderInfo));
 4539 tgl                       899 CBC      779279 :     Assert(!IsA(node, MinMaxAggInfo));
                                900                 : 
 7651 tgl                       901 GIC      779279 :     return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
                                902                 :                                    (void *) context);
                                903                 : }
                                904                 : 
                                905                 : /*
                                906                 :  * Add oldvar's varnullingrels, if any, to a flattened join alias expression.
                                907                 :  * The newnode has been copied, so we can modify it freely.
                                908                 :  */
                                909                 : static Node *
   69 tgl                       910 GNC         267 : add_nullingrels_if_needed(PlannerInfo *root, Node *newnode, Var *oldvar)
                                911                 : {
                                912             267 :     if (oldvar->varnullingrels == NULL)
                                913             189 :         return newnode;         /* nothing to do */
                                914                 :     /* If possible, do it by adding to existing nullingrel fields */
                                915              78 :     if (is_standard_join_alias_expression(newnode, oldvar))
                                916              72 :         adjust_standard_join_alias_expression(newnode, oldvar);
                                917               6 :     else if (root)
                                918                 :     {
                                919                 :         /*
                                920                 :          * We can insert a PlaceHolderVar to carry the nullingrels.  However,
                                921                 :          * deciding where to evaluate the PHV is slightly tricky.  We first
                                922                 :          * try to evaluate it at the natural semantic level of the new
                                923                 :          * expression; but if that expression is variable-free, fall back to
                                924                 :          * evaluating it at the join that the oldvar is an alias Var for.
                                925                 :          */
                                926                 :         PlaceHolderVar *newphv;
                                927               6 :         Index       levelsup = oldvar->varlevelsup;
                                928               6 :         Relids      phrels = pull_varnos_of_level(root, newnode, levelsup);
                                929                 : 
                                930               6 :         if (bms_is_empty(phrels))   /* variable-free? */
                                931                 :         {
                                932               6 :             if (levelsup != 0)  /* this won't work otherwise */
   69 tgl                       933 UNC           0 :                 elog(ERROR, "unsupported join alias expression");
   69 tgl                       934 GNC           6 :             phrels = get_relids_for_join(root->parse, oldvar->varno);
                                935                 :             /* If it's an outer join, eval below not above the join */
                                936               6 :             phrels = bms_del_member(phrels, oldvar->varno);
                                937               6 :             Assert(!bms_is_empty(phrels));
                                938                 :         }
                                939               6 :         newphv = make_placeholder_expr(root, (Expr *) newnode, phrels);
                                940                 :         /* newphv has zero phlevelsup and NULL phnullingrels; fix it */
                                941               6 :         newphv->phlevelsup = levelsup;
                                942               6 :         newphv->phnullingrels = bms_copy(oldvar->varnullingrels);
                                943               6 :         newnode = (Node *) newphv;
                                944                 :     }
                                945                 :     else
                                946                 :     {
                                947                 :         /* ooops, we're missing support for something the parser can make */
   69 tgl                       948 UNC           0 :         elog(ERROR, "unsupported join alias expression");
                                949                 :     }
   69 tgl                       950 GNC          78 :     return newnode;
                                951                 : }
                                952                 : 
                                953                 : /*
                                954                 :  * Check to see if we can insert nullingrels into this join alias expression
                                955                 :  * without use of a separate PlaceHolderVar.
                                956                 :  *
                                957                 :  * This will handle Vars, PlaceHolderVars, and implicit-coercion and COALESCE
                                958                 :  * expressions built from those.  This coverage needs to handle anything
                                959                 :  * that the parser would put into joinaliasvars.
                                960                 :  */
                                961                 : static bool
                                962             234 : is_standard_join_alias_expression(Node *newnode, Var *oldvar)
                                963                 : {
                                964             234 :     if (newnode == NULL)
   69 tgl                       965 UNC           0 :         return false;
   69 tgl                       966 GNC         234 :     if (IsA(newnode, Var) &&
                                967             138 :         ((Var *) newnode)->varlevelsup == oldvar->varlevelsup)
                                968             138 :         return true;
                                969              96 :     else if (IsA(newnode, PlaceHolderVar) &&
   69 tgl                       970 UNC           0 :              ((PlaceHolderVar *) newnode)->phlevelsup == oldvar->varlevelsup)
                                971               0 :         return true;
   69 tgl                       972 GNC          96 :     else if (IsA(newnode, FuncExpr))
                                973                 :     {
                                974              15 :         FuncExpr   *fexpr = (FuncExpr *) newnode;
                                975                 : 
                                976                 :         /*
                                977                 :          * We need to assume that the function wouldn't produce non-NULL from
                                978                 :          * NULL, which is reasonable for implicit coercions but otherwise not
                                979                 :          * so much.  (Looking at its strictness is likely overkill, and anyway
                                980                 :          * it would cause us to fail if someone forgot to mark an implicit
                                981                 :          * coercion as strict.)
                                982                 :          */
                                983              15 :         if (fexpr->funcformat != COERCE_IMPLICIT_CAST ||
                                984              15 :             fexpr->args == NIL)
   69 tgl                       985 UNC           0 :             return false;
                                986                 : 
                                987                 :         /*
                                988                 :          * Examine only the first argument --- coercions might have additional
                                989                 :          * arguments that are constants.
                                990                 :          */
   69 tgl                       991 GNC          15 :         return is_standard_join_alias_expression(linitial(fexpr->args), oldvar);
                                992                 :     }
                                993              81 :     else if (IsA(newnode, RelabelType))
                                994                 :     {
                                995               9 :         RelabelType *relabel = (RelabelType *) newnode;
                                996                 : 
                                997                 :         /* This definitely won't produce non-NULL from NULL */
                                998               9 :         return is_standard_join_alias_expression((Node *) relabel->arg, oldvar);
                                999                 :     }
                               1000              72 :     else if (IsA(newnode, CoerceViaIO))
                               1001                 :     {
   69 tgl                      1002 UNC           0 :         CoerceViaIO *iocoerce = (CoerceViaIO *) newnode;
                               1003                 : 
                               1004                 :         /* This definitely won't produce non-NULL from NULL */
                               1005               0 :         return is_standard_join_alias_expression((Node *) iocoerce->arg, oldvar);
                               1006                 :     }
   69 tgl                      1007 GNC          72 :     else if (IsA(newnode, ArrayCoerceExpr))
                               1008                 :     {
   69 tgl                      1009 UNC           0 :         ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) newnode;
                               1010                 : 
                               1011                 :         /* This definitely won't produce non-NULL from NULL (at array level) */
                               1012               0 :         return is_standard_join_alias_expression((Node *) acoerce->arg, oldvar);
                               1013                 :     }
   69 tgl                      1014 GNC          72 :     else if (IsA(newnode, CoalesceExpr))
                               1015                 :     {
                               1016              66 :         CoalesceExpr *cexpr = (CoalesceExpr *) newnode;
                               1017                 :         ListCell   *lc;
                               1018                 : 
                               1019              66 :         Assert(cexpr->args != NIL);
                               1020             198 :         foreach(lc, cexpr->args)
                               1021                 :         {
                               1022             132 :             if (!is_standard_join_alias_expression(lfirst(lc), oldvar))
   69 tgl                      1023 UNC           0 :                 return false;
                               1024                 :         }
   69 tgl                      1025 GNC          66 :         return true;
                               1026                 :     }
                               1027                 :     else
                               1028               6 :         return false;
                               1029                 : }
                               1030                 : 
                               1031                 : /*
                               1032                 :  * Insert nullingrels into an expression accepted by
                               1033                 :  * is_standard_join_alias_expression.
                               1034                 :  */
                               1035                 : static void
                               1036             222 : adjust_standard_join_alias_expression(Node *newnode, Var *oldvar)
                               1037                 : {
                               1038             222 :     if (IsA(newnode, Var) &&
                               1039             138 :         ((Var *) newnode)->varlevelsup == oldvar->varlevelsup)
                               1040             138 :     {
                               1041             138 :         Var        *newvar = (Var *) newnode;
                               1042                 : 
                               1043             138 :         newvar->varnullingrels = bms_add_members(newvar->varnullingrels,
                               1044             138 :                                                  oldvar->varnullingrels);
                               1045                 :     }
                               1046              84 :     else if (IsA(newnode, PlaceHolderVar) &&
   69 tgl                      1047 UNC           0 :              ((PlaceHolderVar *) newnode)->phlevelsup == oldvar->varlevelsup)
                               1048               0 :     {
                               1049               0 :         PlaceHolderVar *newphv = (PlaceHolderVar *) newnode;
                               1050                 : 
                               1051               0 :         newphv->phnullingrels = bms_add_members(newphv->phnullingrels,
                               1052               0 :                                                 oldvar->varnullingrels);
                               1053                 :     }
   69 tgl                      1054 GNC          84 :     else if (IsA(newnode, FuncExpr))
                               1055                 :     {
                               1056               9 :         FuncExpr   *fexpr = (FuncExpr *) newnode;
                               1057                 : 
                               1058               9 :         adjust_standard_join_alias_expression(linitial(fexpr->args), oldvar);
                               1059                 :     }
                               1060              75 :     else if (IsA(newnode, RelabelType))
                               1061                 :     {
                               1062               9 :         RelabelType *relabel = (RelabelType *) newnode;
                               1063                 : 
                               1064               9 :         adjust_standard_join_alias_expression((Node *) relabel->arg, oldvar);
                               1065                 :     }
                               1066              66 :     else if (IsA(newnode, CoerceViaIO))
                               1067                 :     {
   69 tgl                      1068 UNC           0 :         CoerceViaIO *iocoerce = (CoerceViaIO *) newnode;
                               1069                 : 
                               1070               0 :         adjust_standard_join_alias_expression((Node *) iocoerce->arg, oldvar);
                               1071                 :     }
   69 tgl                      1072 GNC          66 :     else if (IsA(newnode, ArrayCoerceExpr))
                               1073                 :     {
   69 tgl                      1074 UNC           0 :         ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) newnode;
                               1075                 : 
                               1076               0 :         adjust_standard_join_alias_expression((Node *) acoerce->arg, oldvar);
                               1077                 :     }
   69 tgl                      1078 GNC          66 :     else if (IsA(newnode, CoalesceExpr))
                               1079                 :     {
                               1080              66 :         CoalesceExpr *cexpr = (CoalesceExpr *) newnode;
                               1081                 :         ListCell   *lc;
                               1082                 : 
                               1083              66 :         Assert(cexpr->args != NIL);
                               1084             198 :         foreach(lc, cexpr->args)
                               1085                 :         {
                               1086             132 :             adjust_standard_join_alias_expression(lfirst(lc), oldvar);
                               1087                 :         }
                               1088                 :     }
                               1089                 :     else
   69 tgl                      1090 UNC           0 :         Assert(false);
   69 tgl                      1091 GNC         222 : }
                               1092                 : 
 7384 tgl                      1093 ECB             : /*
 7365                          1094                 :  * alias_relid_set: in a set of RT indexes, replace joins by their
                               1095                 :  * underlying base+OJ relids
 7384                          1096                 :  */
                               1097                 : static Relids
 1531 tgl                      1098 GIC         675 : alias_relid_set(Query *query, Relids relids)
                               1099                 : {
 7365 tgl                      1100 CBC         675 :     Relids      result = NULL;
 7365 tgl                      1101 ECB             :     int         rtindex;
 7384                          1102                 : 
 3054 tgl                      1103 CBC         675 :     rtindex = -1;
 3054 tgl                      1104 GIC        1739 :     while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
                               1105                 :     {
 1531 tgl                      1106 CBC        1064 :         RangeTblEntry *rte = rt_fetch(rtindex, query->rtable);
                               1107                 : 
 7384                          1108            1064 :         if (rte->rtekind == RTE_JOIN)
 1531                          1109             134 :             result = bms_join(result, get_relids_for_join(query, rtindex));
 7384 tgl                      1110 ECB             :         else
 7365 tgl                      1111 GIC         930 :             result = bms_add_member(result, rtindex);
 7384 tgl                      1112 ECB             :     }
 7384 tgl                      1113 GIC         675 :     return result;
                               1114                 : }
        

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