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

Generated by: LCOV version 1.14