LCOV - code coverage report
Current view: top level - src/backend/parser - parse_relation.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 1033 1153 89.6 %
Date: 2021-12-04 23:09:10 Functions: 53 53 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14