LCOV - code coverage report
Current view: top level - src/backend/parser - parse_relation.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 1066 1171 91.0 %
Date: 2024-04-26 14:11:25 Functions: 59 59 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14