LCOV - code coverage report
Current view: top level - src/backend/optimizer/util - tlist.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 95.8 % 380 364
Test Date: 2026-02-17 17:20:33 Functions: 100.0 % 34 34
Legend: Lines:     hit not hit

            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        26961 : tlist_member(Expr *node, List *targetlist)
      89              : {
      90              :     ListCell   *temp;
      91              : 
      92        97136 :     foreach(temp, targetlist)
      93              :     {
      94        77182 :         TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
      95              : 
      96        77182 :         if (equal(node, tlentry->expr))
      97         7007 :             return tlentry;
      98              :     }
      99        19954 :     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         1365 : tlist_member_match_var(Var *var, List *targetlist)
     112              : {
     113              :     ListCell   *temp;
     114              : 
     115         3781 :     foreach(temp, targetlist)
     116              :     {
     117         3781 :         TargetEntry *tlentry = (TargetEntry *) lfirst(temp);
     118         3781 :         Var        *tlvar = (Var *) tlentry->expr;
     119              : 
     120         3781 :         if (!tlvar || !IsA(tlvar, Var))
     121            0 :             continue;
     122         3781 :         if (var->varno == tlvar->varno &&
     123         3781 :             var->varattno == tlvar->varattno &&
     124         1365 :             var->varlevelsup == tlvar->varlevelsup &&
     125         1365 :             var->vartype == tlvar->vartype)
     126         1365 :             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          859 : add_to_flat_tlist(List *tlist, List *exprs)
     142              : {
     143          859 :     int         next_resno = list_length(tlist) + 1;
     144              :     ListCell   *lc;
     145              : 
     146         4698 :     foreach(lc, exprs)
     147              :     {
     148         3839 :         Expr       *expr = (Expr *) lfirst(lc);
     149              : 
     150         3839 :         if (!tlist_member(expr, tlist))
     151              :         {
     152              :             TargetEntry *tle;
     153              : 
     154         3819 :             tle = makeTargetEntry(copyObject(expr), /* copy needed?? */
     155         3819 :                                   next_resno++,
     156              :                                   NULL,
     157              :                                   false);
     158         3819 :             tlist = lappend(tlist, tle);
     159              :         }
     160              :     }
     161          859 :     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          689 : get_tlist_exprs(List *tlist, bool includeJunk)
     173              : {
     174          689 :     List       *result = NIL;
     175              :     ListCell   *l;
     176              : 
     177         3012 :     foreach(l, tlist)
     178              :     {
     179         2323 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     180              : 
     181         2323 :         if (tle->resjunk && !includeJunk)
     182            0 :             continue;
     183              : 
     184         2323 :         result = lappend(result, tle->expr);
     185              :     }
     186          689 :     return result;
     187              : }
     188              : 
     189              : 
     190              : /*
     191              :  * count_nonjunk_tlist_entries
     192              :  *      What it says ...
     193              :  */
     194              : int
     195        18140 : count_nonjunk_tlist_entries(List *tlist)
     196              : {
     197        18140 :     int         len = 0;
     198              :     ListCell   *l;
     199              : 
     200        37491 :     foreach(l, tlist)
     201              :     {
     202        19351 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     203              : 
     204        19351 :         if (!tle->resjunk)
     205        18220 :             len++;
     206              :     }
     207        18140 :     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         1018 : tlist_same_exprs(List *tlist1, List *tlist2)
     228              : {
     229              :     ListCell   *lc1,
     230              :                *lc2;
     231              : 
     232         1018 :     if (list_length(tlist1) != list_length(tlist2))
     233          447 :         return false;           /* not same length, so can't match */
     234              : 
     235          765 :     forboth(lc1, tlist1, lc2, tlist2)
     236              :     {
     237          679 :         TargetEntry *tle1 = (TargetEntry *) lfirst(lc1);
     238          679 :         TargetEntry *tle2 = (TargetEntry *) lfirst(lc2);
     239              : 
     240          679 :         if (!equal(tle1->expr, tle2->expr))
     241          485 :             return false;
     242              :     }
     243              : 
     244           86 :     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        11618 : tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
     258              : {
     259              :     ListCell   *l;
     260        11618 :     ListCell   *curColType = list_head(colTypes);
     261              : 
     262        49883 :     foreach(l, tlist)
     263              :     {
     264        38652 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     265              : 
     266        38652 :         if (tle->resjunk)
     267              :         {
     268            6 :             if (!junkOK)
     269          387 :                 return false;
     270              :         }
     271              :         else
     272              :         {
     273        38646 :             if (curColType == NULL)
     274            0 :                 return false;   /* tlist longer than colTypes */
     275        38646 :             if (exprType((Node *) tle->expr) != lfirst_oid(curColType))
     276          387 :                 return false;
     277        38259 :             curColType = lnext(colTypes, curColType);
     278              :         }
     279              :     }
     280        11231 :     if (curColType != NULL)
     281            0 :         return false;           /* tlist shorter than colTypes */
     282        11231 :     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         2715 : tlist_same_collations(List *tlist, List *colCollations, bool junkOK)
     292              : {
     293              :     ListCell   *l;
     294         2715 :     ListCell   *curColColl = list_head(colCollations);
     295              : 
     296        10611 :     foreach(l, tlist)
     297              :     {
     298         7896 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     299              : 
     300         7896 :         if (tle->resjunk)
     301              :         {
     302            0 :             if (!junkOK)
     303            0 :                 return false;
     304              :         }
     305              :         else
     306              :         {
     307         7896 :             if (curColColl == NULL)
     308            0 :                 return false;   /* tlist longer than colCollations */
     309         7896 :             if (exprCollation((Node *) tle->expr) != lfirst_oid(curColColl))
     310            0 :                 return false;
     311         7896 :             curColColl = lnext(colCollations, curColColl);
     312              :         }
     313              :     }
     314         2715 :     if (curColColl != NULL)
     315            0 :         return false;           /* tlist shorter than colCollations */
     316         2715 :     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       287318 : 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      1043153 :     forboth(ld, dest_tlist, ls, src_tlist)
     334              :     {
     335       755835 :         TargetEntry *dest_tle = (TargetEntry *) lfirst(ld);
     336       755835 :         TargetEntry *src_tle = (TargetEntry *) lfirst(ls);
     337              : 
     338              :         Assert(dest_tle->resno == src_tle->resno);
     339       755835 :         dest_tle->resname = src_tle->resname;
     340       755835 :         dest_tle->ressortgroupref = src_tle->ressortgroupref;
     341       755835 :         dest_tle->resorigtbl = src_tle->resorigtbl;
     342       755835 :         dest_tle->resorigcol = src_tle->resorigcol;
     343       755835 :         dest_tle->resjunk = src_tle->resjunk;
     344              :     }
     345       287318 : }
     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       139269 : get_sortgroupref_tle(Index sortref, List *targetList)
     355              : {
     356              :     ListCell   *l;
     357              : 
     358       353135 :     foreach(l, targetList)
     359              :     {
     360       353135 :         TargetEntry *tle = (TargetEntry *) lfirst(l);
     361              : 
     362       353135 :         if (tle->ressortgroupref == sortref)
     363       139269 :             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       138391 : get_sortgroupclause_tle(SortGroupClause *sgClause,
     377              :                         List *targetList)
     378              : {
     379       138391 :     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       112866 : get_sortgroupclause_expr(SortGroupClause *sgClause, List *targetList)
     389              : {
     390       112866 :     TargetEntry *tle = get_sortgroupclause_tle(sgClause, targetList);
     391              : 
     392       112866 :     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         9150 : get_sortgrouplist_exprs(List *sgClauses, List *targetList)
     402              : {
     403         9150 :     List       *result = NIL;
     404              :     ListCell   *l;
     405              : 
     406        21407 :     foreach(l, sgClauses)
     407              :     {
     408        12257 :         SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
     409              :         Node       *sortexpr;
     410              : 
     411        12257 :         sortexpr = get_sortgroupclause_expr(sortcl, targetList);
     412        12257 :         result = lappend(result, sortexpr);
     413              :     }
     414         9150 :     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         5579 : get_sortgroupref_clause(Index sortref, List *clauses)
     432              : {
     433              :     ListCell   *l;
     434              : 
     435         8662 :     foreach(l, clauses)
     436              :     {
     437         8662 :         SortGroupClause *cl = (SortGroupClause *) lfirst(l);
     438              : 
     439         8662 :         if (cl->tleSortGroupRef == sortref)
     440         5579 :             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         7824 : get_sortgroupref_clause_noerr(Index sortref, List *clauses)
     453              : {
     454              :     ListCell   *l;
     455              : 
     456        13324 :     foreach(l, clauses)
     457              :     {
     458        11363 :         SortGroupClause *cl = (SortGroupClause *) lfirst(l);
     459              : 
     460        11363 :         if (cl->tleSortGroupRef == sortref)
     461         5863 :             return cl;
     462              :     }
     463              : 
     464         1961 :     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        25482 : extract_grouping_ops(List *groupClause)
     473              : {
     474        25482 :     int         numCols = list_length(groupClause);
     475        25482 :     int         colno = 0;
     476              :     Oid        *groupOperators;
     477              :     ListCell   *glitem;
     478              : 
     479        25482 :     groupOperators = palloc_array(Oid, numCols);
     480              : 
     481        32784 :     foreach(glitem, groupClause)
     482              :     {
     483         7302 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     484              : 
     485         7302 :         groupOperators[colno] = groupcl->eqop;
     486              :         Assert(OidIsValid(groupOperators[colno]));
     487         7302 :         colno++;
     488              :     }
     489              : 
     490        25482 :     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        25482 : extract_grouping_collations(List *groupClause, List *tlist)
     499              : {
     500        25482 :     int         numCols = list_length(groupClause);
     501        25482 :     int         colno = 0;
     502              :     Oid        *grpCollations;
     503              :     ListCell   *glitem;
     504              : 
     505        25482 :     grpCollations = palloc_array(Oid, numCols);
     506              : 
     507        32784 :     foreach(glitem, groupClause)
     508              :     {
     509         7302 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     510         7302 :         TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
     511              : 
     512         7302 :         grpCollations[colno++] = exprCollation((Node *) tle->expr);
     513              :     }
     514              : 
     515        25482 :     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        24444 : extract_grouping_cols(List *groupClause, List *tlist)
     524              : {
     525              :     AttrNumber *grpColIdx;
     526        24444 :     int         numCols = list_length(groupClause);
     527        24444 :     int         colno = 0;
     528              :     ListCell   *glitem;
     529              : 
     530        24444 :     grpColIdx = palloc_array(AttrNumber, numCols);
     531              : 
     532        30416 :     foreach(glitem, groupClause)
     533              :     {
     534         5972 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     535         5972 :         TargetEntry *tle = get_sortgroupclause_tle(groupcl, tlist);
     536              : 
     537         5972 :         grpColIdx[colno++] = tle->resno;
     538              :     }
     539              : 
     540        24444 :     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        35191 : grouping_is_sortable(List *groupClause)
     550              : {
     551              :     ListCell   *glitem;
     552              : 
     553        57120 :     foreach(glitem, groupClause)
     554              :     {
     555        22039 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     556              : 
     557        22039 :         if (!OidIsValid(groupcl->sortop))
     558          110 :             return false;
     559              :     }
     560        35081 :     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         6350 : grouping_is_hashable(List *groupClause)
     570              : {
     571              :     ListCell   *glitem;
     572              : 
     573        19065 :     foreach(glitem, groupClause)
     574              :     {
     575        12786 :         SortGroupClause *groupcl = (SortGroupClause *) lfirst(glitem);
     576              : 
     577        12786 :         if (!groupcl->hashable)
     578           71 :             return false;
     579              :     }
     580         6279 :     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       285757 : make_pathtarget_from_tlist(List *tlist)
     601              : {
     602       285757 :     PathTarget *target = makeNode(PathTarget);
     603              :     int         i;
     604              :     ListCell   *lc;
     605              : 
     606       285757 :     target->sortgrouprefs = (Index *) palloc(list_length(tlist) * sizeof(Index));
     607              : 
     608       285757 :     i = 0;
     609      1040040 :     foreach(lc, tlist)
     610              :     {
     611       754283 :         TargetEntry *tle = (TargetEntry *) lfirst(lc);
     612              : 
     613       754283 :         target->exprs = lappend(target->exprs, tle->expr);
     614       754283 :         target->sortgrouprefs[i] = tle->ressortgroupref;
     615       754283 :         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       285757 :     target->has_volatile_expr = VOLATILITY_UNKNOWN;
     624              : 
     625       285757 :     return target;
     626              : }
     627              : 
     628              : /*
     629              :  * make_tlist_from_pathtarget
     630              :  *    Construct a targetlist from a PathTarget.
     631              :  */
     632              : List *
     633        35301 : make_tlist_from_pathtarget(PathTarget *target)
     634              : {
     635        35301 :     List       *tlist = NIL;
     636              :     int         i;
     637              :     ListCell   *lc;
     638              : 
     639        35301 :     i = 0;
     640       153850 :     foreach(lc, target->exprs)
     641              :     {
     642       118549 :         Expr       *expr = (Expr *) lfirst(lc);
     643              :         TargetEntry *tle;
     644              : 
     645       118549 :         tle = makeTargetEntry(expr,
     646       118549 :                               i + 1,
     647              :                               NULL,
     648              :                               false);
     649       118549 :         if (target->sortgrouprefs)
     650       115041 :             tle->ressortgroupref = target->sortgrouprefs[i];
     651       118549 :         tlist = lappend(tlist, tle);
     652       118549 :         i++;
     653              :     }
     654              : 
     655        35301 :     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        14012 : copy_pathtarget(PathTarget *src)
     667              : {
     668        14012 :     PathTarget *dst = makeNode(PathTarget);
     669              : 
     670              :     /* Copy scalar fields */
     671        14012 :     memcpy(dst, src, sizeof(PathTarget));
     672              :     /* Shallow-copy the expression list */
     673        14012 :     dst->exprs = list_copy(src->exprs);
     674              :     /* Duplicate sortgrouprefs if any (if not, the memcpy handled this) */
     675        14012 :     if (src->sortgrouprefs)
     676              :     {
     677        13373 :         Size        nbytes = list_length(src->exprs) * sizeof(Index);
     678              : 
     679        13373 :         dst->sortgrouprefs = (Index *) palloc(nbytes);
     680        13373 :         memcpy(dst->sortgrouprefs, src->sortgrouprefs, nbytes);
     681              :     }
     682        14012 :     return dst;
     683              : }
     684              : 
     685              : /*
     686              :  * create_empty_pathtarget
     687              :  *    Create an empty (zero columns, zero cost) PathTarget.
     688              :  */
     689              : PathTarget *
     690       911301 : create_empty_pathtarget(void)
     691              : {
     692              :     /* This is easy, but we don't want callers to hard-wire this ... */
     693       911301 :     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        41063 : add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref)
     705              : {
     706              :     /* Updating the exprs list is easy ... */
     707        41063 :     target->exprs = lappend(target->exprs, expr);
     708              :     /* ... the sortgroupref data, a bit less so */
     709        41063 :     if (target->sortgrouprefs)
     710              :     {
     711        13209 :         int         nexprs = list_length(target->exprs);
     712              : 
     713              :         /* This might look inefficient, but actually it's usually cheap */
     714        13209 :         target->sortgrouprefs = (Index *)
     715        13209 :             repalloc(target->sortgrouprefs, nexprs * sizeof(Index));
     716        13209 :         target->sortgrouprefs[nexprs - 1] = sortgroupref;
     717              :     }
     718        27854 :     else if (sortgroupref)
     719              :     {
     720              :         /* Adding sortgroupref labeling to a previously unlabeled target */
     721         9819 :         int         nexprs = list_length(target->exprs);
     722              : 
     723         9819 :         target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index));
     724         9819 :         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        41063 :     if (target->has_volatile_expr == VOLATILITY_NOVOLATILE)
     735            0 :         target->has_volatile_expr = VOLATILITY_UNKNOWN;
     736        41063 : }
     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        27558 : add_new_column_to_pathtarget(PathTarget *target, Expr *expr)
     751              : {
     752        27558 :     if (!list_member(target->exprs, expr))
     753        22429 :         add_column_to_pathtarget(target, expr, 0);
     754        27558 : }
     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        26455 : add_new_columns_to_pathtarget(PathTarget *target, List *exprs)
     762              : {
     763              :     ListCell   *lc;
     764              : 
     765        51641 :     foreach(lc, exprs)
     766              :     {
     767        25186 :         Expr       *expr = (Expr *) lfirst(lc);
     768              : 
     769        25186 :         add_new_column_to_pathtarget(target, expr);
     770              :     }
     771        26455 : }
     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        11384 : 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        11384 :     if (target->sortgrouprefs == NULL)
     790        10395 :         return;
     791              : 
     792          989 :     i = 0;
     793         2713 :     foreach(lc, target->exprs)
     794              :     {
     795         1724 :         Expr       *expr = (Expr *) lfirst(lc);
     796              :         TargetEntry *tle;
     797              : 
     798         1724 :         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         1365 :             if (expr && IsA(expr, Var))
     810         1365 :                 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         1365 :             if (!tle)
     821            0 :                 elog(ERROR, "ORDER/GROUP BY expression not found in targetlist");
     822         1365 :             if (tle->ressortgroupref != 0 &&
     823            6 :                 tle->ressortgroupref != target->sortgrouprefs[i])
     824            0 :                 elog(ERROR, "targetlist item has multiple sortgroupref labels");
     825              : 
     826         1365 :             tle->ressortgroupref = target->sortgrouprefs[i];
     827              :         }
     828         1724 :         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        18123 : split_pathtarget_at_srfs(PlannerInfo *root,
     846              :                          PathTarget *target, PathTarget *input_target,
     847              :                          List **targets, List **targets_contain_srfs)
     848              : {
     849        18123 :     split_pathtarget_at_srfs_extended(root, target, input_target,
     850              :                                       targets, targets_contain_srfs,
     851              :                                       false);
     852        18123 : }
     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         6041 : split_pathtarget_at_srfs_grouping(PlannerInfo *root,
     869              :                                   PathTarget *target, PathTarget *input_target,
     870              :                                   List **targets, List **targets_contain_srfs)
     871              : {
     872         6041 :     split_pathtarget_at_srfs_extended(root, target, input_target,
     873              :                                       targets, targets_contain_srfs,
     874              :                                       true);
     875         6041 : }
     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        24164 : 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        24164 :     if (target == input_target)
     964              :     {
     965        17843 :         *targets = list_make1(target);
     966        17843 :         *targets_contain_srfs = list_make1_int(false);
     967        17843 :         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         6321 :     context.root = root;
     975         6321 :     context.is_grouping_target = is_grouping_target;
     976         6321 :     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         6321 :     context.level_srfs = list_make1(NIL);
     986         6321 :     context.level_input_vars = list_make1(NIL);
     987         6321 :     context.level_input_srfs = list_make1(NIL);
     988              : 
     989              :     /* Initialize data we'll accumulate across all the target expressions */
     990         6321 :     context.current_input_vars = NIL;
     991         6321 :     context.current_input_srfs = NIL;
     992         6321 :     max_depth = 0;
     993         6321 :     need_extra_projection = false;
     994              : 
     995              :     /* Scan each expression in the PathTarget looking for SRFs */
     996         6321 :     lci = 0;
     997        14522 :     foreach(lc, target->exprs)
     998              :     {
     999         8201 :         Node       *node = (Node *) lfirst(lc);
    1000              : 
    1001              :         /* Tell split_pathtarget_walker about this expr's sortgroupref */
    1002         8201 :         context.current_sgref = get_pathtarget_sortgroupref(target, lci);
    1003         8201 :         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         8201 :         context.current_depth = 0;
    1010         8201 :         split_pathtarget_walker(node, &context);
    1011              : 
    1012              :         /* An expression containing no SRFs is of no further interest */
    1013         8201 :         if (context.current_depth == 0)
    1014         1378 :             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         6823 :         if (max_depth < context.current_depth)
    1023              :         {
    1024         6047 :             max_depth = context.current_depth;
    1025         6047 :             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         6823 :         if (max_depth == context.current_depth && !IS_SRF_CALL(node))
    1034         1228 :             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         6321 :     if (max_depth == 0)
    1043              :     {
    1044          280 :         *targets = list_make1(target);
    1045          280 :         *targets_contain_srfs = list_make1_int(false);
    1046          280 :         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         6041 :     if (need_extra_projection)
    1055              :     {
    1056          562 :         context.level_srfs = lappend(context.level_srfs, NIL);
    1057         1124 :         context.level_input_vars = lappend(context.level_input_vars,
    1058          562 :                                            context.current_input_vars);
    1059          562 :         context.level_input_srfs = lappend(context.level_input_srfs,
    1060          562 :                                            context.current_input_srfs);
    1061              :     }
    1062              :     else
    1063              :     {
    1064         5479 :         lc = list_nth_cell(context.level_input_vars, max_depth);
    1065         5479 :         lfirst(lc) = list_concat(lfirst(lc), context.current_input_vars);
    1066         5479 :         lc = list_nth_cell(context.level_input_srfs, max_depth);
    1067         5479 :         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         6041 :     *targets = *targets_contain_srfs = NIL;
    1077         6041 :     prev_level_tlist = NIL;
    1078              : 
    1079        18715 :     forthree(lc1, context.level_srfs,
    1080              :              lc2, context.level_input_vars,
    1081              :              lc3, context.level_input_srfs)
    1082              :     {
    1083        12674 :         List       *level_srfs = (List *) lfirst(lc1);
    1084              :         PathTarget *ntarget;
    1085              : 
    1086        12674 :         if (lnext(context.level_srfs, lc1) == NULL)
    1087              :         {
    1088         6041 :             ntarget = target;
    1089              :         }
    1090              :         else
    1091              :         {
    1092         6633 :             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         6633 :             add_sp_items_to_pathtarget(ntarget, level_srfs);
    1101        13876 :             for_each_cell(lc, context.level_input_vars,
    1102              :                           lnext(context.level_input_vars, lc2))
    1103              :             {
    1104         7243 :                 List       *input_vars = (List *) lfirst(lc);
    1105              : 
    1106         7243 :                 add_sp_items_to_pathtarget(ntarget, input_vars);
    1107              :             }
    1108        13876 :             for_each_cell(lc, context.level_input_srfs,
    1109              :                           lnext(context.level_input_srfs, lc3))
    1110              :             {
    1111         7243 :                 List       *input_srfs = (List *) lfirst(lc);
    1112              :                 ListCell   *lcx;
    1113              : 
    1114        15471 :                 foreach(lcx, input_srfs)
    1115              :                 {
    1116         8228 :                     split_pathtarget_item *item = lfirst(lcx);
    1117              : 
    1118         8228 :                     if (list_member(prev_level_tlist, item->expr))
    1119           18 :                         add_sp_item_to_pathtarget(ntarget, item);
    1120              :                 }
    1121              :             }
    1122         6633 :             set_pathtarget_cost_width(root, ntarget);
    1123              :         }
    1124              : 
    1125              :         /*
    1126              :          * Add current target and does-it-compute-SRFs flag to output lists.
    1127              :          */
    1128        12674 :         *targets = lappend(*targets, ntarget);
    1129        12674 :         *targets_contain_srfs = lappend_int(*targets_contain_srfs,
    1130              :                                             (level_srfs != NIL));
    1131              : 
    1132              :         /* Remember this level's output for next pass */
    1133        12674 :         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        25810 : split_pathtarget_walker(Node *node, split_pathtarget_context *context)
    1145              : {
    1146        25810 :     Node       *sanitized_node = node;
    1147              : 
    1148        25810 :     if (node == NULL)
    1149           53 :         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        25757 :     if (context->is_grouping_target &&
    1158         2220 :         context->root->parse->hasGroupRTE &&
    1159          303 :         context->root->parse->groupingSets != NIL)
    1160              :     {
    1161              :         sanitized_node =
    1162          117 :             remove_nulling_relids(node,
    1163          117 :                                   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        25757 :     if (list_member(context->input_target_exprs, sanitized_node))
    1176              :     {
    1177          216 :         split_pathtarget_item *item = palloc_object(split_pathtarget_item);
    1178              : 
    1179          216 :         item->expr = node;
    1180          216 :         item->sortgroupref = context->current_sgref;
    1181          216 :         context->current_input_vars = lappend(context->current_input_vars,
    1182              :                                               item);
    1183          216 :         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        25541 :     if (IsA(node, Var) ||
    1192        23843 :         IsA(node, PlaceHolderVar) ||
    1193        23819 :         IsA(node, Aggref) ||
    1194        23104 :         IsA(node, GroupingFunc) ||
    1195        23104 :         IsA(node, WindowFunc))
    1196              :     {
    1197         2446 :         split_pathtarget_item *item = palloc_object(split_pathtarget_item);
    1198              : 
    1199         2446 :         item->expr = node;
    1200         2446 :         item->sortgroupref = context->current_sgref;
    1201         2446 :         context->current_input_vars = lappend(context->current_input_vars,
    1202              :                                               item);
    1203         2446 :         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        23095 :     if (IS_SRF_CALL(node))
    1211              :     {
    1212         6856 :         split_pathtarget_item *item = palloc_object(split_pathtarget_item);
    1213         6856 :         List       *save_input_vars = context->current_input_vars;
    1214         6856 :         List       *save_input_srfs = context->current_input_srfs;
    1215         6856 :         int         save_current_depth = context->current_depth;
    1216              :         int         srf_depth;
    1217              :         ListCell   *lc;
    1218              : 
    1219         6856 :         item->expr = node;
    1220         6856 :         item->sortgroupref = context->current_sgref;
    1221              : 
    1222         6856 :         context->current_input_vars = NIL;
    1223         6856 :         context->current_input_srfs = NIL;
    1224         6856 :         context->current_depth = 0;
    1225         6856 :         context->current_sgref = 0; /* subexpressions are not sortgroup items */
    1226              : 
    1227         6856 :         (void) expression_tree_walker(node, split_pathtarget_walker, context);
    1228              : 
    1229              :         /* Depth is one more than any SRF below it */
    1230         6856 :         srf_depth = context->current_depth + 1;
    1231              : 
    1232              :         /* If new record depth, initialize another level of output lists */
    1233         6856 :         if (srf_depth >= list_length(context->level_srfs))
    1234              :         {
    1235         6071 :             context->level_srfs = lappend(context->level_srfs, NIL);
    1236         6071 :             context->level_input_vars = lappend(context->level_input_vars, NIL);
    1237         6071 :             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         6856 :         lc = list_nth_cell(context->level_srfs, srf_depth);
    1242         6856 :         lfirst(lc) = lappend(lfirst(lc), item);
    1243              : 
    1244              :         /* Record its inputs as being needed at the same level */
    1245         6856 :         lc = list_nth_cell(context->level_input_vars, srf_depth);
    1246         6856 :         lfirst(lc) = list_concat(lfirst(lc), context->current_input_vars);
    1247         6856 :         lc = list_nth_cell(context->level_input_srfs, srf_depth);
    1248         6856 :         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         6856 :         context->current_input_vars = save_input_vars;
    1256         6856 :         context->current_input_srfs = lappend(save_input_srfs, item);
    1257         6856 :         context->current_depth = Max(save_current_depth, srf_depth);
    1258              : 
    1259              :         /* We're done here */
    1260         6856 :         return false;
    1261              :     }
    1262              : 
    1263              :     /*
    1264              :      * Otherwise, the node is a scalar (non-set) expression, so recurse to
    1265              :      * examine its inputs.
    1266              :      */
    1267        16239 :     context->current_sgref = 0; /* subexpressions are not sortgroup items */
    1268        16239 :     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         3778 : 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         3778 :     lci = 0;
    1295         5221 :     foreach(lc, target->exprs)
    1296              :     {
    1297         3021 :         Node       *node = (Node *) lfirst(lc);
    1298         3021 :         Index       sgref = get_pathtarget_sortgroupref(target, lci);
    1299              : 
    1300         3021 :         if ((item->sortgroupref == sgref ||
    1301          150 :              item->sortgroupref == 0 ||
    1302         2994 :              sgref == 0) &&
    1303         2994 :             equal(item->expr, node))
    1304              :         {
    1305              :             /* Found a match.  Assign item's sortgroupref if it has one. */
    1306         1578 :             if (item->sortgroupref)
    1307              :             {
    1308           12 :                 if (target->sortgrouprefs == NULL)
    1309              :                 {
    1310            6 :                     target->sortgrouprefs = (Index *)
    1311            6 :                         palloc0(list_length(target->exprs) * sizeof(Index));
    1312              :                 }
    1313           12 :                 target->sortgrouprefs[lci] = item->sortgroupref;
    1314              :             }
    1315         1578 :             return;
    1316              :         }
    1317         1443 :         lci++;
    1318              :     }
    1319              : 
    1320              :     /*
    1321              :      * No match, so add item to PathTarget.  Copy the expr for safety.
    1322              :      */
    1323         2200 :     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        13876 : add_sp_items_to_pathtarget(PathTarget *target, List *items)
    1332              : {
    1333              :     ListCell   *lc;
    1334              : 
    1335        17636 :     foreach(lc, items)
    1336              :     {
    1337         3760 :         split_pathtarget_item *item = lfirst(lc);
    1338              : 
    1339         3760 :         add_sp_item_to_pathtarget(target, item);
    1340              :     }
    1341        13876 : }
        

Generated by: LCOV version 2.0-1