diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index bdf8ec46e2b..5dfea460216 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -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; diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index ca02982e0b3..b12416535ed 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -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); diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index a71d7e1f74f..70739bcd5b6 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -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? */