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

Generated by: LCOV version 1.11