Add p_names field to ParseNamespaceItem
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
This commit is contained in:
parent
91c5a8caaa
commit
66392d3965
@ -1217,9 +1217,9 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
|||||||
* input column numbers more easily.
|
* input column numbers more easily.
|
||||||
*/
|
*/
|
||||||
l_nscolumns = l_nsitem->p_nscolumns;
|
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_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
|
* 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
|
* 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.
|
* 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++)
|
for (k = 0; k < res_colindex; k++)
|
||||||
{
|
{
|
||||||
ParseNamespaceColumn *nscol = res_nscolumns + k;
|
ParseNamespaceColumn *nscol = res_nscolumns + k;
|
||||||
|
@ -65,6 +65,7 @@ static ParseNamespaceItem *scanNameSpaceForRelid(ParseState *pstate, Oid relid,
|
|||||||
static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
|
static void check_lateral_ref_ok(ParseState *pstate, ParseNamespaceItem *nsitem,
|
||||||
int location);
|
int location);
|
||||||
static int scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
|
static int scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
|
||||||
|
Alias *eref,
|
||||||
const char *colname, int location,
|
const char *colname, int location,
|
||||||
int fuzzy_rte_penalty,
|
int fuzzy_rte_penalty,
|
||||||
FuzzyAttrMatchState *fuzzystate);
|
FuzzyAttrMatchState *fuzzystate);
|
||||||
@ -184,7 +185,6 @@ scanNameSpaceForRefname(ParseState *pstate, const char *refname, int location)
|
|||||||
foreach(l, pstate->p_namespace)
|
foreach(l, pstate->p_namespace)
|
||||||
{
|
{
|
||||||
ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
|
ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(l);
|
||||||
RangeTblEntry *rte = nsitem->p_rte;
|
|
||||||
|
|
||||||
/* Ignore columns-only items */
|
/* Ignore columns-only items */
|
||||||
if (!nsitem->p_rel_visible)
|
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)
|
if (nsitem->p_lateral_only && !pstate->p_lateral_active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strcmp(rte->eref->aliasname, refname) == 0)
|
if (strcmp(nsitem->p_names->aliasname, refname) == 0)
|
||||||
{
|
{
|
||||||
if (result)
|
if (result)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -420,7 +420,7 @@ checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
|
|||||||
{
|
{
|
||||||
ParseNamespaceItem *nsitem1 = (ParseNamespaceItem *) lfirst(l1);
|
ParseNamespaceItem *nsitem1 = (ParseNamespaceItem *) lfirst(l1);
|
||||||
RangeTblEntry *rte1 = nsitem1->p_rte;
|
RangeTblEntry *rte1 = nsitem1->p_rte;
|
||||||
const char *aliasname1 = rte1->eref->aliasname;
|
const char *aliasname1 = nsitem1->p_names->aliasname;
|
||||||
ListCell *l2;
|
ListCell *l2;
|
||||||
|
|
||||||
if (!nsitem1->p_rel_visible)
|
if (!nsitem1->p_rel_visible)
|
||||||
@ -430,10 +430,11 @@ checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
|
|||||||
{
|
{
|
||||||
ParseNamespaceItem *nsitem2 = (ParseNamespaceItem *) lfirst(l2);
|
ParseNamespaceItem *nsitem2 = (ParseNamespaceItem *) lfirst(l2);
|
||||||
RangeTblEntry *rte2 = nsitem2->p_rte;
|
RangeTblEntry *rte2 = nsitem2->p_rte;
|
||||||
|
const char *aliasname2 = nsitem2->p_names->aliasname;
|
||||||
|
|
||||||
if (!nsitem2->p_rel_visible)
|
if (!nsitem2->p_rel_visible)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(rte2->eref->aliasname, aliasname1) != 0)
|
if (strcmp(aliasname2, aliasname1) != 0)
|
||||||
continue; /* definitely no conflict */
|
continue; /* definitely no conflict */
|
||||||
if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
|
if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
|
||||||
rte2->rtekind == RTE_RELATION && rte2->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 */
|
/* SQL:2008 demands this be an error, not an invisible item */
|
||||||
RangeTblEntry *rte = nsitem->p_rte;
|
RangeTblEntry *rte = nsitem->p_rte;
|
||||||
char *refname = rte->eref->aliasname;
|
char *refname = nsitem->p_names->aliasname;
|
||||||
|
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||||
@ -672,10 +673,10 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
|
|||||||
Var *var;
|
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.
|
* multiple matches.
|
||||||
*/
|
*/
|
||||||
attnum = scanRTEForColumn(pstate, rte,
|
attnum = scanRTEForColumn(pstate, rte, nsitem->p_names,
|
||||||
colname, location,
|
colname, location,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
|
|
||||||
@ -712,7 +713,7 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
|
|||||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||||
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
errmsg("column \"%s\" of relation \"%s\" does not exist",
|
||||||
colname,
|
colname,
|
||||||
rte->eref->aliasname)));
|
nsitem->p_names->aliasname)));
|
||||||
|
|
||||||
var = makeVar(nscol->p_varno,
|
var = makeVar(nscol->p_varno,
|
||||||
nscol->p_varattno,
|
nscol->p_varattno,
|
||||||
@ -765,6 +766,7 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
|
scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
|
||||||
|
Alias *eref,
|
||||||
const char *colname, int location,
|
const char *colname, int location,
|
||||||
int fuzzy_rte_penalty,
|
int fuzzy_rte_penalty,
|
||||||
FuzzyAttrMatchState *fuzzystate)
|
FuzzyAttrMatchState *fuzzystate)
|
||||||
@ -786,7 +788,7 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
|
|||||||
* Callers interested in finding match with shortest distance need to
|
* Callers interested in finding match with shortest distance need to
|
||||||
* defend against this directly, though.
|
* defend against this directly, though.
|
||||||
*/
|
*/
|
||||||
foreach(c, rte->eref->colnames)
|
foreach(c, eref->colnames)
|
||||||
{
|
{
|
||||||
const char *attcolname = strVal(lfirst(c));
|
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
|
* Scan for a matching column; if we find an exact match, we're
|
||||||
* done. Otherwise, update fuzzystate.
|
* 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, fuzzystate)
|
||||||
&& fuzzy_rte_penalty == 0)
|
&& fuzzy_rte_penalty == 0)
|
||||||
{
|
{
|
||||||
@ -1252,6 +1254,7 @@ buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, TupleDesc tupdesc)
|
|||||||
|
|
||||||
/* ... and build the nsitem */
|
/* ... and build the nsitem */
|
||||||
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
|
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
|
||||||
|
nsitem->p_names = rte->eref;
|
||||||
nsitem->p_rte = rte;
|
nsitem->p_rte = rte;
|
||||||
nsitem->p_rtindex = rtindex;
|
nsitem->p_rtindex = rtindex;
|
||||||
nsitem->p_nscolumns = nscolumns;
|
nsitem->p_nscolumns = nscolumns;
|
||||||
@ -1313,6 +1316,7 @@ buildNSItemFromLists(RangeTblEntry *rte, Index rtindex,
|
|||||||
|
|
||||||
/* ... and build the nsitem */
|
/* ... and build the nsitem */
|
||||||
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
|
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
|
||||||
|
nsitem->p_names = rte->eref;
|
||||||
nsitem->p_rte = rte;
|
nsitem->p_rte = rte;
|
||||||
nsitem->p_rtindex = rtindex;
|
nsitem->p_rtindex = rtindex;
|
||||||
nsitem->p_nscolumns = nscolumns;
|
nsitem->p_nscolumns = nscolumns;
|
||||||
@ -2198,6 +2202,7 @@ addRangeTableEntryForJoin(ParseState *pstate,
|
|||||||
* list --- caller must do that if appropriate.
|
* list --- caller must do that if appropriate.
|
||||||
*/
|
*/
|
||||||
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
|
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
|
||||||
|
nsitem->p_names = rte->eref;
|
||||||
nsitem->p_rte = rte;
|
nsitem->p_rte = rte;
|
||||||
nsitem->p_rtindex = list_length(pstate->p_rtable);
|
nsitem->p_rtindex = list_length(pstate->p_rtable);
|
||||||
nsitem->p_nscolumns = nscolumns;
|
nsitem->p_nscolumns = nscolumns;
|
||||||
@ -2356,7 +2361,7 @@ addRangeTableEntryForCTE(ParseState *pstate,
|
|||||||
*/
|
*/
|
||||||
if (rte->ctelevelsup > 0)
|
if (rte->ctelevelsup > 0)
|
||||||
for (int i = 0; i < n_dontexpand_columns; i++)
|
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;
|
return psi;
|
||||||
}
|
}
|
||||||
@ -3037,7 +3042,7 @@ expandNSItemVars(ParseNamespaceItem *nsitem,
|
|||||||
if (colnames)
|
if (colnames)
|
||||||
*colnames = NIL;
|
*colnames = NIL;
|
||||||
colindex = 0;
|
colindex = 0;
|
||||||
foreach(lc, nsitem->p_rte->eref->colnames)
|
foreach(lc, nsitem->p_names->colnames)
|
||||||
{
|
{
|
||||||
Value *colnameval = (Value *) lfirst(lc);
|
Value *colnameval = (Value *) lfirst(lc);
|
||||||
const char *colname = strVal(colnameval);
|
const char *colname = strVal(colnameval);
|
||||||
|
@ -227,8 +227,13 @@ struct ParseState
|
|||||||
/*
|
/*
|
||||||
* An element of a namespace list.
|
* 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
|
* 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
|
* 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
|
* qualified names, while those with p_cols_visible set define which RTEs are
|
||||||
@ -256,9 +261,10 @@ struct ParseState
|
|||||||
*/
|
*/
|
||||||
struct ParseNamespaceItem
|
struct ParseNamespaceItem
|
||||||
{
|
{
|
||||||
|
Alias *p_names; /* Table and column names */
|
||||||
RangeTblEntry *p_rte; /* The relation's rangetable entry */
|
RangeTblEntry *p_rte; /* The relation's rangetable entry */
|
||||||
int p_rtindex; /* The relation's index in the rangetable */
|
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 */
|
ParseNamespaceColumn *p_nscolumns; /* per-column data */
|
||||||
bool p_rel_visible; /* Relation name is visible? */
|
bool p_rel_visible; /* Relation name is visible? */
|
||||||
bool p_cols_visible; /* Column names visible as unqualified refs? */
|
bool p_cols_visible; /* Column names visible as unqualified refs? */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user