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

Generated by: LCOV version 2.0-1