LCOV - code coverage report
Current view: top level - src/backend/optimizer/util - tlist.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 95.8 % 380 364
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 34 34
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 85.5 % 366 313

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * tlist.c
       4                 :             :  *    Target list manipulation routines
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *    src/backend/optimizer/util/tlist.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include "nodes/makefuncs.h"
      18                 :             : #include "nodes/nodeFuncs.h"
      19                 :             : #include "optimizer/cost.h"
      20                 :             : #include "optimizer/optimizer.h"
      21                 :             : #include "optimizer/tlist.h"
      22                 :             : #include "rewrite/rewriteManip.h"
      23                 :             : 
      24                 :             : 
      25                 :             : /*
      26                 :             :  * Test if an expression node represents a SRF call.  Beware multiple eval!
      27                 :             :  *
      28                 :             :  * Please note that this is only meant for use in split_pathtarget_at_srfs();
      29                 :             :  * if you use it anywhere else, your code is almost certainly wrong for SRFs
      30                 :             :  * nested within expressions.  Use expression_returns_set() instead.
      31                 :             :  */
      32                 :             : #define IS_SRF_CALL(node) \
      33                 :             :     ((IsA(node, FuncExpr) && ((FuncExpr *) (node))->funcretset) || \
      34                 :             :      (IsA(node, OpExpr) && ((OpExpr *) (node))->opretset))
      35                 :             : 
      36                 :             : /*
      37                 :             :  * Data structures for split_pathtarget_at_srfs().  To preserve the identity
      38                 :             :  * of sortgroupref items even if they are textually equal(), what we track is
      39                 :             :  * not just bare expressions but expressions plus their sortgroupref indexes.
      40                 :             :  */
      41                 :             : typedef struct
      42                 :             : {
      43                 :             :     Node       *expr;           /* some subexpression of a PathTarget */
      44                 :             :     Index       sortgroupref;   /* its sortgroupref, or 0 if none */
      45                 :             : } split_pathtarget_item;
      46                 :             : 
      47                 :             : typedef struct
      48                 :             : {
      49                 :             :     PlannerInfo *root;
      50                 :             :     bool        is_grouping_target; /* true if processing grouping target */
      51                 :             :     /* This is a List of bare expressions: */
      52                 :             :     List       *input_target_exprs; /* exprs available from input */
      53                 :             :     /* These are Lists of Lists of split_pathtarget_items: */
      54                 :             :     List       *level_srfs;     /* SRF exprs to evaluate at each level */
      55                 :             :     List       *level_input_vars;   /* input vars needed at each level */
      56                 :             :     List       *level_input_srfs;   /* input SRFs needed at each level */
      57                 :             :     /* These are Lists of split_pathtarget_items: */
      58                 :             :     List       *current_input_vars; /* vars needed in current subexpr */
      59                 :             :     List       *current_input_srfs; /* SRFs needed in current subexpr */
      60                 :             :     /* Auxiliary data for current split_pathtarget_walker traversal: */
      61                 :             :     int         current_depth;  /* max SRF depth in current subexpr */
      62                 :             :     Index       current_sgref;  /* current subexpr's sortgroupref, or 0 */
      63                 :             : } split_pathtarget_context;
      64                 :             : 
      65                 :             : static void split_pathtarget_at_srfs_extended(PlannerInfo *root,
      66                 :             :                                               PathTarget *target,
      67                 :             :                                               PathTarget *input_target,
      68                 :             :                                               List **targets,
      69                 :             :                                               List **targets_contain_srfs,
      70                 :             :                                               bool is_grouping_target);
      71                 :             : static bool split_pathtarget_walker(Node *node,
      72                 :             :                                     split_pathtarget_context *context);
      73                 :             : static void add_sp_item_to_pathtarget(PathTarget *target,
      74                 :             :                                       split_pathtarget_item *item);
      75                 :             : static void add_sp_items_to_pathtarget(PathTarget *target, List *items);
      76                 :             : 
      77                 :             : 
      78                 :             : /*****************************************************************************
      79                 :             :  *      Target list creation and searching utilities
      80                 :             :  *****************************************************************************/
      81                 :             : 
      82                 :             : /*
      83                 :             :  * tlist_member
      84                 :             :  *    Finds the (first) member of the given tlist whose expression is
      85                 :             :  *    equal() to the given expression.  Result is NULL if no such member.
      86                 :             :  */
      87                 :             : TargetEntry *
      88                 :       39795 : tlist_member(Expr *node, List *targetlist)
      89                 :             : {
      90                 :             :     ListCell   *temp;
      91                 :             : 
      92   [ +  +  +  +  :      139635 :     foreach(temp, targetlist)
                   +  + ]
      93                 :             :     {
      94                 :      110604 :         TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
      95                 :             : 
      96         [ +  + ]:      110604 :         if (equal(node, tlentry->expr))
      97                 :       10764 :             return tlentry;
      98                 :             :     }
      99                 :       29031 :     return NULL;
     100                 :             : }
     101                 :             : 
     102                 :             : /*
     103                 :             :  * tlist_member_match_var
     104                 :             :  *    Same as above, except that we match the provided Var on the basis
     105                 :             :  *    of varno/varattno/varlevelsup/vartype only, rather than full equal().
     106                 :             :  *
     107                 :             :  * This is needed in some cases where we can't be sure of an exact typmod
     108                 :             :  * match.  For safety, though, we insist on vartype match.
     109                 :             :  */
     110                 :             : static TargetEntry *
     111                 :        2277 : tlist_member_match_var(Var *var, List *targetlist)
     112                 :             : {
     113                 :             :     ListCell   *temp;
     114                 :             : 
     115   [ +  -  +  -  :        6320 :     foreach(temp, targetlist)
                   +  - ]
     116                 :             :     {
     117                 :        6320 :         TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
     118                 :        6320 :         Var        *tlvar = (Var *) tlentry->expr;
     119                 :             : 
     120   [ +  -  -  + ]:        6320 :         if (!tlvar || !IsA(tlvar, Var))
     121                 :           0 :             continue;
     122         [ +  - ]:        6320 :         if (var->varno == tlvar->varno &&
     123         [ +  + ]:        6320 :             var->varattno == tlvar->varattno &&
     124         [ +  - ]:        2277 :             var->varlevelsup == tlvar->varlevelsup &&
     125         [ +  - ]:        2277 :             var->vartype == tlvar->vartype)
     126                 :        2277 :             return tlentry;
     127                 :             :     }
     128                 :           0 :     return NULL;
     129                 :             : }
     130                 :             : 
     131                 :             : /*
     132                 :             :  * add_to_flat_tlist
     133                 :             :  *      Add more items to a flattened tlist (if they're not already in it)
     134                 :             :  *
     135                 :             :  * 'tlist' is the flattened tlist
     136                 :             :  * 'exprs' is a list of expressions (usually, but not necessarily, Vars)
     137                 :             :  *
     138                 :             :  * Returns the extended tlist.
     139                 :             :  */
     140                 :             : List *
     141                 :         862 : add_to_flat_tlist(List *tlist, List *exprs)
     142                 :             : {
     143                 :         862 :     int         next_resno = list_length(tlist) + 1;
     144                 :             :     ListCell   *lc;
     145                 :             : 
     146   [ +  +  +  +  :        4704 :     foreach(lc, exprs)
                   +  + ]
     147                 :             :     {
     148                 :        3842 :         Expr       *expr = (Expr *) lfirst(lc);
     149                 :             : 
     150         [ +  + ]:        3842 :         if (!tlist_member(expr, tlist))
     151                 :             :         {
     152                 :             :             TargetEntry *tle;
     153                 :             : 
     154                 :        3822 :             tle = makeTargetEntry(copyObject(expr), /* copy needed?? */
     155                 :        3822 :                                   next_resno++,
     156                 :             :                                   NULL,
     157                 :             :                                   false);
     158                 :        3822 :             tlist = lappend(tlist, tle);
     159                 :             :         }
     160                 :             :     }
     161                 :         862 :     return tlist;
     162                 :             : }
     163                 :             : 
     164                 :             : 
     165                 :             : /*
     166                 :             :  * get_tlist_exprs
     167                 :             :  *      Get just the expression subtrees of a tlist
     168                 :             :  *
     169                 :             :  * Resjunk columns are ignored unless includeJunk is true
     170                 :             :  */
     171                 :             : List *
     172                 :       10488 : get_tlist_exprs(List *tlist, bool includeJunk)
     173                 :             : {
     174                 :       10488 :     List       *result = NIL;
     175                 :             :     ListCell   *l;
     176                 :             : 
     177   [ +  +  +  +  :       41264 :     foreach(l, tlist)
                   +  + ]
     178                 :             :     {
     179                 :       30776 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     180                 :             : 
     181   [ -  +  -  - ]:       30776 :         if (tle->resjunk && !includeJunk)
     182                 :           0 :             continue;
     183                 :             : 
     184                 :       30776 :         result = lappend(result, tle->expr);
     185                 :             :     }
     186                 :       10488 :     return result;
     187                 :             : }
     188                 :             : 
     189                 :             : 
     190                 :             : /*
     191                 :             :  * count_nonjunk_tlist_entries
     192                 :             :  *      What it says ...
     193                 :             :  */
     194                 :             : int
     195                 :       22257 : count_nonjunk_tlist_entries(List *tlist)
     196                 :             : {
     197                 :       22257 :     int         len = 0;
     198                 :             :     ListCell   *l;
     199                 :             : 
     200   [ +  +  +  +  :       45881 :     foreach(l, tlist)
                   +  + ]
     201                 :             :     {
     202                 :       23624 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     203                 :             : 
     204         [ +  + ]:       23624 :         if (!tle->resjunk)
     205                 :       22363 :             len++;
     206                 :             :     }
     207                 :       22257 :     return len;
     208                 :             : }
     209                 :             : 
     210                 :             : 
     211                 :             : /*
     212                 :             :  * tlist_same_exprs
     213                 :             :  *      Check whether two target lists contain the same expressions
     214                 :             :  *
     215                 :             :  * Note: this function is used to decide whether it's safe to jam a new tlist
     216                 :             :  * into a non-projection-capable plan node.  Obviously we can't do that unless
     217                 :             :  * the node's tlist shows it already returns the column values we want.
     218                 :             :  * However, we can ignore the TargetEntry attributes resname, ressortgroupref,
     219                 :             :  * resorigtbl, resorigcol, and resjunk, because those are only labelings that
     220                 :             :  * don't affect the row values computed by the node.  (Moreover, if we didn't
     221                 :             :  * ignore them, we'd frequently fail to make the desired optimization, since
     222                 :             :  * the planner tends to not bother to make resname etc. valid in intermediate
     223                 :             :  * plan nodes.)  Note that on success, the caller must still jam the desired
     224                 :             :  * tlist into the plan node, else it won't have the desired labeling fields.
     225                 :             :  */
     226                 :             : bool
     227                 :        1489 : tlist_same_exprs(List *tlist1, List *tlist2)
     228                 :             : {
     229                 :             :     ListCell   *lc1,
     230                 :             :                *lc2;
     231                 :             : 
     232         [ +  + ]:        1489 :     if (list_length(tlist1) != list_length(tlist2))
     233                 :         647 :         return false;           /* not same length, so can't match */
     234                 :             : 
     235   [ +  -  +  +  :        1136 :     forboth(lc1, tlist1, lc2, tlist2)
          +  -  +  +  +  
             +  +  -  +  
                      + ]
     236                 :             :     {
     237                 :        1002 :         TargetEntry *tle1 = (TargetEntry *) lfirst(lc1);
     238                 :        1002 :         TargetEntry *tle2 = (TargetEntry *) lfirst(lc2);
     239                 :             : 
     240         [ +  + ]:        1002 :         if (!equal(tle1->expr, tle2->expr))
     241                 :         708 :             return false;
     242                 :             :     }
     243                 :             : 
     244                 :         134 :     return true;
     245                 :             : }
     246                 :             : 
     247                 :             : 
     248                 :             : /*
     249                 :             :  * Does tlist have same output datatypes as listed in colTypes?
     250                 :             :  *
     251                 :             :  * Resjunk columns are ignored if junkOK is true; otherwise presence of
     252                 :             :  * a resjunk column will always cause a 'false' result.
     253                 :             :  *
     254                 :             :  * Note: currently no callers care about comparing typmods.
     255                 :             :  */
     256                 :             : bool
     257                 :       17205 : tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
     258                 :             : {
     259                 :             :     ListCell   *l;
     260                 :       17205 :     ListCell   *curColType = list_head(colTypes);
     261                 :             : 
     262   [ +  +  +  +  :       67072 :     foreach(l, tlist)
                   +  + ]
     263                 :             :     {
     264                 :       50337 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     265                 :             : 
     266         [ +  + ]:       50337 :         if (tle->resjunk)
     267                 :             :         {
     268         [ -  + ]:          10 :             if (!junkOK)
     269                 :         470 :                 return false;
     270                 :             :         }
     271                 :             :         else
     272                 :             :         {
     273         [ -  + ]:       50327 :             if (curColType == NULL)
     274                 :           0 :                 return false;   /* tlist longer than colTypes */
     275         [ +  + ]:       50327 :             if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
     276                 :         470 :                 return false;
     277                 :       49857 :             curColType = lnext(colTypes, curColType);
     278                 :             :         }
     279                 :             :     }
     280         [ -  + ]:       16735 :     if (curColType != NULL)
     281                 :           0 :         return false;           /* tlist shorter than colTypes */
     282                 :       16735 :     return true;
     283                 :             : }
     284                 :             : 
     285                 :             : /*
     286                 :             :  * Does tlist have same exposed collations as listed in colCollations?
     287                 :             :  *
     288                 :             :  * Identical logic to the above, but for collations.
     289                 :             :  */
     290                 :             : bool
     291                 :        4328 : tlist_same_collations(List *tlist, List *colCollations, bool junkOK)
     292                 :             : {
     293                 :             :     ListCell   *l;
     294                 :        4328 :     ListCell   *curColColl = list_head(colCollations);
     295                 :             : 
     296   [ +  +  +  +  :       16865 :     foreach(l, tlist)
                   +  + ]
     297                 :             :     {
     298                 :       12537 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     299                 :             : 
     300         [ -  + ]:       12537 :         if (tle->resjunk)
     301                 :             :         {
     302         [ #  # ]:           0 :             if (!junkOK)
     303                 :           0 :                 return false;
     304                 :             :         }
     305                 :             :         else
     306                 :             :         {
     307         [ -  + ]:       12537 :             if (curColColl == NULL)
     308                 :           0 :                 return false;   /* tlist longer than colCollations */
     309         [ -  + ]:       12537 :             if (exprCollation((Node *) tle->expr) != lfirst_oid(curColColl))
     310                 :           0 :                 return false;
     311                 :       12537 :             curColColl = lnext(colCollations, curColColl);
     312                 :             :         }
     313                 :             :     }
     314         [ -  + ]:        4328 :     if (curColColl != NULL)
     315                 :           0 :         return false;           /* tlist shorter than colCollations */
     316                 :        4328 :     return true;
     317                 :             : }
     318                 :             : 
     319                 :             : /*
     320                 :             :  * apply_tlist_labeling
     321                 :             :  *      Apply the TargetEntry labeling attributes of src_tlist to dest_tlist
     322                 :             :  *
     323                 :             :  * This is useful for reattaching column names etc to a plan's final output
     324                 :             :  * targetlist.
     325                 :             :  */
     326                 :             : void
     327                 :      409024 : apply_tlist_labeling(List *dest_tlist, List *src_tlist)
     328                 :             : {
     329                 :             :     ListCell   *ld,
     330                 :             :                *ls;
     331                 :             : 
     332                 :             :     Assert(list_length(dest_tlist) == list_length(src_tlist));
     333   [ +  +  +  +  :     1484954 :     forboth(ld, dest_tlist, ls, src_tlist)
          +  +  +  +  +  
             +  +  -  +  
                      + ]
     334                 :             :     {
     335                 :     1075930 :         TargetEntry *dest_tle = (TargetEntry *) lfirst(ld);
     336                 :     1075930 :         TargetEntry *src_tle = (TargetEntry *) lfirst(ls);
     337                 :             : 
     338                 :             :         Assert(dest_tle->resno == src_tle->resno);
     339                 :     1075930 :         dest_tle->resname = src_tle->resname;
     340                 :     1075930 :         dest_tle->ressortgroupref = src_tle->ressortgroupref;
     341                 :     1075930 :         dest_tle->resorigtbl = src_tle->resorigtbl;
     342                 :     1075930 :         dest_tle->resorigcol = src_tle->resorigcol;
     343                 :     1075930 :         dest_tle->resjunk = src_tle->resjunk;
     344                 :             :     }
     345                 :      409024 : }
     346                 :             : 
     347                 :             : 
     348                 :             : /*
     349                 :             :  * get_sortgroupref_tle
     350                 :             :  *      Find the targetlist entry matching the given SortGroupRef index,
     351                 :             :  *      and return it.
     352                 :             :  */
     353                 :             : TargetEntry *
     354                 :      224553 : get_sortgroupref_tle(Index sortref, List *targetList)
     355                 :             : {
     356                 :             :     ListCell   *l;
     357                 :             : 
     358   [ +  -  +  -  :      572307 :     foreach(l, targetList)
                   +  - ]
     359                 :             :     {
     360                 :      572307 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     361                 :             : 
     362         [ +  + ]:      572307 :         if (tle->ressortgroupref == sortref)
     363                 :      224553 :             return tle;
     364                 :             :     }
     365                 :             : 
     366         [ #  # ]:           0 :     elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
     367                 :             :     return NULL;                /* keep compiler quiet */
     368                 :             : }
     369                 :             : 
     370                 :             : /*
     371                 :             :  * get_sortgroupclause_tle
     372                 :             :  *      Find the targetlist entry matching the given SortGroupClause
     373                 :             :  *      by ressortgroupref, and return it.
     374                 :             :  */
     375                 :             : TargetEntry *
     376                 :      223427 : get_sortgroupclause_tle(SortGroupClause *sgClause,
     377                 :             :                         List *targetList)
     378                 :             : {
     379                 :      223427 :     return get_sortgroupref_tle(sgClause->tleSortGroupRef, targetList);
     380                 :             : }
     381                 :             : 
     382                 :             : /*
     383                 :             :  * get_sortgroupclause_expr
     384                 :             :  *      Find the targetlist entry matching the given SortGroupClause
     385                 :             :  *      by ressortgroupref, and return its expression.
     386                 :             :  */
     387                 :             : Node *
     388                 :      183026 : get_sortgroupclause_expr(SortGroupClause *sgClause, List *targetList)
     389                 :             : {
     390                 :      183026 :     TargetEntry *tle = get_sortgroupclause_tle(sgClause, targetList);
     391                 :             : 
     392                 :      183026 :     return (Node *) tle->expr;
     393                 :             : }
     394                 :             : 
     395                 :             : /*
     396                 :             :  * get_sortgrouplist_exprs
     397                 :             :  *      Given a list of SortGroupClauses, build a list
     398                 :             :  *      of the referenced targetlist expressions.
     399                 :             :  */
     400                 :             : List *
     401                 :       14723 : get_sortgrouplist_exprs(List *sgClauses, List *targetList)
     402                 :             : {
     403                 :       14723 :     List       *result = NIL;
     404                 :             :     ListCell   *l;
     405                 :             : 
     406   [ +  +  +  +  :       34400 :     foreach(l, sgClauses)
                   +  + ]
     407                 :             :     {
     408                 :       19677 :         SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
     409                 :             :         Node       *sortexpr;
     410                 :             : 
     411                 :       19677 :         sortexpr = get_sortgroupclause_expr(sortcl, targetList);
     412                 :       19677 :         result = lappend(result, sortexpr);
     413                 :             :     }
     414                 :       14723 :     return result;
     415                 :             : }
     416                 :             : 
     417                 :             : 
     418                 :             : /*****************************************************************************
     419                 :             :  *      Functions to extract data from a list of SortGroupClauses
     420                 :             :  *
     421                 :             :  * These don't really belong in tlist.c, but they are sort of related to the
     422                 :             :  * functions just above, and they don't seem to deserve their own file.
     423                 :             :  *****************************************************************************/
     424                 :             : 
     425                 :             : /*
     426                 :             :  * get_sortgroupref_clause
     427                 :             :  *      Find the SortGroupClause matching the given SortGroupRef index,
     428                 :             :  *      and return it.
     429                 :             :  */
     430                 :             : SortGroupClause *
     431                 :        9459 : get_sortgroupref_clause(Index sortref, List *clauses)
     432                 :             : {
     433                 :             :     ListCell   *l;
     434                 :             : 
     435   [ +  -  +  -  :       14793 :     foreach(l, clauses)
                   +  - ]
     436                 :             :     {
     437                 :       14793 :         SortGroupClause *cl = (SortGroupClause *) lfirst(l);
     438                 :             : 
     439         [ +  + ]:       14793 :         if (cl->tleSortGroupRef == sortref)
     440                 :        9459 :             return cl;
     441                 :             :     }
     442                 :             : 
     443         [ #  # ]:           0 :     elog(ERROR, "ORDER/GROUP BY expression not found in list");
     444                 :             :     return NULL;                /* keep compiler quiet */
     445                 :             : }
     446                 :             : 
     447                 :             : /*
     448                 :             :  * get_sortgroupref_clause_noerr
     449                 :             :  *      As above, but return NULL rather than throwing an error if not found.
     450                 :             :  */
     451                 :             : SortGroupClause *
     452                 :       12806 : get_sortgroupref_clause_noerr(Index sortref, List *clauses)
     453                 :             : {
     454                 :             :     ListCell   *l;
     455                 :             : 
     456   [ +  +  +  +  :       21848 :     foreach(l, clauses)
                   +  + ]
     457                 :             :     {
     458                 :       18678 :         SortGroupClause *cl = (SortGroupClause *) lfirst(l);
     459                 :             : 
     460         [ +  + ]:       18678 :         if (cl->tleSortGroupRef == sortref)
     461                 :        9636 :             return cl;
     462                 :             :     }
     463                 :             : 
     464                 :        3170 :     return NULL;
     465                 :             : }
     466                 :             : 
     467                 :             : /*
     468                 :             :  * extract_grouping_ops - make an array of the equality operator OIDs
     469                 :             :  *      for a SortGroupClause list
     470                 :             :  */
     471                 :             : Oid *
     472                 :       38252 : extract_grouping_ops(List *groupClause)
     473                 :             : {
     474                 :       38252 :     int         numCols = list_length(groupClause);
     475                 :       38252 :     int         colno = 0;
     476                 :             :     Oid        *groupOperators;
     477                 :             :     ListCell   *glitem;
     478                 :             : 
     479                 :       38252 :     groupOperators = palloc_array(Oid, numCols);
     480                 :             : 
     481   [ +  +  +  +  :       50082 :     foreach(glitem, groupClause)
                   +  + ]
     482                 :             :     {
     483                 :       11830 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     484                 :             : 
     485                 :       11830 :         groupOperators[colno] = groupcl->eqop;
     486                 :             :         Assert(OidIsValid(groupOperators[colno]));
     487                 :       11830 :         colno++;
     488                 :             :     }
     489                 :             : 
     490                 :       38252 :     return groupOperators;
     491                 :             : }
     492                 :             : 
     493                 :             : /*
     494                 :             :  * extract_grouping_collations - make an array of the grouping column collations
     495                 :             :  *      for a SortGroupClause list
     496                 :             :  */
     497                 :             : Oid *
     498                 :       38252 : extract_grouping_collations(List *groupClause, List *tlist)
     499                 :             : {
     500                 :       38252 :     int         numCols = list_length(groupClause);
     501                 :       38252 :     int         colno = 0;
     502                 :             :     Oid        *grpCollations;
     503                 :             :     ListCell   *glitem;
     504                 :             : 
     505                 :       38252 :     grpCollations = palloc_array(Oid, numCols);
     506                 :             : 
     507   [ +  +  +  +  :       50082 :     foreach(glitem, groupClause)
                   +  + ]
     508                 :             :     {
     509                 :       11830 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     510                 :       11830 :         TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
     511                 :             : 
     512                 :       11830 :         grpCollations[colno++] = exprCollation((Node *) tle->expr);
     513                 :             :     }
     514                 :             : 
     515                 :       38252 :     return grpCollations;
     516                 :             : }
     517                 :             : 
     518                 :             : /*
     519                 :             :  * extract_grouping_cols - make an array of the grouping column resnos
     520                 :             :  *      for a SortGroupClause list
     521                 :             :  */
     522                 :             : AttrNumber *
     523                 :       36422 : extract_grouping_cols(List *groupClause, List *tlist)
     524                 :             : {
     525                 :             :     AttrNumber *grpColIdx;
     526                 :       36422 :     int         numCols = list_length(groupClause);
     527                 :       36422 :     int         colno = 0;
     528                 :             :     ListCell   *glitem;
     529                 :             : 
     530                 :       36422 :     grpColIdx = palloc_array(AttrNumber, numCols);
     531                 :             : 
     532   [ +  +  +  +  :       45926 :     foreach(glitem, groupClause)
                   +  + ]
     533                 :             :     {
     534                 :        9504 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     535                 :        9504 :         TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
     536                 :             : 
     537                 :        9504 :         grpColIdx[colno++] = tle->resno;
     538                 :             :     }
     539                 :             : 
     540                 :       36422 :     return grpColIdx;
     541                 :             : }
     542                 :             : 
     543                 :             : /*
     544                 :             :  * grouping_is_sortable - is it possible to implement grouping list by sorting?
     545                 :             :  *
     546                 :             :  * This is easy since the parser will have included a sortop if one exists.
     547                 :             :  */
     548                 :             : bool
     549                 :       53624 : grouping_is_sortable(List *groupClause)
     550                 :             : {
     551                 :             :     ListCell   *glitem;
     552                 :             : 
     553   [ +  +  +  +  :       89267 :     foreach(glitem, groupClause)
                   +  + ]
     554                 :             :     {
     555                 :       35773 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     556                 :             : 
     557         [ +  + ]:       35773 :         if (!OidIsValid(groupcl->sortop))
     558                 :         130 :             return false;
     559                 :             :     }
     560                 :       53494 :     return true;
     561                 :             : }
     562                 :             : 
     563                 :             : /*
     564                 :             :  * grouping_is_hashable - is it possible to implement grouping list by hashing?
     565                 :             :  *
     566                 :             :  * We rely on the parser to have set the hashable flag correctly.
     567                 :             :  */
     568                 :             : bool
     569                 :        9928 : grouping_is_hashable(List *groupClause)
     570                 :             : {
     571                 :             :     ListCell   *glitem;
     572                 :             : 
     573   [ +  +  +  +  :       30117 :     foreach(glitem, groupClause)
                   +  + ]
     574                 :             :     {
     575                 :       20306 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     576                 :             : 
     577         [ +  + ]:       20306 :         if (!groupcl->hashable)
     578                 :         117 :             return false;
     579                 :             :     }
     580                 :        9811 :     return true;
     581                 :             : }
     582                 :             : 
     583                 :             : 
     584                 :             : /*****************************************************************************
     585                 :             :  *      PathTarget manipulation functions
     586                 :             :  *
     587                 :             :  * PathTarget is a somewhat stripped-down version of a full targetlist; it
     588                 :             :  * omits all the TargetEntry decoration except (optionally) sortgroupref data,
     589                 :             :  * and it adds evaluation cost and output data width info.
     590                 :             :  *****************************************************************************/
     591                 :             : 
     592                 :             : /*
     593                 :             :  * make_pathtarget_from_tlist
     594                 :             :  *    Construct a PathTarget equivalent to the given targetlist.
     595                 :             :  *
     596                 :             :  * This leaves the cost and width fields as zeroes.  Most callers will want
     597                 :             :  * to use create_pathtarget(), so as to get those set.
     598                 :             :  */
     599                 :             : PathTarget *
     600                 :      407387 : make_pathtarget_from_tlist(List *tlist)
     601                 :             : {
     602                 :      407387 :     PathTarget *target = makeNode(PathTarget);
     603                 :             :     int         i;
     604                 :             :     ListCell   *lc;
     605                 :             : 
     606                 :      407387 :     target->sortgrouprefs = (Index *) palloc(list_length(tlist) * sizeof(Index));
     607                 :             : 
     608                 :      407387 :     i = 0;
     609   [ +  +  +  +  :     1481511 :     foreach(lc, tlist)
                   +  + ]
     610                 :             :     {
     611                 :     1074124 :         TargetEntry *tle = (TargetEntry *) lfirst(lc);
     612                 :             : 
     613                 :     1074124 :         target->exprs = lappend(target->exprs, tle->expr);
     614                 :     1074124 :         target->sortgrouprefs[i] = tle->ressortgroupref;
     615                 :     1074124 :         i++;
     616                 :             :     }
     617                 :             : 
     618                 :             :     /*
     619                 :             :      * Mark volatility as unknown.  The contain_volatile_functions function
     620                 :             :      * will determine if there are any volatile functions when called for the
     621                 :             :      * first time with this PathTarget.
     622                 :             :      */
     623                 :      407387 :     target->has_volatile_expr = VOLATILITY_UNKNOWN;
     624                 :             : 
     625                 :      407387 :     return target;
     626                 :             : }
     627                 :             : 
     628                 :             : /*
     629                 :             :  * make_tlist_from_pathtarget
     630                 :             :  *    Construct a targetlist from a PathTarget.
     631                 :             :  */
     632                 :             : List *
     633                 :       54320 : make_tlist_from_pathtarget(PathTarget *target)
     634                 :             : {
     635                 :       54320 :     List       *tlist = NIL;
     636                 :             :     int         i;
     637                 :             :     ListCell   *lc;
     638                 :             : 
     639                 :       54320 :     i = 0;
     640   [ +  +  +  +  :      236351 :     foreach(lc, target->exprs)
                   +  + ]
     641                 :             :     {
     642                 :      182031 :         Expr       *expr = (Expr *) lfirst(lc);
     643                 :             :         TargetEntry *tle;
     644                 :             : 
     645                 :      182031 :         tle = makeTargetEntry(expr,
     646                 :      182031 :                               i + 1,
     647                 :             :                               NULL,
     648                 :             :                               false);
     649         [ +  + ]:      182031 :         if (target->sortgrouprefs)
     650                 :      176368 :             tle->ressortgroupref = target->sortgrouprefs[i];
     651                 :      182031 :         tlist = lappend(tlist, tle);
     652                 :      182031 :         i++;
     653                 :             :     }
     654                 :             : 
     655                 :       54320 :     return tlist;
     656                 :             : }
     657                 :             : 
     658                 :             : /*
     659                 :             :  * copy_pathtarget
     660                 :             :  *    Copy a PathTarget.
     661                 :             :  *
     662                 :             :  * The new PathTarget has its own exprs List, but shares the underlying
     663                 :             :  * target expression trees with the old one.
     664                 :             :  */
     665                 :             : PathTarget *
     666                 :       22800 : copy_pathtarget(PathTarget *src)
     667                 :             : {
     668                 :       22800 :     PathTarget *dst = makeNode(PathTarget);
     669                 :             : 
     670                 :             :     /* Copy scalar fields */
     671                 :       22800 :     memcpy(dst, src, sizeof(PathTarget));
     672                 :             :     /* Shallow-copy the expression list */
     673                 :       22800 :     dst->exprs = list_copy(src->exprs);
     674                 :             :     /* Duplicate sortgrouprefs if any (if not, the memcpy handled this) */
     675         [ +  + ]:       22800 :     if (src->sortgrouprefs)
     676                 :             :     {
     677                 :       21092 :         Size        nbytes = list_length(src->exprs) * sizeof(Index);
     678                 :             : 
     679                 :       21092 :         dst->sortgrouprefs = (Index *) palloc(nbytes);
     680                 :       21092 :         memcpy(dst->sortgrouprefs, src->sortgrouprefs, nbytes);
     681                 :             :     }
     682                 :       22800 :     return dst;
     683                 :             : }
     684                 :             : 
     685                 :             : /*
     686                 :             :  * create_empty_pathtarget
     687                 :             :  *    Create an empty (zero columns, zero cost) PathTarget.
     688                 :             :  */
     689                 :             : PathTarget *
     690                 :     1330883 : create_empty_pathtarget(void)
     691                 :             : {
     692                 :             :     /* This is easy, but we don't want callers to hard-wire this ... */
     693                 :     1330883 :     return makeNode(PathTarget);
     694                 :             : }
     695                 :             : 
     696                 :             : /*
     697                 :             :  * add_column_to_pathtarget
     698                 :             :  *      Append a target column to the PathTarget.
     699                 :             :  *
     700                 :             :  * As with make_pathtarget_from_tlist, we leave it to the caller to update
     701                 :             :  * the cost and width fields.
     702                 :             :  */
     703                 :             : void
     704                 :       66155 : add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
     705                 :             : {
     706                 :             :     /* Updating the exprs list is easy ... */
     707                 :       66155 :     target->exprs = lappend(target->exprs, expr);
     708                 :             :     /* ... the sortgroupref data, a bit less so */
     709         [ +  + ]:       66155 :     if (target->sortgrouprefs)
     710                 :             :     {
     711                 :       21802 :         int         nexprs = list_length(target->exprs);
     712                 :             : 
     713                 :             :         /* This might look inefficient, but actually it's usually cheap */
     714                 :       21802 :         target->sortgrouprefs = (Index *)
     715                 :       21802 :             repalloc(target->sortgrouprefs, nexprs * sizeof(Index));
     716                 :       21802 :         target->sortgrouprefs[nexprs - 1] = sortgroupref;
     717                 :             :     }
     718         [ +  + ]:       44353 :     else if (sortgroupref)
     719                 :             :     {
     720                 :             :         /* Adding sortgroupref labeling to a previously unlabeled target */
     721                 :       16334 :         int         nexprs = list_length(target->exprs);
     722                 :             : 
     723                 :       16334 :         target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index));
     724                 :       16334 :         target->sortgrouprefs[nexprs - 1] = sortgroupref;
     725                 :             :     }
     726                 :             : 
     727                 :             :     /*
     728                 :             :      * Reset has_volatile_expr to UNKNOWN.  We just leave it up to
     729                 :             :      * contain_volatile_functions to set this properly again.  Technically we
     730                 :             :      * could save some effort here and just check the new Expr, but it seems
     731                 :             :      * better to keep the logic for setting this flag in one location rather
     732                 :             :      * than duplicating the logic here.
     733                 :             :      */
     734         [ -  + ]:       66155 :     if (target->has_volatile_expr == VOLATILITY_NOVOLATILE)
     735                 :           0 :         target->has_volatile_expr = VOLATILITY_UNKNOWN;
     736                 :       66155 : }
     737                 :             : 
     738                 :             : /*
     739                 :             :  * add_new_column_to_pathtarget
     740                 :             :  *      Append a target column to the PathTarget, but only if it's not
     741                 :             :  *      equal() to any pre-existing target expression.
     742                 :             :  *
     743                 :             :  * The caller cannot specify a sortgroupref, since it would be unclear how
     744                 :             :  * to merge that with a pre-existing column.
     745                 :             :  *
     746                 :             :  * As with make_pathtarget_from_tlist, we leave it to the caller to update
     747                 :             :  * the cost and width fields.
     748                 :             :  */
     749                 :             : void
     750                 :       43608 : add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
     751                 :             : {
     752         [ +  + ]:       43608 :     if (!list_member(target->exprs, expr))
     753                 :       35603 :         add_column_to_pathtarget(target, expr, 0);
     754                 :       43608 : }
     755                 :             : 
     756                 :             : /*
     757                 :             :  * add_new_columns_to_pathtarget
     758                 :             :  *      Apply add_new_column_to_pathtarget() for each element of the list.
     759                 :             :  */
     760                 :             : void
     761                 :       39808 : add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
     762                 :             : {
     763                 :             :     ListCell   *lc;
     764                 :             : 
     765   [ +  +  +  +  :       79464 :     foreach(lc, exprs)
                   +  + ]
     766                 :             :     {
     767                 :       39656 :         Expr       *expr = (Expr *) lfirst(lc);
     768                 :             : 
     769                 :       39656 :         add_new_column_to_pathtarget(target, expr);
     770                 :             :     }
     771                 :       39808 : }
     772                 :             : 
     773                 :             : /*
     774                 :             :  * apply_pathtarget_labeling_to_tlist
     775                 :             :  *      Apply any sortgrouprefs in the PathTarget to matching tlist entries
     776                 :             :  *
     777                 :             :  * Here, we do not assume that the tlist entries are one-for-one with the
     778                 :             :  * PathTarget.  The intended use of this function is to deal with cases
     779                 :             :  * where createplan.c has decided to use some other tlist and we have
     780                 :             :  * to identify what matches exist.
     781                 :             :  */
     782                 :             : void
     783                 :       14888 : apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
     784                 :             : {
     785                 :             :     int         i;
     786                 :             :     ListCell   *lc;
     787                 :             : 
     788                 :             :     /* Nothing to do if PathTarget has no sortgrouprefs data */
     789         [ +  + ]:       14888 :     if (target->sortgrouprefs == NULL)
     790                 :       13258 :         return;
     791                 :             : 
     792                 :        1630 :     i = 0;
     793   [ +  -  +  +  :        4478 :     foreach(lc, target->exprs)
                   +  + ]
     794                 :             :     {
     795                 :        2848 :         Expr       *expr = (Expr *) lfirst(lc);
     796                 :             :         TargetEntry *tle;
     797                 :             : 
     798         [ +  + ]:        2848 :         if (target->sortgrouprefs[i])
     799                 :             :         {
     800                 :             :             /*
     801                 :             :              * For Vars, use tlist_member_match_var's weakened matching rule;
     802                 :             :              * this allows us to deal with some cases where a set-returning
     803                 :             :              * function has been inlined, so that we now have more knowledge
     804                 :             :              * about what it returns than we did when the original Var was
     805                 :             :              * created.  Otherwise, use regular equal() to find the matching
     806                 :             :              * TLE.  (In current usage, only the Var case is actually needed;
     807                 :             :              * but it seems best to have sane behavior here for non-Vars too.)
     808                 :             :              */
     809   [ +  -  +  - ]:        2277 :             if (expr && IsA(expr, Var))
     810                 :        2277 :                 tle = tlist_member_match_var((Var *) expr, tlist);
     811                 :             :             else
     812                 :           0 :                 tle = tlist_member(expr, tlist);
     813                 :             : 
     814                 :             :             /*
     815                 :             :              * Complain if noplace for the sortgrouprefs label, or if we'd
     816                 :             :              * have to label a column twice.  (The case where it already has
     817                 :             :              * the desired label probably can't happen, but we may as well
     818                 :             :              * allow for it.)
     819                 :             :              */
     820         [ -  + ]:        2277 :             if (!tle)
     821         [ #  # ]:           0 :                 elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
     822         [ +  + ]:        2277 :             if (tle->ressortgroupref != 0 &&
     823         [ -  + ]:          10 :                 tle->ressortgroupref != target->sortgrouprefs[i])
     824         [ #  # ]:           0 :                 elog(ERROR, "targetlist item has multiple sortgroupref labels");
     825                 :             : 
     826                 :        2277 :             tle->ressortgroupref = target->sortgrouprefs[i];
     827                 :             :         }
     828                 :        2848 :         i++;
     829                 :             :     }
     830                 :             : }
     831                 :             : 
     832                 :             : /*
     833                 :             :  * split_pathtarget_at_srfs
     834                 :             :  *      Split given PathTarget into multiple levels to position SRFs safely,
     835                 :             :  *      performing exact matching against input_target.
     836                 :             :  *
     837                 :             :  * This is a wrapper for split_pathtarget_at_srfs_extended() that is used when
     838                 :             :  * both targets are on the same side of the grouping boundary (i.e., both are
     839                 :             :  * pre-grouping or both are post-grouping).  In this case, no special handling
     840                 :             :  * for the grouping nulling bit is required.
     841                 :             :  *
     842                 :             :  * See split_pathtarget_at_srfs_extended() for more details.
     843                 :             :  */
     844                 :             : void
     845                 :       30573 : split_pathtarget_at_srfs(PlannerInfo *root,
     846                 :             :                          PathTarget *target, PathTarget *input_target,
     847                 :             :                          List **targets, List **targets_contain_srfs)
     848                 :             : {
     849                 :       30573 :     split_pathtarget_at_srfs_extended(root, target, input_target,
     850                 :             :                                       targets, targets_contain_srfs,
     851                 :             :                                       false);
     852                 :       30573 : }
     853                 :             : 
     854                 :             : /*
     855                 :             :  * split_pathtarget_at_srfs_grouping
     856                 :             :  *      Split given PathTarget into multiple levels to position SRFs safely,
     857                 :             :  *      ignoring the grouping nulling bit when matching against input_target.
     858                 :             :  *
     859                 :             :  * This variant is used when the targets cross the grouping boundary (i.e.,
     860                 :             :  * target is post-grouping while input_target is pre-grouping).  In this case,
     861                 :             :  * we need to ignore the grouping nulling bit when checking for expression
     862                 :             :  * availability to avoid incorrectly re-evaluating SRFs that have already been
     863                 :             :  * computed in input_target.
     864                 :             :  *
     865                 :             :  * See split_pathtarget_at_srfs_extended() for more details.
     866                 :             :  */
     867                 :             : void
     868                 :       10191 : split_pathtarget_at_srfs_grouping(PlannerInfo *root,
     869                 :             :                                   PathTarget *target, PathTarget *input_target,
     870                 :             :                                   List **targets, List **targets_contain_srfs)
     871                 :             : {
     872                 :       10191 :     split_pathtarget_at_srfs_extended(root, target, input_target,
     873                 :             :                                       targets, targets_contain_srfs,
     874                 :             :                                       true);
     875                 :       10191 : }
     876                 :             : 
     877                 :             : /*
     878                 :             :  * split_pathtarget_at_srfs_extended
     879                 :             :  *      Split given PathTarget into multiple levels to position SRFs safely
     880                 :             :  *
     881                 :             :  * The executor can only handle set-returning functions that appear at the
     882                 :             :  * top level of the targetlist of a ProjectSet plan node.  If we have any SRFs
     883                 :             :  * that are not at top level, we need to split up the evaluation into multiple
     884                 :             :  * plan levels in which each level satisfies this constraint.  This function
     885                 :             :  * creates appropriate PathTarget(s) for each level.
     886                 :             :  *
     887                 :             :  * As an example, consider the tlist expression
     888                 :             :  *      x + srf1(srf2(y + z))
     889                 :             :  * This expression should appear as-is in the top PathTarget, but below that
     890                 :             :  * we must have a PathTarget containing
     891                 :             :  *      x, srf1(srf2(y + z))
     892                 :             :  * and below that, another PathTarget containing
     893                 :             :  *      x, srf2(y + z)
     894                 :             :  * and below that, another PathTarget containing
     895                 :             :  *      x, y, z
     896                 :             :  * When these tlists are processed by setrefs.c, subexpressions that match
     897                 :             :  * output expressions of the next lower tlist will be replaced by Vars,
     898                 :             :  * so that what the executor gets are tlists looking like
     899                 :             :  *      Var1 + Var2
     900                 :             :  *      Var1, srf1(Var2)
     901                 :             :  *      Var1, srf2(Var2 + Var3)
     902                 :             :  *      x, y, z
     903                 :             :  * which satisfy the desired property.
     904                 :             :  *
     905                 :             :  * Another example is
     906                 :             :  *      srf1(x), srf2(srf3(y))
     907                 :             :  * That must appear as-is in the top PathTarget, but below that we need
     908                 :             :  *      srf1(x), srf3(y)
     909                 :             :  * That is, each SRF must be computed at a level corresponding to the nesting
     910                 :             :  * depth of SRFs within its arguments.
     911                 :             :  *
     912                 :             :  * In some cases, a SRF has already been evaluated in some previous plan level
     913                 :             :  * and we shouldn't expand it again (that is, what we see in the target is
     914                 :             :  * already meant as a reference to a lower subexpression).  So, don't expand
     915                 :             :  * any tlist expressions that appear in input_target, if that's not NULL.
     916                 :             :  *
     917                 :             :  * This check requires extra care when processing the grouping target
     918                 :             :  * (indicated by the is_grouping_target flag).  In this case input_target is
     919                 :             :  * pre-grouping while target is post-grouping, so the latter may carry
     920                 :             :  * nullingrels bits from the grouping step that are absent in the former.  We
     921                 :             :  * must ignore those bits to correctly recognize that the tlist expressions are
     922                 :             :  * available in input_target.
     923                 :             :  *
     924                 :             :  * It's also important that we preserve any sortgroupref annotation appearing
     925                 :             :  * in the given target, especially on expressions matching input_target items.
     926                 :             :  *
     927                 :             :  * The outputs of this function are two parallel lists, one a list of
     928                 :             :  * PathTargets and the other an integer list of bool flags indicating
     929                 :             :  * whether the corresponding PathTarget contains any evaluable SRFs.
     930                 :             :  * The lists are given in the order they'd need to be evaluated in, with
     931                 :             :  * the "lowest" PathTarget first.  So the last list entry is always the
     932                 :             :  * originally given PathTarget, and any entries before it indicate evaluation
     933                 :             :  * levels that must be inserted below it.  The first list entry must not
     934                 :             :  * contain any SRFs (other than ones duplicating input_target entries), since
     935                 :             :  * it will typically be attached to a plan node that cannot evaluate SRFs.
     936                 :             :  *
     937                 :             :  * Note: using a list for the flags may seem like overkill, since there
     938                 :             :  * are only a few possible patterns for which levels contain SRFs.
     939                 :             :  * But this representation decouples callers from that knowledge.
     940                 :             :  */
     941                 :             : static void
     942                 :       40764 : split_pathtarget_at_srfs_extended(PlannerInfo *root,
     943                 :             :                                   PathTarget *target, PathTarget *input_target,
     944                 :             :                                   List **targets, List **targets_contain_srfs,
     945                 :             :                                   bool is_grouping_target)
     946                 :             : {
     947                 :             :     split_pathtarget_context context;
     948                 :             :     int         max_depth;
     949                 :             :     bool        need_extra_projection;
     950                 :             :     List       *prev_level_tlist;
     951                 :             :     int         lci;
     952                 :             :     ListCell   *lc,
     953                 :             :                *lc1,
     954                 :             :                *lc2,
     955                 :             :                *lc3;
     956                 :             : 
     957                 :             :     /*
     958                 :             :      * It's not unusual for planner.c to pass us two physically identical
     959                 :             :      * targets, in which case we can conclude without further ado that all
     960                 :             :      * expressions are available from the input.  (The logic below would
     961                 :             :      * arrive at the same conclusion, but much more tediously.)
     962                 :             :      */
     963         [ +  + ]:       40764 :     if (target == input_target)
     964                 :             :     {
     965                 :       30214 :         *targets = list_make1(target);
     966                 :       30214 :         *targets_contain_srfs = list_make1_int(false);
     967                 :       30573 :         return;
     968                 :             :     }
     969                 :             : 
     970                 :             :     /*
     971                 :             :      * Pass 'root', the is_grouping_target flag, and any input_target exprs
     972                 :             :      * down to split_pathtarget_walker().
     973                 :             :      */
     974                 :       10550 :     context.root = root;
     975                 :       10550 :     context.is_grouping_target = is_grouping_target;
     976         [ +  + ]:       10550 :     context.input_target_exprs = input_target ? input_target->exprs : NIL;
     977                 :             : 
     978                 :             :     /*
     979                 :             :      * Initialize with empty level-zero lists, and no levels after that.
     980                 :             :      * (Note: we could dispense with representing level zero explicitly, since
     981                 :             :      * it will never receive any SRFs, but then we'd have to special-case that
     982                 :             :      * level when we get to building result PathTargets.  Level zero describes
     983                 :             :      * the SRF-free PathTarget that will be given to the input plan node.)
     984                 :             :      */
     985                 :       10550 :     context.level_srfs = list_make1(NIL);
     986                 :       10550 :     context.level_input_vars = list_make1(NIL);
     987                 :       10550 :     context.level_input_srfs = list_make1(NIL);
     988                 :             : 
     989                 :             :     /* Initialize data we'll accumulate across all the target expressions */
     990                 :       10550 :     context.current_input_vars = NIL;
     991                 :       10550 :     context.current_input_srfs = NIL;
     992                 :       10550 :     max_depth = 0;
     993                 :       10550 :     need_extra_projection = false;
     994                 :             : 
     995                 :             :     /* Scan each expression in the PathTarget looking for SRFs */
     996                 :       10550 :     lci = 0;
     997   [ +  -  +  +  :       24217 :     foreach(lc, target->exprs)
                   +  + ]
     998                 :             :     {
     999                 :       13667 :         Node       *node = (Node *) lfirst(lc);
    1000                 :             : 
    1001                 :             :         /* Tell split_pathtarget_walker about this expr's sortgroupref */
    1002         [ +  + ]:       13667 :         context.current_sgref = get_pathtarget_sortgroupref(target, lci);
    1003                 :       13667 :         lci++;
    1004                 :             : 
    1005                 :             :         /*
    1006                 :             :          * Find all SRFs and Vars (and Var-like nodes) in this expression, and
    1007                 :             :          * enter them into appropriate lists within the context struct.
    1008                 :             :          */
    1009                 :       13667 :         context.current_depth = 0;
    1010                 :       13667 :         split_pathtarget_walker(node, &context);
    1011                 :             : 
    1012                 :             :         /* An expression containing no SRFs is of no further interest */
    1013         [ +  + ]:       13667 :         if (context.current_depth == 0)
    1014                 :        2177 :             continue;
    1015                 :             : 
    1016                 :             :         /*
    1017                 :             :          * Track max SRF nesting depth over the whole PathTarget.  Also, if
    1018                 :             :          * this expression establishes a new max depth, we no longer care
    1019                 :             :          * whether previous expressions contained nested SRFs; we can handle
    1020                 :             :          * any required projection for them in the final ProjectSet node.
    1021                 :             :          */
    1022         [ +  + ]:       11490 :         if (max_depth < context.current_depth)
    1023                 :             :         {
    1024                 :       10201 :             max_depth = context.current_depth;
    1025                 :       10201 :             need_extra_projection = false;
    1026                 :             :         }
    1027                 :             : 
    1028                 :             :         /*
    1029                 :             :          * If any maximum-depth SRF is not at the top level of its expression,
    1030                 :             :          * we'll need an extra Result node to compute the top-level scalar
    1031                 :             :          * expression.
    1032                 :             :          */
    1033   [ +  +  +  +  :       11490 :         if (max_depth == context.current_depth && !IS_SRF_CALL(node))
          +  +  +  +  +  
                      + ]
    1034                 :        1602 :             need_extra_projection = true;
    1035                 :             :     }
    1036                 :             : 
    1037                 :             :     /*
    1038                 :             :      * If we found no SRFs needing evaluation (maybe they were all present in
    1039                 :             :      * input_target, or maybe they were all removed by const-simplification),
    1040                 :             :      * then no ProjectSet is needed; fall out.
    1041                 :             :      */
    1042         [ +  + ]:       10550 :     if (max_depth == 0)
    1043                 :             :     {
    1044                 :         359 :         *targets = list_make1(target);
    1045                 :         359 :         *targets_contain_srfs = list_make1_int(false);
    1046                 :         359 :         return;
    1047                 :             :     }
    1048                 :             : 
    1049                 :             :     /*
    1050                 :             :      * The Vars and SRF outputs needed at top level can be added to the last
    1051                 :             :      * level_input lists if we don't need an extra projection step.  If we do
    1052                 :             :      * need one, add a SRF-free level to the lists.
    1053                 :             :      */
    1054         [ +  + ]:       10191 :     if (need_extra_projection)
    1055                 :             :     {
    1056                 :         725 :         context.level_srfs = lappend(context.level_srfs, NIL);
    1057                 :        1450 :         context.level_input_vars = lappend(context.level_input_vars,
    1058                 :         725 :                                            context.current_input_vars);
    1059                 :         725 :         context.level_input_srfs = lappend(context.level_input_srfs,
    1060                 :         725 :                                            context.current_input_srfs);
    1061                 :             :     }
    1062                 :             :     else
    1063                 :             :     {
    1064                 :        9466 :         lc = list_nth_cell(context.level_input_vars, max_depth);
    1065                 :        9466 :         lfirst(lc) = list_concat(lfirst(lc), context.current_input_vars);
    1066                 :        9466 :         lc = list_nth_cell(context.level_input_srfs, max_depth);
    1067                 :        9466 :         lfirst(lc) = list_concat(lfirst(lc), context.current_input_srfs);
    1068                 :             :     }
    1069                 :             : 
    1070                 :             :     /*
    1071                 :             :      * Now construct the output PathTargets.  The original target can be used
    1072                 :             :      * as-is for the last one, but we need to construct a new SRF-free target
    1073                 :             :      * representing what the preceding plan node has to emit, as well as a
    1074                 :             :      * target for each intermediate ProjectSet node.
    1075                 :             :      */
    1076                 :       10191 :     *targets = *targets_contain_srfs = NIL;
    1077                 :       10191 :     prev_level_tlist = NIL;
    1078                 :             : 
    1079   [ +  -  +  +  :       31348 :     forthree(lc1, context.level_srfs,
          +  -  +  +  +  
          -  +  +  +  +  
          +  -  +  -  +  
                      + ]
    1080                 :             :              lc2, context.level_input_vars,
    1081                 :             :              lc3, context.level_input_srfs)
    1082                 :             :     {
    1083                 :       21157 :         List       *level_srfs = (List *) lfirst(lc1);
    1084                 :             :         PathTarget *ntarget;
    1085                 :             : 
    1086         [ +  + ]:       21157 :         if (lnext(context.level_srfs, lc1) == NULL)
    1087                 :             :         {
    1088                 :       10191 :             ntarget = target;
    1089                 :             :         }
    1090                 :             :         else
    1091                 :             :         {
    1092                 :       10966 :             ntarget = create_empty_pathtarget();
    1093                 :             : 
    1094                 :             :             /*
    1095                 :             :              * This target should actually evaluate any SRFs of the current
    1096                 :             :              * level, and it needs to propagate forward any Vars needed by
    1097                 :             :              * later levels, as well as SRFs computed earlier and needed by
    1098                 :             :              * later levels.
    1099                 :             :              */
    1100                 :       10966 :             add_sp_items_to_pathtarget(ntarget, level_srfs);
    1101   [ +  -  +  +  :       22737 :             for_each_cell(lc, context.level_input_vars,
                   +  + ]
    1102                 :             :                           lnext(context.level_input_vars, lc2))
    1103                 :             :             {
    1104                 :       11771 :                 List       *input_vars = (List *) lfirst(lc);
    1105                 :             : 
    1106                 :       11771 :                 add_sp_items_to_pathtarget(ntarget, input_vars);
    1107                 :             :             }
    1108   [ +  -  +  +  :       22737 :             for_each_cell(lc, context.level_input_srfs,
                   +  + ]
    1109                 :             :                           lnext(context.level_input_srfs, lc3))
    1110                 :             :             {
    1111                 :       11771 :                 List       *input_srfs = (List *) lfirst(lc);
    1112                 :             :                 ListCell   *lcx;
    1113                 :             : 
    1114   [ +  +  +  +  :       25158 :                 foreach(lcx, input_srfs)
                   +  + ]
    1115                 :             :                 {
    1116                 :       13387 :                     split_pathtarget_item *item = lfirst(lcx);
    1117                 :             : 
    1118         [ +  + ]:       13387 :                     if (list_member(prev_level_tlist, item->expr))
    1119                 :          30 :                         add_sp_item_to_pathtarget(ntarget, item);
    1120                 :             :                 }
    1121                 :             :             }
    1122                 :       10966 :             set_pathtarget_cost_width(root, ntarget);
    1123                 :             :         }
    1124                 :             : 
    1125                 :             :         /*
    1126                 :             :          * Add current target and does-it-compute-SRFs flag to output lists.
    1127                 :             :          */
    1128                 :       21157 :         *targets = lappend(*targets, ntarget);
    1129                 :       21157 :         *targets_contain_srfs = lappend_int(*targets_contain_srfs,
    1130                 :             :                                             (level_srfs != NIL));
    1131                 :             : 
    1132                 :             :         /* Remember this level's output for next pass */
    1133                 :       21157 :         prev_level_tlist = ntarget->exprs;
    1134                 :             :     }
    1135                 :             : }
    1136                 :             : 
    1137                 :             : /*
    1138                 :             :  * Recursively examine expressions for split_pathtarget_at_srfs.
    1139                 :             :  *
    1140                 :             :  * Note we make no effort here to prevent duplicate entries in the output
    1141                 :             :  * lists.  Duplicates will be gotten rid of later.
    1142                 :             :  */
    1143                 :             : static bool
    1144                 :       44065 : split_pathtarget_walker(Node *node, split_pathtarget_context *context)
    1145                 :             : {
    1146                 :       44065 :     Node       *sanitized_node = node;
    1147                 :             : 
    1148         [ +  + ]:       44065 :     if (node == NULL)
    1149                 :          61 :         return false;
    1150                 :             : 
    1151                 :             :     /*
    1152                 :             :      * If we are crossing the grouping boundary (post-grouping target vs
    1153                 :             :      * pre-grouping input_target), we must ignore the grouping nulling bit to
    1154                 :             :      * correctly check if the subexpression is available in input_target. This
    1155                 :             :      * aligns with the matching logic in set_upper_references().
    1156                 :             :      */
    1157         [ +  + ]:       44004 :     if (context->is_grouping_target &&
    1158         [ +  + ]:        2518 :         context->root->parse->hasGroupRTE &&
    1159         [ +  + ]:         495 :         context->root->parse->groupingSets != NIL)
    1160                 :             :     {
    1161                 :             :         sanitized_node =
    1162                 :         195 :             remove_nulling_relids(node,
    1163                 :         195 :                                   bms_make_singleton(context->root->group_rtindex),
    1164                 :             :                                   NULL);
    1165                 :             :     }
    1166                 :             : 
    1167                 :             :     /*
    1168                 :             :      * A subexpression that matches an expression already computed in
    1169                 :             :      * input_target can be treated like a Var (which indeed it will be after
    1170                 :             :      * setrefs.c gets done with it), even if it's actually a SRF.  Record it
    1171                 :             :      * as being needed for the current expression, and ignore any
    1172                 :             :      * substructure.  (Note in particular that this preserves the identity of
    1173                 :             :      * any expressions that appear as sortgrouprefs in input_target.)
    1174                 :             :      */
    1175         [ +  + ]:       44004 :     if (list_member(context->input_target_exprs, sanitized_node))
    1176                 :             :     {
    1177                 :         350 :         split_pathtarget_item *item = palloc_object(split_pathtarget_item);
    1178                 :             : 
    1179                 :         350 :         item->expr = node;
    1180                 :         350 :         item->sortgroupref = context->current_sgref;
    1181                 :         350 :         context->current_input_vars = lappend(context->current_input_vars,
    1182                 :             :                                               item);
    1183                 :         350 :         return false;
    1184                 :             :     }
    1185                 :             : 
    1186                 :             :     /*
    1187                 :             :      * Vars and Var-like constructs are expected to be gotten from the input,
    1188                 :             :      * too.  We assume that these constructs cannot contain any SRFs (if one
    1189                 :             :      * does, there will be an executor failure from a misplaced SRF).
    1190                 :             :      */
    1191         [ +  + ]:       43654 :     if (IsA(node, Var) ||
    1192         [ +  + ]:       40860 :         IsA(node, PlaceHolderVar) ||
    1193         [ +  + ]:       40820 :         IsA(node, Aggref) ||
    1194         [ +  - ]:       40024 :         IsA(node, GroupingFunc) ||
    1195         [ +  + ]:       40024 :         IsA(node, WindowFunc))
    1196                 :             :     {
    1197                 :        3640 :         split_pathtarget_item *item = palloc_object(split_pathtarget_item);
    1198                 :             : 
    1199                 :        3640 :         item->expr = node;
    1200                 :        3640 :         item->sortgroupref = context->current_sgref;
    1201                 :        3640 :         context->current_input_vars = lappend(context->current_input_vars,
    1202                 :             :                                               item);
    1203                 :        3640 :         return false;
    1204                 :             :     }
    1205                 :             : 
    1206                 :             :     /*
    1207                 :             :      * If it's a SRF, recursively examine its inputs, determine its level, and
    1208                 :             :      * make appropriate entries in the output lists.
    1209                 :             :      */
    1210   [ +  +  +  +  :       40014 :     if (IS_SRF_CALL(node))
             +  +  +  + ]
    1211                 :             :     {
    1212                 :       11545 :         split_pathtarget_item *item = palloc_object(split_pathtarget_item);
    1213                 :       11545 :         List       *save_input_vars = context->current_input_vars;
    1214                 :       11545 :         List       *save_input_srfs = context->current_input_srfs;
    1215                 :       11545 :         int         save_current_depth = context->current_depth;
    1216                 :             :         int         srf_depth;
    1217                 :             :         ListCell   *lc;
    1218                 :             : 
    1219                 :       11545 :         item->expr = node;
    1220                 :       11545 :         item->sortgroupref = context->current_sgref;
    1221                 :             : 
    1222                 :       11545 :         context->current_input_vars = NIL;
    1223                 :       11545 :         context->current_input_srfs = NIL;
    1224                 :       11545 :         context->current_depth = 0;
    1225                 :       11545 :         context->current_sgref = 0; /* subexpressions are not sortgroup items */
    1226                 :             : 
    1227                 :       11545 :         (void) expression_tree_walker(node, split_pathtarget_walker, context);
    1228                 :             : 
    1229                 :             :         /* Depth is one more than any SRF below it */
    1230                 :       11545 :         srf_depth = context->current_depth + 1;
    1231                 :             : 
    1232                 :             :         /* If new record depth, initialize another level of output lists */
    1233         [ +  + ]:       11545 :         if (srf_depth >= list_length(context->level_srfs))
    1234                 :             :         {
    1235                 :       10241 :             context->level_srfs = lappend(context->level_srfs, NIL);
    1236                 :       10241 :             context->level_input_vars = lappend(context->level_input_vars, NIL);
    1237                 :       10241 :             context->level_input_srfs = lappend(context->level_input_srfs, NIL);
    1238                 :             :         }
    1239                 :             : 
    1240                 :             :         /* Record this SRF as needing to be evaluated at appropriate level */
    1241                 :       11545 :         lc = list_nth_cell(context->level_srfs, srf_depth);
    1242                 :       11545 :         lfirst(lc) = lappend(lfirst(lc), item);
    1243                 :             : 
    1244                 :             :         /* Record its inputs as being needed at the same level */
    1245                 :       11545 :         lc = list_nth_cell(context->level_input_vars, srf_depth);
    1246                 :       11545 :         lfirst(lc) = list_concat(lfirst(lc), context->current_input_vars);
    1247                 :       11545 :         lc = list_nth_cell(context->level_input_srfs, srf_depth);
    1248                 :       11545 :         lfirst(lc) = list_concat(lfirst(lc), context->current_input_srfs);
    1249                 :             : 
    1250                 :             :         /*
    1251                 :             :          * Restore caller-level state and update it for presence of this SRF.
    1252                 :             :          * Notice we report the SRF itself as being needed for evaluation of
    1253                 :             :          * surrounding expression.
    1254                 :             :          */
    1255                 :       11545 :         context->current_input_vars = save_input_vars;
    1256                 :       11545 :         context->current_input_srfs = lappend(save_input_srfs, item);
    1257                 :       11545 :         context->current_depth = Max(save_current_depth, srf_depth);
    1258                 :             : 
    1259                 :             :         /* We're done here */
    1260                 :       11545 :         return false;
    1261                 :             :     }
    1262                 :             : 
    1263                 :             :     /*
    1264                 :             :      * Otherwise, the node is a scalar (non-set) expression, so recurse to
    1265                 :             :      * examine its inputs.
    1266                 :             :      */
    1267                 :       28469 :     context->current_sgref = 0; /* subexpressions are not sortgroup items */
    1268                 :       28469 :     return expression_tree_walker(node, split_pathtarget_walker, context);
    1269                 :             : }
    1270                 :             : 
    1271                 :             : /*
    1272                 :             :  * Add a split_pathtarget_item to the PathTarget, unless a matching item is
    1273                 :             :  * already present.  This is like add_new_column_to_pathtarget, but allows
    1274                 :             :  * for sortgrouprefs to be handled.  An item having zero sortgroupref can
    1275                 :             :  * be merged with one that has a sortgroupref, acquiring the latter's
    1276                 :             :  * sortgroupref.
    1277                 :             :  *
    1278                 :             :  * Note that we don't worry about possibly adding duplicate sortgrouprefs
    1279                 :             :  * to the PathTarget.  That would be bad, but it should be impossible unless
    1280                 :             :  * the target passed to split_pathtarget_at_srfs already had duplicates.
    1281                 :             :  * As long as it didn't, we can have at most one split_pathtarget_item with
    1282                 :             :  * any particular nonzero sortgroupref.
    1283                 :             :  */
    1284                 :             : static void
    1285                 :        5583 : add_sp_item_to_pathtarget(PathTarget *target, split_pathtarget_item *item)
    1286                 :             : {
    1287                 :             :     int         lci;
    1288                 :             :     ListCell   *lc;
    1289                 :             : 
    1290                 :             :     /*
    1291                 :             :      * Look for a pre-existing entry that is equal() and does not have a
    1292                 :             :      * conflicting sortgroupref already.
    1293                 :             :      */
    1294                 :        5583 :     lci = 0;
    1295   [ +  +  +  +  :        8435 :     foreach(lc, target->exprs)
                   +  + ]
    1296                 :             :     {
    1297                 :        5096 :         Node       *node = (Node *) lfirst(lc);
    1298         [ +  + ]:        5096 :         Index       sgref = get_pathtarget_sortgroupref(target, lci);
    1299                 :             : 
    1300         [ +  + ]:        5096 :         if ((item->sortgroupref == sgref ||
    1301   [ +  +  +  + ]:         250 :              item->sortgroupref == 0 ||
    1302         [ +  + ]:        5051 :              sgref == 0) &&
    1303                 :        5051 :             equal(item->expr, node))
    1304                 :             :         {
    1305                 :             :             /* Found a match.  Assign item's sortgroupref if it has one. */
    1306         [ +  + ]:        2244 :             if (item->sortgroupref)
    1307                 :             :             {
    1308         [ +  + ]:          20 :                 if (target->sortgrouprefs == NULL)
    1309                 :             :                 {
    1310                 :          10 :                     target->sortgrouprefs = (Index *)
    1311                 :          10 :                         palloc0(list_length(target->exprs) * sizeof(Index));
    1312                 :             :                 }
    1313                 :          20 :                 target->sortgrouprefs[lci] = item->sortgroupref;
    1314                 :             :             }
    1315                 :        2244 :             return;
    1316                 :             :         }
    1317                 :        2852 :         lci++;
    1318                 :             :     }
    1319                 :             : 
    1320                 :             :     /*
    1321                 :             :      * No match, so add item to PathTarget.  Copy the expr for safety.
    1322                 :             :      */
    1323                 :        3339 :     add_column_to_pathtarget(target, (Expr *) copyObject(item->expr),
    1324                 :             :                              item->sortgroupref);
    1325                 :             : }
    1326                 :             : 
    1327                 :             : /*
    1328                 :             :  * Apply add_sp_item_to_pathtarget to each element of list.
    1329                 :             :  */
    1330                 :             : static void
    1331                 :       22737 : add_sp_items_to_pathtarget(PathTarget *target, List *items)
    1332                 :             : {
    1333                 :             :     ListCell   *lc;
    1334                 :             : 
    1335   [ +  +  +  +  :       28290 :     foreach(lc, items)
                   +  + ]
    1336                 :             :     {
    1337                 :        5553 :         split_pathtarget_item *item = lfirst(lc);
    1338                 :             : 
    1339                 :        5553 :         add_sp_item_to_pathtarget(target, item);
    1340                 :             :     }
    1341                 :       22737 : }
        

Generated by: LCOV version 2.0-1