LCOV - code coverage report
Current view: top level - src/backend/parser - parse_relation.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 1108 1211 91.5 %
Date: 2025-02-21 17:14:59 Functions: 60 60 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14