LCOV - code coverage report
Current view: top level - src/backend/parser - parse_relation.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 91.3 % 1640 1498
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 58 58
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 68.6 % 1282 880

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * parse_relation.c
       4                 :             :  *        parser support routines dealing with relations
       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/parser/parse_relation.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include <ctype.h>
      18                 :             : 
      19                 :             : #include "access/htup_details.h"
      20                 :             : #include "access/relation.h"
      21                 :             : #include "access/table.h"
      22                 :             : #include "catalog/heap.h"
      23                 :             : #include "catalog/namespace.h"
      24                 :             : #include "funcapi.h"
      25                 :             : #include "nodes/makefuncs.h"
      26                 :             : #include "nodes/nodeFuncs.h"
      27                 :             : #include "parser/parse_enr.h"
      28                 :             : #include "parser/parse_relation.h"
      29                 :             : #include "parser/parse_type.h"
      30                 :             : #include "parser/parsetree.h"
      31                 :             : #include "storage/lmgr.h"
      32                 :             : #include "utils/builtins.h"
      33                 :             : #include "utils/lsyscache.h"
      34                 :             : #include "utils/syscache.h"
      35                 :             : #include "utils/varlena.h"
      36                 :             : 
      37                 :             : 
      38                 :             : /*
      39                 :             :  * Support for fuzzily matching columns.
      40                 :             :  *
      41                 :             :  * This is for building diagnostic messages, where multiple or non-exact
      42                 :             :  * matching attributes are of interest.
      43                 :             :  *
      44                 :             :  * "distance" is the current best fuzzy-match distance if rfirst isn't NULL,
      45                 :             :  * otherwise it is the maximum acceptable distance plus 1.
      46                 :             :  *
      47                 :             :  * rfirst/first record the closest non-exact match so far, and distance
      48                 :             :  * is its distance from the target name.  If we have found a second non-exact
      49                 :             :  * match of exactly the same distance, rsecond/second record that.  (If
      50                 :             :  * we find three of the same distance, we conclude that "distance" is not
      51                 :             :  * a tight enough bound for a useful hint and clear rfirst/rsecond again.
      52                 :             :  * Only if we later find something closer will we re-populate rfirst.)
      53                 :             :  *
      54                 :             :  * rexact1/exact1 record the location of the first exactly-matching column,
      55                 :             :  * if any.  If we find multiple exact matches then rexact2/exact2 record
      56                 :             :  * another one (we don't especially care which).  Currently, these get
      57                 :             :  * populated independently of the fuzzy-match fields.
      58                 :             :  */
      59                 :             : typedef struct
      60                 :             : {
      61                 :             :         int                     distance;               /* Current or limit distance */
      62                 :             :         RangeTblEntry *rfirst;          /* RTE of closest non-exact match, or NULL */
      63                 :             :         AttrNumber      first;                  /* Col index in rfirst */
      64                 :             :         RangeTblEntry *rsecond;         /* RTE of another non-exact match w/same dist */
      65                 :             :         AttrNumber      second;                 /* Col index in rsecond */
      66                 :             :         RangeTblEntry *rexact1;         /* RTE of first exact match, or NULL */
      67                 :             :         AttrNumber      exact1;                 /* Col index in rexact1 */
      68                 :             :         RangeTblEntry *rexact2;         /* RTE of second exact match, or NULL */
      69                 :             :         AttrNumber      exact2;                 /* Col index in rexact2 */
      70                 :             : } FuzzyAttrMatchState;
      71                 :             : 
      72                 :             : #define MAX_FUZZY_DISTANCE                              3
      73                 :             : 
      74                 :             : 
      75                 :             : static ParseNamespaceItem *scanNameSpaceForRefname(ParseState *pstate,
      76                 :             :                                                                                                    const char *refname,
      77                 :             :                                                                                                    int location);
      78                 :             : static ParseNamespaceItem *scanNameSpaceForRelid(ParseState *pstate, Oid relid,
      79                 :             :                                                                                                  int location);
      80                 :             : static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
      81                 :             :                                                                  int location);
      82                 :             : static int      scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
      83                 :             :                                                          Alias *eref,
      84                 :             :                                                          const char *colname, int location,
      85                 :             :                                                          int fuzzy_rte_penalty,
      86                 :             :                                                          FuzzyAttrMatchState *fuzzystate);
      87                 :             : static void markRTEForSelectPriv(ParseState *pstate,
      88                 :             :                                                                  int rtindex, AttrNumber col);
      89                 :             : static void expandRelation(Oid relid, Alias *eref,
      90                 :             :                                                    int rtindex, int sublevels_up,
      91                 :             :                                                    VarReturningType returning_type,
      92                 :             :                                                    int location, bool include_dropped,
      93                 :             :                                                    List **colnames, List **colvars);
      94                 :             : static void expandTupleDesc(TupleDesc tupdesc, Alias *eref,
      95                 :             :                                                         int count, int offset,
      96                 :             :                                                         int rtindex, int sublevels_up,
      97                 :             :                                                         VarReturningType returning_type,
      98                 :             :                                                         int location, bool include_dropped,
      99                 :             :                                                         List **colnames, List **colvars);
     100                 :             : static int      specialAttNum(const char *attname);
     101                 :             : static bool rte_visible_if_lateral(ParseState *pstate, RangeTblEntry *rte);
     102                 :             : static bool rte_visible_if_qualified(ParseState *pstate, RangeTblEntry *rte);
     103                 :             : 
     104                 :             : 
     105                 :             : /*
     106                 :             :  * refnameNamespaceItem
     107                 :             :  *        Given a possibly-qualified refname, look to see if it matches any visible
     108                 :             :  *        namespace item.  If so, return a pointer to the nsitem; else return NULL.
     109                 :             :  *
     110                 :             :  *        Optionally get nsitem's nesting depth (0 = current) into *sublevels_up.
     111                 :             :  *        If sublevels_up is NULL, only consider items at the current nesting
     112                 :             :  *        level.
     113                 :             :  *
     114                 :             :  * An unqualified refname (schemaname == NULL) can match any item with matching
     115                 :             :  * alias, or matching unqualified relname in the case of alias-less relation
     116                 :             :  * items.  It is possible that such a refname matches multiple items in the
     117                 :             :  * nearest nesting level that has a match; if so, we report an error via
     118                 :             :  * ereport().
     119                 :             :  *
     120                 :             :  * A qualified refname (schemaname != NULL) can only match a relation item
     121                 :             :  * that (a) has no alias and (b) is for the same relation identified by
     122                 :             :  * schemaname.refname.  In this case we convert schemaname.refname to a
     123                 :             :  * relation OID and search by relid, rather than by alias name.  This is
     124                 :             :  * peculiar, but it's what SQL says to do.  While processing a query's
     125                 :             :  * RETURNING list, there may be additional namespace items for OLD and NEW,
     126                 :             :  * with the same relation OID as the target namespace item.  These are
     127                 :             :  * ignored in the search, since they don't match by schemaname.refname.
     128                 :             :  */
     129                 :             : ParseNamespaceItem *
     130                 :       92973 : refnameNamespaceItem(ParseState *pstate,
     131                 :             :                                          const char *schemaname,
     132                 :             :                                          const char *refname,
     133                 :             :                                          int location,
     134                 :             :                                          int *sublevels_up)
     135                 :             : {
     136                 :       92973 :         Oid                     relId = InvalidOid;
     137                 :             : 
     138         [ +  + ]:       92973 :         if (sublevels_up)
     139                 :       92208 :                 *sublevels_up = 0;
     140                 :             : 
     141         [ +  + ]:       92973 :         if (schemaname != NULL)
     142                 :             :         {
     143                 :          10 :                 Oid                     namespaceId;
     144                 :             : 
     145                 :             :                 /*
     146                 :             :                  * We can use LookupNamespaceNoError() here because we are only
     147                 :             :                  * interested in finding existing RTEs.  Checking USAGE permission on
     148                 :             :                  * the schema is unnecessary since it would have already been checked
     149                 :             :                  * when the RTE was made.  Furthermore, we want to report "RTE not
     150                 :             :                  * found", not "no permissions for schema", if the name happens to
     151                 :             :                  * match a schema name the user hasn't got access to.
     152                 :             :                  */
     153                 :          10 :                 namespaceId = LookupNamespaceNoError(schemaname);
     154         [ +  + ]:          10 :                 if (!OidIsValid(namespaceId))
     155                 :           7 :                         return NULL;
     156                 :           3 :                 relId = get_relname_relid(refname, namespaceId);
     157         [ +  - ]:           3 :                 if (!OidIsValid(relId))
     158                 :           0 :                         return NULL;
     159         [ +  + ]:          10 :         }
     160                 :             : 
     161         [ +  + ]:      103906 :         while (pstate != NULL)
     162                 :             :         {
     163                 :       99772 :                 ParseNamespaceItem *result;
     164                 :             : 
     165         [ -  + ]:       99772 :                 if (OidIsValid(relId))
     166                 :           0 :                         result = scanNameSpaceForRelid(pstate, relId, location);
     167                 :             :                 else
     168                 :       99772 :                         result = scanNameSpaceForRefname(pstate, refname, location);
     169                 :             : 
     170         [ +  + ]:       99772 :                 if (result)
     171                 :       88089 :                         return result;
     172                 :             : 
     173         [ +  + ]:       11683 :                 if (sublevels_up)
     174                 :       10940 :                         (*sublevels_up)++;
     175                 :             :                 else
     176                 :         743 :                         break;
     177                 :             : 
     178                 :       10940 :                 pstate = pstate->parentParseState;
     179      [ +  +  + ]:       99772 :         }
     180                 :        4873 :         return NULL;
     181                 :       92973 : }
     182                 :             : 
     183                 :             : /*
     184                 :             :  * Search the query's table namespace for an item matching the
     185                 :             :  * given unqualified refname.  Return the nsitem if a unique match, or NULL
     186                 :             :  * if no match.  Raise error if multiple matches.
     187                 :             :  *
     188                 :             :  * Note: it might seem that we shouldn't have to worry about the possibility
     189                 :             :  * of multiple matches; after all, the SQL standard disallows duplicate table
     190                 :             :  * aliases within a given SELECT level.  Historically, however, Postgres has
     191                 :             :  * been laxer than that.  For example, we allow
     192                 :             :  *              SELECT ... FROM tab1 x CROSS JOIN (tab2 x CROSS JOIN tab3 y) z
     193                 :             :  * on the grounds that the aliased join (z) hides the aliases within it,
     194                 :             :  * therefore there is no conflict between the two RTEs named "x".  However,
     195                 :             :  * if tab3 is a LATERAL subquery, then from within the subquery both "x"es
     196                 :             :  * are visible.  Rather than rejecting queries that used to work, we allow
     197                 :             :  * this situation, and complain only if there's actually an ambiguous
     198                 :             :  * reference to "x".
     199                 :             :  */
     200                 :             : static ParseNamespaceItem *
     201                 :       99770 : scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)
     202                 :             : {
     203                 :       99770 :         ParseNamespaceItem *result = NULL;
     204                 :       99770 :         ListCell   *l;
     205                 :             : 
     206   [ +  +  +  +  :      352410 :         foreach(l, pstate->p_namespace)
                   +  + ]
     207                 :             :         {
     208                 :      252642 :                 ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
     209                 :             : 
     210                 :             :                 /* Ignore columns-only items */
     211         [ +  + ]:      252642 :                 if (!nsitem->p_rel_visible)
     212                 :       54403 :                         continue;
     213                 :             :                 /* If not inside LATERAL, ignore lateral-only items */
     214   [ +  +  +  + ]:      198239 :                 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
     215                 :          10 :                         continue;
     216                 :             : 
     217         [ +  + ]:      198229 :                 if (strcmp(nsitem->p_names->aliasname, refname) == 0)
     218                 :             :                 {
     219         [ +  + ]:       88092 :                         if (result)
     220   [ +  -  +  - ]:           2 :                                 ereport(ERROR,
     221                 :             :                                                 (errcode(ERRCODE_AMBIGUOUS_ALIAS),
     222                 :             :                                                  errmsg("table reference \"%s\" is ambiguous",
     223                 :             :                                                                 refname),
     224                 :             :                                                  parser_errposition(pstate, location)));
     225                 :       88090 :                         check_lateral_ref_ok(pstate, nsitem, location);
     226                 :       88090 :                         result = nsitem;
     227                 :       88090 :                 }
     228      [ -  +  + ]:      252640 :         }
     229                 :      199536 :         return result;
     230                 :       99768 : }
     231                 :             : 
     232                 :             : /*
     233                 :             :  * Search the query's table namespace for a relation item matching the
     234                 :             :  * given relation OID.  Return the nsitem if a unique match, or NULL
     235                 :             :  * if no match.  Raise error if multiple matches.
     236                 :             :  *
     237                 :             :  * See the comments for refnameNamespaceItem to understand why this
     238                 :             :  * acts the way it does.
     239                 :             :  */
     240                 :             : static ParseNamespaceItem *
     241                 :           4 : scanNameSpaceForRelid(ParseState *pstate, Oid relid, int location)
     242                 :             : {
     243                 :           4 :         ParseNamespaceItem *result = NULL;
     244                 :           4 :         ListCell   *l;
     245                 :             : 
     246   [ +  -  +  +  :          10 :         foreach(l, pstate->p_namespace)
                   +  + ]
     247                 :             :         {
     248                 :           6 :                 ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
     249                 :           6 :                 RangeTblEntry *rte = nsitem->p_rte;
     250                 :             : 
     251                 :             :                 /* Ignore columns-only items */
     252         [ +  - ]:           6 :                 if (!nsitem->p_rel_visible)
     253                 :           0 :                         continue;
     254                 :             :                 /* If not inside LATERAL, ignore lateral-only items */
     255   [ -  +  #  # ]:           6 :                 if (nsitem->p_lateral_only && !pstate->p_lateral_active)
     256                 :           0 :                         continue;
     257                 :             :                 /* Ignore OLD/NEW namespace items that can appear in RETURNING */
     258         [ +  + ]:           6 :                 if (nsitem->p_returning_type != VAR_RETURNING_DEFAULT)
     259                 :           2 :                         continue;
     260                 :             : 
     261                 :             :                 /* yes, the test for alias == NULL should be there... */
     262         [ +  - ]:           4 :                 if (rte->rtekind == RTE_RELATION &&
     263   [ +  +  -  + ]:           4 :                         rte->relid == relid &&
     264                 :           3 :                         rte->alias == NULL)
     265                 :             :                 {
     266         [ -  + ]:           3 :                         if (result)
     267   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
     268                 :             :                                                 (errcode(ERRCODE_AMBIGUOUS_ALIAS),
     269                 :             :                                                  errmsg("table reference %u is ambiguous",
     270                 :             :                                                                 relid),
     271                 :             :                                                  parser_errposition(pstate, location)));
     272                 :           3 :                         check_lateral_ref_ok(pstate, nsitem, location);
     273                 :           3 :                         result = nsitem;
     274                 :           3 :                 }
     275      [ -  +  + ]:           6 :         }
     276                 :           8 :         return result;
     277                 :           4 : }
     278                 :             : 
     279                 :             : /*
     280                 :             :  * Search the query's CTE namespace for a CTE matching the given unqualified
     281                 :             :  * refname.  Return the CTE (and its levelsup count) if a match, or NULL
     282                 :             :  * if no match.  We need not worry about multiple matches, since parse_cte.c
     283                 :             :  * rejects WITH lists containing duplicate CTE names.
     284                 :             :  */
     285                 :             : CommonTableExpr *
     286                 :       19058 : scanNameSpaceForCTE(ParseState *pstate, const char *refname,
     287                 :             :                                         Index *ctelevelsup)
     288                 :             : {
     289                 :       19058 :         Index           levelsup;
     290                 :             : 
     291         [ +  + ]:       41068 :         for (levelsup = 0;
     292                 :       41068 :                  pstate != NULL;
     293                 :       22010 :                  pstate = pstate->parentParseState, levelsup++)
     294                 :             :         {
     295                 :       22472 :                 ListCell   *lc;
     296                 :             : 
     297   [ +  +  +  +  :       23126 :                 foreach(lc, pstate->p_ctenamespace)
             +  +  +  + ]
     298                 :             :                 {
     299                 :         654 :                         CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     300                 :             : 
     301         [ +  + ]:         654 :                         if (strcmp(cte->ctename, refname) == 0)
     302                 :             :                         {
     303                 :         462 :                                 *ctelevelsup = levelsup;
     304                 :         462 :                                 return cte;
     305                 :             :                         }
     306         [ +  + ]:         654 :                 }
     307         [ +  + ]:       22472 :         }
     308                 :       18596 :         return NULL;
     309                 :       19058 : }
     310                 :             : 
     311                 :             : /*
     312                 :             :  * Search for a possible "future CTE", that is one that is not yet in scope
     313                 :             :  * according to the WITH scoping rules.  This has nothing to do with valid
     314                 :             :  * SQL semantics, but it's important for error reporting purposes.
     315                 :             :  */
     316                 :             : static bool
     317                 :          22 : isFutureCTE(ParseState *pstate, const char *refname)
     318                 :             : {
     319         [ +  + ]:          46 :         for (; pstate != NULL; pstate = pstate->parentParseState)
     320                 :             :         {
     321                 :          25 :                 ListCell   *lc;
     322                 :             : 
     323   [ +  +  -  +  :          26 :                 foreach(lc, pstate->p_future_ctes)
             +  +  +  + ]
     324                 :             :                 {
     325                 :           1 :                         CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     326                 :             : 
     327         [ -  + ]:           1 :                         if (strcmp(cte->ctename, refname) == 0)
     328                 :           1 :                                 return true;
     329         [ +  - ]:           1 :                 }
     330      [ -  +  + ]:          25 :         }
     331                 :          21 :         return false;
     332                 :          22 : }
     333                 :             : 
     334                 :             : /*
     335                 :             :  * Search the query's ephemeral named relation namespace for a relation
     336                 :             :  * matching the given unqualified refname.
     337                 :             :  */
     338                 :             : bool
     339                 :       25994 : scanNameSpaceForENR(ParseState *pstate, const char *refname)
     340                 :             : {
     341                 :       25994 :         return name_matches_visible_ENR(pstate, refname);
     342                 :             : }
     343                 :             : 
     344                 :             : /*
     345                 :             :  * searchRangeTableForRel
     346                 :             :  *        See if any RangeTblEntry could possibly match the RangeVar.
     347                 :             :  *        If so, return a pointer to the RangeTblEntry; else return NULL.
     348                 :             :  *
     349                 :             :  * This is different from refnameNamespaceItem in that it considers every
     350                 :             :  * entry in the ParseState's rangetable(s), not only those that are currently
     351                 :             :  * visible in the p_namespace list(s).  This behavior is invalid per the SQL
     352                 :             :  * spec, and it may give ambiguous results (there might be multiple equally
     353                 :             :  * valid matches, but only one will be returned).  This must be used ONLY
     354                 :             :  * as a heuristic in giving suitable error messages.  See errorMissingRTE.
     355                 :             :  *
     356                 :             :  * Notice that we consider both matches on actual relation (or CTE) name
     357                 :             :  * and matches on alias.
     358                 :             :  */
     359                 :             : static RangeTblEntry *
     360                 :          19 : searchRangeTableForRel(ParseState *pstate, RangeVar *relation)
     361                 :             : {
     362                 :          19 :         const char *refname = relation->relname;
     363                 :          19 :         Oid                     relId = InvalidOid;
     364                 :          19 :         CommonTableExpr *cte = NULL;
     365                 :          19 :         bool            isenr = false;
     366                 :          19 :         Index           ctelevelsup = 0;
     367                 :          19 :         Index           levelsup;
     368                 :             : 
     369                 :             :         /*
     370                 :             :          * If it's an unqualified name, check for possible CTE matches. A CTE
     371                 :             :          * hides any real relation matches.  If no CTE, look for a matching
     372                 :             :          * relation.
     373                 :             :          *
     374                 :             :          * NB: It's not critical that RangeVarGetRelid return the correct answer
     375                 :             :          * here in the face of concurrent DDL.  If it doesn't, the worst case
     376                 :             :          * scenario is a less-clear error message.  Also, the tables involved in
     377                 :             :          * the query are already locked, which reduces the number of cases in
     378                 :             :          * which surprising behavior can occur.  So we do the name lookup
     379                 :             :          * unlocked.
     380                 :             :          */
     381         [ -  + ]:          19 :         if (!relation->schemaname)
     382                 :             :         {
     383                 :          19 :                 cte = scanNameSpaceForCTE(pstate, refname, &ctelevelsup);
     384         [ -  + ]:          19 :                 if (!cte)
     385                 :          19 :                         isenr = scanNameSpaceForENR(pstate, refname);
     386                 :          19 :         }
     387                 :             : 
     388   [ +  -  -  + ]:          19 :         if (!cte && !isenr)
     389                 :          19 :                 relId = RangeVarGetRelid(relation, NoLock, true);
     390                 :             : 
     391                 :             :         /* Now look for RTEs matching either the relation/CTE/ENR or the alias */
     392         [ +  + ]:          27 :         for (levelsup = 0;
     393                 :          27 :                  pstate != NULL;
     394                 :           8 :                  pstate = pstate->parentParseState, levelsup++)
     395                 :             :         {
     396                 :          24 :                 ListCell   *l;
     397                 :             : 
     398   [ +  +  +  +  :          52 :                 foreach(l, pstate->p_rtable)
             +  +  +  + ]
     399                 :             :                 {
     400                 :          28 :                         RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
     401                 :             : 
     402         [ +  + ]:          28 :                         if (rte->rtekind == RTE_RELATION &&
     403   [ +  +  +  + ]:          26 :                                 OidIsValid(relId) &&
     404                 :          19 :                                 rte->relid == relId)
     405                 :           7 :                                 return rte;
     406         [ -  + ]:          21 :                         if (rte->rtekind == RTE_CTE &&
     407         [ #  # ]:           0 :                                 cte != NULL &&
     408   [ #  #  #  # ]:           0 :                                 rte->ctelevelsup + levelsup == ctelevelsup &&
     409                 :           0 :                                 strcmp(rte->ctename, refname) == 0)
     410                 :           0 :                                 return rte;
     411         [ -  + ]:          21 :                         if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
     412   [ #  #  #  # ]:           0 :                                 isenr &&
     413                 :           0 :                                 strcmp(rte->enrname, refname) == 0)
     414                 :           0 :                                 return rte;
     415         [ +  + ]:          21 :                         if (strcmp(rte->eref->aliasname, refname) == 0)
     416                 :           9 :                                 return rte;
     417         [ +  + ]:          28 :                 }
     418         [ +  + ]:          24 :         }
     419                 :           3 :         return NULL;
     420                 :          19 : }
     421                 :             : 
     422                 :             : /*
     423                 :             :  * Check for relation-name conflicts between two namespace lists.
     424                 :             :  * Raise an error if any is found.
     425                 :             :  *
     426                 :             :  * Note: we assume that each given argument does not contain conflicts
     427                 :             :  * itself; we just want to know if the two can be merged together.
     428                 :             :  *
     429                 :             :  * Per SQL, two alias-less plain relation RTEs do not conflict even if
     430                 :             :  * they have the same eref->aliasname (ie, same relation name), if they
     431                 :             :  * are for different relation OIDs (implying they are in different schemas).
     432                 :             :  *
     433                 :             :  * We ignore the lateral-only flags in the namespace items: the lists must
     434                 :             :  * not conflict, even when all items are considered visible.  However,
     435                 :             :  * columns-only items should be ignored.
     436                 :             :  */
     437                 :             : void
     438                 :       43350 : checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
     439                 :             :                                                 List *namespace2)
     440                 :             : {
     441                 :       43350 :         ListCell   *l1;
     442                 :             : 
     443   [ +  +  +  +  :       60673 :         foreach(l1, namespace1)
                   +  + ]
     444                 :             :         {
     445                 :       17325 :                 ParseNamespaceItem *nsitem1 = (ParseNamespaceItem *) lfirst(l1);
     446                 :       17325 :                 RangeTblEntry *rte1 = nsitem1->p_rte;
     447                 :       17325 :                 const char *aliasname1 = nsitem1->p_names->aliasname;
     448                 :       17325 :                 ListCell   *l2;
     449                 :             : 
     450         [ +  + ]:       17325 :                 if (!nsitem1->p_rel_visible)
     451                 :        2600 :                         continue;
     452                 :             : 
     453   [ +  -  +  +  :       30569 :                 foreach(l2, namespace2)
                   +  + ]
     454                 :             :                 {
     455                 :       15846 :                         ParseNamespaceItem *nsitem2 = (ParseNamespaceItem *) lfirst(l2);
     456                 :       15846 :                         RangeTblEntry *rte2 = nsitem2->p_rte;
     457                 :       15846 :                         const char *aliasname2 = nsitem2->p_names->aliasname;
     458                 :             : 
     459         [ +  + ]:       15846 :                         if (!nsitem2->p_rel_visible)
     460                 :         563 :                                 continue;
     461         [ +  + ]:       15283 :                         if (strcmp(aliasname2, aliasname1) != 0)
     462                 :       15281 :                                 continue;               /* definitely no conflict */
     463         [ -  + ]:           2 :                         if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
     464                 :           0 :                                 rte2->rtekind == RTE_RELATION && rte2->alias == NULL &&
     465                 :           0 :                                 rte1->relid != rte2->relid)
     466                 :           0 :                                 continue;               /* no conflict per SQL rule */
     467   [ +  -  +  - ]:           2 :                         ereport(ERROR,
     468                 :             :                                         (errcode(ERRCODE_DUPLICATE_ALIAS),
     469                 :             :                                          errmsg("table name \"%s\" specified more than once",
     470                 :             :                                                         aliasname1)));
     471         [ +  - ]:       15844 :                 }
     472         [ +  + ]:       17323 :         }
     473                 :       43348 : }
     474                 :             : 
     475                 :             : /*
     476                 :             :  * Complain if a namespace item is currently disallowed as a LATERAL reference.
     477                 :             :  * This enforces both SQL:2008's rather odd idea of what to do with a LATERAL
     478                 :             :  * reference to the wrong side of an outer join, and our own prohibition on
     479                 :             :  * referencing the target table of an UPDATE or DELETE as a lateral reference
     480                 :             :  * in a FROM/USING clause.
     481                 :             :  *
     482                 :             :  * Note: the pstate should be the same query level the nsitem was found in.
     483                 :             :  *
     484                 :             :  * Convenience subroutine to avoid multiple copies of a rather ugly ereport.
     485                 :             :  */
     486                 :             : static void
     487                 :      140827 : check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
     488                 :             :                                          int location)
     489                 :             : {
     490   [ +  +  +  + ]:      140827 :         if (nsitem->p_lateral_only && !nsitem->p_lateral_ok)
     491                 :             :         {
     492                 :             :                 /* SQL:2008 demands this be an error, not an invisible item */
     493                 :           4 :                 RangeTblEntry *rte = nsitem->p_rte;
     494                 :           4 :                 char       *refname = nsitem->p_names->aliasname;
     495                 :             : 
     496   [ +  -  +  -  :           4 :                 ereport(ERROR,
             +  +  -  + ]
     497                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
     498                 :             :                                  errmsg("invalid reference to FROM-clause entry for table \"%s\"",
     499                 :             :                                                 refname),
     500                 :             :                                  (pstate->p_target_nsitem != NULL &&
     501                 :             :                                   rte == pstate->p_target_nsitem->p_rte) ?
     502                 :             :                                  errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
     503                 :             :                                                  refname) :
     504                 :             :                                  errdetail("The combining JOIN type must be INNER or LEFT for a LATERAL reference."),
     505                 :             :                                  parser_errposition(pstate, location)));
     506                 :           0 :         }
     507                 :      140823 : }
     508                 :             : 
     509                 :             : /*
     510                 :             :  * Given an RT index and nesting depth, find the corresponding
     511                 :             :  * ParseNamespaceItem (there must be one).
     512                 :             :  */
     513                 :             : ParseNamespaceItem *
     514                 :         343 : GetNSItemByRangeTablePosn(ParseState *pstate,
     515                 :             :                                                   int varno,
     516                 :             :                                                   int sublevels_up)
     517                 :             : {
     518                 :         343 :         ListCell   *lc;
     519                 :             : 
     520         [ -  + ]:         343 :         while (sublevels_up-- > 0)
     521                 :             :         {
     522                 :           0 :                 pstate = pstate->parentParseState;
     523         [ #  # ]:           0 :                 Assert(pstate != NULL);
     524                 :             :         }
     525   [ +  -  -  +  :         721 :         foreach(lc, pstate->p_namespace)
             +  -  +  - ]
     526                 :             :         {
     527                 :         378 :                 ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(lc);
     528                 :             : 
     529         [ +  + ]:         378 :                 if (nsitem->p_rtindex == varno)
     530                 :         343 :                         return nsitem;
     531         [ +  + ]:         378 :         }
     532   [ #  #  #  # ]:           0 :         elog(ERROR, "nsitem not found (internal error)");
     533                 :           0 :         return NULL;                            /* keep compiler quiet */
     534                 :         343 : }
     535                 :             : 
     536                 :             : /*
     537                 :             :  * Given an RT index and nesting depth, find the corresponding RTE.
     538                 :             :  * (Note that the RTE need not be in the query's namespace.)
     539                 :             :  */
     540                 :             : RangeTblEntry *
     541                 :       65708 : GetRTEByRangeTablePosn(ParseState *pstate,
     542                 :             :                                            int varno,
     543                 :             :                                            int sublevels_up)
     544                 :             : {
     545         [ +  + ]:       65936 :         while (sublevels_up-- > 0)
     546                 :             :         {
     547                 :         228 :                 pstate = pstate->parentParseState;
     548         [ +  - ]:         228 :                 Assert(pstate != NULL);
     549                 :             :         }
     550         [ +  - ]:       65708 :         Assert(varno > 0 && varno <= list_length(pstate->p_rtable));
     551                 :       65708 :         return rt_fetch(varno, pstate->p_rtable);
     552                 :             : }
     553                 :             : 
     554                 :             : /*
     555                 :             :  * Fetch the CTE for a CTE-reference RTE.
     556                 :             :  *
     557                 :             :  * rtelevelsup is the number of query levels above the given pstate that the
     558                 :             :  * RTE came from.
     559                 :             :  */
     560                 :             : CommonTableExpr *
     561                 :         523 : GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, int rtelevelsup)
     562                 :             : {
     563                 :         523 :         Index           levelsup;
     564                 :         523 :         ListCell   *lc;
     565                 :             : 
     566         [ +  - ]:         523 :         Assert(rte->rtekind == RTE_CTE);
     567                 :         523 :         levelsup = rte->ctelevelsup + rtelevelsup;
     568         [ +  + ]:         731 :         while (levelsup-- > 0)
     569                 :             :         {
     570                 :         208 :                 pstate = pstate->parentParseState;
     571         [ +  - ]:         208 :                 if (!pstate)                    /* shouldn't happen */
     572   [ #  #  #  # ]:           0 :                         elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
     573                 :             :         }
     574   [ +  -  -  +  :        1146 :         foreach(lc, pstate->p_ctenamespace)
             +  -  +  - ]
     575                 :             :         {
     576                 :         623 :                 CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
     577                 :             : 
     578         [ +  + ]:         623 :                 if (strcmp(cte->ctename, rte->ctename) == 0)
     579                 :         523 :                         return cte;
     580         [ +  + ]:         623 :         }
     581                 :             :         /* shouldn't happen */
     582   [ #  #  #  # ]:           0 :         elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
     583                 :           0 :         return NULL;                            /* keep compiler quiet */
     584                 :         523 : }
     585                 :             : 
     586                 :             : /*
     587                 :             :  * updateFuzzyAttrMatchState
     588                 :             :  *        Using Levenshtein distance, consider if column is best fuzzy match.
     589                 :             :  */
     590                 :             : static void
     591                 :         383 : updateFuzzyAttrMatchState(int fuzzy_rte_penalty,
     592                 :             :                                                   FuzzyAttrMatchState *fuzzystate, RangeTblEntry *rte,
     593                 :             :                                                   const char *actual, const char *match, int attnum)
     594                 :             : {
     595                 :         383 :         int                     columndistance;
     596                 :         383 :         int                     matchlen;
     597                 :             : 
     598                 :             :         /* Bail before computing the Levenshtein distance if there's no hope. */
     599         [ +  + ]:         383 :         if (fuzzy_rte_penalty > fuzzystate->distance)
     600                 :           9 :                 return;
     601                 :             : 
     602                 :             :         /*
     603                 :             :          * Outright reject dropped columns, which can appear here with apparent
     604                 :             :          * empty actual names, per remarks within scanRTEForColumn().
     605                 :             :          */
     606         [ +  + ]:         374 :         if (actual[0] == '\0')
     607                 :          22 :                 return;
     608                 :             : 
     609                 :             :         /* Use Levenshtein to compute match distance. */
     610                 :         352 :         matchlen = strlen(match);
     611                 :         352 :         columndistance =
     612                 :         704 :                 varstr_levenshtein_less_equal(actual, strlen(actual), match, matchlen,
     613                 :             :                                                                           1, 1, 1,
     614                 :         352 :                                                                           fuzzystate->distance + 1
     615                 :         352 :                                                                           - fuzzy_rte_penalty,
     616                 :             :                                                                           true);
     617                 :             : 
     618                 :             :         /*
     619                 :             :          * If more than half the characters are different, don't treat it as a
     620                 :             :          * match, to avoid making ridiculous suggestions.
     621                 :             :          */
     622         [ +  + ]:         352 :         if (columndistance > matchlen / 2)
     623                 :         206 :                 return;
     624                 :             : 
     625                 :             :         /*
     626                 :             :          * From this point on, we can ignore the distinction between the RTE-name
     627                 :             :          * distance and the column-name distance.
     628                 :             :          */
     629                 :         146 :         columndistance += fuzzy_rte_penalty;
     630                 :             : 
     631                 :             :         /*
     632                 :             :          * If the new distance is less than or equal to that of the best match
     633                 :             :          * found so far, update fuzzystate.
     634                 :             :          */
     635         [ +  + ]:         146 :         if (columndistance < fuzzystate->distance)
     636                 :             :         {
     637                 :             :                 /* Store new lowest observed distance as first/only match */
     638                 :          19 :                 fuzzystate->distance = columndistance;
     639                 :          19 :                 fuzzystate->rfirst = rte;
     640                 :          19 :                 fuzzystate->first = attnum;
     641                 :          19 :                 fuzzystate->rsecond = NULL;
     642                 :          19 :         }
     643         [ +  + ]:         127 :         else if (columndistance == fuzzystate->distance)
     644                 :             :         {
     645                 :             :                 /* If we already have a match of this distance, update state */
     646         [ +  + ]:           7 :                 if (fuzzystate->rsecond != NULL)
     647                 :             :                 {
     648                 :             :                         /*
     649                 :             :                          * Too many matches at same distance.  Clearly, this value of
     650                 :             :                          * distance is too low a bar, so drop these entries while keeping
     651                 :             :                          * the current distance value, so that only smaller distances will
     652                 :             :                          * be considered interesting.  Only if we find something of lower
     653                 :             :                          * distance will we re-populate rfirst (via the stanza above).
     654                 :             :                          */
     655                 :           1 :                         fuzzystate->rfirst = NULL;
     656                 :           1 :                         fuzzystate->rsecond = NULL;
     657                 :           1 :                 }
     658         [ +  + ]:           6 :                 else if (fuzzystate->rfirst != NULL)
     659                 :             :                 {
     660                 :             :                         /* Record as provisional second match */
     661                 :           3 :                         fuzzystate->rsecond = rte;
     662                 :           3 :                         fuzzystate->second = attnum;
     663                 :           3 :                 }
     664                 :             :                 else
     665                 :             :                 {
     666                 :             :                         /*
     667                 :             :                          * Do nothing.  When rfirst is NULL, distance is more than what we
     668                 :             :                          * want to consider acceptable, so we should ignore this match.
     669                 :             :                          */
     670                 :             :                 }
     671                 :           7 :         }
     672         [ -  + ]:         383 : }
     673                 :             : 
     674                 :             : /*
     675                 :             :  * scanNSItemForColumn
     676                 :             :  *        Search the column names of a single namespace item for the given name.
     677                 :             :  *        If found, return an appropriate Var node, else return NULL.
     678                 :             :  *        If the name proves ambiguous within this nsitem, raise error.
     679                 :             :  *
     680                 :             :  * Side effect: if we find a match, mark the corresponding RTE as requiring
     681                 :             :  * read access for the column.
     682                 :             :  */
     683                 :             : Node *
     684                 :      149400 : scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
     685                 :             :                                         int sublevels_up, const char *colname, int location)
     686                 :             : {
     687                 :      149400 :         RangeTblEntry *rte = nsitem->p_rte;
     688                 :      149400 :         int                     attnum;
     689                 :      149400 :         Var                *var;
     690                 :             : 
     691                 :             :         /*
     692                 :             :          * Scan the nsitem's column names (or aliases) for a match.  Complain if
     693                 :             :          * multiple matches.
     694                 :             :          */
     695                 :      298800 :         attnum = scanRTEForColumn(pstate, rte, nsitem->p_names,
     696                 :      149400 :                                                           colname, location,
     697                 :             :                                                           0, NULL);
     698                 :             : 
     699         [ +  + ]:      149400 :         if (attnum == InvalidAttrNumber)
     700                 :        9706 :                 return NULL;                    /* Return NULL if no match */
     701                 :             : 
     702                 :             :         /* In constraint check, no system column is allowed except tableOid */
     703         [ +  + ]:      139694 :         if (pstate->p_expr_kind == EXPR_KIND_CHECK_CONSTRAINT &&
     704   [ +  +  +  + ]:         415 :                 attnum < InvalidAttrNumber && attnum != TableOidAttributeNumber)
     705   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     706                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
     707                 :             :                                  errmsg("system column \"%s\" reference in check constraint is invalid",
     708                 :             :                                                 colname),
     709                 :             :                                  parser_errposition(pstate, location)));
     710                 :             : 
     711                 :             :         /*
     712                 :             :          * In generated column, no system column is allowed except tableOid.
     713                 :             :          * (Required for stored generated, but we also do it for virtual generated
     714                 :             :          * for now for consistency.)
     715                 :             :          */
     716         [ +  + ]:      139693 :         if (pstate->p_expr_kind == EXPR_KIND_GENERATED_COLUMN &&
     717   [ +  +  +  + ]:         232 :                 attnum < InvalidAttrNumber && attnum != TableOidAttributeNumber)
     718   [ +  -  +  - ]:           2 :                 ereport(ERROR,
     719                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
     720                 :             :                                  errmsg("cannot use system column \"%s\" in column generation expression",
     721                 :             :                                                 colname),
     722                 :             :                                  parser_errposition(pstate, location)));
     723                 :             : 
     724                 :             :         /*
     725                 :             :          * In a MERGE WHEN condition, no system column is allowed except tableOid
     726                 :             :          */
     727         [ +  + ]:      139691 :         if (pstate->p_expr_kind == EXPR_KIND_MERGE_WHEN &&
     728   [ +  +  +  + ]:         125 :                 attnum < InvalidAttrNumber && attnum != TableOidAttributeNumber)
     729   [ +  -  +  - ]:           1 :                 ereport(ERROR,
     730                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
     731                 :             :                                  errmsg("cannot use system column \"%s\" in MERGE WHEN condition",
     732                 :             :                                                 colname),
     733                 :             :                                  parser_errposition(pstate, location)));
     734                 :             : 
     735                 :             :         /* Found a valid match, so build a Var */
     736         [ +  + ]:      139690 :         if (attnum > InvalidAttrNumber)
     737                 :             :         {
     738                 :             :                 /* Get attribute data from the ParseNamespaceColumn array */
     739                 :      136500 :                 ParseNamespaceColumn *nscol = &nsitem->p_nscolumns[attnum - 1];
     740                 :             : 
     741                 :             :                 /* Complain if dropped column.  See notes in scanRTEForColumn. */
     742         [ +  - ]:      136500 :                 if (nscol->p_varno == 0)
     743   [ #  #  #  # ]:           0 :                         ereport(ERROR,
     744                 :             :                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
     745                 :             :                                          errmsg("column \"%s\" of relation \"%s\" does not exist",
     746                 :             :                                                         colname,
     747                 :             :                                                         nsitem->p_names->aliasname)));
     748                 :             : 
     749                 :      273000 :                 var = makeVar(nscol->p_varno,
     750                 :      136500 :                                           nscol->p_varattno,
     751                 :      136500 :                                           nscol->p_vartype,
     752                 :      136500 :                                           nscol->p_vartypmod,
     753                 :      136500 :                                           nscol->p_varcollid,
     754                 :      136500 :                                           sublevels_up);
     755                 :             :                 /* makeVar doesn't offer parameters for these, so set them by hand: */
     756                 :      136500 :                 var->varnosyn = nscol->p_varnosyn;
     757                 :      136500 :                 var->varattnosyn = nscol->p_varattnosyn;
     758                 :      136500 :         }
     759                 :             :         else
     760                 :             :         {
     761                 :             :                 /* System column, so use predetermined type data */
     762                 :        3190 :                 const FormData_pg_attribute *sysatt;
     763                 :             : 
     764                 :        3190 :                 sysatt = SystemAttributeDefinition(attnum);
     765                 :        6380 :                 var = makeVar(nsitem->p_rtindex,
     766                 :        3190 :                                           attnum,
     767                 :        3190 :                                           sysatt->atttypid,
     768                 :        3190 :                                           sysatt->atttypmod,
     769                 :        3190 :                                           sysatt->attcollation,
     770                 :        3190 :                                           sublevels_up);
     771                 :        3190 :         }
     772                 :      139690 :         var->location = location;
     773                 :             : 
     774                 :             :         /* Mark Var for RETURNING OLD/NEW, as necessary */
     775                 :      139690 :         var->varreturningtype = nsitem->p_returning_type;
     776                 :             : 
     777                 :             :         /* Mark Var if it's nulled by any outer joins */
     778                 :      139690 :         markNullableIfNeeded(pstate, var);
     779                 :             : 
     780                 :             :         /* Require read access to the column */
     781                 :      139690 :         markVarForSelectPriv(pstate, var);
     782                 :             : 
     783                 :      139690 :         return (Node *) var;
     784                 :      149396 : }
     785                 :             : 
     786                 :             : /*
     787                 :             :  * scanRTEForColumn
     788                 :             :  *        Search the column names of a single RTE for the given name.
     789                 :             :  *        If found, return the attnum (possibly negative, for a system column);
     790                 :             :  *        else return InvalidAttrNumber.
     791                 :             :  *        If the name proves ambiguous within this RTE, raise error.
     792                 :             :  *
     793                 :             :  * Actually, we only search the names listed in "eref".  This can be either
     794                 :             :  * rte->eref, in which case we are indeed searching all the column names,
     795                 :             :  * or for a join it can be rte->join_using_alias, in which case we are only
     796                 :             :  * considering the common column names (which are the first N columns of the
     797                 :             :  * join, so everything works).
     798                 :             :  *
     799                 :             :  * pstate and location are passed only for error-reporting purposes.
     800                 :             :  *
     801                 :             :  * Side effect: if fuzzystate is non-NULL, check non-system columns
     802                 :             :  * for an approximate match and update fuzzystate accordingly.
     803                 :             :  *
     804                 :             :  * Note: this is factored out of scanNSItemForColumn because error message
     805                 :             :  * creation may want to check RTEs that are not in the namespace.  To support
     806                 :             :  * that usage, minimize the number of validity checks performed here.  It's
     807                 :             :  * okay to complain about ambiguous-name cases, though, since if we are
     808                 :             :  * working to complain about an invalid name, we've already eliminated that.
     809                 :             :  */
     810                 :             : static int
     811                 :      149469 : scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
     812                 :             :                                  Alias *eref,
     813                 :             :                                  const char *colname, int location,
     814                 :             :                                  int fuzzy_rte_penalty,
     815                 :             :                                  FuzzyAttrMatchState *fuzzystate)
     816                 :             : {
     817                 :      149469 :         int                     result = InvalidAttrNumber;
     818                 :      149469 :         int                     attnum = 0;
     819                 :      149469 :         ListCell   *c;
     820                 :             : 
     821                 :             :         /*
     822                 :             :          * Scan the user column names (or aliases) for a match. Complain if
     823                 :             :          * multiple matches.
     824                 :             :          *
     825                 :             :          * Note: eref->colnames may include entries for dropped columns, but those
     826                 :             :          * will be empty strings that cannot match any legal SQL identifier, so we
     827                 :             :          * don't bother to test for that case here.
     828                 :             :          *
     829                 :             :          * Should this somehow go wrong and we try to access a dropped column,
     830                 :             :          * we'll still catch it by virtue of the check in scanNSItemForColumn().
     831                 :             :          * Callers interested in finding match with shortest distance need to
     832                 :             :          * defend against this directly, though.
     833                 :             :          */
     834   [ +  +  +  +  :     2769660 :         foreach(c, eref->colnames)
                   +  + ]
     835                 :             :         {
     836                 :     2620193 :                 const char *attcolname = strVal(lfirst(c));
     837                 :             : 
     838                 :     2620193 :                 attnum++;
     839         [ +  + ]:     2620193 :                 if (strcmp(attcolname, colname) == 0)
     840                 :             :                 {
     841         [ +  + ]:      136514 :                         if (result)
     842   [ +  -  +  - ]:           2 :                                 ereport(ERROR,
     843                 :             :                                                 (errcode(ERRCODE_AMBIGUOUS_COLUMN),
     844                 :             :                                                  errmsg("column reference \"%s\" is ambiguous",
     845                 :             :                                                                 colname),
     846                 :             :                                                  parser_errposition(pstate, location)));
     847                 :      136512 :                         result = attnum;
     848                 :      136512 :                 }
     849                 :             : 
     850                 :             :                 /* Update fuzzy match state, if provided. */
     851         [ +  + ]:     2620191 :                 if (fuzzystate != NULL)
     852                 :         766 :                         updateFuzzyAttrMatchState(fuzzy_rte_penalty, fuzzystate,
     853                 :         383 :                                                                           rte, attcolname, colname, attnum);
     854                 :     2620191 :         }
     855                 :             : 
     856                 :             :         /*
     857                 :             :          * If we have a unique match, return it.  Note that this allows a user
     858                 :             :          * alias to override a system column name (such as OID) without error.
     859                 :             :          */
     860         [ +  + ]:      149467 :         if (result)
     861                 :      136510 :                 return result;
     862                 :             : 
     863                 :             :         /*
     864                 :             :          * If the RTE represents a real relation, consider system column names.
     865                 :             :          * Composites are only used for pseudo-relations like ON CONFLICT's
     866                 :             :          * excluded.
     867                 :             :          */
     868   [ +  +  +  + ]:       12957 :         if (rte->rtekind == RTE_RELATION &&
     869                 :        8633 :                 rte->relkind != RELKIND_COMPOSITE_TYPE)
     870                 :             :         {
     871                 :             :                 /* quick check to see if name could be a system column */
     872                 :        8624 :                 attnum = specialAttNum(colname);
     873         [ +  + ]:        8624 :                 if (attnum != InvalidAttrNumber)
     874                 :             :                 {
     875                 :             :                         /* now check to see if column actually is defined */
     876         [ -  + ]:        3197 :                         if (SearchSysCacheExists2(ATTNUM,
     877                 :             :                                                                           ObjectIdGetDatum(rte->relid),
     878                 :             :                                                                           Int16GetDatum(attnum)))
     879                 :        3197 :                                 result = attnum;
     880                 :        3197 :                 }
     881                 :        8624 :         }
     882                 :             : 
     883                 :       12957 :         return result;
     884                 :      149467 : }
     885                 :             : 
     886                 :             : /*
     887                 :             :  * colNameToVar
     888                 :             :  *        Search for an unqualified column name.
     889                 :             :  *        If found, return the appropriate Var node (or expression).
     890                 :             :  *        If not found, return NULL.  If the name proves ambiguous, raise error.
     891                 :             :  *        If localonly is true, only names in the innermost query are considered.
     892                 :             :  */
     893                 :             : Node *
     894                 :       56524 : colNameToVar(ParseState *pstate, const char *colname, bool localonly,
     895                 :             :                          int location)
     896                 :             : {
     897                 :       56524 :         Node       *result = NULL;
     898                 :       56524 :         int                     sublevels_up = 0;
     899                 :       56524 :         ParseState *orig_pstate = pstate;
     900                 :             : 
     901         [ +  + ]:       61254 :         while (pstate != NULL)
     902                 :             :         {
     903                 :       57484 :                 ListCell   *l;
     904                 :             : 
     905   [ +  +  +  +  :      132509 :                 foreach(l, pstate->p_namespace)
                   +  + ]
     906                 :             :                 {
     907                 :       75029 :                         ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
     908                 :       75029 :                         Node       *newresult;
     909                 :             : 
     910                 :             :                         /* Ignore table-only items */
     911         [ +  + ]:       75029 :                         if (!nsitem->p_cols_visible)
     912                 :       12636 :                                 continue;
     913                 :             :                         /* If not inside LATERAL, ignore lateral-only items */
     914   [ +  +  +  + ]:       62393 :                         if (nsitem->p_lateral_only && !pstate->p_lateral_active)
     915                 :           7 :                                 continue;
     916                 :             : 
     917                 :             :                         /* use orig_pstate here for consistency with other callers */
     918                 :      124772 :                         newresult = scanNSItemForColumn(orig_pstate, nsitem, sublevels_up,
     919                 :       62386 :                                                                                         colname, location);
     920                 :             : 
     921         [ +  + ]:       62386 :                         if (newresult)
     922                 :             :                         {
     923         [ +  + ]:       52738 :                                 if (result)
     924   [ +  -  +  - ]:           4 :                                         ereport(ERROR,
     925                 :             :                                                         (errcode(ERRCODE_AMBIGUOUS_COLUMN),
     926                 :             :                                                          errmsg("column reference \"%s\" is ambiguous",
     927                 :             :                                                                         colname),
     928                 :             :                                                          parser_errposition(pstate, location)));
     929                 :       52734 :                                 check_lateral_ref_ok(pstate, nsitem, location);
     930                 :       52734 :                                 result = newresult;
     931                 :       52734 :                         }
     932         [ +  + ]:       75025 :                 }
     933                 :             : 
     934   [ +  +  +  + ]:       57480 :                 if (result != NULL || localonly)
     935                 :       52750 :                         break;                          /* found, or don't want to look at parent */
     936                 :             : 
     937                 :        4730 :                 pstate = pstate->parentParseState;
     938                 :        4730 :                 sublevels_up++;
     939         [ +  + ]:       57480 :         }
     940                 :             : 
     941                 :      113040 :         return result;
     942                 :       56520 : }
     943                 :             : 
     944                 :             : /*
     945                 :             :  * searchRangeTableForCol
     946                 :             :  *        See if any RangeTblEntry could possibly provide the given column name (or
     947                 :             :  *        find the best match available).  Returns state with relevant details.
     948                 :             :  *
     949                 :             :  * This is different from colNameToVar in that it considers every entry in
     950                 :             :  * the ParseState's rangetable(s), not only those that are currently visible
     951                 :             :  * in the p_namespace list(s).  This behavior is invalid per the SQL spec,
     952                 :             :  * and it may give ambiguous results (since there might be multiple equally
     953                 :             :  * valid matches).  This must be used ONLY as a heuristic in giving suitable
     954                 :             :  * error messages.  See errorMissingColumn.
     955                 :             :  *
     956                 :             :  * This function is also different in that it will consider approximate
     957                 :             :  * matches -- if the user entered an alias/column pair that is only slightly
     958                 :             :  * different from a valid pair, we may be able to infer what they meant to
     959                 :             :  * type and provide a reasonable hint.  We return a FuzzyAttrMatchState
     960                 :             :  * struct providing information about both exact and approximate matches.
     961                 :             :  */
     962                 :             : static FuzzyAttrMatchState *
     963                 :          59 : searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colname,
     964                 :             :                                            int location)
     965                 :             : {
     966                 :          59 :         ParseState *orig_pstate = pstate;
     967                 :          59 :         FuzzyAttrMatchState *fuzzystate = palloc_object(FuzzyAttrMatchState);
     968                 :             : 
     969                 :          59 :         fuzzystate->distance = MAX_FUZZY_DISTANCE + 1;
     970                 :          59 :         fuzzystate->rfirst = NULL;
     971                 :          59 :         fuzzystate->rsecond = NULL;
     972                 :          59 :         fuzzystate->rexact1 = NULL;
     973                 :          59 :         fuzzystate->rexact2 = NULL;
     974                 :             : 
     975         [ +  + ]:         123 :         while (pstate != NULL)
     976                 :             :         {
     977                 :          64 :                 ListCell   *l;
     978                 :             : 
     979   [ +  +  +  +  :         140 :                 foreach(l, pstate->p_rtable)
                   +  + ]
     980                 :             :                 {
     981                 :          76 :                         RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
     982                 :          76 :                         int                     fuzzy_rte_penalty = 0;
     983                 :          76 :                         int                     attnum;
     984                 :             : 
     985                 :             :                         /*
     986                 :             :                          * Typically, it is not useful to look for matches within join
     987                 :             :                          * RTEs; they effectively duplicate other RTEs for our purposes,
     988                 :             :                          * and if a match is chosen from a join RTE, an unhelpful alias is
     989                 :             :                          * displayed in the final diagnostic message.
     990                 :             :                          */
     991         [ +  + ]:          76 :                         if (rte->rtekind == RTE_JOIN)
     992                 :           9 :                                 continue;
     993                 :             : 
     994                 :             :                         /*
     995                 :             :                          * If the user didn't specify an alias, then matches against one
     996                 :             :                          * RTE are as good as another.  But if the user did specify an
     997                 :             :                          * alias, then we want at least a fuzzy - and preferably an exact
     998                 :             :                          * - match for the range table entry.
     999                 :             :                          */
    1000         [ +  + ]:          67 :                         if (alias != NULL)
    1001                 :          19 :                                 fuzzy_rte_penalty =
    1002                 :          38 :                                         varstr_levenshtein_less_equal(alias, strlen(alias),
    1003                 :          19 :                                                                                                   rte->eref->aliasname,
    1004                 :          19 :                                                                                                   strlen(rte->eref->aliasname),
    1005                 :             :                                                                                                   1, 1, 1,
    1006                 :             :                                                                                                   MAX_FUZZY_DISTANCE + 1,
    1007                 :             :                                                                                                   true);
    1008                 :             : 
    1009                 :             :                         /*
    1010                 :             :                          * Scan for a matching column, and update fuzzystate.  Non-exact
    1011                 :             :                          * matches are dealt with inside scanRTEForColumn, but exact
    1012                 :             :                          * matches are handled here.  (There won't be more than one exact
    1013                 :             :                          * match in the same RTE, else we'd have thrown error earlier.)
    1014                 :             :                          */
    1015                 :         134 :                         attnum = scanRTEForColumn(orig_pstate, rte, rte->eref,
    1016                 :          67 :                                                                           colname, location,
    1017                 :          67 :                                                                           fuzzy_rte_penalty, fuzzystate);
    1018   [ +  +  +  + ]:          67 :                         if (attnum != InvalidAttrNumber && fuzzy_rte_penalty == 0)
    1019                 :             :                         {
    1020         [ +  + ]:          10 :                                 if (fuzzystate->rexact1 == NULL)
    1021                 :             :                                 {
    1022                 :           7 :                                         fuzzystate->rexact1 = rte;
    1023                 :           7 :                                         fuzzystate->exact1 = attnum;
    1024                 :           7 :                                 }
    1025                 :             :                                 else
    1026                 :             :                                 {
    1027                 :             :                                         /* Needn't worry about overwriting previous rexact2 */
    1028                 :           3 :                                         fuzzystate->rexact2 = rte;
    1029                 :           3 :                                         fuzzystate->exact2 = attnum;
    1030                 :             :                                 }
    1031                 :          10 :                         }
    1032      [ -  +  + ]:          76 :                 }
    1033                 :             : 
    1034                 :          64 :                 pstate = pstate->parentParseState;
    1035                 :          64 :         }
    1036                 :             : 
    1037                 :         118 :         return fuzzystate;
    1038                 :          59 : }
    1039                 :             : 
    1040                 :             : /*
    1041                 :             :  * markNullableIfNeeded
    1042                 :             :  *              If the RTE referenced by the Var is nullable by outer join(s)
    1043                 :             :  *              at this point in the query, set var->varnullingrels to show that.
    1044                 :             :  */
    1045                 :             : void
    1046                 :      432328 : markNullableIfNeeded(ParseState *pstate, Var *var)
    1047                 :             : {
    1048                 :      432328 :         int                     rtindex = var->varno;
    1049                 :      432328 :         Bitmapset  *relids;
    1050                 :             : 
    1051                 :             :         /* Find the appropriate pstate */
    1052         [ +  + ]:      439936 :         for (int lv = 0; lv < var->varlevelsup; lv++)
    1053                 :        7608 :                 pstate = pstate->parentParseState;
    1054                 :             : 
    1055                 :             :         /* Find currently-relevant join relids for the Var's rel */
    1056   [ +  -  +  + ]:      432328 :         if (rtindex > 0 && rtindex <= list_length(pstate->p_nullingrels))
    1057                 :      182587 :                 relids = (Bitmapset *) list_nth(pstate->p_nullingrels, rtindex - 1);
    1058                 :             :         else
    1059                 :      249741 :                 relids = NULL;
    1060                 :             : 
    1061                 :             :         /*
    1062                 :             :          * Merge with any already-declared nulling rels.  (Typically there won't
    1063                 :             :          * be any, but let's get it right if there are.)
    1064                 :             :          */
    1065         [ +  + ]:      432328 :         if (relids != NULL)
    1066                 :       74862 :                 var->varnullingrels = bms_union(var->varnullingrels, relids);
    1067                 :      432328 : }
    1068                 :             : 
    1069                 :             : /*
    1070                 :             :  * markRTEForSelectPriv
    1071                 :             :  *         Mark the specified column of the RTE with index rtindex
    1072                 :             :  *         as requiring SELECT privilege
    1073                 :             :  *
    1074                 :             :  * col == InvalidAttrNumber means a "whole row" reference
    1075                 :             :  */
    1076                 :             : static void
    1077                 :      170877 : markRTEForSelectPriv(ParseState *pstate, int rtindex, AttrNumber col)
    1078                 :             : {
    1079                 :      170877 :         RangeTblEntry *rte = rt_fetch(rtindex, pstate->p_rtable);
    1080                 :             : 
    1081         [ +  + ]:      170877 :         if (rte->rtekind == RTE_RELATION)
    1082                 :             :         {
    1083                 :      155677 :                 RTEPermissionInfo *perminfo;
    1084                 :             : 
    1085                 :             :                 /* Make sure the rel as a whole is marked for SELECT access */
    1086                 :      155677 :                 perminfo = getRTEPermissionInfo(pstate->p_rteperminfos, rte);
    1087                 :      155677 :                 perminfo->requiredPerms |= ACL_SELECT;
    1088                 :             :                 /* Must offset the attnum to fit in a bitmapset */
    1089                 :      155677 :                 perminfo->selectedCols =
    1090                 :      311354 :                         bms_add_member(perminfo->selectedCols,
    1091                 :      155677 :                                                    col - FirstLowInvalidHeapAttributeNumber);
    1092                 :      155677 :         }
    1093         [ +  + ]:       15200 :         else if (rte->rtekind == RTE_JOIN)
    1094                 :             :         {
    1095         [ +  + ]:          70 :                 if (col == InvalidAttrNumber)
    1096                 :             :                 {
    1097                 :             :                         /*
    1098                 :             :                          * A whole-row reference to a join has to be treated as whole-row
    1099                 :             :                          * references to the two inputs.
    1100                 :             :                          */
    1101                 :           1 :                         JoinExpr   *j;
    1102                 :             : 
    1103   [ +  -  -  + ]:           1 :                         if (rtindex > 0 && rtindex <= list_length(pstate->p_joinexprs))
    1104                 :           1 :                                 j = list_nth_node(JoinExpr, pstate->p_joinexprs, rtindex - 1);
    1105                 :             :                         else
    1106                 :           0 :                                 j = NULL;
    1107         [ +  - ]:           1 :                         if (j == NULL)
    1108   [ #  #  #  # ]:           0 :                                 elog(ERROR, "could not find JoinExpr for whole-row reference");
    1109                 :             : 
    1110                 :             :                         /* Note: we can't see FromExpr here */
    1111         [ +  - ]:           1 :                         if (IsA(j->larg, RangeTblRef))
    1112                 :             :                         {
    1113                 :           1 :                                 int                     varno = ((RangeTblRef *) j->larg)->rtindex;
    1114                 :             : 
    1115                 :           1 :                                 markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
    1116                 :           1 :                         }
    1117         [ #  # ]:           0 :                         else if (IsA(j->larg, JoinExpr))
    1118                 :             :                         {
    1119                 :           0 :                                 int                     varno = ((JoinExpr *) j->larg)->rtindex;
    1120                 :             : 
    1121                 :           0 :                                 markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
    1122                 :           0 :                         }
    1123                 :             :                         else
    1124   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unrecognized node type: %d",
    1125                 :             :                                          (int) nodeTag(j->larg));
    1126         [ +  - ]:           1 :                         if (IsA(j->rarg, RangeTblRef))
    1127                 :             :                         {
    1128                 :           1 :                                 int                     varno = ((RangeTblRef *) j->rarg)->rtindex;
    1129                 :             : 
    1130                 :           1 :                                 markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
    1131                 :           1 :                         }
    1132         [ #  # ]:           0 :                         else if (IsA(j->rarg, JoinExpr))
    1133                 :             :                         {
    1134                 :           0 :                                 int                     varno = ((JoinExpr *) j->rarg)->rtindex;
    1135                 :             : 
    1136                 :           0 :                                 markRTEForSelectPriv(pstate, varno, InvalidAttrNumber);
    1137                 :           0 :                         }
    1138                 :             :                         else
    1139   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unrecognized node type: %d",
    1140                 :             :                                          (int) nodeTag(j->rarg));
    1141                 :           1 :                 }
    1142                 :             :                 else
    1143                 :             :                 {
    1144                 :             :                         /*
    1145                 :             :                          * Join alias Vars for ordinary columns must refer to merged JOIN
    1146                 :             :                          * USING columns.  We don't need to do anything here, because the
    1147                 :             :                          * join input columns will also be referenced in the join's qual
    1148                 :             :                          * clause, and will get marked for select privilege there.
    1149                 :             :                          */
    1150                 :             :                 }
    1151                 :          70 :         }
    1152                 :             :         /* other RTE types don't require privilege marking */
    1153                 :      170877 : }
    1154                 :             : 
    1155                 :             : /*
    1156                 :             :  * markVarForSelectPriv
    1157                 :             :  *         Mark the RTE referenced by the Var as requiring SELECT privilege
    1158                 :             :  *         for the Var's column (the Var could be a whole-row Var, too)
    1159                 :             :  */
    1160                 :             : void
    1161                 :      170875 : markVarForSelectPriv(ParseState *pstate, Var *var)
    1162                 :             : {
    1163                 :      170875 :         Index           lv;
    1164                 :             : 
    1165         [ +  - ]:      170875 :         Assert(IsA(var, Var));
    1166                 :             :         /* Find the appropriate pstate if it's an uplevel Var */
    1167         [ +  + ]:      178483 :         for (lv = 0; lv < var->varlevelsup; lv++)
    1168                 :        7608 :                 pstate = pstate->parentParseState;
    1169                 :      170875 :         markRTEForSelectPriv(pstate, var->varno, var->varattno);
    1170                 :      170875 : }
    1171                 :             : 
    1172                 :             : /*
    1173                 :             :  * buildRelationAliases
    1174                 :             :  *              Construct the eref column name list for a relation RTE.
    1175                 :             :  *              This code is also used for function RTEs.
    1176                 :             :  *
    1177                 :             :  * tupdesc: the physical column information
    1178                 :             :  * alias: the user-supplied alias, or NULL if none
    1179                 :             :  * eref: the eref Alias to store column names in
    1180                 :             :  *
    1181                 :             :  * eref->colnames is filled in.  Also, alias->colnames is rebuilt to insert
    1182                 :             :  * empty strings for any dropped columns, so that it will be one-to-one with
    1183                 :             :  * physical column numbers.
    1184                 :             :  *
    1185                 :             :  * It is an error for there to be more aliases present than required.
    1186                 :             :  */
    1187                 :             : static void
    1188                 :       57167 : buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
    1189                 :             : {
    1190                 :       57167 :         int                     maxattrs = tupdesc->natts;
    1191                 :       57167 :         List       *aliaslist;
    1192                 :       57167 :         ListCell   *aliaslc;
    1193                 :       57167 :         int                     numaliases;
    1194                 :       57167 :         int                     varattno;
    1195                 :       57167 :         int                     numdropped = 0;
    1196                 :             : 
    1197         [ +  - ]:       57167 :         Assert(eref->colnames == NIL);
    1198                 :             : 
    1199         [ +  + ]:       57167 :         if (alias)
    1200                 :             :         {
    1201                 :       24751 :                 aliaslist = alias->colnames;
    1202                 :       24751 :                 aliaslc = list_head(aliaslist);
    1203                 :       24751 :                 numaliases = list_length(aliaslist);
    1204                 :             :                 /* We'll rebuild the alias colname list */
    1205                 :       24751 :                 alias->colnames = NIL;
    1206                 :       24751 :         }
    1207                 :             :         else
    1208                 :             :         {
    1209                 :       32416 :                 aliaslist = NIL;
    1210                 :       32416 :                 aliaslc = NULL;
    1211                 :       32416 :                 numaliases = 0;
    1212                 :             :         }
    1213                 :             : 
    1214         [ +  + ]:      598860 :         for (varattno = 0; varattno < maxattrs; varattno++)
    1215                 :             :         {
    1216                 :      541693 :                 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
    1217                 :      541693 :                 String     *attrname;
    1218                 :             : 
    1219         [ +  + ]:      541693 :                 if (attr->attisdropped)
    1220                 :             :                 {
    1221                 :             :                         /* Always insert an empty string for a dropped column */
    1222                 :         594 :                         attrname = makeString(pstrdup(""));
    1223         [ +  - ]:         594 :                         if (aliaslc)
    1224                 :           0 :                                 alias->colnames = lappend(alias->colnames, attrname);
    1225                 :         594 :                         numdropped++;
    1226                 :         594 :                 }
    1227         [ +  + ]:      541099 :                 else if (aliaslc)
    1228                 :             :                 {
    1229                 :             :                         /* Use the next user-supplied alias */
    1230                 :         679 :                         attrname = lfirst_node(String, aliaslc);
    1231                 :         679 :                         aliaslc = lnext(aliaslist, aliaslc);
    1232                 :         679 :                         alias->colnames = lappend(alias->colnames, attrname);
    1233                 :         679 :                 }
    1234                 :             :                 else
    1235                 :             :                 {
    1236                 :      540420 :                         attrname = makeString(pstrdup(NameStr(attr->attname)));
    1237                 :             :                         /* we're done with the alias if any */
    1238                 :             :                 }
    1239                 :             : 
    1240                 :      541693 :                 eref->colnames = lappend(eref->colnames, attrname);
    1241                 :      541693 :         }
    1242                 :             : 
    1243                 :             :         /* Too many user-supplied aliases? */
    1244         [ +  + ]:       57167 :         if (aliaslc)
    1245   [ +  -  +  - ]:           1 :                 ereport(ERROR,
    1246                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    1247                 :             :                                  errmsg("table \"%s\" has %d columns available but %d columns specified",
    1248                 :             :                                                 eref->aliasname, maxattrs - numdropped, numaliases)));
    1249                 :       57166 : }
    1250                 :             : 
    1251                 :             : /*
    1252                 :             :  * chooseScalarFunctionAlias
    1253                 :             :  *              Select the column alias for a function in a function RTE,
    1254                 :             :  *              when the function returns a scalar type (not composite or RECORD).
    1255                 :             :  *
    1256                 :             :  * funcexpr: transformed expression tree for the function call
    1257                 :             :  * funcname: function name (as determined by FigureColname)
    1258                 :             :  * alias: the user-supplied alias for the RTE, or NULL if none
    1259                 :             :  * nfuncs: the number of functions appearing in the function RTE
    1260                 :             :  *
    1261                 :             :  * Note that the name we choose might be overridden later, if the user-given
    1262                 :             :  * alias includes column alias names.  That's of no concern here.
    1263                 :             :  */
    1264                 :             : static char *
    1265                 :        2224 : chooseScalarFunctionAlias(Node *funcexpr, char *funcname,
    1266                 :             :                                                   Alias *alias, int nfuncs)
    1267                 :             : {
    1268                 :        2224 :         char       *pname;
    1269                 :             : 
    1270                 :             :         /*
    1271                 :             :          * If the expression is a simple function call, and the function has a
    1272                 :             :          * single OUT parameter that is named, use the parameter's name.
    1273                 :             :          */
    1274   [ +  -  +  + ]:        2224 :         if (funcexpr && IsA(funcexpr, FuncExpr))
    1275                 :             :         {
    1276                 :        2205 :                 pname = get_func_result_name(((FuncExpr *) funcexpr)->funcid);
    1277         [ +  + ]:        2205 :                 if (pname)
    1278                 :         224 :                         return pname;
    1279                 :        1981 :         }
    1280                 :             : 
    1281                 :             :         /*
    1282                 :             :          * If there's just one function in the RTE, and the user gave an RTE alias
    1283                 :             :          * name, use that name.  (This makes FROM func() AS foo use "foo" as the
    1284                 :             :          * column name as well as the table alias.)
    1285                 :             :          */
    1286   [ +  +  +  + ]:        2000 :         if (nfuncs == 1 && alias)
    1287                 :        1724 :                 return alias->aliasname;
    1288                 :             : 
    1289                 :             :         /*
    1290                 :             :          * Otherwise use the function name.
    1291                 :             :          */
    1292                 :         276 :         return funcname;
    1293                 :        2224 : }
    1294                 :             : 
    1295                 :             : /*
    1296                 :             :  * buildNSItemFromTupleDesc
    1297                 :             :  *              Build a ParseNamespaceItem, given a tupdesc describing the columns.
    1298                 :             :  *
    1299                 :             :  * rte: the new RangeTblEntry for the rel
    1300                 :             :  * rtindex: its index in the rangetable list
    1301                 :             :  * perminfo: permission list entry for the rel
    1302                 :             :  * tupdesc: the physical column information
    1303                 :             :  */
    1304                 :             : static ParseNamespaceItem *
    1305                 :       57166 : buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex,
    1306                 :             :                                                  RTEPermissionInfo *perminfo,
    1307                 :             :                                                  TupleDesc tupdesc)
    1308                 :             : {
    1309                 :       57166 :         ParseNamespaceItem *nsitem;
    1310                 :       57166 :         ParseNamespaceColumn *nscolumns;
    1311                 :       57166 :         int                     maxattrs = tupdesc->natts;
    1312                 :       57166 :         int                     varattno;
    1313                 :             : 
    1314                 :             :         /* colnames must have the same number of entries as the nsitem */
    1315         [ +  - ]:       57166 :         Assert(maxattrs == list_length(rte->eref->colnames));
    1316                 :             : 
    1317                 :             :         /* extract per-column data from the tupdesc */
    1318                 :       57166 :         nscolumns = (ParseNamespaceColumn *)
    1319                 :       57166 :                 palloc0(maxattrs * sizeof(ParseNamespaceColumn));
    1320                 :             : 
    1321         [ +  + ]:      598858 :         for (varattno = 0; varattno < maxattrs; varattno++)
    1322                 :             :         {
    1323                 :      541692 :                 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
    1324                 :             : 
    1325                 :             :                 /* For a dropped column, just leave the entry as zeroes */
    1326         [ +  + ]:      541692 :                 if (attr->attisdropped)
    1327                 :         594 :                         continue;
    1328                 :             : 
    1329                 :      541098 :                 nscolumns[varattno].p_varno = rtindex;
    1330                 :      541098 :                 nscolumns[varattno].p_varattno = varattno + 1;
    1331                 :      541098 :                 nscolumns[varattno].p_vartype = attr->atttypid;
    1332                 :      541098 :                 nscolumns[varattno].p_vartypmod = attr->atttypmod;
    1333                 :      541098 :                 nscolumns[varattno].p_varcollid = attr->attcollation;
    1334                 :      541098 :                 nscolumns[varattno].p_varnosyn = rtindex;
    1335                 :      541098 :                 nscolumns[varattno].p_varattnosyn = varattno + 1;
    1336      [ -  +  + ]:      541692 :         }
    1337                 :             : 
    1338                 :             :         /* ... and build the nsitem */
    1339                 :       57166 :         nsitem = palloc_object(ParseNamespaceItem);
    1340                 :       57166 :         nsitem->p_names = rte->eref;
    1341                 :       57166 :         nsitem->p_rte = rte;
    1342                 :       57166 :         nsitem->p_rtindex = rtindex;
    1343                 :       57166 :         nsitem->p_perminfo = perminfo;
    1344                 :       57166 :         nsitem->p_nscolumns = nscolumns;
    1345                 :             :         /* set default visibility flags; might get changed later */
    1346                 :       57166 :         nsitem->p_rel_visible = true;
    1347                 :       57166 :         nsitem->p_cols_visible = true;
    1348                 :       57166 :         nsitem->p_lateral_only = false;
    1349                 :       57166 :         nsitem->p_lateral_ok = true;
    1350                 :       57166 :         nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
    1351                 :             : 
    1352                 :      114332 :         return nsitem;
    1353                 :       57166 : }
    1354                 :             : 
    1355                 :             : /*
    1356                 :             :  * buildNSItemFromLists
    1357                 :             :  *              Build a ParseNamespaceItem, given column type information in lists.
    1358                 :             :  *
    1359                 :             :  * rte: the new RangeTblEntry for the rel
    1360                 :             :  * rtindex: its index in the rangetable list
    1361                 :             :  * coltypes: per-column datatype OIDs
    1362                 :             :  * coltypmods: per-column type modifiers
    1363                 :             :  * colcollation: per-column collation OIDs
    1364                 :             :  */
    1365                 :             : static ParseNamespaceItem *
    1366                 :        9881 : buildNSItemFromLists(RangeTblEntry *rte, Index rtindex,
    1367                 :             :                                          List *coltypes, List *coltypmods, List *colcollations)
    1368                 :             : {
    1369                 :        9881 :         ParseNamespaceItem *nsitem;
    1370                 :        9881 :         ParseNamespaceColumn *nscolumns;
    1371                 :        9881 :         int                     maxattrs = list_length(coltypes);
    1372                 :        9881 :         int                     varattno;
    1373                 :        9881 :         ListCell   *lct;
    1374                 :        9881 :         ListCell   *lcm;
    1375                 :        9881 :         ListCell   *lcc;
    1376                 :             : 
    1377                 :             :         /* colnames must have the same number of entries as the nsitem */
    1378         [ +  - ]:        9881 :         Assert(maxattrs == list_length(rte->eref->colnames));
    1379                 :             : 
    1380         [ +  - ]:        9881 :         Assert(maxattrs == list_length(coltypmods));
    1381         [ +  - ]:        9881 :         Assert(maxattrs == list_length(colcollations));
    1382                 :             : 
    1383                 :             :         /* extract per-column data from the lists */
    1384                 :        9881 :         nscolumns = (ParseNamespaceColumn *)
    1385                 :        9881 :                 palloc0(maxattrs * sizeof(ParseNamespaceColumn));
    1386                 :             : 
    1387                 :        9881 :         varattno = 0;
    1388   [ +  +  +  +  :       29244 :         forthree(lct, coltypes,
          +  +  +  +  +  
          +  +  +  +  +  
             -  +  +  + ]
    1389                 :             :                          lcm, coltypmods,
    1390                 :             :                          lcc, colcollations)
    1391                 :             :         {
    1392                 :       19363 :                 nscolumns[varattno].p_varno = rtindex;
    1393                 :       19363 :                 nscolumns[varattno].p_varattno = varattno + 1;
    1394                 :       19363 :                 nscolumns[varattno].p_vartype = lfirst_oid(lct);
    1395                 :       19363 :                 nscolumns[varattno].p_vartypmod = lfirst_int(lcm);
    1396                 :       19363 :                 nscolumns[varattno].p_varcollid = lfirst_oid(lcc);
    1397                 :       19363 :                 nscolumns[varattno].p_varnosyn = rtindex;
    1398                 :       19363 :                 nscolumns[varattno].p_varattnosyn = varattno + 1;
    1399                 :       19363 :                 varattno++;
    1400                 :       19363 :         }
    1401                 :             : 
    1402                 :             :         /* ... and build the nsitem */
    1403                 :        9881 :         nsitem = palloc_object(ParseNamespaceItem);
    1404                 :        9881 :         nsitem->p_names = rte->eref;
    1405                 :        9881 :         nsitem->p_rte = rte;
    1406                 :        9881 :         nsitem->p_rtindex = rtindex;
    1407                 :        9881 :         nsitem->p_perminfo = NULL;
    1408                 :        9881 :         nsitem->p_nscolumns = nscolumns;
    1409                 :             :         /* set default visibility flags; might get changed later */
    1410                 :        9881 :         nsitem->p_rel_visible = true;
    1411                 :        9881 :         nsitem->p_cols_visible = true;
    1412                 :        9881 :         nsitem->p_lateral_only = false;
    1413                 :        9881 :         nsitem->p_lateral_ok = true;
    1414                 :        9881 :         nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
    1415                 :             : 
    1416                 :       19762 :         return nsitem;
    1417                 :        9881 : }
    1418                 :             : 
    1419                 :             : /*
    1420                 :             :  * Open a table during parse analysis
    1421                 :             :  *
    1422                 :             :  * This is essentially just the same as table_openrv(), except that it caters
    1423                 :             :  * to some parser-specific error reporting needs, notably that it arranges
    1424                 :             :  * to include the RangeVar's parse location in any resulting error.
    1425                 :             :  *
    1426                 :             :  * Note: properly, lockmode should be declared LOCKMODE not int, but that
    1427                 :             :  * would require importing storage/lock.h into parse_relation.h.  Since
    1428                 :             :  * LOCKMODE is typedef'd as int anyway, that seems like overkill.
    1429                 :             :  */
    1430                 :             : Relation
    1431                 :       44900 : parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockmode)
    1432                 :             : {
    1433                 :       44900 :         Relation        rel;
    1434                 :       44900 :         ParseCallbackState pcbstate;
    1435                 :             : 
    1436                 :       44900 :         setup_parser_errposition_callback(&pcbstate, pstate, relation->location);
    1437                 :       44900 :         rel = table_openrv_extended(relation, lockmode, true);
    1438         [ +  + ]:       44900 :         if (rel == NULL)
    1439                 :             :         {
    1440         [ -  + ]:          22 :                 if (relation->schemaname)
    1441   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    1442                 :             :                                         (errcode(ERRCODE_UNDEFINED_TABLE),
    1443                 :             :                                          errmsg("relation \"%s.%s\" does not exist",
    1444                 :             :                                                         relation->schemaname, relation->relname)));
    1445                 :             :                 else
    1446                 :             :                 {
    1447                 :             :                         /*
    1448                 :             :                          * An unqualified name might have been meant as a reference to
    1449                 :             :                          * some not-yet-in-scope CTE.  The bare "does not exist" message
    1450                 :             :                          * has proven remarkably unhelpful for figuring out such problems,
    1451                 :             :                          * so we take pains to offer a specific hint.
    1452                 :             :                          */
    1453         [ +  + ]:          22 :                         if (isFutureCTE(pstate, relation->relname))
    1454   [ +  -  +  - ]:           1 :                                 ereport(ERROR,
    1455                 :             :                                                 (errcode(ERRCODE_UNDEFINED_TABLE),
    1456                 :             :                                                  errmsg("relation \"%s\" does not exist",
    1457                 :             :                                                                 relation->relname),
    1458                 :             :                                                  errdetail("There is a WITH item named \"%s\", but it cannot be referenced from this part of the query.",
    1459                 :             :                                                                    relation->relname),
    1460                 :             :                                                  errhint("Use WITH RECURSIVE, or re-order the WITH items to remove forward references.")));
    1461                 :             :                         else
    1462   [ +  -  +  - ]:          21 :                                 ereport(ERROR,
    1463                 :             :                                                 (errcode(ERRCODE_UNDEFINED_TABLE),
    1464                 :             :                                                  errmsg("relation \"%s\" does not exist",
    1465                 :             :                                                                 relation->relname)));
    1466                 :             :                 }
    1467                 :           0 :         }
    1468                 :       44878 :         cancel_parser_errposition_callback(&pcbstate);
    1469                 :       89756 :         return rel;
    1470                 :       44878 : }
    1471                 :             : 
    1472                 :             : /*
    1473                 :             :  * Add an entry for a relation to the pstate's range table (p_rtable).
    1474                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    1475                 :             :  *
    1476                 :             :  * We do not link the ParseNamespaceItem into the pstate here; it's the
    1477                 :             :  * caller's job to do that in the appropriate way.
    1478                 :             :  *
    1479                 :             :  * Note: formerly this checked for refname conflicts, but that's wrong.
    1480                 :             :  * Caller is responsible for checking for conflicts in the appropriate scope.
    1481                 :             :  */
    1482                 :             : ParseNamespaceItem *
    1483                 :       37316 : addRangeTableEntry(ParseState *pstate,
    1484                 :             :                                    RangeVar *relation,
    1485                 :             :                                    Alias *alias,
    1486                 :             :                                    bool inh,
    1487                 :             :                                    bool inFromCl)
    1488                 :             : {
    1489                 :       37316 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    1490                 :       37316 :         RTEPermissionInfo *perminfo;
    1491         [ +  + ]:       37316 :         char       *refname = alias ? alias->aliasname : relation->relname;
    1492                 :       37316 :         LOCKMODE        lockmode;
    1493                 :       37316 :         Relation        rel;
    1494                 :       37316 :         ParseNamespaceItem *nsitem;
    1495                 :             : 
    1496         [ +  - ]:       37316 :         Assert(pstate != NULL);
    1497                 :             : 
    1498                 :       37316 :         rte->rtekind = RTE_RELATION;
    1499                 :       37316 :         rte->alias = alias;
    1500                 :             : 
    1501                 :             :         /*
    1502                 :             :          * Identify the type of lock we'll need on this relation.  It's not the
    1503                 :             :          * query's target table (that case is handled elsewhere), so we need
    1504                 :             :          * either RowShareLock if it's locked by FOR UPDATE/SHARE, or plain
    1505                 :             :          * AccessShareLock otherwise.
    1506                 :             :          */
    1507                 :       37316 :         lockmode = isLockedRefname(pstate, refname) ? RowShareLock : AccessShareLock;
    1508                 :             : 
    1509                 :             :         /*
    1510                 :             :          * Get the rel's OID.  This access also ensures that we have an up-to-date
    1511                 :             :          * relcache entry for the rel.  Since this is typically the first access
    1512                 :             :          * to a rel in a statement, we must open the rel with the proper lockmode.
    1513                 :             :          */
    1514                 :       37316 :         rel = parserOpenTable(pstate, relation, lockmode);
    1515                 :       37316 :         rte->relid = RelationGetRelid(rel);
    1516                 :       37316 :         rte->inh = inh;
    1517                 :       37316 :         rte->relkind = rel->rd_rel->relkind;
    1518                 :       37316 :         rte->rellockmode = lockmode;
    1519                 :             : 
    1520                 :             :         /*
    1521                 :             :          * Build the list of effective column names using user-supplied aliases
    1522                 :             :          * and/or actual column names.
    1523                 :             :          */
    1524                 :       37316 :         rte->eref = makeAlias(refname, NIL);
    1525                 :       37316 :         buildRelationAliases(rel->rd_att, alias, rte->eref);
    1526                 :             : 
    1527                 :             :         /*
    1528                 :             :          * Set flags and initialize access permissions.
    1529                 :             :          *
    1530                 :             :          * The initial default on access checks is always check-for-READ-access,
    1531                 :             :          * which is the right thing for all except target tables.
    1532                 :             :          */
    1533                 :       37316 :         rte->lateral = false;
    1534                 :       37316 :         rte->inFromCl = inFromCl;
    1535                 :             : 
    1536                 :       37316 :         perminfo = addRTEPermissionInfo(&pstate->p_rteperminfos, rte);
    1537                 :       37316 :         perminfo->requiredPerms = ACL_SELECT;
    1538                 :             : 
    1539                 :             :         /*
    1540                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    1541                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    1542                 :             :          * appropriate.
    1543                 :             :          */
    1544                 :       37316 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    1545                 :             : 
    1546                 :             :         /*
    1547                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    1548                 :             :          * list --- caller must do that if appropriate.
    1549                 :             :          */
    1550                 :       74632 :         nsitem = buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
    1551                 :       37316 :                                                                           perminfo, rel->rd_att);
    1552                 :             : 
    1553                 :             :         /*
    1554                 :             :          * Drop the rel refcount, but keep the access lock till end of transaction
    1555                 :             :          * so that the table can't be deleted or have its schema modified
    1556                 :             :          * underneath us.
    1557                 :             :          */
    1558                 :       37316 :         table_close(rel, NoLock);
    1559                 :             : 
    1560                 :       74632 :         return nsitem;
    1561                 :       37316 : }
    1562                 :             : 
    1563                 :             : /*
    1564                 :             :  * Add an entry for a relation to the pstate's range table (p_rtable).
    1565                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    1566                 :             :  *
    1567                 :             :  * This is just like addRangeTableEntry() except that it makes an RTE
    1568                 :             :  * given an already-open relation instead of a RangeVar reference.
    1569                 :             :  *
    1570                 :             :  * lockmode is the lock type required for query execution; it must be one
    1571                 :             :  * of AccessShareLock, RowShareLock, or RowExclusiveLock depending on the
    1572                 :             :  * RTE's role within the query.  The caller must hold that lock mode
    1573                 :             :  * or a stronger one.
    1574                 :             :  *
    1575                 :             :  * Note: properly, lockmode should be declared LOCKMODE not int, but that
    1576                 :             :  * would require importing storage/lock.h into parse_relation.h.  Since
    1577                 :             :  * LOCKMODE is typedef'd as int anyway, that seems like overkill.
    1578                 :             :  */
    1579                 :             : ParseNamespaceItem *
    1580                 :       16249 : addRangeTableEntryForRelation(ParseState *pstate,
    1581                 :             :                                                           Relation rel,
    1582                 :             :                                                           int lockmode,
    1583                 :             :                                                           Alias *alias,
    1584                 :             :                                                           bool inh,
    1585                 :             :                                                           bool inFromCl)
    1586                 :             : {
    1587                 :       16249 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    1588                 :       16249 :         RTEPermissionInfo *perminfo;
    1589         [ +  + ]:       16249 :         char       *refname = alias ? alias->aliasname : RelationGetRelationName(rel);
    1590                 :             : 
    1591         [ +  - ]:       16249 :         Assert(pstate != NULL);
    1592                 :             : 
    1593   [ +  +  +  -  :       16249 :         Assert(lockmode == AccessShareLock ||
                   +  - ]
    1594                 :             :                    lockmode == RowShareLock ||
    1595                 :             :                    lockmode == RowExclusiveLock);
    1596         [ +  - ]:       16249 :         Assert(CheckRelationLockedByMe(rel, lockmode, true));
    1597                 :             : 
    1598                 :       16249 :         rte->rtekind = RTE_RELATION;
    1599                 :       16249 :         rte->alias = alias;
    1600                 :       16249 :         rte->relid = RelationGetRelid(rel);
    1601                 :       16249 :         rte->inh = inh;
    1602                 :       16249 :         rte->relkind = rel->rd_rel->relkind;
    1603                 :       16249 :         rte->rellockmode = lockmode;
    1604                 :             : 
    1605                 :             :         /*
    1606                 :             :          * Build the list of effective column names using user-supplied aliases
    1607                 :             :          * and/or actual column names.
    1608                 :             :          */
    1609                 :       16249 :         rte->eref = makeAlias(refname, NIL);
    1610                 :       16249 :         buildRelationAliases(rel->rd_att, alias, rte->eref);
    1611                 :             : 
    1612                 :             :         /*
    1613                 :             :          * Set flags and initialize access permissions.
    1614                 :             :          *
    1615                 :             :          * The initial default on access checks is always check-for-READ-access,
    1616                 :             :          * which is the right thing for all except target tables.
    1617                 :             :          */
    1618                 :       16249 :         rte->lateral = false;
    1619                 :       16249 :         rte->inFromCl = inFromCl;
    1620                 :             : 
    1621                 :       16249 :         perminfo = addRTEPermissionInfo(&pstate->p_rteperminfos, rte);
    1622                 :       16249 :         perminfo->requiredPerms = ACL_SELECT;
    1623                 :             : 
    1624                 :             :         /*
    1625                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    1626                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    1627                 :             :          * appropriate.
    1628                 :             :          */
    1629                 :       16249 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    1630                 :             : 
    1631                 :             :         /*
    1632                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    1633                 :             :          * list --- caller must do that if appropriate.
    1634                 :             :          */
    1635                 :       48747 :         return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
    1636                 :       16249 :                                                                         perminfo, rel->rd_att);
    1637                 :       16249 : }
    1638                 :             : 
    1639                 :             : /*
    1640                 :             :  * Add an entry for a subquery to the pstate's range table (p_rtable).
    1641                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    1642                 :             :  *
    1643                 :             :  * This is much like addRangeTableEntry() except that it makes a subquery RTE.
    1644                 :             :  *
    1645                 :             :  * If the subquery does not have an alias, the auto-generated relation name in
    1646                 :             :  * the returned ParseNamespaceItem will be marked as not visible, and so only
    1647                 :             :  * unqualified references to the subquery columns will be allowed, and the
    1648                 :             :  * relation name will not conflict with others in the pstate's namespace list.
    1649                 :             :  */
    1650                 :             : ParseNamespaceItem *
    1651                 :        6719 : addRangeTableEntryForSubquery(ParseState *pstate,
    1652                 :             :                                                           Query *subquery,
    1653                 :             :                                                           Alias *alias,
    1654                 :             :                                                           bool lateral,
    1655                 :             :                                                           bool inFromCl)
    1656                 :             : {
    1657                 :        6719 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    1658                 :        6719 :         Alias      *eref;
    1659                 :        6719 :         int                     numaliases;
    1660                 :        6719 :         List       *coltypes,
    1661                 :             :                            *coltypmods,
    1662                 :             :                            *colcollations;
    1663                 :        6719 :         int                     varattno;
    1664                 :        6719 :         ListCell   *tlistitem;
    1665                 :        6719 :         ParseNamespaceItem *nsitem;
    1666                 :             : 
    1667         [ +  - ]:        6719 :         Assert(pstate != NULL);
    1668                 :             : 
    1669                 :        6719 :         rte->rtekind = RTE_SUBQUERY;
    1670                 :        6719 :         rte->subquery = subquery;
    1671                 :        6719 :         rte->alias = alias;
    1672                 :             : 
    1673         [ +  + ]:        6719 :         eref = alias ? copyObject(alias) : makeAlias("unnamed_subquery", NIL);
    1674                 :        6719 :         numaliases = list_length(eref->colnames);
    1675                 :             : 
    1676                 :             :         /* fill in any unspecified alias columns, and extract column type info */
    1677                 :        6719 :         coltypes = coltypmods = colcollations = NIL;
    1678                 :        6719 :         varattno = 0;
    1679   [ +  +  +  +  :       20969 :         foreach(tlistitem, subquery->targetList)
                   +  + ]
    1680                 :             :         {
    1681                 :       14250 :                 TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
    1682                 :             : 
    1683         [ +  + ]:       14250 :                 if (te->resjunk)
    1684                 :          40 :                         continue;
    1685                 :       14210 :                 varattno++;
    1686         [ -  + ]:       14210 :                 Assert(varattno == te->resno);
    1687         [ +  + ]:       14210 :                 if (varattno > numaliases)
    1688                 :             :                 {
    1689                 :       13033 :                         char       *attrname;
    1690                 :             : 
    1691                 :       13033 :                         attrname = pstrdup(te->resname);
    1692                 :       13033 :                         eref->colnames = lappend(eref->colnames, makeString(attrname));
    1693                 :       13033 :                 }
    1694                 :       28420 :                 coltypes = lappend_oid(coltypes,
    1695                 :       14210 :                                                            exprType((Node *) te->expr));
    1696                 :       28420 :                 coltypmods = lappend_int(coltypmods,
    1697                 :       14210 :                                                                  exprTypmod((Node *) te->expr));
    1698                 :       28420 :                 colcollations = lappend_oid(colcollations,
    1699                 :       14210 :                                                                         exprCollation((Node *) te->expr));
    1700      [ -  +  + ]:       14250 :         }
    1701         [ +  + ]:        6719 :         if (varattno < numaliases)
    1702   [ +  -  +  - ]:           1 :                 ereport(ERROR,
    1703                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    1704                 :             :                                  errmsg("table \"%s\" has %d columns available but %d columns specified",
    1705                 :             :                                                 eref->aliasname, varattno, numaliases)));
    1706                 :             : 
    1707                 :        6718 :         rte->eref = eref;
    1708                 :             : 
    1709                 :             :         /*
    1710                 :             :          * Set flags.
    1711                 :             :          *
    1712                 :             :          * Subqueries are never checked for access rights, so no need to perform
    1713                 :             :          * addRTEPermissionInfo().
    1714                 :             :          */
    1715                 :        6718 :         rte->lateral = lateral;
    1716                 :        6718 :         rte->inFromCl = inFromCl;
    1717                 :             : 
    1718                 :             :         /*
    1719                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    1720                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    1721                 :             :          * appropriate.
    1722                 :             :          */
    1723                 :        6718 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    1724                 :             : 
    1725                 :             :         /*
    1726                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    1727                 :             :          * list --- caller must do that if appropriate.
    1728                 :             :          */
    1729                 :       13436 :         nsitem = buildNSItemFromLists(rte, list_length(pstate->p_rtable),
    1730                 :        6718 :                                                                   coltypes, coltypmods, colcollations);
    1731                 :             : 
    1732                 :             :         /*
    1733                 :             :          * Mark it visible as a relation name only if it had a user-written alias.
    1734                 :             :          */
    1735                 :        6718 :         nsitem->p_rel_visible = (alias != NULL);
    1736                 :             : 
    1737                 :       13436 :         return nsitem;
    1738                 :        6718 : }
    1739                 :             : 
    1740                 :             : /*
    1741                 :             :  * Add an entry for a function (or functions) to the pstate's range table
    1742                 :             :  * (p_rtable).  Then, construct and return a ParseNamespaceItem for the new RTE.
    1743                 :             :  *
    1744                 :             :  * This is much like addRangeTableEntry() except that it makes a function RTE.
    1745                 :             :  */
    1746                 :             : ParseNamespaceItem *
    1747                 :        3549 : addRangeTableEntryForFunction(ParseState *pstate,
    1748                 :             :                                                           List *funcnames,
    1749                 :             :                                                           List *funcexprs,
    1750                 :             :                                                           List *coldeflists,
    1751                 :             :                                                           RangeFunction *rangefunc,
    1752                 :             :                                                           bool lateral,
    1753                 :             :                                                           bool inFromCl)
    1754                 :             : {
    1755                 :        3549 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    1756                 :        3549 :         Alias      *alias = rangefunc->alias;
    1757                 :        3549 :         Alias      *eref;
    1758                 :        3549 :         char       *aliasname;
    1759                 :        3549 :         int                     nfuncs = list_length(funcexprs);
    1760                 :        3549 :         TupleDesc  *functupdescs;
    1761                 :        3549 :         TupleDesc       tupdesc;
    1762                 :        3549 :         ListCell   *lc1,
    1763                 :             :                            *lc2,
    1764                 :             :                            *lc3;
    1765                 :        3549 :         int                     i;
    1766                 :        3549 :         int                     j;
    1767                 :        3549 :         int                     funcno;
    1768                 :        3549 :         int                     natts,
    1769                 :             :                                 totalatts;
    1770                 :             : 
    1771         [ +  - ]:        3549 :         Assert(pstate != NULL);
    1772                 :             : 
    1773                 :        3549 :         rte->rtekind = RTE_FUNCTION;
    1774                 :        3549 :         rte->relid = InvalidOid;
    1775                 :        3549 :         rte->subquery = NULL;
    1776                 :        3549 :         rte->functions = NIL;                /* we'll fill this list below */
    1777                 :        3549 :         rte->funcordinality = rangefunc->ordinality;
    1778                 :        3549 :         rte->alias = alias;
    1779                 :             : 
    1780                 :             :         /*
    1781                 :             :          * Choose the RTE alias name.  We default to using the first function's
    1782                 :             :          * name even when there's more than one; which is maybe arguable but beats
    1783                 :             :          * using something constant like "table".
    1784                 :             :          */
    1785         [ +  + ]:        3549 :         if (alias)
    1786                 :        2172 :                 aliasname = alias->aliasname;
    1787                 :             :         else
    1788                 :        1377 :                 aliasname = linitial(funcnames);
    1789                 :             : 
    1790                 :        3549 :         eref = makeAlias(aliasname, NIL);
    1791                 :        3549 :         rte->eref = eref;
    1792                 :             : 
    1793                 :             :         /* Process each function ... */
    1794                 :        3549 :         functupdescs = palloc_array(TupleDesc, nfuncs);
    1795                 :             : 
    1796                 :        3549 :         totalatts = 0;
    1797                 :        3549 :         funcno = 0;
    1798   [ +  -  +  +  :        7136 :         forthree(lc1, funcexprs, lc2, funcnames, lc3, coldeflists)
          +  -  +  +  +  
          -  +  +  +  +  
             +  -  +  + ]
    1799                 :             :         {
    1800                 :        3594 :                 Node       *funcexpr = (Node *) lfirst(lc1);
    1801                 :        3594 :                 char       *funcname = (char *) lfirst(lc2);
    1802                 :        3594 :                 List       *coldeflist = (List *) lfirst(lc3);
    1803                 :        3594 :                 RangeTblFunction *rtfunc = makeNode(RangeTblFunction);
    1804                 :        3594 :                 TypeFuncClass functypclass;
    1805                 :        3594 :                 Oid                     funcrettype;
    1806                 :             : 
    1807                 :             :                 /* Initialize RangeTblFunction node */
    1808                 :        3594 :                 rtfunc->funcexpr = funcexpr;
    1809                 :        3594 :                 rtfunc->funccolnames = NIL;
    1810                 :        3594 :                 rtfunc->funccoltypes = NIL;
    1811                 :        3594 :                 rtfunc->funccoltypmods = NIL;
    1812                 :        3594 :                 rtfunc->funccolcollations = NIL;
    1813                 :        3594 :                 rtfunc->funcparams = NULL;   /* not set until planning */
    1814                 :             : 
    1815                 :             :                 /*
    1816                 :             :                  * Now determine if the function returns a simple or composite type.
    1817                 :             :                  */
    1818                 :        3594 :                 functypclass = get_expr_result_type(funcexpr,
    1819                 :             :                                                                                         &funcrettype,
    1820                 :             :                                                                                         &tupdesc);
    1821                 :             : 
    1822                 :             :                 /*
    1823                 :             :                  * A coldeflist is required if the function returns RECORD and hasn't
    1824                 :             :                  * got a predetermined record type, and is prohibited otherwise.  This
    1825                 :             :                  * can be a bit confusing, so we expend some effort on delivering a
    1826                 :             :                  * relevant error message.
    1827                 :             :                  */
    1828         [ +  + ]:        3594 :                 if (coldeflist != NIL)
    1829                 :             :                 {
    1830      [ +  +  + ]:          90 :                         switch (functypclass)
    1831                 :             :                         {
    1832                 :             :                                 case TYPEFUNC_RECORD:
    1833                 :             :                                         /* ok */
    1834                 :             :                                         break;
    1835                 :             :                                 case TYPEFUNC_COMPOSITE:
    1836                 :             :                                 case TYPEFUNC_COMPOSITE_DOMAIN:
    1837                 :             : 
    1838                 :             :                                         /*
    1839                 :             :                                          * If the function's raw result type is RECORD, we must
    1840                 :             :                                          * have resolved it using its OUT parameters.  Otherwise,
    1841                 :             :                                          * it must have a named composite type.
    1842                 :             :                                          */
    1843         [ +  + ]:           2 :                                         if (exprType(funcexpr) == RECORDOID)
    1844   [ +  -  +  - ]:           1 :                                                 ereport(ERROR,
    1845                 :             :                                                                 (errcode(ERRCODE_SYNTAX_ERROR),
    1846                 :             :                                                                  errmsg("a column definition list is redundant for a function with OUT parameters"),
    1847                 :             :                                                                  parser_errposition(pstate,
    1848                 :             :                                                                                                         exprLocation((Node *) coldeflist))));
    1849                 :             :                                         else
    1850   [ +  -  +  - ]:           1 :                                                 ereport(ERROR,
    1851                 :             :                                                                 (errcode(ERRCODE_SYNTAX_ERROR),
    1852                 :             :                                                                  errmsg("a column definition list is redundant for a function returning a named composite type"),
    1853                 :             :                                                                  parser_errposition(pstate,
    1854                 :             :                                                                                                         exprLocation((Node *) coldeflist))));
    1855                 :           0 :                                         break;
    1856                 :             :                                 default:
    1857   [ +  -  +  - ]:           1 :                                         ereport(ERROR,
    1858                 :             :                                                         (errcode(ERRCODE_SYNTAX_ERROR),
    1859                 :             :                                                          errmsg("a column definition list is only allowed for functions returning \"record\""),
    1860                 :             :                                                          parser_errposition(pstate,
    1861                 :             :                                                                                                 exprLocation((Node *) coldeflist))));
    1862                 :           0 :                                         break;
    1863                 :             :                         }
    1864                 :          87 :                 }
    1865                 :             :                 else
    1866                 :             :                 {
    1867         [ +  + ]:        3504 :                         if (functypclass == TYPEFUNC_RECORD)
    1868   [ +  -  +  - ]:           3 :                                 ereport(ERROR,
    1869                 :             :                                                 (errcode(ERRCODE_SYNTAX_ERROR),
    1870                 :             :                                                  errmsg("a column definition list is required for functions returning \"record\""),
    1871                 :             :                                                  parser_errposition(pstate, exprLocation(funcexpr))));
    1872                 :             :                 }
    1873                 :             : 
    1874   [ +  +  +  + ]:        3588 :                 if (functypclass == TYPEFUNC_COMPOSITE ||
    1875                 :        2314 :                         functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
    1876                 :             :                 {
    1877                 :             :                         /* Composite data type, e.g. a table's row type */
    1878         [ -  + ]:        1276 :                         Assert(tupdesc);
    1879                 :        1276 :                 }
    1880         [ +  + ]:        2312 :                 else if (functypclass == TYPEFUNC_SCALAR)
    1881                 :             :                 {
    1882                 :             :                         /* Base data type, i.e. scalar */
    1883                 :        2224 :                         tupdesc = CreateTemplateTupleDesc(1);
    1884                 :        4448 :                         TupleDescInitEntry(tupdesc,
    1885                 :             :                                                            (AttrNumber) 1,
    1886                 :        4448 :                                                            chooseScalarFunctionAlias(funcexpr, funcname,
    1887                 :        2224 :                                                                                                                  alias, nfuncs),
    1888                 :        2224 :                                                            funcrettype,
    1889                 :        2224 :                                                            exprTypmod(funcexpr),
    1890                 :             :                                                            0);
    1891                 :        4448 :                         TupleDescInitEntryCollation(tupdesc,
    1892                 :             :                                                                                 (AttrNumber) 1,
    1893                 :        2224 :                                                                                 exprCollation(funcexpr));
    1894                 :        2224 :                 }
    1895         [ +  + ]:          88 :                 else if (functypclass == TYPEFUNC_RECORD)
    1896                 :             :                 {
    1897                 :          87 :                         ListCell   *col;
    1898                 :             : 
    1899                 :             :                         /*
    1900                 :             :                          * Use the column definition list to construct a tupdesc and fill
    1901                 :             :                          * in the RangeTblFunction's lists.  Limit number of columns to
    1902                 :             :                          * MaxHeapAttributeNumber, because CheckAttributeNamesTypes will.
    1903                 :             :                          */
    1904         [ +  - ]:          87 :                         if (list_length(coldeflist) > MaxHeapAttributeNumber)
    1905   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    1906                 :             :                                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
    1907                 :             :                                                  errmsg("column definition lists can have at most %d entries",
    1908                 :             :                                                                 MaxHeapAttributeNumber),
    1909                 :             :                                                  parser_errposition(pstate,
    1910                 :             :                                                                                         exprLocation((Node *) coldeflist))));
    1911                 :          87 :                         tupdesc = CreateTemplateTupleDesc(list_length(coldeflist));
    1912                 :          87 :                         i = 1;
    1913   [ +  -  +  +  :         270 :                         foreach(col, coldeflist)
                   +  + ]
    1914                 :             :                         {
    1915                 :         183 :                                 ColumnDef  *n = (ColumnDef *) lfirst(col);
    1916                 :         183 :                                 char       *attrname;
    1917                 :         183 :                                 Oid                     attrtype;
    1918                 :         183 :                                 int32           attrtypmod;
    1919                 :         183 :                                 Oid                     attrcollation;
    1920                 :             : 
    1921                 :         183 :                                 attrname = n->colname;
    1922         [ +  - ]:         183 :                                 if (n->typeName->setof)
    1923   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
    1924                 :             :                                                         (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
    1925                 :             :                                                          errmsg("column \"%s\" cannot be declared SETOF",
    1926                 :             :                                                                         attrname),
    1927                 :             :                                                          parser_errposition(pstate, n->location)));
    1928                 :         183 :                                 typenameTypeIdAndMod(pstate, n->typeName,
    1929                 :             :                                                                          &attrtype, &attrtypmod);
    1930                 :         183 :                                 attrcollation = GetColumnDefCollation(pstate, n, attrtype);
    1931                 :         366 :                                 TupleDescInitEntry(tupdesc,
    1932                 :         183 :                                                                    (AttrNumber) i,
    1933                 :         183 :                                                                    attrname,
    1934                 :         183 :                                                                    attrtype,
    1935                 :         183 :                                                                    attrtypmod,
    1936                 :             :                                                                    0);
    1937                 :         366 :                                 TupleDescInitEntryCollation(tupdesc,
    1938                 :         183 :                                                                                         (AttrNumber) i,
    1939                 :         183 :                                                                                         attrcollation);
    1940                 :         366 :                                 rtfunc->funccolnames = lappend(rtfunc->funccolnames,
    1941                 :         183 :                                                                                            makeString(pstrdup(attrname)));
    1942                 :         366 :                                 rtfunc->funccoltypes = lappend_oid(rtfunc->funccoltypes,
    1943                 :         183 :                                                                                                    attrtype);
    1944                 :         366 :                                 rtfunc->funccoltypmods = lappend_int(rtfunc->funccoltypmods,
    1945                 :         183 :                                                                                                          attrtypmod);
    1946                 :         366 :                                 rtfunc->funccolcollations = lappend_oid(rtfunc->funccolcollations,
    1947                 :         183 :                                                                                                                 attrcollation);
    1948                 :             : 
    1949                 :         183 :                                 i++;
    1950                 :         183 :                         }
    1951                 :             : 
    1952                 :             :                         /*
    1953                 :             :                          * Ensure that the coldeflist defines a legal set of names (no
    1954                 :             :                          * duplicates, but we needn't worry about system column names) and
    1955                 :             :                          * datatypes.  Although we mostly can't allow pseudo-types, it
    1956                 :             :                          * seems safe to allow RECORD and RECORD[], since values within
    1957                 :             :                          * those type classes are self-identifying at runtime, and the
    1958                 :             :                          * coldeflist doesn't represent anything that will be visible to
    1959                 :             :                          * other sessions.
    1960                 :             :                          */
    1961                 :          87 :                         CheckAttributeNamesTypes(tupdesc, RELKIND_COMPOSITE_TYPE,
    1962                 :             :                                                                          CHKATYPE_ANYRECORD);
    1963                 :          87 :                 }
    1964                 :             :                 else
    1965   [ +  -  +  - ]:           1 :                         ereport(ERROR,
    1966                 :             :                                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    1967                 :             :                                          errmsg("function \"%s\" in FROM has unsupported return type %s",
    1968                 :             :                                                         funcname, format_type_be(funcrettype)),
    1969                 :             :                                          parser_errposition(pstate, exprLocation(funcexpr))));
    1970                 :             : 
    1971                 :             :                 /* Finish off the RangeTblFunction and add it to the RTE's list */
    1972                 :        3587 :                 rtfunc->funccolcount = tupdesc->natts;
    1973                 :        3587 :                 rte->functions = lappend(rte->functions, rtfunc);
    1974                 :             : 
    1975                 :             :                 /* Save the tupdesc for use below */
    1976                 :        3587 :                 functupdescs[funcno] = tupdesc;
    1977                 :        3587 :                 totalatts += tupdesc->natts;
    1978                 :        3587 :                 funcno++;
    1979                 :        3587 :         }
    1980                 :             : 
    1981                 :             :         /*
    1982                 :             :          * If there's more than one function, or we want an ordinality column, we
    1983                 :             :          * have to produce a merged tupdesc.
    1984                 :             :          */
    1985   [ +  +  +  + ]:        3542 :         if (nfuncs > 1 || rangefunc->ordinality)
    1986                 :             :         {
    1987         [ +  + ]:         128 :                 if (rangefunc->ordinality)
    1988                 :         118 :                         totalatts++;
    1989                 :             : 
    1990                 :             :                 /* Disallow more columns than will fit in a tuple */
    1991         [ +  - ]:         128 :                 if (totalatts > MaxTupleAttributeNumber)
    1992   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    1993                 :             :                                         (errcode(ERRCODE_TOO_MANY_COLUMNS),
    1994                 :             :                                          errmsg("functions in FROM can return at most %d columns",
    1995                 :             :                                                         MaxTupleAttributeNumber),
    1996                 :             :                                          parser_errposition(pstate,
    1997                 :             :                                                                                 exprLocation((Node *) funcexprs))));
    1998                 :             : 
    1999                 :             :                 /* Merge the tuple descs of each function into a composite one */
    2000                 :         128 :                 tupdesc = CreateTemplateTupleDesc(totalatts);
    2001                 :         128 :                 natts = 0;
    2002         [ +  + ]:         301 :                 for (i = 0; i < nfuncs; i++)
    2003                 :             :                 {
    2004         [ +  + ]:         437 :                         for (j = 1; j <= functupdescs[i]->natts; j++)
    2005                 :         264 :                                 TupleDescCopyEntry(tupdesc, ++natts, functupdescs[i], j);
    2006                 :         173 :                 }
    2007                 :             : 
    2008                 :             :                 /* Add the ordinality column if needed */
    2009         [ +  + ]:         128 :                 if (rangefunc->ordinality)
    2010                 :             :                 {
    2011                 :         236 :                         TupleDescInitEntry(tupdesc,
    2012                 :         118 :                                                            (AttrNumber) ++natts,
    2013                 :             :                                                            "ordinality",
    2014                 :             :                                                            INT8OID,
    2015                 :             :                                                            -1,
    2016                 :             :                                                            0);
    2017                 :             :                         /* no need to set collation */
    2018                 :         118 :                 }
    2019                 :             : 
    2020         [ +  - ]:         128 :                 Assert(natts == totalatts);
    2021                 :         128 :         }
    2022                 :             :         else
    2023                 :             :         {
    2024                 :             :                 /* We can just use the single function's tupdesc as-is */
    2025                 :        3414 :                 tupdesc = functupdescs[0];
    2026                 :             :         }
    2027                 :             : 
    2028                 :             :         /* Use the tupdesc while assigning column aliases for the RTE */
    2029                 :        3542 :         buildRelationAliases(tupdesc, alias, eref);
    2030                 :             : 
    2031                 :             :         /*
    2032                 :             :          * Set flags and access permissions.
    2033                 :             :          *
    2034                 :             :          * Functions are never checked for access rights (at least, not by
    2035                 :             :          * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
    2036                 :             :          */
    2037                 :        3542 :         rte->lateral = lateral;
    2038                 :        3542 :         rte->inFromCl = inFromCl;
    2039                 :             : 
    2040                 :             :         /*
    2041                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    2042                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    2043                 :             :          * appropriate.
    2044                 :             :          */
    2045                 :        3542 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    2046                 :             : 
    2047                 :             :         /*
    2048                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    2049                 :             :          * list --- caller must do that if appropriate.
    2050                 :             :          */
    2051                 :       10626 :         return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable), NULL,
    2052                 :        3542 :                                                                         tupdesc);
    2053                 :        3542 : }
    2054                 :             : 
    2055                 :             : /*
    2056                 :             :  * Add an entry for a table function to the pstate's range table (p_rtable).
    2057                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    2058                 :             :  *
    2059                 :             :  * This is much like addRangeTableEntry() except that it makes a tablefunc RTE.
    2060                 :             :  */
    2061                 :             : ParseNamespaceItem *
    2062                 :         109 : addRangeTableEntryForTableFunc(ParseState *pstate,
    2063                 :             :                                                            TableFunc *tf,
    2064                 :             :                                                            Alias *alias,
    2065                 :             :                                                            bool lateral,
    2066                 :             :                                                            bool inFromCl)
    2067                 :             : {
    2068                 :         109 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    2069                 :         109 :         char       *refname;
    2070                 :         109 :         Alias      *eref;
    2071                 :         109 :         int                     numaliases;
    2072                 :             : 
    2073         [ +  - ]:         109 :         Assert(pstate != NULL);
    2074                 :             : 
    2075                 :             :         /* Disallow more columns than will fit in a tuple */
    2076         [ +  - ]:         109 :         if (list_length(tf->colnames) > MaxTupleAttributeNumber)
    2077   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2078                 :             :                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
    2079                 :             :                                  errmsg("functions in FROM can return at most %d columns",
    2080                 :             :                                                 MaxTupleAttributeNumber),
    2081                 :             :                                  parser_errposition(pstate,
    2082                 :             :                                                                         exprLocation((Node *) tf))));
    2083         [ +  - ]:         109 :         Assert(list_length(tf->coltypes) == list_length(tf->colnames));
    2084         [ +  - ]:         109 :         Assert(list_length(tf->coltypmods) == list_length(tf->colnames));
    2085         [ +  - ]:         109 :         Assert(list_length(tf->colcollations) == list_length(tf->colnames));
    2086                 :             : 
    2087                 :         109 :         rte->rtekind = RTE_TABLEFUNC;
    2088                 :         109 :         rte->relid = InvalidOid;
    2089                 :         109 :         rte->subquery = NULL;
    2090                 :         109 :         rte->tablefunc = tf;
    2091                 :         109 :         rte->coltypes = tf->coltypes;
    2092                 :         109 :         rte->coltypmods = tf->coltypmods;
    2093                 :         109 :         rte->colcollations = tf->colcollations;
    2094                 :         109 :         rte->alias = alias;
    2095                 :             : 
    2096         [ +  + ]:         109 :         refname = alias ? alias->aliasname :
    2097                 :          75 :                 pstrdup(tf->functype == TFT_XMLTABLE ? "xmltable" : "json_table");
    2098         [ +  + ]:         109 :         eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
    2099                 :         109 :         numaliases = list_length(eref->colnames);
    2100                 :             : 
    2101                 :             :         /* fill in any unspecified alias columns */
    2102         [ +  + ]:         109 :         if (numaliases < list_length(tf->colnames))
    2103                 :         214 :                 eref->colnames = list_concat(eref->colnames,
    2104                 :         107 :                                                                          list_copy_tail(tf->colnames, numaliases));
    2105                 :             : 
    2106         [ +  + ]:         109 :         if (numaliases > list_length(tf->colnames))
    2107   [ +  -  +  - ]:           2 :                 ereport(ERROR,
    2108                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    2109                 :             :                                  errmsg("%s function has %d columns available but %d columns specified",
    2110                 :             :                                                 tf->functype == TFT_XMLTABLE ? "XMLTABLE" : "JSON_TABLE",
    2111                 :             :                                                 list_length(tf->colnames), numaliases)));
    2112                 :             : 
    2113                 :         107 :         rte->eref = eref;
    2114                 :             : 
    2115                 :             :         /*
    2116                 :             :          * Set flags and access permissions.
    2117                 :             :          *
    2118                 :             :          * Tablefuncs are never checked for access rights (at least, not by
    2119                 :             :          * ExecCheckPermissions()), so no need to perform addRTEPermissionInfo().
    2120                 :             :          */
    2121                 :         107 :         rte->lateral = lateral;
    2122                 :         107 :         rte->inFromCl = inFromCl;
    2123                 :             : 
    2124                 :             :         /*
    2125                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    2126                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    2127                 :             :          * appropriate.
    2128                 :             :          */
    2129                 :         107 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    2130                 :             : 
    2131                 :             :         /*
    2132                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    2133                 :             :          * list --- caller must do that if appropriate.
    2134                 :             :          */
    2135                 :         321 :         return buildNSItemFromLists(rte, list_length(pstate->p_rtable),
    2136                 :         107 :                                                                 rte->coltypes, rte->coltypmods,
    2137                 :         107 :                                                                 rte->colcollations);
    2138                 :         107 : }
    2139                 :             : 
    2140                 :             : /*
    2141                 :             :  * Add an entry for a VALUES list to the pstate's range table (p_rtable).
    2142                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    2143                 :             :  *
    2144                 :             :  * This is much like addRangeTableEntry() except that it makes a values RTE.
    2145                 :             :  */
    2146                 :             : ParseNamespaceItem *
    2147                 :        1896 : addRangeTableEntryForValues(ParseState *pstate,
    2148                 :             :                                                         List *exprs,
    2149                 :             :                                                         List *coltypes,
    2150                 :             :                                                         List *coltypmods,
    2151                 :             :                                                         List *colcollations,
    2152                 :             :                                                         Alias *alias,
    2153                 :             :                                                         bool lateral,
    2154                 :             :                                                         bool inFromCl)
    2155                 :             : {
    2156                 :        1896 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    2157         [ -  + ]:        1896 :         char       *refname = alias ? alias->aliasname : pstrdup("*VALUES*");
    2158                 :        1896 :         Alias      *eref;
    2159                 :        1896 :         int                     numaliases;
    2160                 :        1896 :         int                     numcolumns;
    2161                 :             : 
    2162         [ +  - ]:        1896 :         Assert(pstate != NULL);
    2163                 :             : 
    2164                 :        1896 :         rte->rtekind = RTE_VALUES;
    2165                 :        1896 :         rte->relid = InvalidOid;
    2166                 :        1896 :         rte->subquery = NULL;
    2167                 :        1896 :         rte->values_lists = exprs;
    2168                 :        1896 :         rte->coltypes = coltypes;
    2169                 :        1896 :         rte->coltypmods = coltypmods;
    2170                 :        1896 :         rte->colcollations = colcollations;
    2171                 :        1896 :         rte->alias = alias;
    2172                 :             : 
    2173         [ -  + ]:        1896 :         eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
    2174                 :             : 
    2175                 :             :         /* fill in any unspecified alias columns */
    2176                 :        1896 :         numcolumns = list_length((List *) linitial(exprs));
    2177                 :        1896 :         numaliases = list_length(eref->colnames);
    2178         [ +  + ]:        4634 :         while (numaliases < numcolumns)
    2179                 :             :         {
    2180                 :        2738 :                 char            attrname[64];
    2181                 :             : 
    2182                 :        2738 :                 numaliases++;
    2183                 :        2738 :                 snprintf(attrname, sizeof(attrname), "column%d", numaliases);
    2184                 :        5476 :                 eref->colnames = lappend(eref->colnames,
    2185                 :        2738 :                                                                  makeString(pstrdup(attrname)));
    2186                 :        2738 :         }
    2187         [ +  - ]:        1896 :         if (numcolumns < numaliases)
    2188   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2189                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    2190                 :             :                                  errmsg("VALUES lists \"%s\" have %d columns available but %d columns specified",
    2191                 :             :                                                 refname, numcolumns, numaliases)));
    2192                 :             : 
    2193                 :        1896 :         rte->eref = eref;
    2194                 :             : 
    2195                 :             :         /*
    2196                 :             :          * Set flags and access permissions.
    2197                 :             :          *
    2198                 :             :          * Subqueries are never checked for access rights, so no need to perform
    2199                 :             :          * addRTEPermissionInfo().
    2200                 :             :          */
    2201                 :        1896 :         rte->lateral = lateral;
    2202                 :        1896 :         rte->inFromCl = inFromCl;
    2203                 :             : 
    2204                 :             :         /*
    2205                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    2206                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    2207                 :             :          * appropriate.
    2208                 :             :          */
    2209                 :        1896 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    2210                 :             : 
    2211                 :             :         /*
    2212                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    2213                 :             :          * list --- caller must do that if appropriate.
    2214                 :             :          */
    2215                 :        5688 :         return buildNSItemFromLists(rte, list_length(pstate->p_rtable),
    2216                 :        1896 :                                                                 rte->coltypes, rte->coltypmods,
    2217                 :        1896 :                                                                 rte->colcollations);
    2218                 :        1896 : }
    2219                 :             : 
    2220                 :             : /*
    2221                 :             :  * Add an entry for a join to the pstate's range table (p_rtable).
    2222                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    2223                 :             :  *
    2224                 :             :  * This is much like addRangeTableEntry() except that it makes a join RTE.
    2225                 :             :  * Also, it's more convenient for the caller to construct the
    2226                 :             :  * ParseNamespaceColumn array, so we pass that in.
    2227                 :             :  */
    2228                 :             : ParseNamespaceItem *
    2229                 :        8529 : addRangeTableEntryForJoin(ParseState *pstate,
    2230                 :             :                                                   List *colnames,
    2231                 :             :                                                   ParseNamespaceColumn *nscolumns,
    2232                 :             :                                                   JoinType jointype,
    2233                 :             :                                                   int nummergedcols,
    2234                 :             :                                                   List *aliasvars,
    2235                 :             :                                                   List *leftcols,
    2236                 :             :                                                   List *rightcols,
    2237                 :             :                                                   Alias *join_using_alias,
    2238                 :             :                                                   Alias *alias,
    2239                 :             :                                                   bool inFromCl)
    2240                 :             : {
    2241                 :        8529 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    2242                 :        8529 :         Alias      *eref;
    2243                 :        8529 :         int                     numaliases;
    2244                 :        8529 :         ParseNamespaceItem *nsitem;
    2245                 :             : 
    2246         [ +  - ]:        8529 :         Assert(pstate != NULL);
    2247                 :             : 
    2248                 :             :         /*
    2249                 :             :          * Fail if join has too many columns --- we must be able to reference any
    2250                 :             :          * of the columns with an AttrNumber.
    2251                 :             :          */
    2252         [ +  - ]:        8529 :         if (list_length(aliasvars) > MaxAttrNumber)
    2253   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2254                 :             :                                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    2255                 :             :                                  errmsg("joins can have at most %d columns",
    2256                 :             :                                                 MaxAttrNumber)));
    2257                 :             : 
    2258                 :        8529 :         rte->rtekind = RTE_JOIN;
    2259                 :        8529 :         rte->relid = InvalidOid;
    2260                 :        8529 :         rte->subquery = NULL;
    2261                 :        8529 :         rte->jointype = jointype;
    2262                 :        8529 :         rte->joinmergedcols = nummergedcols;
    2263                 :        8529 :         rte->joinaliasvars = aliasvars;
    2264                 :        8529 :         rte->joinleftcols = leftcols;
    2265                 :        8529 :         rte->joinrightcols = rightcols;
    2266                 :        8529 :         rte->join_using_alias = join_using_alias;
    2267                 :        8529 :         rte->alias = alias;
    2268                 :             : 
    2269         [ +  + ]:        8529 :         eref = alias ? copyObject(alias) : makeAlias("unnamed_join", NIL);
    2270                 :        8529 :         numaliases = list_length(eref->colnames);
    2271                 :             : 
    2272                 :             :         /* fill in any unspecified alias columns */
    2273         [ +  + ]:        8529 :         if (numaliases < list_length(colnames))
    2274                 :       17012 :                 eref->colnames = list_concat(eref->colnames,
    2275                 :        8506 :                                                                          list_copy_tail(colnames, numaliases));
    2276                 :             : 
    2277         [ +  + ]:        8529 :         if (numaliases > list_length(colnames))
    2278   [ +  -  +  - ]:           1 :                 ereport(ERROR,
    2279                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    2280                 :             :                                  errmsg("join expression \"%s\" has %d columns available but %d columns specified",
    2281                 :             :                                                 eref->aliasname, list_length(colnames), numaliases)));
    2282                 :             : 
    2283                 :        8528 :         rte->eref = eref;
    2284                 :             : 
    2285                 :             :         /*
    2286                 :             :          * Set flags and access permissions.
    2287                 :             :          *
    2288                 :             :          * Joins are never checked for access rights, so no need to perform
    2289                 :             :          * addRTEPermissionInfo().
    2290                 :             :          */
    2291                 :        8528 :         rte->lateral = false;
    2292                 :        8528 :         rte->inFromCl = inFromCl;
    2293                 :             : 
    2294                 :             :         /*
    2295                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    2296                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    2297                 :             :          * appropriate.
    2298                 :             :          */
    2299                 :        8528 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    2300                 :             : 
    2301                 :             :         /*
    2302                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    2303                 :             :          * list --- caller must do that if appropriate.
    2304                 :             :          */
    2305                 :        8528 :         nsitem = palloc_object(ParseNamespaceItem);
    2306                 :        8528 :         nsitem->p_names = rte->eref;
    2307                 :        8528 :         nsitem->p_rte = rte;
    2308                 :        8528 :         nsitem->p_perminfo = NULL;
    2309                 :        8528 :         nsitem->p_rtindex = list_length(pstate->p_rtable);
    2310                 :        8528 :         nsitem->p_nscolumns = nscolumns;
    2311                 :             :         /* set default visibility flags; might get changed later */
    2312                 :        8528 :         nsitem->p_rel_visible = true;
    2313                 :        8528 :         nsitem->p_cols_visible = true;
    2314                 :        8528 :         nsitem->p_lateral_only = false;
    2315                 :        8528 :         nsitem->p_lateral_ok = true;
    2316                 :        8528 :         nsitem->p_returning_type = VAR_RETURNING_DEFAULT;
    2317                 :             : 
    2318                 :       17056 :         return nsitem;
    2319                 :        8528 : }
    2320                 :             : 
    2321                 :             : /*
    2322                 :             :  * Add an entry for a CTE reference to the pstate's range table (p_rtable).
    2323                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    2324                 :             :  *
    2325                 :             :  * This is much like addRangeTableEntry() except that it makes a CTE RTE.
    2326                 :             :  */
    2327                 :             : ParseNamespaceItem *
    2328                 :         462 : addRangeTableEntryForCTE(ParseState *pstate,
    2329                 :             :                                                  CommonTableExpr *cte,
    2330                 :             :                                                  Index levelsup,
    2331                 :             :                                                  RangeVar *rv,
    2332                 :             :                                                  bool inFromCl)
    2333                 :             : {
    2334                 :         462 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    2335                 :         462 :         Alias      *alias = rv->alias;
    2336         [ +  + ]:         462 :         char       *refname = alias ? alias->aliasname : cte->ctename;
    2337                 :         462 :         Alias      *eref;
    2338                 :         462 :         int                     numaliases;
    2339                 :         462 :         int                     varattno;
    2340                 :         462 :         ListCell   *lc;
    2341                 :         462 :         int                     n_dontexpand_columns = 0;
    2342                 :         462 :         ParseNamespaceItem *psi;
    2343                 :             : 
    2344         [ +  - ]:         462 :         Assert(pstate != NULL);
    2345                 :             : 
    2346                 :         462 :         rte->rtekind = RTE_CTE;
    2347                 :         462 :         rte->ctename = cte->ctename;
    2348                 :         462 :         rte->ctelevelsup = levelsup;
    2349                 :             : 
    2350                 :             :         /* Self-reference if and only if CTE's parse analysis isn't completed */
    2351                 :         462 :         rte->self_reference = !IsA(cte->ctequery, Query);
    2352   [ +  +  +  - ]:         462 :         Assert(cte->cterecursive || !rte->self_reference);
    2353                 :             :         /* Bump the CTE's refcount if this isn't a self-reference */
    2354         [ +  + ]:         462 :         if (!rte->self_reference)
    2355                 :         367 :                 cte->cterefcount++;
    2356                 :             : 
    2357                 :             :         /*
    2358                 :             :          * We throw error if the CTE is INSERT/UPDATE/DELETE/MERGE without
    2359                 :             :          * RETURNING.  This won't get checked in case of a self-reference, but
    2360                 :             :          * that's OK because data-modifying CTEs aren't allowed to be recursive
    2361                 :             :          * anyhow.
    2362                 :             :          */
    2363         [ +  + ]:         462 :         if (IsA(cte->ctequery, Query))
    2364                 :             :         {
    2365                 :         367 :                 Query      *ctequery = (Query *) cte->ctequery;
    2366                 :             : 
    2367   [ +  +  +  + ]:         367 :                 if (ctequery->commandType != CMD_SELECT &&
    2368                 :          42 :                         ctequery->returningList == NIL)
    2369   [ +  -  +  - ]:           2 :                         ereport(ERROR,
    2370                 :             :                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2371                 :             :                                          errmsg("WITH query \"%s\" does not have a RETURNING clause",
    2372                 :             :                                                         cte->ctename),
    2373                 :             :                                          parser_errposition(pstate, rv->location)));
    2374                 :         365 :         }
    2375                 :             : 
    2376                 :         460 :         rte->coltypes = list_copy(cte->ctecoltypes);
    2377                 :         460 :         rte->coltypmods = list_copy(cte->ctecoltypmods);
    2378                 :         460 :         rte->colcollations = list_copy(cte->ctecolcollations);
    2379                 :             : 
    2380                 :         460 :         rte->alias = alias;
    2381         [ +  + ]:         460 :         if (alias)
    2382                 :          83 :                 eref = copyObject(alias);
    2383                 :             :         else
    2384                 :         377 :                 eref = makeAlias(refname, NIL);
    2385                 :         460 :         numaliases = list_length(eref->colnames);
    2386                 :             : 
    2387                 :             :         /* fill in any unspecified alias columns */
    2388                 :         460 :         varattno = 0;
    2389   [ +  -  +  +  :        1315 :         foreach(lc, cte->ctecolnames)
                   +  + ]
    2390                 :             :         {
    2391                 :         855 :                 varattno++;
    2392         [ +  + ]:         855 :                 if (varattno > numaliases)
    2393                 :         847 :                         eref->colnames = lappend(eref->colnames, lfirst(lc));
    2394                 :         855 :         }
    2395         [ +  - ]:         460 :         if (varattno < numaliases)
    2396   [ #  #  #  # ]:           0 :                 ereport(ERROR,
    2397                 :             :                                 (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
    2398                 :             :                                  errmsg("table \"%s\" has %d columns available but %d columns specified",
    2399                 :             :                                                 refname, varattno, numaliases)));
    2400                 :             : 
    2401                 :         460 :         rte->eref = eref;
    2402                 :             : 
    2403         [ +  + ]:         460 :         if (cte->search_clause)
    2404                 :             :         {
    2405                 :          35 :                 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->search_clause->search_seq_column));
    2406         [ +  + ]:          35 :                 if (cte->search_clause->search_breadth_first)
    2407                 :          12 :                         rte->coltypes = lappend_oid(rte->coltypes, RECORDOID);
    2408                 :             :                 else
    2409                 :          23 :                         rte->coltypes = lappend_oid(rte->coltypes, RECORDARRAYOID);
    2410                 :          35 :                 rte->coltypmods = lappend_int(rte->coltypmods, -1);
    2411                 :          35 :                 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
    2412                 :             : 
    2413                 :          35 :                 n_dontexpand_columns += 1;
    2414                 :          35 :         }
    2415                 :             : 
    2416         [ +  + ]:         460 :         if (cte->cycle_clause)
    2417                 :             :         {
    2418                 :          31 :                 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->cycle_clause->cycle_mark_column));
    2419                 :          31 :                 rte->coltypes = lappend_oid(rte->coltypes, cte->cycle_clause->cycle_mark_type);
    2420                 :          31 :                 rte->coltypmods = lappend_int(rte->coltypmods, cte->cycle_clause->cycle_mark_typmod);
    2421                 :          31 :                 rte->colcollations = lappend_oid(rte->colcollations, cte->cycle_clause->cycle_mark_collation);
    2422                 :             : 
    2423                 :          31 :                 rte->eref->colnames = lappend(rte->eref->colnames, makeString(cte->cycle_clause->cycle_path_column));
    2424                 :          31 :                 rte->coltypes = lappend_oid(rte->coltypes, RECORDARRAYOID);
    2425                 :          31 :                 rte->coltypmods = lappend_int(rte->coltypmods, -1);
    2426                 :          31 :                 rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
    2427                 :             : 
    2428                 :          31 :                 n_dontexpand_columns += 2;
    2429                 :          31 :         }
    2430                 :             : 
    2431                 :             :         /*
    2432                 :             :          * Set flags and access permissions.
    2433                 :             :          *
    2434                 :             :          * Subqueries are never checked for access rights, so no need to perform
    2435                 :             :          * addRTEPermissionInfo().
    2436                 :             :          */
    2437                 :         460 :         rte->lateral = false;
    2438                 :         460 :         rte->inFromCl = inFromCl;
    2439                 :             : 
    2440                 :             :         /*
    2441                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    2442                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    2443                 :             :          * appropriate.
    2444                 :             :          */
    2445                 :         460 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    2446                 :             : 
    2447                 :             :         /*
    2448                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    2449                 :             :          * list --- caller must do that if appropriate.
    2450                 :             :          */
    2451                 :         920 :         psi = buildNSItemFromLists(rte, list_length(pstate->p_rtable),
    2452                 :         460 :                                                            rte->coltypes, rte->coltypmods,
    2453                 :         460 :                                                            rte->colcollations);
    2454                 :             : 
    2455                 :             :         /*
    2456                 :             :          * The columns added by search and cycle clauses are not included in star
    2457                 :             :          * expansion in queries contained in the CTE.
    2458                 :             :          */
    2459         [ +  + ]:         460 :         if (rte->ctelevelsup > 0)
    2460         [ +  + ]:         288 :                 for (int i = 0; i < n_dontexpand_columns; i++)
    2461                 :         288 :                         psi->p_nscolumns[list_length(psi->p_names->colnames) - 1 - i].p_dontexpand = true;
    2462                 :             : 
    2463                 :         920 :         return psi;
    2464                 :         460 : }
    2465                 :             : 
    2466                 :             : /*
    2467                 :             :  * Add an entry for an ephemeral named relation reference to the pstate's
    2468                 :             :  * range table (p_rtable).
    2469                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    2470                 :             :  *
    2471                 :             :  * It is expected that the RangeVar, which up until now is only known to be an
    2472                 :             :  * ephemeral named relation, will (in conjunction with the QueryEnvironment in
    2473                 :             :  * the ParseState), create a RangeTblEntry for a specific *kind* of ephemeral
    2474                 :             :  * named relation, based on enrtype.
    2475                 :             :  *
    2476                 :             :  * This is much like addRangeTableEntry() except that it makes an RTE for an
    2477                 :             :  * ephemeral named relation.
    2478                 :             :  */
    2479                 :             : ParseNamespaceItem *
    2480                 :          79 : addRangeTableEntryForENR(ParseState *pstate,
    2481                 :             :                                                  RangeVar *rv,
    2482                 :             :                                                  bool inFromCl)
    2483                 :             : {
    2484                 :          79 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    2485                 :          79 :         Alias      *alias = rv->alias;
    2486         [ +  + ]:          79 :         char       *refname = alias ? alias->aliasname : rv->relname;
    2487                 :          79 :         EphemeralNamedRelationMetadata enrmd;
    2488                 :          79 :         TupleDesc       tupdesc;
    2489                 :          79 :         int                     attno;
    2490                 :             : 
    2491         [ +  - ]:          79 :         Assert(pstate != NULL);
    2492                 :          79 :         enrmd = get_visible_ENR(pstate, rv->relname);
    2493         [ +  - ]:          79 :         Assert(enrmd != NULL);
    2494                 :             : 
    2495         [ +  - ]:          79 :         switch (enrmd->enrtype)
    2496                 :             :         {
    2497                 :             :                 case ENR_NAMED_TUPLESTORE:
    2498                 :          79 :                         rte->rtekind = RTE_NAMEDTUPLESTORE;
    2499                 :          79 :                         break;
    2500                 :             : 
    2501                 :             :                 default:
    2502   [ #  #  #  # ]:           0 :                         elog(ERROR, "unexpected enrtype: %d", enrmd->enrtype);
    2503                 :           0 :                         return NULL;            /* for fussy compilers */
    2504                 :             :         }
    2505                 :             : 
    2506                 :             :         /*
    2507                 :             :          * Record dependency on a relation.  This allows plans to be invalidated
    2508                 :             :          * if they access transition tables linked to a table that is altered.
    2509                 :             :          */
    2510                 :          79 :         rte->relid = enrmd->reliddesc;
    2511                 :             : 
    2512                 :             :         /*
    2513                 :             :          * Build the list of effective column names using user-supplied aliases
    2514                 :             :          * and/or actual column names.
    2515                 :             :          */
    2516                 :          79 :         tupdesc = ENRMetadataGetTupDesc(enrmd);
    2517                 :          79 :         rte->eref = makeAlias(refname, NIL);
    2518                 :          79 :         buildRelationAliases(tupdesc, alias, rte->eref);
    2519                 :             : 
    2520                 :             :         /* Record additional data for ENR, including column type info */
    2521                 :          79 :         rte->enrname = enrmd->name;
    2522                 :          79 :         rte->enrtuples = enrmd->enrtuples;
    2523                 :          79 :         rte->coltypes = NIL;
    2524                 :          79 :         rte->coltypmods = NIL;
    2525                 :          79 :         rte->colcollations = NIL;
    2526         [ +  + ]:         253 :         for (attno = 1; attno <= tupdesc->natts; ++attno)
    2527                 :             :         {
    2528                 :         174 :                 Form_pg_attribute att = TupleDescAttr(tupdesc, attno - 1);
    2529                 :             : 
    2530         [ +  + ]:         174 :                 if (att->attisdropped)
    2531                 :             :                 {
    2532                 :             :                         /* Record zeroes for a dropped column */
    2533                 :           3 :                         rte->coltypes = lappend_oid(rte->coltypes, InvalidOid);
    2534                 :           3 :                         rte->coltypmods = lappend_int(rte->coltypmods, 0);
    2535                 :           3 :                         rte->colcollations = lappend_oid(rte->colcollations, InvalidOid);
    2536                 :           3 :                 }
    2537                 :             :                 else
    2538                 :             :                 {
    2539                 :             :                         /* Let's just make sure we can tell this isn't dropped */
    2540         [ +  - ]:         171 :                         if (att->atttypid == InvalidOid)
    2541   [ #  #  #  # ]:           0 :                                 elog(ERROR, "atttypid is invalid for non-dropped column in \"%s\"",
    2542                 :             :                                          rv->relname);
    2543                 :         171 :                         rte->coltypes = lappend_oid(rte->coltypes, att->atttypid);
    2544                 :         171 :                         rte->coltypmods = lappend_int(rte->coltypmods, att->atttypmod);
    2545                 :         342 :                         rte->colcollations = lappend_oid(rte->colcollations,
    2546                 :         171 :                                                                                          att->attcollation);
    2547                 :             :                 }
    2548                 :         174 :         }
    2549                 :             : 
    2550                 :             :         /*
    2551                 :             :          * Set flags and access permissions.
    2552                 :             :          *
    2553                 :             :          * ENRs are never checked for access rights, so no need to perform
    2554                 :             :          * addRTEPermissionInfo().
    2555                 :             :          */
    2556                 :          79 :         rte->lateral = false;
    2557                 :          79 :         rte->inFromCl = inFromCl;
    2558                 :             : 
    2559                 :             :         /*
    2560                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    2561                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    2562                 :             :          * appropriate.
    2563                 :             :          */
    2564                 :          79 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    2565                 :             : 
    2566                 :             :         /*
    2567                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    2568                 :             :          * list --- caller must do that if appropriate.
    2569                 :             :          */
    2570                 :         158 :         return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable), NULL,
    2571                 :          79 :                                                                         tupdesc);
    2572                 :          79 : }
    2573                 :             : 
    2574                 :             : /*
    2575                 :             :  * Add an entry for grouping step to the pstate's range table (p_rtable).
    2576                 :             :  * Then, construct and return a ParseNamespaceItem for the new RTE.
    2577                 :             :  */
    2578                 :             : ParseNamespaceItem *
    2579                 :         700 : addRangeTableEntryForGroup(ParseState *pstate,
    2580                 :             :                                                    List *groupClauses)
    2581                 :             : {
    2582                 :         700 :         RangeTblEntry *rte = makeNode(RangeTblEntry);
    2583                 :         700 :         Alias      *eref;
    2584                 :         700 :         List       *groupexprs;
    2585                 :         700 :         List       *coltypes,
    2586                 :             :                            *coltypmods,
    2587                 :             :                            *colcollations;
    2588                 :         700 :         ListCell   *lc;
    2589                 :         700 :         ParseNamespaceItem *nsitem;
    2590                 :             : 
    2591         [ +  - ]:         700 :         Assert(pstate != NULL);
    2592                 :             : 
    2593                 :         700 :         rte->rtekind = RTE_GROUP;
    2594                 :         700 :         rte->alias = NULL;
    2595                 :             : 
    2596                 :         700 :         eref = makeAlias("*GROUP*", NIL);
    2597                 :             : 
    2598                 :             :         /* fill in any unspecified alias columns, and extract column type info */
    2599                 :         700 :         groupexprs = NIL;
    2600                 :         700 :         coltypes = coltypmods = colcollations = NIL;
    2601   [ +  -  +  +  :        1889 :         foreach(lc, groupClauses)
                   +  + ]
    2602                 :             :         {
    2603                 :        1189 :                 TargetEntry *te = (TargetEntry *) lfirst(lc);
    2604         [ +  + ]:        1189 :                 char       *colname = te->resname ? pstrdup(te->resname) : "?column?";
    2605                 :             : 
    2606                 :        1189 :                 eref->colnames = lappend(eref->colnames, makeString(colname));
    2607                 :             : 
    2608                 :        1189 :                 groupexprs = lappend(groupexprs, copyObject(te->expr));
    2609                 :             : 
    2610                 :        2378 :                 coltypes = lappend_oid(coltypes,
    2611                 :        1189 :                                                            exprType((Node *) te->expr));
    2612                 :        2378 :                 coltypmods = lappend_int(coltypmods,
    2613                 :        1189 :                                                                  exprTypmod((Node *) te->expr));
    2614                 :        2378 :                 colcollations = lappend_oid(colcollations,
    2615                 :        1189 :                                                                         exprCollation((Node *) te->expr));
    2616                 :        1189 :         }
    2617                 :             : 
    2618                 :         700 :         rte->eref = eref;
    2619                 :         700 :         rte->groupexprs = groupexprs;
    2620                 :             : 
    2621                 :             :         /*
    2622                 :             :          * Set flags.
    2623                 :             :          *
    2624                 :             :          * The grouping step is never checked for access rights, so no need to
    2625                 :             :          * perform addRTEPermissionInfo().
    2626                 :             :          */
    2627                 :         700 :         rte->lateral = false;
    2628                 :         700 :         rte->inFromCl = false;
    2629                 :             : 
    2630                 :             :         /*
    2631                 :             :          * Add completed RTE to pstate's range table list, so that we know its
    2632                 :             :          * index.  But we don't add it to the join list --- caller must do that if
    2633                 :             :          * appropriate.
    2634                 :             :          */
    2635                 :         700 :         pstate->p_rtable = lappend(pstate->p_rtable, rte);
    2636                 :             : 
    2637                 :             :         /*
    2638                 :             :          * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
    2639                 :             :          * list --- caller must do that if appropriate.
    2640                 :             :          */
    2641                 :        1400 :         nsitem = buildNSItemFromLists(rte, list_length(pstate->p_rtable),
    2642                 :         700 :                                                                   coltypes, coltypmods, colcollations);
    2643                 :             : 
    2644                 :        1400 :         return nsitem;
    2645                 :         700 : }
    2646                 :             : 
    2647                 :             : 
    2648                 :             : /*
    2649                 :             :  * Has the specified refname been selected FOR UPDATE/FOR SHARE?
    2650                 :             :  *
    2651                 :             :  * This is used when we have not yet done transformLockingClause, but need
    2652                 :             :  * to know the correct lock to take during initial opening of relations.
    2653                 :             :  *
    2654                 :             :  * Note that refname may be NULL (for a subquery without an alias), in which
    2655                 :             :  * case the relation can't be locked by name, but it might still be locked if
    2656                 :             :  * a locking clause requests that all tables be locked.
    2657                 :             :  *
    2658                 :             :  * Note: we pay no attention to whether it's FOR UPDATE vs FOR SHARE,
    2659                 :             :  * since the table-level lock is the same either way.
    2660                 :             :  */
    2661                 :             : bool
    2662                 :       39201 : isLockedRefname(ParseState *pstate, const char *refname)
    2663                 :             : {
    2664                 :       39201 :         ListCell   *l;
    2665                 :             : 
    2666                 :             :         /*
    2667                 :             :          * If we are in a subquery specified as locked FOR UPDATE/SHARE from
    2668                 :             :          * parent level, then act as though there's a generic FOR UPDATE here.
    2669                 :             :          */
    2670         [ -  + ]:       39201 :         if (pstate->p_locked_from_parent)
    2671                 :           0 :                 return true;
    2672                 :             : 
    2673   [ +  +  +  +  :       39573 :         foreach(l, pstate->p_locking_clause)
             +  +  +  + ]
    2674                 :             :         {
    2675                 :         372 :                 LockingClause *lc = (LockingClause *) lfirst(l);
    2676                 :             : 
    2677         [ +  + ]:         372 :                 if (lc->lockedRels == NIL)
    2678                 :             :                 {
    2679                 :             :                         /* all tables used in query */
    2680                 :          43 :                         return true;
    2681                 :             :                 }
    2682         [ +  + ]:         329 :                 else if (refname != NULL)
    2683                 :             :                 {
    2684                 :             :                         /* just the named tables */
    2685                 :         328 :                         ListCell   *l2;
    2686                 :             : 
    2687   [ +  -  +  +  :         656 :                         foreach(l2, lc->lockedRels)
             +  +  +  + ]
    2688                 :             :                         {
    2689                 :         328 :                                 RangeVar   *thisrel = (RangeVar *) lfirst(l2);
    2690                 :             : 
    2691         [ +  + ]:         328 :                                 if (strcmp(refname, thisrel->relname) == 0)
    2692                 :         313 :                                         return true;
    2693         [ +  + ]:         328 :                         }
    2694         [ +  + ]:         328 :                 }
    2695         [ +  + ]:         372 :         }
    2696                 :       38845 :         return false;
    2697                 :       39201 : }
    2698                 :             : 
    2699                 :             : /*
    2700                 :             :  * Add the given nsitem/RTE as a top-level entry in the pstate's join list
    2701                 :             :  * and/or namespace list.  (We assume caller has checked for any
    2702                 :             :  * namespace conflicts.)  The nsitem is always marked as unconditionally
    2703                 :             :  * visible, that is, not LATERAL-only.
    2704                 :             :  */
    2705                 :             : void
    2706                 :       15322 : addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem,
    2707                 :             :                                  bool addToJoinList,
    2708                 :             :                                  bool addToRelNameSpace, bool addToVarNameSpace)
    2709                 :             : {
    2710         [ +  + ]:       15322 :         if (addToJoinList)
    2711                 :             :         {
    2712                 :        6241 :                 RangeTblRef *rtr = makeNode(RangeTblRef);
    2713                 :             : 
    2714                 :        6241 :                 rtr->rtindex = nsitem->p_rtindex;
    2715                 :        6241 :                 pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
    2716                 :        6241 :         }
    2717   [ +  +  +  + ]:       15322 :         if (addToRelNameSpace || addToVarNameSpace)
    2718                 :             :         {
    2719                 :             :                 /* Set the new nsitem's visibility flags correctly */
    2720                 :       14181 :                 nsitem->p_rel_visible = addToRelNameSpace;
    2721                 :       14181 :                 nsitem->p_cols_visible = addToVarNameSpace;
    2722                 :       14181 :                 nsitem->p_lateral_only = false;
    2723                 :       14181 :                 nsitem->p_lateral_ok = true;
    2724                 :       14181 :                 pstate->p_namespace = lappend(pstate->p_namespace, nsitem);
    2725                 :       14181 :         }
    2726                 :       15322 : }
    2727                 :             : 
    2728                 :             : /*
    2729                 :             :  * expandRTE -- expand the columns of a rangetable entry
    2730                 :             :  *
    2731                 :             :  * This creates lists of an RTE's column names (aliases if provided, else
    2732                 :             :  * real names) and Vars for each column.  Only user columns are considered.
    2733                 :             :  * If include_dropped is false then dropped columns are omitted from the
    2734                 :             :  * results.  If include_dropped is true then empty strings and NULL constants
    2735                 :             :  * (not Vars!) are returned for dropped columns.
    2736                 :             :  *
    2737                 :             :  * rtindex, sublevels_up, returning_type, and location are the varno,
    2738                 :             :  * varlevelsup, varreturningtype, and location values to use in the created
    2739                 :             :  * Vars.  Ordinarily rtindex should match the actual position of the RTE in
    2740                 :             :  * its rangetable.
    2741                 :             :  *
    2742                 :             :  * The output lists go into *colnames and *colvars.
    2743                 :             :  * If only one of the two kinds of output list is needed, pass NULL for the
    2744                 :             :  * output pointer for the unwanted one.
    2745                 :             :  */
    2746                 :             : void
    2747                 :        1693 : expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
    2748                 :             :                   VarReturningType returning_type,
    2749                 :             :                   int location, bool include_dropped,
    2750                 :             :                   List **colnames, List **colvars)
    2751                 :             : {
    2752                 :        1693 :         int                     varattno;
    2753                 :             : 
    2754         [ +  + ]:        1693 :         if (colnames)
    2755                 :         218 :                 *colnames = NIL;
    2756         [ +  + ]:        1693 :         if (colvars)
    2757                 :        1597 :                 *colvars = NIL;
    2758                 :             : 
    2759   [ +  +  -  +  :        1693 :         switch (rte->rtekind)
                +  +  - ]
    2760                 :             :         {
    2761                 :             :                 case RTE_RELATION:
    2762                 :             :                         /* Ordinary relation RTE */
    2763                 :          52 :                         expandRelation(rte->relid, rte->eref,
    2764                 :          26 :                                                    rtindex, sublevels_up, returning_type, location,
    2765                 :          26 :                                                    include_dropped, colnames, colvars);
    2766                 :          26 :                         break;
    2767                 :             :                 case RTE_SUBQUERY:
    2768                 :             :                         {
    2769                 :             :                                 /* Subquery RTE */
    2770                 :          96 :                                 ListCell   *aliasp_item = list_head(rte->eref->colnames);
    2771                 :          96 :                                 ListCell   *tlistitem;
    2772                 :             : 
    2773                 :          96 :                                 varattno = 0;
    2774   [ +  -  +  +  :         342 :                                 foreach(tlistitem, rte->subquery->targetList)
                   +  + ]
    2775                 :             :                                 {
    2776                 :         246 :                                         TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
    2777                 :             : 
    2778         [ -  + ]:         246 :                                         if (te->resjunk)
    2779                 :           0 :                                                 continue;
    2780                 :         246 :                                         varattno++;
    2781         [ +  - ]:         246 :                                         Assert(varattno == te->resno);
    2782                 :             : 
    2783                 :             :                                         /*
    2784                 :             :                                          * Formerly it was possible for the subquery tlist to have
    2785                 :             :                                          * more non-junk entries than the colnames list does (if
    2786                 :             :                                          * this RTE has been expanded from a view that has more
    2787                 :             :                                          * columns than it did when the current query was parsed).
    2788                 :             :                                          * Now that ApplyRetrieveRule cleans up such cases, we
    2789                 :             :                                          * shouldn't see that anymore, but let's just check.
    2790                 :             :                                          */
    2791         [ +  - ]:         246 :                                         if (!aliasp_item)
    2792   [ #  #  #  # ]:           0 :                                                 elog(ERROR, "too few column names for subquery %s",
    2793                 :             :                                                          rte->eref->aliasname);
    2794                 :             : 
    2795         [ -  + ]:         246 :                                         if (colnames)
    2796                 :             :                                         {
    2797                 :         246 :                                                 char       *label = strVal(lfirst(aliasp_item));
    2798                 :             : 
    2799                 :         246 :                                                 *colnames = lappend(*colnames, makeString(pstrdup(label)));
    2800                 :         246 :                                         }
    2801                 :             : 
    2802         [ -  + ]:         246 :                                         if (colvars)
    2803                 :             :                                         {
    2804                 :         246 :                                                 Var                *varnode;
    2805                 :             : 
    2806                 :         492 :                                                 varnode = makeVar(rtindex, varattno,
    2807                 :         246 :                                                                                   exprType((Node *) te->expr),
    2808                 :         246 :                                                                                   exprTypmod((Node *) te->expr),
    2809                 :         246 :                                                                                   exprCollation((Node *) te->expr),
    2810                 :         246 :                                                                                   sublevels_up);
    2811                 :         246 :                                                 varnode->varreturningtype = returning_type;
    2812                 :         246 :                                                 varnode->location = location;
    2813                 :             : 
    2814                 :         246 :                                                 *colvars = lappend(*colvars, varnode);
    2815                 :         246 :                                         }
    2816                 :             : 
    2817                 :         246 :                                         aliasp_item = lnext(rte->eref->colnames, aliasp_item);
    2818         [ -  + ]:         246 :                                 }
    2819                 :          96 :                         }
    2820                 :          96 :                         break;
    2821                 :             :                 case RTE_FUNCTION:
    2822                 :             :                         {
    2823                 :             :                                 /* Function RTE */
    2824                 :        1310 :                                 int                     atts_done = 0;
    2825                 :        1310 :                                 ListCell   *lc;
    2826                 :             : 
    2827   [ +  -  +  +  :        2634 :                                 foreach(lc, rte->functions)
                   +  + ]
    2828                 :             :                                 {
    2829                 :        1324 :                                         RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
    2830                 :        1324 :                                         TypeFuncClass functypclass;
    2831                 :        1324 :                                         Oid                     funcrettype = InvalidOid;
    2832                 :        1324 :                                         TupleDesc       tupdesc = NULL;
    2833                 :             : 
    2834                 :             :                                         /* If it has a coldeflist, it returns RECORD */
    2835         [ +  + ]:        1324 :                                         if (rtfunc->funccolnames != NIL)
    2836                 :           4 :                                                 functypclass = TYPEFUNC_RECORD;
    2837                 :             :                                         else
    2838                 :        1320 :                                                 functypclass = get_expr_result_type(rtfunc->funcexpr,
    2839                 :             :                                                                                                                         &funcrettype,
    2840                 :             :                                                                                                                         &tupdesc);
    2841                 :             : 
    2842   [ +  +  -  + ]:        1324 :                                         if (functypclass == TYPEFUNC_COMPOSITE ||
    2843                 :        1065 :                                                 functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
    2844                 :             :                                         {
    2845                 :             :                                                 /* Composite data type, e.g. a table's row type */
    2846         [ +  - ]:         259 :                                                 Assert(tupdesc);
    2847                 :         518 :                                                 expandTupleDesc(tupdesc, rte->eref,
    2848                 :         259 :                                                                                 rtfunc->funccolcount, atts_done,
    2849                 :         259 :                                                                                 rtindex, sublevels_up,
    2850                 :         259 :                                                                                 returning_type, location,
    2851                 :         259 :                                                                                 include_dropped, colnames, colvars);
    2852                 :         259 :                                         }
    2853         [ +  + ]:        1065 :                                         else if (functypclass == TYPEFUNC_SCALAR)
    2854                 :             :                                         {
    2855                 :             :                                                 /* Base data type, i.e. scalar */
    2856         [ +  + ]:        1061 :                                                 if (colnames)
    2857                 :          96 :                                                         *colnames = lappend(*colnames,
    2858                 :          96 :                                                                                                 list_nth(rte->eref->colnames,
    2859                 :          48 :                                                                                                                  atts_done));
    2860                 :             : 
    2861         [ +  + ]:        1061 :                                                 if (colvars)
    2862                 :             :                                                 {
    2863                 :        1013 :                                                         Var                *varnode;
    2864                 :             : 
    2865                 :        2026 :                                                         varnode = makeVar(rtindex, atts_done + 1,
    2866                 :        1013 :                                                                                           funcrettype,
    2867                 :        1013 :                                                                                           exprTypmod(rtfunc->funcexpr),
    2868                 :        1013 :                                                                                           exprCollation(rtfunc->funcexpr),
    2869                 :        1013 :                                                                                           sublevels_up);
    2870                 :        1013 :                                                         varnode->varreturningtype = returning_type;
    2871                 :        1013 :                                                         varnode->location = location;
    2872                 :             : 
    2873                 :        1013 :                                                         *colvars = lappend(*colvars, varnode);
    2874                 :        1013 :                                                 }
    2875                 :        1061 :                                         }
    2876         [ +  - ]:           4 :                                         else if (functypclass == TYPEFUNC_RECORD)
    2877                 :             :                                         {
    2878         [ +  + ]:           4 :                                                 if (colnames)
    2879                 :             :                                                 {
    2880                 :           1 :                                                         List       *namelist;
    2881                 :             : 
    2882                 :             :                                                         /* extract appropriate subset of column list */
    2883                 :           2 :                                                         namelist = list_copy_tail(rte->eref->colnames,
    2884                 :           1 :                                                                                                           atts_done);
    2885                 :           2 :                                                         namelist = list_truncate(namelist,
    2886                 :           1 :                                                                                                          rtfunc->funccolcount);
    2887                 :           1 :                                                         *colnames = list_concat(*colnames, namelist);
    2888                 :           1 :                                                 }
    2889                 :             : 
    2890         [ +  + ]:           4 :                                                 if (colvars)
    2891                 :             :                                                 {
    2892                 :           3 :                                                         ListCell   *l1;
    2893                 :           3 :                                                         ListCell   *l2;
    2894                 :           3 :                                                         ListCell   *l3;
    2895                 :           3 :                                                         int                     attnum = atts_done;
    2896                 :             : 
    2897   [ +  -  +  +  :           7 :                                                         forthree(l1, rtfunc->funccoltypes,
          +  -  +  +  +  
          -  +  +  +  +  
             -  +  +  + ]
    2898                 :             :                                                                          l2, rtfunc->funccoltypmods,
    2899                 :             :                                                                          l3, rtfunc->funccolcollations)
    2900                 :             :                                                         {
    2901                 :           4 :                                                                 Oid                     attrtype = lfirst_oid(l1);
    2902                 :           4 :                                                                 int32           attrtypmod = lfirst_int(l2);
    2903                 :           4 :                                                                 Oid                     attrcollation = lfirst_oid(l3);
    2904                 :           4 :                                                                 Var                *varnode;
    2905                 :             : 
    2906                 :           4 :                                                                 attnum++;
    2907                 :           8 :                                                                 varnode = makeVar(rtindex,
    2908                 :           4 :                                                                                                   attnum,
    2909                 :           4 :                                                                                                   attrtype,
    2910                 :           4 :                                                                                                   attrtypmod,
    2911                 :           4 :                                                                                                   attrcollation,
    2912                 :           4 :                                                                                                   sublevels_up);
    2913                 :           4 :                                                                 varnode->varreturningtype = returning_type;
    2914                 :           4 :                                                                 varnode->location = location;
    2915                 :           4 :                                                                 *colvars = lappend(*colvars, varnode);
    2916                 :           4 :                                                         }
    2917                 :           3 :                                                 }
    2918                 :           4 :                                         }
    2919                 :             :                                         else
    2920                 :             :                                         {
    2921                 :             :                                                 /* addRangeTableEntryForFunction should've caught this */
    2922   [ #  #  #  # ]:           0 :                                                 elog(ERROR, "function in FROM has unsupported return type");
    2923                 :             :                                         }
    2924                 :        1324 :                                         atts_done += rtfunc->funccolcount;
    2925                 :        1324 :                                 }
    2926                 :             : 
    2927                 :             :                                 /* Append the ordinality column if any */
    2928         [ +  + ]:        1310 :                                 if (rte->funcordinality)
    2929                 :             :                                 {
    2930         [ +  + ]:          77 :                                         if (colnames)
    2931                 :           6 :                                                 *colnames = lappend(*colnames,
    2932                 :           3 :                                                                                         llast(rte->eref->colnames));
    2933                 :             : 
    2934         [ +  + ]:          77 :                                         if (colvars)
    2935                 :             :                                         {
    2936                 :         148 :                                                 Var                *varnode = makeVar(rtindex,
    2937                 :          74 :                                                                                                           atts_done + 1,
    2938                 :             :                                                                                                           INT8OID,
    2939                 :             :                                                                                                           -1,
    2940                 :             :                                                                                                           InvalidOid,
    2941                 :          74 :                                                                                                           sublevels_up);
    2942                 :             : 
    2943                 :          74 :                                                 varnode->varreturningtype = returning_type;
    2944                 :          74 :                                                 *colvars = lappend(*colvars, varnode);
    2945                 :          74 :                                         }
    2946                 :          77 :                                 }
    2947                 :        1310 :                         }
    2948                 :        1310 :                         break;
    2949                 :             :                 case RTE_JOIN:
    2950                 :             :                         {
    2951                 :             :                                 /* Join RTE */
    2952                 :           2 :                                 ListCell   *colname;
    2953                 :           2 :                                 ListCell   *aliasvar;
    2954                 :             : 
    2955         [ -  + ]:           2 :                                 Assert(list_length(rte->eref->colnames) == list_length(rte->joinaliasvars));
    2956                 :             : 
    2957                 :           2 :                                 varattno = 0;
    2958   [ +  -  +  +  :          10 :                                 forboth(colname, rte->eref->colnames, aliasvar, rte->joinaliasvars)
          +  -  +  +  +  
                +  +  + ]
    2959                 :             :                                 {
    2960                 :           8 :                                         Node       *avar = (Node *) lfirst(aliasvar);
    2961                 :             : 
    2962                 :           8 :                                         varattno++;
    2963                 :             : 
    2964                 :             :                                         /*
    2965                 :             :                                          * During ordinary parsing, there will never be any
    2966                 :             :                                          * deleted columns in the join.  While this function is
    2967                 :             :                                          * also used by the rewriter and planner, they do not
    2968                 :             :                                          * currently call it on any JOIN RTEs.  Therefore, this
    2969                 :             :                                          * next bit is dead code, but it seems prudent to handle
    2970                 :             :                                          * the case correctly anyway.
    2971                 :             :                                          */
    2972         [ +  - ]:           8 :                                         if (avar == NULL)
    2973                 :             :                                         {
    2974         [ #  # ]:           0 :                                                 if (include_dropped)
    2975                 :             :                                                 {
    2976         [ #  # ]:           0 :                                                         if (colnames)
    2977                 :           0 :                                                                 *colnames = lappend(*colnames,
    2978                 :           0 :                                                                                                         makeString(pstrdup("")));
    2979         [ #  # ]:           0 :                                                         if (colvars)
    2980                 :             :                                                         {
    2981                 :             :                                                                 /*
    2982                 :             :                                                                  * Can't use join's column type here (it might
    2983                 :             :                                                                  * be dropped!); but it doesn't really matter
    2984                 :             :                                                                  * what type the Const claims to be.
    2985                 :             :                                                                  */
    2986                 :           0 :                                                                 *colvars = lappend(*colvars,
    2987                 :           0 :                                                                                                    makeNullConst(INT4OID, -1,
    2988                 :             :                                                                                                                                  InvalidOid));
    2989                 :           0 :                                                         }
    2990                 :           0 :                                                 }
    2991                 :           0 :                                                 continue;
    2992                 :             :                                         }
    2993                 :             : 
    2994         [ +  - ]:           8 :                                         if (colnames)
    2995                 :             :                                         {
    2996                 :           0 :                                                 char       *label = strVal(lfirst(colname));
    2997                 :             : 
    2998                 :           0 :                                                 *colnames = lappend(*colnames,
    2999                 :           0 :                                                                                         makeString(pstrdup(label)));
    3000                 :           0 :                                         }
    3001                 :             : 
    3002         [ -  + ]:           8 :                                         if (colvars)
    3003                 :             :                                         {
    3004                 :           8 :                                                 Var                *varnode;
    3005                 :             : 
    3006                 :             :                                                 /*
    3007                 :             :                                                  * If the joinaliasvars entry is a simple Var, just
    3008                 :             :                                                  * copy it (with adjustment of varlevelsup and
    3009                 :             :                                                  * location); otherwise it is a JOIN USING column and
    3010                 :             :                                                  * we must generate a join alias Var.  This matches
    3011                 :             :                                                  * the results that expansion of "join.*" by
    3012                 :             :                                                  * expandNSItemVars would have produced, if we had
    3013                 :             :                                                  * access to the ParseNamespaceItem for the join.
    3014                 :             :                                                  */
    3015         [ +  - ]:           8 :                                                 if (IsA(avar, Var))
    3016                 :             :                                                 {
    3017                 :           8 :                                                         varnode = copyObject((Var *) avar);
    3018                 :           8 :                                                         varnode->varlevelsup = sublevels_up;
    3019                 :           8 :                                                 }
    3020                 :             :                                                 else
    3021                 :           0 :                                                         varnode = makeVar(rtindex, varattno,
    3022                 :           0 :                                                                                           exprType(avar),
    3023                 :           0 :                                                                                           exprTypmod(avar),
    3024                 :           0 :                                                                                           exprCollation(avar),
    3025                 :           0 :                                                                                           sublevels_up);
    3026                 :           8 :                                                 varnode->varreturningtype = returning_type;
    3027                 :           8 :                                                 varnode->location = location;
    3028                 :             : 
    3029                 :           8 :                                                 *colvars = lappend(*colvars, varnode);
    3030                 :           8 :                                         }
    3031         [ -  + ]:           8 :                                 }
    3032                 :           2 :                         }
    3033                 :           2 :                         break;
    3034                 :             :                 case RTE_TABLEFUNC:
    3035                 :             :                 case RTE_VALUES:
    3036                 :             :                 case RTE_CTE:
    3037                 :             :                 case RTE_NAMEDTUPLESTORE:
    3038                 :             :                         {
    3039                 :             :                                 /* Tablefunc, Values, CTE, or ENR RTE */
    3040                 :         259 :                                 ListCell   *aliasp_item = list_head(rte->eref->colnames);
    3041                 :         259 :                                 ListCell   *lct;
    3042                 :         259 :                                 ListCell   *lcm;
    3043                 :         259 :                                 ListCell   *lcc;
    3044                 :             : 
    3045                 :         259 :                                 varattno = 0;
    3046   [ +  -  +  +  :         767 :                                 forthree(lct, rte->coltypes,
          +  -  +  +  +  
          -  +  +  +  +  
             -  +  +  + ]
    3047                 :             :                                                  lcm, rte->coltypmods,
    3048                 :             :                                                  lcc, rte->colcollations)
    3049                 :             :                                 {
    3050                 :         508 :                                         Oid                     coltype = lfirst_oid(lct);
    3051                 :         508 :                                         int32           coltypmod = lfirst_int(lcm);
    3052                 :         508 :                                         Oid                     colcoll = lfirst_oid(lcc);
    3053                 :             : 
    3054                 :         508 :                                         varattno++;
    3055                 :             : 
    3056         [ +  - ]:         508 :                                         if (colnames)
    3057                 :             :                                         {
    3058                 :             :                                                 /* Assume there is one alias per output column */
    3059         [ #  # ]:           0 :                                                 if (OidIsValid(coltype))
    3060                 :             :                                                 {
    3061                 :           0 :                                                         char       *label = strVal(lfirst(aliasp_item));
    3062                 :             : 
    3063                 :           0 :                                                         *colnames = lappend(*colnames,
    3064                 :           0 :                                                                                                 makeString(pstrdup(label)));
    3065                 :           0 :                                                 }
    3066         [ #  # ]:           0 :                                                 else if (include_dropped)
    3067                 :           0 :                                                         *colnames = lappend(*colnames,
    3068                 :           0 :                                                                                                 makeString(pstrdup("")));
    3069                 :             : 
    3070                 :           0 :                                                 aliasp_item = lnext(rte->eref->colnames, aliasp_item);
    3071                 :           0 :                                         }
    3072                 :             : 
    3073         [ -  + ]:         508 :                                         if (colvars)
    3074                 :             :                                         {
    3075         [ +  - ]:         508 :                                                 if (OidIsValid(coltype))
    3076                 :             :                                                 {
    3077                 :         508 :                                                         Var                *varnode;
    3078                 :             : 
    3079                 :        1016 :                                                         varnode = makeVar(rtindex, varattno,
    3080                 :         508 :                                                                                           coltype, coltypmod, colcoll,
    3081                 :         508 :                                                                                           sublevels_up);
    3082                 :         508 :                                                         varnode->varreturningtype = returning_type;
    3083                 :         508 :                                                         varnode->location = location;
    3084                 :             : 
    3085                 :         508 :                                                         *colvars = lappend(*colvars, varnode);
    3086                 :         508 :                                                 }
    3087         [ #  # ]:           0 :                                                 else if (include_dropped)
    3088                 :             :                                                 {
    3089                 :             :                                                         /*
    3090                 :             :                                                          * It doesn't really matter what type the Const
    3091                 :             :                                                          * claims to be.
    3092                 :             :                                                          */
    3093                 :           0 :                                                         *colvars = lappend(*colvars,
    3094                 :           0 :                                                                                            makeNullConst(INT4OID, -1,
    3095                 :             :                                                                                                                          InvalidOid));
    3096                 :           0 :                                                 }
    3097                 :         508 :                                         }
    3098                 :         508 :                                 }
    3099                 :         259 :                         }
    3100                 :         259 :                         break;
    3101                 :             :                 case RTE_RESULT:
    3102                 :             :                 case RTE_GROUP:
    3103                 :             :                         /* These expose no columns, so nothing to do */
    3104                 :           0 :                         break;
    3105                 :             :                 default:
    3106   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
    3107                 :           0 :         }
    3108                 :        1693 : }
    3109                 :             : 
    3110                 :             : /*
    3111                 :             :  * expandRelation -- expandRTE subroutine
    3112                 :             :  */
    3113                 :             : static void
    3114                 :          26 : expandRelation(Oid relid, Alias *eref, int rtindex, int sublevels_up,
    3115                 :             :                            VarReturningType returning_type,
    3116                 :             :                            int location, bool include_dropped,
    3117                 :             :                            List **colnames, List **colvars)
    3118                 :             : {
    3119                 :          26 :         Relation        rel;
    3120                 :             : 
    3121                 :             :         /* Get the tupledesc and turn it over to expandTupleDesc */
    3122                 :          26 :         rel = relation_open(relid, AccessShareLock);
    3123                 :          52 :         expandTupleDesc(rel->rd_att, eref, rel->rd_att->natts, 0,
    3124                 :          26 :                                         rtindex, sublevels_up, returning_type,
    3125                 :          26 :                                         location, include_dropped,
    3126                 :          26 :                                         colnames, colvars);
    3127                 :          26 :         relation_close(rel, AccessShareLock);
    3128                 :          26 : }
    3129                 :             : 
    3130                 :             : /*
    3131                 :             :  * expandTupleDesc -- expandRTE subroutine
    3132                 :             :  *
    3133                 :             :  * Generate names and/or Vars for the first "count" attributes of the tupdesc,
    3134                 :             :  * and append them to colnames/colvars.  "offset" is added to the varattno
    3135                 :             :  * that each Var would otherwise have, and we also skip the first "offset"
    3136                 :             :  * entries in eref->colnames.  (These provisions allow use of this code for
    3137                 :             :  * an individual composite-returning function in an RTE_FUNCTION RTE.)
    3138                 :             :  */
    3139                 :             : static void
    3140                 :         285 : expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset,
    3141                 :             :                                 int rtindex, int sublevels_up,
    3142                 :             :                                 VarReturningType returning_type,
    3143                 :             :                                 int location, bool include_dropped,
    3144                 :             :                                 List **colnames, List **colvars)
    3145                 :             : {
    3146                 :         285 :         ListCell   *aliascell;
    3147                 :         285 :         int                     varattno;
    3148                 :             : 
    3149         [ +  + ]:         285 :         aliascell = (offset < list_length(eref->colnames)) ?
    3150                 :         282 :                 list_nth_cell(eref->colnames, offset) : NULL;
    3151                 :             : 
    3152         [ +  - ]:         285 :         Assert(count <= tupdesc->natts);
    3153         [ +  + ]:        2717 :         for (varattno = 0; varattno < count; varattno++)
    3154                 :             :         {
    3155                 :        2432 :                 Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
    3156                 :             : 
    3157         [ +  + ]:        2432 :                 if (attr->attisdropped)
    3158                 :             :                 {
    3159         [ -  + ]:           7 :                         if (include_dropped)
    3160                 :             :                         {
    3161         [ -  + ]:           7 :                                 if (colnames)
    3162                 :           7 :                                         *colnames = lappend(*colnames, makeString(pstrdup("")));
    3163         [ +  - ]:           7 :                                 if (colvars)
    3164                 :             :                                 {
    3165                 :             :                                         /*
    3166                 :             :                                          * can't use atttypid here, but it doesn't really matter
    3167                 :             :                                          * what type the Const claims to be.
    3168                 :             :                                          */
    3169                 :           0 :                                         *colvars = lappend(*colvars,
    3170                 :           0 :                                                                            makeNullConst(INT4OID, -1, InvalidOid));
    3171                 :           0 :                                 }
    3172                 :           7 :                         }
    3173         [ -  + ]:           7 :                         if (aliascell)
    3174                 :           7 :                                 aliascell = lnext(eref->colnames, aliascell);
    3175                 :           7 :                         continue;
    3176                 :             :                 }
    3177                 :             : 
    3178         [ +  + ]:        2425 :                 if (colnames)
    3179                 :             :                 {
    3180                 :         671 :                         char       *label;
    3181                 :             : 
    3182         [ +  + ]:         671 :                         if (aliascell)
    3183                 :             :                         {
    3184                 :         665 :                                 label = strVal(lfirst(aliascell));
    3185                 :         665 :                                 aliascell = lnext(eref->colnames, aliascell);
    3186                 :         665 :                         }
    3187                 :             :                         else
    3188                 :             :                         {
    3189                 :             :                                 /* If we run out of aliases, use the underlying name */
    3190                 :           6 :                                 label = NameStr(attr->attname);
    3191                 :             :                         }
    3192                 :         671 :                         *colnames = lappend(*colnames, makeString(pstrdup(label)));
    3193                 :         671 :                 }
    3194                 :             : 
    3195         [ +  + ]:        2425 :                 if (colvars)
    3196                 :             :                 {
    3197                 :        1837 :                         Var                *varnode;
    3198                 :             : 
    3199                 :        3674 :                         varnode = makeVar(rtindex, varattno + offset + 1,
    3200                 :        1837 :                                                           attr->atttypid, attr->atttypmod,
    3201                 :        1837 :                                                           attr->attcollation,
    3202                 :        1837 :                                                           sublevels_up);
    3203                 :        1837 :                         varnode->varreturningtype = returning_type;
    3204                 :        1837 :                         varnode->location = location;
    3205                 :             : 
    3206                 :        1837 :                         *colvars = lappend(*colvars, varnode);
    3207                 :        1837 :                 }
    3208      [ -  +  + ]:        2432 :         }
    3209                 :         285 : }
    3210                 :             : 
    3211                 :             : /*
    3212                 :             :  * expandNSItemVars
    3213                 :             :  *        Produce a list of Vars, and optionally a list of column names,
    3214                 :             :  *        for the non-dropped columns of the nsitem.
    3215                 :             :  *
    3216                 :             :  * The emitted Vars are marked with the given sublevels_up and location.
    3217                 :             :  *
    3218                 :             :  * If colnames isn't NULL, a list of String items for the columns is stored
    3219                 :             :  * there; note that it's just a subset of the RTE's eref list, and hence
    3220                 :             :  * the list elements mustn't be modified.
    3221                 :             :  */
    3222                 :             : List *
    3223                 :       11311 : expandNSItemVars(ParseState *pstate, ParseNamespaceItem *nsitem,
    3224                 :             :                                  int sublevels_up, int location,
    3225                 :             :                                  List **colnames)
    3226                 :             : {
    3227                 :       11311 :         List       *result = NIL;
    3228                 :       11311 :         int                     colindex;
    3229                 :       11311 :         ListCell   *lc;
    3230                 :             : 
    3231         [ +  + ]:       11311 :         if (colnames)
    3232                 :       10721 :                 *colnames = NIL;
    3233                 :       11311 :         colindex = 0;
    3234   [ +  +  +  +  :       42606 :         foreach(lc, nsitem->p_names->colnames)
                   +  + ]
    3235                 :             :         {
    3236                 :       31295 :                 String     *colnameval = lfirst(lc);
    3237                 :       31295 :                 const char *colname = strVal(colnameval);
    3238                 :       31295 :                 ParseNamespaceColumn *nscol = nsitem->p_nscolumns + colindex;
    3239                 :             : 
    3240         [ +  + ]:       31295 :                 if (nscol->p_dontexpand)
    3241                 :             :                 {
    3242                 :             :                         /* skip */
    3243                 :           3 :                 }
    3244         [ +  + ]:       31292 :                 else if (colname[0])
    3245                 :             :                 {
    3246                 :       31153 :                         Var                *var;
    3247                 :             : 
    3248         [ -  + ]:       31153 :                         Assert(nscol->p_varno > 0);
    3249                 :       62306 :                         var = makeVar(nscol->p_varno,
    3250                 :       31153 :                                                   nscol->p_varattno,
    3251                 :       31153 :                                                   nscol->p_vartype,
    3252                 :       31153 :                                                   nscol->p_vartypmod,
    3253                 :       31153 :                                                   nscol->p_varcollid,
    3254                 :       31153 :                                                   sublevels_up);
    3255                 :             :                         /* makeVar doesn't offer parameters for these, so set by hand: */
    3256                 :       31153 :                         var->varreturningtype = nscol->p_varreturningtype;
    3257                 :       31153 :                         var->varnosyn = nscol->p_varnosyn;
    3258                 :       31153 :                         var->varattnosyn = nscol->p_varattnosyn;
    3259                 :       31153 :                         var->location = location;
    3260                 :             : 
    3261                 :             :                         /* ... and update varnullingrels */
    3262                 :       31153 :                         markNullableIfNeeded(pstate, var);
    3263                 :             : 
    3264                 :       31153 :                         result = lappend(result, var);
    3265         [ +  + ]:       31153 :                         if (colnames)
    3266                 :       29976 :                                 *colnames = lappend(*colnames, colnameval);
    3267                 :       31153 :                 }
    3268                 :             :                 else
    3269                 :             :                 {
    3270                 :             :                         /* dropped column, ignore */
    3271         [ -  + ]:         139 :                         Assert(nscol->p_varno == 0);
    3272                 :             :                 }
    3273                 :       31295 :                 colindex++;
    3274                 :       31295 :         }
    3275                 :       22622 :         return result;
    3276                 :       11311 : }
    3277                 :             : 
    3278                 :             : /*
    3279                 :             :  * expandNSItemAttrs -
    3280                 :             :  *        Workhorse for "*" expansion: produce a list of targetentries
    3281                 :             :  *        for the attributes of the nsitem
    3282                 :             :  *
    3283                 :             :  * pstate->p_next_resno determines the resnos assigned to the TLEs.
    3284                 :             :  * The referenced columns are marked as requiring SELECT access, if
    3285                 :             :  * caller requests that.
    3286                 :             :  */
    3287                 :             : List *
    3288                 :       10721 : expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem,
    3289                 :             :                                   int sublevels_up, bool require_col_privs, int location)
    3290                 :             : {
    3291                 :       10721 :         RangeTblEntry *rte = nsitem->p_rte;
    3292                 :       10721 :         RTEPermissionInfo *perminfo = nsitem->p_perminfo;
    3293                 :       10721 :         List       *names,
    3294                 :             :                            *vars;
    3295                 :       10721 :         ListCell   *name,
    3296                 :             :                            *var;
    3297                 :       10721 :         List       *te_list = NIL;
    3298                 :             : 
    3299                 :       10721 :         vars = expandNSItemVars(pstate, nsitem, sublevels_up, location, &names);
    3300                 :             : 
    3301                 :             :         /*
    3302                 :             :          * Require read access to the table.  This is normally redundant with the
    3303                 :             :          * markVarForSelectPriv calls below, but not if the table has zero
    3304                 :             :          * columns.  We need not do anything if the nsitem is for a join: its
    3305                 :             :          * component tables will have been marked ACL_SELECT when they were added
    3306                 :             :          * to the rangetable.  (This step changes things only for the target
    3307                 :             :          * relation of UPDATE/DELETE, which cannot be under a join.)
    3308                 :             :          */
    3309         [ +  + ]:       10721 :         if (rte->rtekind == RTE_RELATION)
    3310                 :             :         {
    3311         [ +  - ]:        7126 :                 Assert(perminfo != NULL);
    3312                 :        7126 :                 perminfo->requiredPerms |= ACL_SELECT;
    3313                 :        7126 :         }
    3314                 :             : 
    3315   [ +  +  +  +  :       40697 :         forboth(name, names, var, vars)
          +  +  +  +  +  
                +  +  + ]
    3316                 :             :         {
    3317                 :       29976 :                 char       *label = strVal(lfirst(name));
    3318                 :       29976 :                 Var                *varnode = (Var *) lfirst(var);
    3319                 :       29976 :                 TargetEntry *te;
    3320                 :             : 
    3321                 :       59952 :                 te = makeTargetEntry((Expr *) varnode,
    3322                 :       29976 :                                                          (AttrNumber) pstate->p_next_resno++,
    3323                 :       29976 :                                                          label,
    3324                 :             :                                                          false);
    3325                 :       29976 :                 te_list = lappend(te_list, te);
    3326                 :             : 
    3327         [ -  + ]:       29976 :                 if (require_col_privs)
    3328                 :             :                 {
    3329                 :             :                         /* Require read access to each column */
    3330                 :       29976 :                         markVarForSelectPriv(pstate, varnode);
    3331                 :       29976 :                 }
    3332                 :       29976 :         }
    3333                 :             : 
    3334         [ +  - ]:       10721 :         Assert(name == NULL && var == NULL);    /* lists not the same length? */
    3335                 :             : 
    3336                 :       21442 :         return te_list;
    3337                 :       10721 : }
    3338                 :             : 
    3339                 :             : /*
    3340                 :             :  * get_rte_attribute_name
    3341                 :             :  *              Get an attribute name from a RangeTblEntry
    3342                 :             :  *
    3343                 :             :  * This is unlike get_attname() because we use aliases if available.
    3344                 :             :  * In particular, it will work on an RTE for a subselect or join, whereas
    3345                 :             :  * get_attname() only works on real relations.
    3346                 :             :  *
    3347                 :             :  * "*" is returned if the given attnum is InvalidAttrNumber --- this case
    3348                 :             :  * occurs when a Var represents a whole tuple of a relation.
    3349                 :             :  *
    3350                 :             :  * It is caller's responsibility to not call this on a dropped attribute.
    3351                 :             :  * (You will get some answer for such cases, but it might not be sensible.)
    3352                 :             :  */
    3353                 :             : char *
    3354                 :         253 : get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
    3355                 :             : {
    3356         [ +  - ]:         253 :         if (attnum == InvalidAttrNumber)
    3357                 :           0 :                 return "*";
    3358                 :             : 
    3359                 :             :         /*
    3360                 :             :          * If there is a user-written column alias, use it.
    3361                 :             :          */
    3362         [ +  + ]:         253 :         if (rte->alias &&
    3363   [ +  +  +  - ]:         158 :                 attnum > 0 && attnum <= list_length(rte->alias->colnames))
    3364                 :           0 :                 return strVal(list_nth(rte->alias->colnames, attnum - 1));
    3365                 :             : 
    3366                 :             :         /*
    3367                 :             :          * If the RTE is a relation, go to the system catalogs not the
    3368                 :             :          * eref->colnames list.  This is a little slower but it will give the
    3369                 :             :          * right answer if the column has been renamed since the eref list was
    3370                 :             :          * built (which can easily happen for rules).
    3371                 :             :          */
    3372         [ +  + ]:         253 :         if (rte->rtekind == RTE_RELATION)
    3373                 :         248 :                 return get_attname(rte->relid, attnum, false);
    3374                 :             : 
    3375                 :             :         /*
    3376                 :             :          * Otherwise use the column name from eref.  There should always be one.
    3377                 :             :          */
    3378         [ +  - ]:           5 :         if (attnum > 0 && attnum <= list_length(rte->eref->colnames))
    3379                 :           5 :                 return strVal(list_nth(rte->eref->colnames, attnum - 1));
    3380                 :             : 
    3381                 :             :         /* else caller gave us a bogus attnum */
    3382   [ #  #  #  # ]:           0 :         elog(ERROR, "invalid attnum %d for rangetable entry %s",
    3383                 :             :                  attnum, rte->eref->aliasname);
    3384                 :           0 :         return NULL;                            /* keep compiler quiet */
    3385                 :         253 : }
    3386                 :             : 
    3387                 :             : /*
    3388                 :             :  * get_rte_attribute_is_dropped
    3389                 :             :  *              Check whether attempted attribute ref is to a dropped column
    3390                 :             :  */
    3391                 :             : bool
    3392                 :       63945 : get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
    3393                 :             : {
    3394                 :       63945 :         bool            result;
    3395                 :             : 
    3396   [ +  +  -  -  :       63945 :         switch (rte->rtekind)
                +  -  - ]
    3397                 :             :         {
    3398                 :             :                 case RTE_RELATION:
    3399                 :             :                         {
    3400                 :             :                                 /*
    3401                 :             :                                  * Plain relation RTE --- get the attribute's catalog entry
    3402                 :             :                                  */
    3403                 :       63058 :                                 HeapTuple       tp;
    3404                 :       63058 :                                 Form_pg_attribute att_tup;
    3405                 :             : 
    3406                 :       63058 :                                 tp = SearchSysCache2(ATTNUM,
    3407                 :       63058 :                                                                          ObjectIdGetDatum(rte->relid),
    3408                 :       63058 :                                                                          Int16GetDatum(attnum));
    3409         [ +  - ]:       63058 :                                 if (!HeapTupleIsValid(tp))      /* shouldn't happen */
    3410   [ #  #  #  # ]:           0 :                                         elog(ERROR, "cache lookup failed for attribute %d of relation %u",
    3411                 :             :                                                  attnum, rte->relid);
    3412                 :       63058 :                                 att_tup = (Form_pg_attribute) GETSTRUCT(tp);
    3413                 :       63058 :                                 result = att_tup->attisdropped;
    3414                 :       63058 :                                 ReleaseSysCache(tp);
    3415                 :       63058 :                         }
    3416                 :       63058 :                         break;
    3417                 :             :                 case RTE_SUBQUERY:
    3418                 :             :                 case RTE_TABLEFUNC:
    3419                 :             :                 case RTE_VALUES:
    3420                 :             :                 case RTE_CTE:
    3421                 :             :                 case RTE_GROUP:
    3422                 :             : 
    3423                 :             :                         /*
    3424                 :             :                          * Subselect, Table Functions, Values, CTE, GROUP RTEs never have
    3425                 :             :                          * dropped columns
    3426                 :             :                          */
    3427                 :          86 :                         result = false;
    3428                 :          86 :                         break;
    3429                 :             :                 case RTE_NAMEDTUPLESTORE:
    3430                 :             :                         {
    3431                 :             :                                 /* Check dropped-ness by testing for valid coltype */
    3432         [ #  # ]:           0 :                                 if (attnum <= 0 ||
    3433                 :           0 :                                         attnum > list_length(rte->coltypes))
    3434   [ #  #  #  # ]:           0 :                                         elog(ERROR, "invalid varattno %d", attnum);
    3435                 :           0 :                                 result = !OidIsValid((list_nth_oid(rte->coltypes, attnum - 1)));
    3436                 :             :                         }
    3437                 :           0 :                         break;
    3438                 :             :                 case RTE_JOIN:
    3439                 :             :                         {
    3440                 :             :                                 /*
    3441                 :             :                                  * A join RTE would not have dropped columns when constructed,
    3442                 :             :                                  * but one in a stored rule might contain columns that were
    3443                 :             :                                  * dropped from the underlying tables, if said columns are
    3444                 :             :                                  * nowhere explicitly referenced in the rule.  This will be
    3445                 :             :                                  * signaled to us by a null pointer in the joinaliasvars list.
    3446                 :             :                                  */
    3447                 :           0 :                                 Var                *aliasvar;
    3448                 :             : 
    3449         [ #  # ]:           0 :                                 if (attnum <= 0 ||
    3450                 :           0 :                                         attnum > list_length(rte->joinaliasvars))
    3451   [ #  #  #  # ]:           0 :                                         elog(ERROR, "invalid varattno %d", attnum);
    3452                 :           0 :                                 aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1);
    3453                 :             : 
    3454                 :           0 :                                 result = (aliasvar == NULL);
    3455                 :           0 :                         }
    3456                 :           0 :                         break;
    3457                 :             :                 case RTE_FUNCTION:
    3458                 :             :                         {
    3459                 :             :                                 /* Function RTE */
    3460                 :         801 :                                 ListCell   *lc;
    3461                 :         801 :                                 int                     atts_done = 0;
    3462                 :             : 
    3463                 :             :                                 /*
    3464                 :             :                                  * Dropped attributes are only possible with functions that
    3465                 :             :                                  * return named composite types.  In such a case we have to
    3466                 :             :                                  * look up the result type to see if it currently has this
    3467                 :             :                                  * column dropped.  So first, loop over the funcs until we
    3468                 :             :                                  * find the one that covers the requested column.
    3469                 :             :                                  */
    3470   [ +  -  +  +  :        1608 :                                 foreach(lc, rte->functions)
             +  +  +  + ]
    3471                 :             :                                 {
    3472                 :         807 :                                         RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
    3473                 :             : 
    3474   [ +  -  +  + ]:         807 :                                         if (attnum > atts_done &&
    3475                 :         807 :                                                 attnum <= atts_done + rtfunc->funccolcount)
    3476                 :             :                                         {
    3477                 :         797 :                                                 TupleDesc       tupdesc;
    3478                 :             : 
    3479                 :             :                                                 /* If it has a coldeflist, it returns RECORD */
    3480         [ -  + ]:         797 :                                                 if (rtfunc->funccolnames != NIL)
    3481                 :           0 :                                                         return false;   /* can't have any dropped columns */
    3482                 :             : 
    3483                 :         797 :                                                 tupdesc = get_expr_result_tupdesc(rtfunc->funcexpr,
    3484                 :             :                                                                                                                   true);
    3485         [ +  + ]:         797 :                                                 if (tupdesc)
    3486                 :             :                                                 {
    3487                 :             :                                                         /* Composite data type, e.g. a table's row type */
    3488                 :         785 :                                                         CompactAttribute *att;
    3489                 :             : 
    3490         [ -  + ]:         785 :                                                         Assert(tupdesc);
    3491         [ -  + ]:         785 :                                                         Assert(attnum - atts_done <= tupdesc->natts);
    3492                 :        1570 :                                                         att = TupleDescCompactAttr(tupdesc,
    3493                 :         785 :                                                                                                            attnum - atts_done - 1);
    3494                 :         785 :                                                         return att->attisdropped;
    3495                 :         785 :                                                 }
    3496                 :             :                                                 /* Otherwise, it can't have any dropped columns */
    3497                 :          12 :                                                 return false;
    3498                 :         797 :                                         }
    3499                 :          10 :                                         atts_done += rtfunc->funccolcount;
    3500         [ +  + ]:         807 :                                 }
    3501                 :             : 
    3502                 :             :                                 /* If we get here, must be looking for the ordinality column */
    3503         [ +  - ]:           4 :                                 if (rte->funcordinality && attnum == atts_done + 1)
    3504                 :           4 :                                         return false;
    3505                 :             : 
    3506                 :             :                                 /* this probably can't happen ... */
    3507   [ #  #  #  # ]:           0 :                                 ereport(ERROR,
    3508                 :             :                                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    3509                 :             :                                                  errmsg("column %d of relation \"%s\" does not exist",
    3510                 :             :                                                                 attnum,
    3511                 :             :                                                                 rte->eref->aliasname)));
    3512                 :           0 :                                 result = false; /* keep compiler quiet */
    3513         [ +  - ]:         801 :                         }
    3514                 :           0 :                         break;
    3515                 :             :                 case RTE_RESULT:
    3516                 :             :                         /* this probably can't happen ... */
    3517   [ #  #  #  # ]:           0 :                         ereport(ERROR,
    3518                 :             :                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
    3519                 :             :                                          errmsg("column %d of relation \"%s\" does not exist",
    3520                 :             :                                                         attnum,
    3521                 :             :                                                         rte->eref->aliasname)));
    3522                 :           0 :                         result = false;         /* keep compiler quiet */
    3523                 :           0 :                         break;
    3524                 :             :                 default:
    3525   [ #  #  #  # ]:           0 :                         elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
    3526                 :           0 :                         result = false;         /* keep compiler quiet */
    3527                 :           0 :         }
    3528                 :             : 
    3529                 :       63144 :         return result;
    3530                 :       63945 : }
    3531                 :             : 
    3532                 :             : /*
    3533                 :             :  * Given a targetlist and a resno, return the matching TargetEntry
    3534                 :             :  *
    3535                 :             :  * Returns NULL if resno is not present in list.
    3536                 :             :  *
    3537                 :             :  * Note: we need to search, rather than just indexing with list_nth(),
    3538                 :             :  * because not all tlists are sorted by resno.
    3539                 :             :  */
    3540                 :             : TargetEntry *
    3541                 :       36651 : get_tle_by_resno(List *tlist, AttrNumber resno)
    3542                 :             : {
    3543                 :       36651 :         ListCell   *l;
    3544                 :             : 
    3545   [ +  +  +  +  :      136079 :         foreach(l, tlist)
             +  +  +  + ]
    3546                 :             :         {
    3547                 :       99428 :                 TargetEntry *tle = (TargetEntry *) lfirst(l);
    3548                 :             : 
    3549         [ +  + ]:       99428 :                 if (tle->resno == resno)
    3550                 :       36539 :                         return tle;
    3551         [ +  + ]:       99428 :         }
    3552                 :         112 :         return NULL;
    3553                 :       36651 : }
    3554                 :             : 
    3555                 :             : /*
    3556                 :             :  * Given a Query and rangetable index, return relation's RowMarkClause if any
    3557                 :             :  *
    3558                 :             :  * Returns NULL if relation is not selected FOR UPDATE/SHARE
    3559                 :             :  */
    3560                 :             : RowMarkClause *
    3561                 :        2342 : get_parse_rowmark(Query *qry, Index rtindex)
    3562                 :             : {
    3563                 :        2342 :         ListCell   *l;
    3564                 :             : 
    3565   [ +  +  +  +  :        2361 :         foreach(l, qry->rowMarks)
             +  +  +  + ]
    3566                 :             :         {
    3567                 :          19 :                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
    3568                 :             : 
    3569         [ +  + ]:          19 :                 if (rc->rti == rtindex)
    3570                 :          16 :                         return rc;
    3571         [ +  + ]:          19 :         }
    3572                 :        2326 :         return NULL;
    3573                 :        2342 : }
    3574                 :             : 
    3575                 :             : /*
    3576                 :             :  *      given relation and att name, return attnum of variable
    3577                 :             :  *
    3578                 :             :  *      Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
    3579                 :             :  *
    3580                 :             :  *      This should only be used if the relation is already
    3581                 :             :  *      table_open()'ed.  Use the cache version get_attnum()
    3582                 :             :  *      for access to non-opened relations.
    3583                 :             :  */
    3584                 :             : int
    3585                 :        4355 : attnameAttNum(Relation rd, const char *attname, bool sysColOK)
    3586                 :             : {
    3587                 :        4355 :         int                     i;
    3588                 :             : 
    3589         [ +  + ]:       10295 :         for (i = 0; i < RelationGetNumberOfAttributes(rd); i++)
    3590                 :             :         {
    3591                 :       10277 :                 Form_pg_attribute att = TupleDescAttr(rd->rd_att, i);
    3592                 :             : 
    3593   [ +  +  +  + ]:       10277 :                 if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped)
    3594                 :        4337 :                         return i + 1;
    3595         [ +  + ]:       10277 :         }
    3596                 :             : 
    3597         [ +  + ]:          18 :         if (sysColOK)
    3598                 :             :         {
    3599         [ -  + ]:           4 :                 if ((i = specialAttNum(attname)) != InvalidAttrNumber)
    3600                 :           0 :                         return i;
    3601                 :           4 :         }
    3602                 :             : 
    3603                 :             :         /* on failure */
    3604                 :          18 :         return InvalidAttrNumber;
    3605                 :        4355 : }
    3606                 :             : 
    3607                 :             : /* specialAttNum()
    3608                 :             :  *
    3609                 :             :  * Check attribute name to see if it is "special", e.g. "xmin".
    3610                 :             :  * - thomas 2000-02-07
    3611                 :             :  *
    3612                 :             :  * Note: this only discovers whether the name could be a system attribute.
    3613                 :             :  * Caller needs to ensure that it really is an attribute of the rel.
    3614                 :             :  */
    3615                 :             : static int
    3616                 :        8628 : specialAttNum(const char *attname)
    3617                 :             : {
    3618                 :        8628 :         const FormData_pg_attribute *sysatt;
    3619                 :             : 
    3620                 :        8628 :         sysatt = SystemAttributeByName(attname);
    3621         [ +  + ]:        8628 :         if (sysatt != NULL)
    3622                 :        3197 :                 return sysatt->attnum;
    3623                 :        5431 :         return InvalidAttrNumber;
    3624                 :        8628 : }
    3625                 :             : 
    3626                 :             : 
    3627                 :             : /*
    3628                 :             :  * given attribute id, return name of that attribute
    3629                 :             :  *
    3630                 :             :  *      This should only be used if the relation is already
    3631                 :             :  *      table_open()'ed.  Use the cache version get_atttype()
    3632                 :             :  *      for access to non-opened relations.
    3633                 :             :  */
    3634                 :             : const NameData *
    3635                 :        1715 : attnumAttName(Relation rd, int attid)
    3636                 :             : {
    3637         [ -  + ]:        1715 :         if (attid <= 0)
    3638                 :             :         {
    3639                 :           0 :                 const FormData_pg_attribute *sysatt;
    3640                 :             : 
    3641                 :           0 :                 sysatt = SystemAttributeDefinition(attid);
    3642                 :           0 :                 return &sysatt->attname;
    3643                 :           0 :         }
    3644         [ +  - ]:        1715 :         if (attid > rd->rd_att->natts)
    3645   [ #  #  #  # ]:           0 :                 elog(ERROR, "invalid attribute number %d", attid);
    3646                 :        1715 :         return &TupleDescAttr(rd->rd_att, attid - 1)->attname;
    3647                 :        1715 : }
    3648                 :             : 
    3649                 :             : /*
    3650                 :             :  * given attribute id, return type of that attribute
    3651                 :             :  *
    3652                 :             :  *      This should only be used if the relation is already
    3653                 :             :  *      table_open()'ed.  Use the cache version get_atttype()
    3654                 :             :  *      for access to non-opened relations.
    3655                 :             :  */
    3656                 :             : Oid
    3657                 :       19805 : attnumTypeId(Relation rd, int attid)
    3658                 :             : {
    3659         [ -  + ]:       19805 :         if (attid <= 0)
    3660                 :             :         {
    3661                 :           0 :                 const FormData_pg_attribute *sysatt;
    3662                 :             : 
    3663                 :           0 :                 sysatt = SystemAttributeDefinition(attid);
    3664                 :           0 :                 return sysatt->atttypid;
    3665                 :           0 :         }
    3666         [ +  - ]:       19805 :         if (attid > rd->rd_att->natts)
    3667   [ #  #  #  # ]:           0 :                 elog(ERROR, "invalid attribute number %d", attid);
    3668                 :       19805 :         return TupleDescAttr(rd->rd_att, attid - 1)->atttypid;
    3669                 :       19805 : }
    3670                 :             : 
    3671                 :             : /*
    3672                 :             :  * given attribute id, return collation of that attribute
    3673                 :             :  *
    3674                 :             :  *      This should only be used if the relation is already table_open()'ed.
    3675                 :             :  */
    3676                 :             : Oid
    3677                 :         709 : attnumCollationId(Relation rd, int attid)
    3678                 :             : {
    3679         [ -  + ]:         709 :         if (attid <= 0)
    3680                 :             :         {
    3681                 :             :                 /* All system attributes are of noncollatable types. */
    3682                 :           0 :                 return InvalidOid;
    3683                 :             :         }
    3684         [ +  - ]:         709 :         if (attid > rd->rd_att->natts)
    3685   [ #  #  #  # ]:           0 :                 elog(ERROR, "invalid attribute number %d", attid);
    3686                 :         709 :         return TupleDescAttr(rd->rd_att, attid - 1)->attcollation;
    3687                 :         709 : }
    3688                 :             : 
    3689                 :             : /*
    3690                 :             :  * Generate a suitable error about a missing RTE.
    3691                 :             :  *
    3692                 :             :  * Since this is a very common type of error, we work rather hard to
    3693                 :             :  * produce a helpful message.
    3694                 :             :  */
    3695                 :             : void
    3696                 :          19 : errorMissingRTE(ParseState *pstate, RangeVar *relation)
    3697                 :             : {
    3698                 :          19 :         RangeTblEntry *rte;
    3699                 :          19 :         const char *badAlias = NULL;
    3700                 :             : 
    3701                 :             :         /*
    3702                 :             :          * Check to see if there are any potential matches in the query's
    3703                 :             :          * rangetable.  (Note: cases involving a bad schema name in the RangeVar
    3704                 :             :          * will throw error immediately here.  That seems OK.)
    3705                 :             :          */
    3706                 :          19 :         rte = searchRangeTableForRel(pstate, relation);
    3707                 :             : 
    3708                 :             :         /*
    3709                 :             :          * If we found a match that has an alias and the alias is visible in the
    3710                 :             :          * namespace, then the problem is probably use of the relation's real name
    3711                 :             :          * instead of its alias, ie "SELECT foo.* FROM foo f". This mistake is
    3712                 :             :          * common enough to justify a specific hint.
    3713                 :             :          *
    3714                 :             :          * If we found a match that doesn't meet those criteria, assume the
    3715                 :             :          * problem is illegal use of a relation outside its scope, as in the
    3716                 :             :          * MySQL-ism "SELECT ... FROM a, b LEFT JOIN c ON (a.x = c.y)".
    3717                 :             :          */
    3718   [ +  +  +  +  :          19 :         if (rte && rte->alias &&
                   +  + ]
    3719                 :          13 :                 strcmp(rte->eref->aliasname, relation->relname) != 0)
    3720                 :             :         {
    3721                 :           4 :                 ParseNamespaceItem *nsitem;
    3722                 :           4 :                 int                     sublevels_up;
    3723                 :             : 
    3724                 :           8 :                 nsitem = refnameNamespaceItem(pstate, NULL, rte->eref->aliasname,
    3725                 :           4 :                                                                           relation->location,
    3726                 :             :                                                                           &sublevels_up);
    3727   [ +  -  -  + ]:           4 :                 if (nsitem && nsitem->p_rte == rte)
    3728                 :           4 :                         badAlias = rte->eref->aliasname;
    3729                 :           4 :         }
    3730                 :             : 
    3731                 :             :         /* If it looks like the user forgot to use an alias, hint about that */
    3732         [ +  + ]:          19 :         if (badAlias)
    3733   [ +  -  +  - ]:           4 :                 ereport(ERROR,
    3734                 :             :                                 (errcode(ERRCODE_UNDEFINED_TABLE),
    3735                 :             :                                  errmsg("invalid reference to FROM-clause entry for table \"%s\"",
    3736                 :             :                                                 relation->relname),
    3737                 :             :                                  errhint("Perhaps you meant to reference the table alias \"%s\".",
    3738                 :             :                                                  badAlias),
    3739                 :             :                                  parser_errposition(pstate, relation->location)));
    3740                 :             :         /* Hint about case where we found an (inaccessible) exact match */
    3741         [ +  + ]:          15 :         else if (rte)
    3742   [ +  -  +  -  :          12 :                 ereport(ERROR,
                   +  + ]
    3743                 :             :                                 (errcode(ERRCODE_UNDEFINED_TABLE),
    3744                 :             :                                  errmsg("invalid reference to FROM-clause entry for table \"%s\"",
    3745                 :             :                                                 relation->relname),
    3746                 :             :                                  errdetail("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
    3747                 :             :                                                    rte->eref->aliasname),
    3748                 :             :                                  rte_visible_if_lateral(pstate, rte) ?
    3749                 :             :                                  errhint("To reference that table, you must mark this subquery with LATERAL.") : 0,
    3750                 :             :                                  parser_errposition(pstate, relation->location)));
    3751                 :             :         /* Else, we have nothing to offer but the bald statement of error */
    3752                 :             :         else
    3753   [ +  -  +  - ]:           3 :                 ereport(ERROR,
    3754                 :             :                                 (errcode(ERRCODE_UNDEFINED_TABLE),
    3755                 :             :                                  errmsg("missing FROM-clause entry for table \"%s\"",
    3756                 :             :                                                 relation->relname),
    3757                 :             :                                  parser_errposition(pstate, relation->location)));
    3758                 :           0 : }
    3759                 :             : 
    3760                 :             : /*
    3761                 :             :  * Generate a suitable error about a missing column.
    3762                 :             :  *
    3763                 :             :  * Since this is a very common type of error, we work rather hard to
    3764                 :             :  * produce a helpful message.
    3765                 :             :  */
    3766                 :             : void
    3767                 :          59 : errorMissingColumn(ParseState *pstate,
    3768                 :             :                                    const char *relname, const char *colname, int location)
    3769                 :             : {
    3770                 :          59 :         FuzzyAttrMatchState *state;
    3771                 :             : 
    3772                 :             :         /*
    3773                 :             :          * Search the entire rtable looking for possible matches.  If we find one,
    3774                 :             :          * emit a hint about it.
    3775                 :             :          */
    3776                 :          59 :         state = searchRangeTableForCol(pstate, relname, colname, location);
    3777                 :             : 
    3778                 :             :         /*
    3779                 :             :          * If there are exact match(es), they must be inaccessible for some
    3780                 :             :          * reason.
    3781                 :             :          */
    3782         [ +  + ]:          59 :         if (state->rexact1)
    3783                 :             :         {
    3784                 :             :                 /*
    3785                 :             :                  * We don't try too hard when there's multiple inaccessible exact
    3786                 :             :                  * matches, but at least be sure that we don't misleadingly suggest
    3787                 :             :                  * that there's only one.
    3788                 :             :                  */
    3789         [ +  + ]:           7 :                 if (state->rexact2)
    3790   [ +  -  +  -  :           2 :                         ereport(ERROR,
             -  +  -  + ]
    3791                 :             :                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
    3792                 :             :                                          relname ?
    3793                 :             :                                          errmsg("column %s.%s does not exist", relname, colname) :
    3794                 :             :                                          errmsg("column \"%s\" does not exist", colname),
    3795                 :             :                                          errdetail("There are columns named \"%s\", but they are in tables that cannot be referenced from this part of the query.",
    3796                 :             :                                                            colname),
    3797                 :             :                                          !relname ? errhint("Try using a table-qualified name.") : 0,
    3798                 :             :                                          parser_errposition(pstate, location)));
    3799                 :             :                 /* Single exact match, so try to determine why it's inaccessible. */
    3800   [ +  -  +  -  :           5 :                 ereport(ERROR,
          -  +  +  +  +  
                -  +  - ]
    3801                 :             :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    3802                 :             :                                  relname ?
    3803                 :             :                                  errmsg("column %s.%s does not exist", relname, colname) :
    3804                 :             :                                  errmsg("column \"%s\" does not exist", colname),
    3805                 :             :                                  errdetail("There is a column named \"%s\" in table \"%s\", but it cannot be referenced from this part of the query.",
    3806                 :             :                                                    colname, state->rexact1->eref->aliasname),
    3807                 :             :                                  rte_visible_if_lateral(pstate, state->rexact1) ?
    3808                 :             :                                  errhint("To reference that column, you must mark this subquery with LATERAL.") :
    3809                 :             :                                  (!relname && rte_visible_if_qualified(pstate, state->rexact1)) ?
    3810                 :             :                                  errhint("To reference that column, you must use a table-qualified name.") : 0,
    3811                 :             :                                  parser_errposition(pstate, location)));
    3812                 :           0 :         }
    3813                 :             : 
    3814         [ +  + ]:          52 :         if (!state->rsecond)
    3815                 :             :         {
    3816                 :             :                 /* If we found no match at all, we have little to report */
    3817         [ +  + ]:          50 :                 if (!state->rfirst)
    3818   [ +  -  +  -  :          43 :                         ereport(ERROR,
                   +  + ]
    3819                 :             :                                         (errcode(ERRCODE_UNDEFINED_COLUMN),
    3820                 :             :                                          relname ?
    3821                 :             :                                          errmsg("column %s.%s does not exist", relname, colname) :
    3822                 :             :                                          errmsg("column \"%s\" does not exist", colname),
    3823                 :             :                                          parser_errposition(pstate, location)));
    3824                 :             :                 /* Handle case where we have a single alternative spelling to offer */
    3825   [ +  -  +  -  :           7 :                 ereport(ERROR,
                   +  + ]
    3826                 :             :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    3827                 :             :                                  relname ?
    3828                 :             :                                  errmsg("column %s.%s does not exist", relname, colname) :
    3829                 :             :                                  errmsg("column \"%s\" does not exist", colname),
    3830                 :             :                                  errhint("Perhaps you meant to reference the column \"%s.%s\".",
    3831                 :             :                                                  state->rfirst->eref->aliasname,
    3832                 :             :                                                  strVal(list_nth(state->rfirst->eref->colnames,
    3833                 :             :                                                                                  state->first - 1))),
    3834                 :             :                                  parser_errposition(pstate, location)));
    3835                 :           0 :         }
    3836                 :             :         else
    3837                 :             :         {
    3838                 :             :                 /* Handle case where there are two equally useful column hints */
    3839   [ +  -  +  -  :           2 :                 ereport(ERROR,
                   -  + ]
    3840                 :             :                                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    3841                 :             :                                  relname ?
    3842                 :             :                                  errmsg("column %s.%s does not exist", relname, colname) :
    3843                 :             :                                  errmsg("column \"%s\" does not exist", colname),
    3844                 :             :                                  errhint("Perhaps you meant to reference the column \"%s.%s\" or the column \"%s.%s\".",
    3845                 :             :                                                  state->rfirst->eref->aliasname,
    3846                 :             :                                                  strVal(list_nth(state->rfirst->eref->colnames,
    3847                 :             :                                                                                  state->first - 1)),
    3848                 :             :                                                  state->rsecond->eref->aliasname,
    3849                 :             :                                                  strVal(list_nth(state->rsecond->eref->colnames,
    3850                 :             :                                                                                  state->second - 1))),
    3851                 :             :                                  parser_errposition(pstate, location)));
    3852                 :             :         }
    3853                 :           0 : }
    3854                 :             : 
    3855                 :             : /*
    3856                 :             :  * Find ParseNamespaceItem for RTE, if it's visible at all.
    3857                 :             :  * We assume an RTE couldn't appear more than once in the namespace lists.
    3858                 :             :  */
    3859                 :             : static ParseNamespaceItem *
    3860                 :          20 : findNSItemForRTE(ParseState *pstate, RangeTblEntry *rte)
    3861                 :             : {
    3862         [ +  + ]:          37 :         while (pstate != NULL)
    3863                 :             :         {
    3864                 :          31 :                 ListCell   *l;
    3865                 :             : 
    3866   [ +  +  +  +  :          63 :                 foreach(l, pstate->p_namespace)
             +  +  +  + ]
    3867                 :             :                 {
    3868                 :          32 :                         ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
    3869                 :             : 
    3870         [ +  + ]:          32 :                         if (nsitem->p_rte == rte)
    3871                 :          14 :                                 return nsitem;
    3872         [ +  + ]:          32 :                 }
    3873                 :          17 :                 pstate = pstate->parentParseState;
    3874      [ -  +  + ]:          31 :         }
    3875                 :           6 :         return NULL;
    3876                 :          20 : }
    3877                 :             : 
    3878                 :             : /*
    3879                 :             :  * Would this RTE be visible, if only the user had written LATERAL?
    3880                 :             :  *
    3881                 :             :  * This is a helper for deciding whether to issue a HINT about LATERAL.
    3882                 :             :  * As such, it doesn't need to be 100% accurate; the HINT could be useful
    3883                 :             :  * even if it's not quite right.  Hence, we don't delve into fine points
    3884                 :             :  * about whether a found nsitem has the appropriate one of p_rel_visible or
    3885                 :             :  * p_cols_visible set.
    3886                 :             :  */
    3887                 :             : static bool
    3888                 :          17 : rte_visible_if_lateral(ParseState *pstate, RangeTblEntry *rte)
    3889                 :             : {
    3890                 :          17 :         ParseNamespaceItem *nsitem;
    3891                 :             : 
    3892                 :             :         /* If LATERAL *is* active, we're clearly barking up the wrong tree */
    3893         [ -  + ]:          17 :         if (pstate->p_lateral_active)
    3894                 :           0 :                 return false;
    3895                 :          17 :         nsitem = findNSItemForRTE(pstate, rte);
    3896         [ +  + ]:          17 :         if (nsitem)
    3897                 :             :         {
    3898                 :             :                 /* Found it, report whether it's LATERAL-only */
    3899         [ +  + ]:          12 :                 return nsitem->p_lateral_only && nsitem->p_lateral_ok;
    3900                 :             :         }
    3901                 :           5 :         return false;
    3902                 :          17 : }
    3903                 :             : 
    3904                 :             : /*
    3905                 :             :  * Would columns in this RTE be visible if qualified?
    3906                 :             :  */
    3907                 :             : static bool
    3908                 :           3 : rte_visible_if_qualified(ParseState *pstate, RangeTblEntry *rte)
    3909                 :             : {
    3910                 :           3 :         ParseNamespaceItem *nsitem = findNSItemForRTE(pstate, rte);
    3911                 :             : 
    3912         [ +  + ]:           3 :         if (nsitem)
    3913                 :             :         {
    3914                 :             :                 /* Found it, report whether it's relation-only */
    3915         [ -  + ]:           2 :                 return nsitem->p_rel_visible && !nsitem->p_cols_visible;
    3916                 :             :         }
    3917                 :           1 :         return false;
    3918                 :           3 : }
    3919                 :             : 
    3920                 :             : 
    3921                 :             : /*
    3922                 :             :  * addRTEPermissionInfo
    3923                 :             :  *              Creates RTEPermissionInfo for a given RTE and adds it into the
    3924                 :             :  *              provided list.
    3925                 :             :  *
    3926                 :             :  * Returns the RTEPermissionInfo and sets rte->perminfoindex.
    3927                 :             :  */
    3928                 :             : RTEPermissionInfo *
    3929                 :      106624 : addRTEPermissionInfo(List **rteperminfos, RangeTblEntry *rte)
    3930                 :             : {
    3931                 :      106624 :         RTEPermissionInfo *perminfo;
    3932                 :             : 
    3933         [ +  - ]:      106624 :         Assert(OidIsValid(rte->relid));
    3934         [ +  - ]:      106624 :         Assert(rte->perminfoindex == 0);
    3935                 :             : 
    3936                 :             :         /* Nope, so make one and add to the list. */
    3937                 :      106624 :         perminfo = makeNode(RTEPermissionInfo);
    3938                 :      106624 :         perminfo->relid = rte->relid;
    3939                 :      106624 :         perminfo->inh = rte->inh;
    3940                 :             :         /* Other information is set by fetching the node as and where needed. */
    3941                 :             : 
    3942                 :      106624 :         *rteperminfos = lappend(*rteperminfos, perminfo);
    3943                 :             : 
    3944                 :             :         /* Note its index (1-based!) */
    3945                 :      106624 :         rte->perminfoindex = list_length(*rteperminfos);
    3946                 :             : 
    3947                 :      213248 :         return perminfo;
    3948                 :      106624 : }
    3949                 :             : 
    3950                 :             : /*
    3951                 :             :  * getRTEPermissionInfo
    3952                 :             :  *              Find RTEPermissionInfo for a given relation in the provided list.
    3953                 :             :  *
    3954                 :             :  * This is a simple list_nth() operation, though it's good to have the
    3955                 :             :  * function for the various sanity checks.
    3956                 :             :  */
    3957                 :             : RTEPermissionInfo *
    3958                 :      757667 : getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
    3959                 :             : {
    3960                 :      757667 :         RTEPermissionInfo *perminfo;
    3961                 :             : 
    3962         [ +  - ]:      757667 :         if (rte->perminfoindex == 0 ||
    3963                 :      757667 :                 rte->perminfoindex > list_length(rteperminfos))
    3964   [ #  #  #  # ]:           0 :                 elog(ERROR, "invalid perminfoindex %u in RTE with relid %u",
    3965                 :             :                          rte->perminfoindex, rte->relid);
    3966                 :      757667 :         perminfo = list_nth_node(RTEPermissionInfo, rteperminfos,
    3967                 :             :                                                          rte->perminfoindex - 1);
    3968         [ +  - ]:      757667 :         if (perminfo->relid != rte->relid)
    3969   [ #  #  #  # ]:           0 :                 elog(ERROR, "permission info at index %u (with relid=%u) does not match provided RTE (with relid=%u)",
    3970                 :             :                          rte->perminfoindex, perminfo->relid, rte->relid);
    3971                 :             : 
    3972                 :     1515334 :         return perminfo;
    3973                 :      757667 : }
        

Generated by: LCOV version 2.3.2-1