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

Generated by: LCOV version 1.13