Add p_names field to ParseNamespaceItem
authorPeter Eisentraut <peter@eisentraut.org>
Wed, 31 Mar 2021 08:52:37 +0000 (10:52 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Wed, 31 Mar 2021 08:52:37 +0000 (10:52 +0200)
ParseNamespaceItem had a wired-in assumption that p_rte->eref
describes the table and column aliases exposed by the nsitem.  This
relaxes this by creating a separate p_names field in an nsitem.  This
is mainly preparation for a patch for JOIN USING aliases, but it saves
one indirection in common code paths, so it's possibly a win on its
own.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://www.postgresql.org/message-id/785329.1616455091@sss.pgh.pa.us

src/backend/parser/parse_clause.c
src/backend/parser/parse_relation.c
src/include/parser/parse_node.h

index bdf8ec46e2b234241274bf76edca43681ae815db..5dfea460216e069d0636f12650f1cce5fe675b41 100644 (file)
@@ -1217,9 +1217,9 @@ transformFromClauseItem(ParseState *pstate, Node *n,
                 * input column numbers more easily.
                 */
                l_nscolumns = l_nsitem->p_nscolumns;
-               l_colnames = l_nsitem->p_rte->eref->colnames;
+               l_colnames = l_nsitem->p_names->colnames;
                r_nscolumns = r_nsitem->p_nscolumns;
-               r_colnames = r_nsitem->p_rte->eref->colnames;
+               r_colnames = r_nsitem->p_names->colnames;
 
                /*
                 * Natural join does not explicitly specify columns; must generate
@@ -1469,7 +1469,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
                 * Now that we know the join RTE's rangetable index, we can fix up the
                 * res_nscolumns data in places where it should contain that.
                 */
-               Assert(res_colindex == list_length(nsitem->p_rte->eref->colnames));
+               Assert(res_colindex == list_length(nsitem->p_names->colnames));
                for (k = 0; k < res_colindex; k++)
                {
                        ParseNamespaceColumn *nscol = res_nscolumns + k;
index ca02982e0b367ec58216b5ea4aa9674cf5ff90cb..b12416535ede9cb9f5e86e949470c7ac572a7257 100644 (file)
@@ -65,6 +65,7 @@ static ParseNamespaceItem *scanNameSpaceForRelid(ParseState *pstate, Oid relid,
 static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
                                                                 int location);
 static int     scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
+                                                        Alias *eref,
                                                         const char *colname, int location,
                                                         int fuzzy_rte_penalty,
                                                         FuzzyAttrMatchState *fuzzystate);
@@ -184,7 +185,6 @@ scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)
        foreach(l, pstate->p_namespace)
        {
                ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
-               RangeTblEntry *rte = nsitem->p_rte;
 
                /* Ignore columns-only items */
                if (!nsitem->p_rel_visible)
@@ -193,7 +193,7 @@ scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)
                if (nsitem->p_lateral_only && !pstate->p_lateral_active)
                        continue;
 
-               if (strcmp(rte->eref->aliasname, refname) == 0)
+               if (strcmp(nsitem->p_names->aliasname, refname) == 0)
                {
                        if (result)
                                ereport(ERROR,
@@ -420,7 +420,7 @@ checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
        {
                ParseNamespaceItem *nsitem1 = (ParseNamespaceItem *) lfirst(l1);
                RangeTblEntry *rte1 = nsitem1->p_rte;
-               const char *aliasname1 = rte1->eref->aliasname;
+               const char *aliasname1 = nsitem1->p_names->aliasname;
                ListCell   *l2;
 
                if (!nsitem1->p_rel_visible)
@@ -430,10 +430,11 @@ checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
                {
                        ParseNamespaceItem *nsitem2 = (ParseNamespaceItem *) lfirst(l2);
                        RangeTblEntry *rte2 = nsitem2->p_rte;
+                       const char *aliasname2 = nsitem2->p_names->aliasname;
 
                        if (!nsitem2->p_rel_visible)
                                continue;
-                       if (strcmp(rte2->eref->aliasname, aliasname1) != 0)
+                       if (strcmp(aliasname2, aliasname1) != 0)
                                continue;               /* definitely no conflict */
                        if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
                                rte2->rtekind == RTE_RELATION && rte2->alias == NULL &&
@@ -466,7 +467,7 @@ check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
        {
                /* SQL:2008 demands this be an error, not an invisible item */
                RangeTblEntry *rte = nsitem->p_rte;
-               char       *refname = rte->eref->aliasname;
+               char       *refname = nsitem->p_names->aliasname;
 
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
@@ -672,10 +673,10 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
        Var                *var;
 
        /*
-        * Scan the RTE's column names (or aliases) for a match.  Complain if
+        * Scan the nsitem's column names (or aliases) for a match.  Complain if
         * multiple matches.
         */
-       attnum = scanRTEForColumn(pstate, rte,
+       attnum = scanRTEForColumn(pstate, rte, nsitem->p_names,
                                                          colname, location,
                                                          0, NULL);
 
@@ -712,7 +713,7 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
                                        (errcode(ERRCODE_UNDEFINED_COLUMN),
                                         errmsg("column \"%s\" of relation \"%s\" does not exist",
                                                        colname,
-                                                       rte->eref->aliasname)));
+                                                       nsitem->p_names->aliasname)));
 
                var = makeVar(nscol->p_varno,
                                          nscol->p_varattno,
@@ -765,6 +766,7 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
  */
 static int
 scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
+                                Alias *eref,
                                 const char *colname, int location,
                                 int fuzzy_rte_penalty,
                                 FuzzyAttrMatchState *fuzzystate)
@@ -786,7 +788,7 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
         * Callers interested in finding match with shortest distance need to
         * defend against this directly, though.
         */
-       foreach(c, rte->eref->colnames)
+       foreach(c, eref->colnames)
        {
                const char *attcolname = strVal(lfirst(c));
 
@@ -970,7 +972,7 @@ searchRangeTableForCol(ParseState *pstate, const char *alias, const char *colnam
                         * Scan for a matching column; if we find an exact match, we're
                         * done.  Otherwise, update fuzzystate.
                         */
-                       if (scanRTEForColumn(orig_pstate, rte, colname, location,
+                       if (scanRTEForColumn(orig_pstate, rte, rte->eref, colname, location,
                                                                 fuzzy_rte_penalty, fuzzystate)
                                && fuzzy_rte_penalty == 0)
                        {
@@ -1252,6 +1254,7 @@ buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, TupleDesc tupdesc)
 
        /* ... and build the nsitem */
        nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+       nsitem->p_names = rte->eref;
        nsitem->p_rte = rte;
        nsitem->p_rtindex = rtindex;
        nsitem->p_nscolumns = nscolumns;
@@ -1313,6 +1316,7 @@ buildNSItemFromLists(RangeTblEntry *rte, Index rtindex,
 
        /* ... and build the nsitem */
        nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+       nsitem->p_names = rte->eref;
        nsitem->p_rte = rte;
        nsitem->p_rtindex = rtindex;
        nsitem->p_nscolumns = nscolumns;
@@ -2198,6 +2202,7 @@ addRangeTableEntryForJoin(ParseState *pstate,
         * list --- caller must do that if appropriate.
         */
        nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+       nsitem->p_names = rte->eref;
        nsitem->p_rte = rte;
        nsitem->p_rtindex = list_length(pstate->p_rtable);
        nsitem->p_nscolumns = nscolumns;
@@ -2356,7 +2361,7 @@ addRangeTableEntryForCTE(ParseState *pstate,
         */
        if (rte->ctelevelsup > 0)
                for (int i = 0; i < n_dontexpand_columns; i++)
-                       psi->p_nscolumns[list_length(psi->p_rte->eref->colnames) - 1 - i].p_dontexpand = true;
+                       psi->p_nscolumns[list_length(psi->p_names->colnames) - 1 - i].p_dontexpand = true;
 
        return psi;
 }
@@ -3037,7 +3042,7 @@ expandNSItemVars(ParseNamespaceItem *nsitem,
        if (colnames)
                *colnames = NIL;
        colindex = 0;
-       foreach(lc, nsitem->p_rte->eref->colnames)
+       foreach(lc, nsitem->p_names->colnames)
        {
                Value      *colnameval = (Value *) lfirst(lc);
                const char *colname = strVal(colnameval);
index a71d7e1f74fbd0328d73d0973e3c7d663be3b253..70739bcd5b6a24df5a4e17f654d62447e9fb0bd5 100644 (file)
@@ -227,8 +227,13 @@ struct ParseState
 /*
  * An element of a namespace list.
  *
+ * p_names contains the table name and column names exposed by this nsitem.
+ * (Currently, it's always equal to p_rte->eref.)
+ *
+ * p_rte and p_rtindex link to the underlying rangetable entry.
+ *
  * The p_nscolumns array contains info showing how to construct Vars
- * referencing corresponding elements of the RTE's colnames list.
+ * referencing the names appearing in the p_names->colnames list.
  *
  * Namespace items with p_rel_visible set define which RTEs are accessible by
  * qualified names, while those with p_cols_visible set define which RTEs are
@@ -256,9 +261,10 @@ struct ParseState
  */
 struct ParseNamespaceItem
 {
+       Alias      *p_names;            /* Table and column names */
        RangeTblEntry *p_rte;           /* The relation's rangetable entry */
        int                     p_rtindex;              /* The relation's index in the rangetable */
-       /* array of same length as p_rte->eref->colnames: */
+       /* array of same length as p_names->colnames: */
        ParseNamespaceColumn *p_nscolumns;      /* per-column data */
        bool            p_rel_visible;  /* Relation name is visible? */
        bool            p_cols_visible; /* Column names visible as unqualified refs? */