LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/util - tlist.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 95.7 % 369 353 16 353
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 32 32 32
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

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