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

Generated by: LCOV version 1.14