Commit b541e9ac authored by Tom Lane's avatar Tom Lane

Refactor parser's generation of Var nodes.

Instead of passing around a pointer to the RangeTblEntry that
provides the desired column, pass a pointer to the associated
ParseNamespaceItem.  The RTE is trivially reachable from the nsitem,
and having the ParseNamespaceItem allows access to additional
information.  As proof of concept for that, add the rangetable index
to ParseNamespaceItem, and use that to get rid of RTERangeTablePosn
searches.

(I have in mind to teach the parser to generate some different
representation for Vars that are nullable by outer joins, and
keeping the necessary information in ParseNamespaceItems seems
like a reasonable approach to that.  But whether that ever
happens or not, this seems like good cleanup.)

Also refactor the code around scanRTEForColumn so that the
"fuzzy match" stuff does not leak out of parse_relation.c.

Discussion: https://postgr.es/m/26144.1576858373@sss.pgh.pa.us
parent 044b319c
...@@ -1344,7 +1344,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ...@@ -1344,7 +1344,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
int sublist_length = -1; int sublist_length = -1;
bool lateral = false; bool lateral = false;
RangeTblEntry *rte; RangeTblEntry *rte;
int rtindex; ParseNamespaceItem *nsitem;
ListCell *lc; ListCell *lc;
ListCell *lc2; ListCell *lc2;
int i; int i;
...@@ -1516,15 +1516,15 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ...@@ -1516,15 +1516,15 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
NULL, lateral, true); NULL, lateral, true);
addRTEtoQuery(pstate, rte, true, true, true); addRTEtoQuery(pstate, rte, true, true, true);
/* assume new rte is at end */ /* grab the namespace item made by addRTEtoQuery */
rtindex = list_length(pstate->p_rtable); nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
Assert(rte == rt_fetch(rtindex, pstate->p_rtable)); Assert(rte == nsitem->p_rte);
/* /*
* Generate a targetlist as though expanding "*" * Generate a targetlist as though expanding "*"
*/ */
Assert(pstate->p_next_resno == 1); Assert(pstate->p_next_resno == 1);
qry->targetList = expandRelAttrs(pstate, rte, rtindex, 0, -1); qry->targetList = expandNSItemAttrs(pstate, nsitem, 0, -1);
/* /*
* The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a * The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a
......
...@@ -52,7 +52,8 @@ ...@@ -52,7 +52,8 @@
#include "utils/syscache.h" #include "utils/syscache.h"
/* Convenience macro for the most common makeNamespaceItem() case */ /* Convenience macro for the most common makeNamespaceItem() case */
#define makeDefaultNSItem(rte) makeNamespaceItem(rte, true, true, false, true) #define makeDefaultNSItem(rte, rti) \
makeNamespaceItem(rte, rti, true, true, false, true)
static void extractRemainingColumns(List *common_colnames, static void extractRemainingColumns(List *common_colnames,
List *src_colnames, List *src_colvars, List *src_colnames, List *src_colvars,
...@@ -78,7 +79,7 @@ static Node *transformFromClauseItem(ParseState *pstate, Node *n, ...@@ -78,7 +79,7 @@ static Node *transformFromClauseItem(ParseState *pstate, Node *n,
List **namespace); List **namespace);
static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype, static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
Var *l_colvar, Var *r_colvar); Var *l_colvar, Var *r_colvar);
static ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte, static ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte, int rtindex,
bool rel_visible, bool cols_visible, bool rel_visible, bool cols_visible,
bool lateral_only, bool lateral_ok); bool lateral_only, bool lateral_ok);
static void setNamespaceColumnVisibility(List *namespace, bool cols_visible); static void setNamespaceColumnVisibility(List *namespace, bool cols_visible);
...@@ -216,12 +217,15 @@ setTargetTable(ParseState *pstate, RangeVar *relation, ...@@ -216,12 +217,15 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
rte = addRangeTableEntryForRelation(pstate, pstate->p_target_relation, rte = addRangeTableEntryForRelation(pstate, pstate->p_target_relation,
RowExclusiveLock, RowExclusiveLock,
relation->alias, inh, false); relation->alias, inh, false);
pstate->p_target_rangetblentry = rte;
/* assume new rte is at end */ /* assume new rte is at end */
rtindex = list_length(pstate->p_rtable); rtindex = list_length(pstate->p_rtable);
Assert(rte == rt_fetch(rtindex, pstate->p_rtable)); Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
/* remember the RTE as being the query target */
pstate->p_target_rangetblentry = rte;
pstate->p_target_rtindex = rtindex;
/* /*
* Override addRangeTableEntry's default ACL_SELECT permissions check, and * Override addRangeTableEntry's default ACL_SELECT permissions check, and
* instead mark target table as requiring exactly the specified * instead mark target table as requiring exactly the specified
...@@ -1084,7 +1088,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, ...@@ -1084,7 +1088,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
Assert(rte == rt_fetch(rtindex, pstate->p_rtable)); Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
*top_rte = rte; *top_rte = rte;
*top_rti = rtindex; *top_rti = rtindex;
*namespace = list_make1(makeDefaultNSItem(rte)); *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
rtr = makeNode(RangeTblRef); rtr = makeNode(RangeTblRef);
rtr->rtindex = rtindex; rtr->rtindex = rtindex;
return (Node *) rtr; return (Node *) rtr;
...@@ -1102,7 +1106,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, ...@@ -1102,7 +1106,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
Assert(rte == rt_fetch(rtindex, pstate->p_rtable)); Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
*top_rte = rte; *top_rte = rte;
*top_rti = rtindex; *top_rti = rtindex;
*namespace = list_make1(makeDefaultNSItem(rte)); *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
rtr = makeNode(RangeTblRef); rtr = makeNode(RangeTblRef);
rtr->rtindex = rtindex; rtr->rtindex = rtindex;
return (Node *) rtr; return (Node *) rtr;
...@@ -1120,7 +1124,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, ...@@ -1120,7 +1124,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
Assert(rte == rt_fetch(rtindex, pstate->p_rtable)); Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
*top_rte = rte; *top_rte = rte;
*top_rti = rtindex; *top_rti = rtindex;
*namespace = list_make1(makeDefaultNSItem(rte)); *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
rtr = makeNode(RangeTblRef); rtr = makeNode(RangeTblRef);
rtr->rtindex = rtindex; rtr->rtindex = rtindex;
return (Node *) rtr; return (Node *) rtr;
...@@ -1138,7 +1142,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, ...@@ -1138,7 +1142,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
Assert(rte == rt_fetch(rtindex, pstate->p_rtable)); Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
*top_rte = rte; *top_rte = rte;
*top_rti = rtindex; *top_rti = rtindex;
*namespace = list_make1(makeDefaultNSItem(rte)); *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
rtr = makeNode(RangeTblRef); rtr = makeNode(RangeTblRef);
rtr->rtindex = rtindex; rtr->rtindex = rtindex;
return (Node *) rtr; return (Node *) rtr;
...@@ -1481,6 +1485,7 @@ transformFromClauseItem(ParseState *pstate, Node *n, ...@@ -1481,6 +1485,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
*/ */
*namespace = lappend(my_namespace, *namespace = lappend(my_namespace,
makeNamespaceItem(rte, makeNamespaceItem(rte,
j->rtindex,
(j->alias != NULL), (j->alias != NULL),
true, true,
false, false,
...@@ -1617,13 +1622,15 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype, ...@@ -1617,13 +1622,15 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
* Convenience subroutine to construct a ParseNamespaceItem. * Convenience subroutine to construct a ParseNamespaceItem.
*/ */
static ParseNamespaceItem * static ParseNamespaceItem *
makeNamespaceItem(RangeTblEntry *rte, bool rel_visible, bool cols_visible, makeNamespaceItem(RangeTblEntry *rte, int rtindex,
bool rel_visible, bool cols_visible,
bool lateral_only, bool lateral_ok) bool lateral_only, bool lateral_ok)
{ {
ParseNamespaceItem *nsitem; ParseNamespaceItem *nsitem;
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem)); nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
nsitem->p_rte = rte; nsitem->p_rte = rte;
nsitem->p_rtindex = rtindex;
nsitem->p_rel_visible = rel_visible; nsitem->p_rel_visible = rel_visible;
nsitem->p_cols_visible = cols_visible; nsitem->p_cols_visible = cols_visible;
nsitem->p_lateral_only = lateral_only; nsitem->p_lateral_only = lateral_only;
......
...@@ -114,8 +114,9 @@ static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs); ...@@ -114,8 +114,9 @@ static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs);
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b); static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr); static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr);
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, static Node *transformWholeRowRef(ParseState *pstate,
int location); ParseNamespaceItem *nsitem,
int sublevels_up, int location);
static Node *transformIndirection(ParseState *pstate, A_Indirection *ind); static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc); static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
static Node *transformCollateClause(ParseState *pstate, CollateClause *c); static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
...@@ -510,7 +511,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -510,7 +511,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
char *nspname = NULL; char *nspname = NULL;
char *relname = NULL; char *relname = NULL;
char *colname = NULL; char *colname = NULL;
RangeTblEntry *rte; ParseNamespaceItem *nsitem;
int levels_up; int levels_up;
enum enum
{ {
...@@ -653,11 +654,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -653,11 +654,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
* PostQUEL-inspired syntax. The preferred form now is * PostQUEL-inspired syntax. The preferred form now is
* "rel.*". * "rel.*".
*/ */
rte = refnameRangeTblEntry(pstate, NULL, colname, nsitem = refnameNamespaceItem(pstate, NULL, colname,
cref->location, cref->location,
&levels_up); &levels_up);
if (rte) if (nsitem)
node = transformWholeRowRef(pstate, rte, node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location); cref->location);
} }
break; break;
...@@ -670,11 +671,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -670,11 +671,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
Assert(IsA(field1, String)); Assert(IsA(field1, String));
relname = strVal(field1); relname = strVal(field1);
/* Locate the referenced RTE */ /* Locate the referenced nsitem */
rte = refnameRangeTblEntry(pstate, nspname, relname, nsitem = refnameNamespaceItem(pstate, nspname, relname,
cref->location, cref->location,
&levels_up); &levels_up);
if (rte == NULL) if (nsitem == NULL)
{ {
crerr = CRERR_NO_RTE; crerr = CRERR_NO_RTE;
break; break;
...@@ -683,20 +684,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -683,20 +684,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */ /* Whole-row reference? */
if (IsA(field2, A_Star)) if (IsA(field2, A_Star))
{ {
node = transformWholeRowRef(pstate, rte, cref->location); node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
break; break;
} }
Assert(IsA(field2, String)); Assert(IsA(field2, String));
colname = strVal(field2); colname = strVal(field2);
/* Try to identify as a column of the RTE */ /* Try to identify as a column of the nsitem */
node = scanRTEForColumn(pstate, rte, colname, cref->location, node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
0, NULL); cref->location);
if (node == NULL) if (node == NULL)
{ {
/* Try it as a function call on the whole row */ /* Try it as a function call on the whole row */
node = transformWholeRowRef(pstate, rte, cref->location); node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
node = ParseFuncOrColumn(pstate, node = ParseFuncOrColumn(pstate,
list_make1(makeString(colname)), list_make1(makeString(colname)),
list_make1(node), list_make1(node),
...@@ -718,11 +721,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -718,11 +721,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
Assert(IsA(field2, String)); Assert(IsA(field2, String));
relname = strVal(field2); relname = strVal(field2);
/* Locate the referenced RTE */ /* Locate the referenced nsitem */
rte = refnameRangeTblEntry(pstate, nspname, relname, nsitem = refnameNamespaceItem(pstate, nspname, relname,
cref->location, cref->location,
&levels_up); &levels_up);
if (rte == NULL) if (nsitem == NULL)
{ {
crerr = CRERR_NO_RTE; crerr = CRERR_NO_RTE;
break; break;
...@@ -731,20 +734,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -731,20 +734,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */ /* Whole-row reference? */
if (IsA(field3, A_Star)) if (IsA(field3, A_Star))
{ {
node = transformWholeRowRef(pstate, rte, cref->location); node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
break; break;
} }
Assert(IsA(field3, String)); Assert(IsA(field3, String));
colname = strVal(field3); colname = strVal(field3);
/* Try to identify as a column of the RTE */ /* Try to identify as a column of the nsitem */
node = scanRTEForColumn(pstate, rte, colname, cref->location, node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
0, NULL); cref->location);
if (node == NULL) if (node == NULL)
{ {
/* Try it as a function call on the whole row */ /* Try it as a function call on the whole row */
node = transformWholeRowRef(pstate, rte, cref->location); node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
node = ParseFuncOrColumn(pstate, node = ParseFuncOrColumn(pstate,
list_make1(makeString(colname)), list_make1(makeString(colname)),
list_make1(node), list_make1(node),
...@@ -779,11 +784,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -779,11 +784,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
break; break;
} }
/* Locate the referenced RTE */ /* Locate the referenced nsitem */
rte = refnameRangeTblEntry(pstate, nspname, relname, nsitem = refnameNamespaceItem(pstate, nspname, relname,
cref->location, cref->location,
&levels_up); &levels_up);
if (rte == NULL) if (nsitem == NULL)
{ {
crerr = CRERR_NO_RTE; crerr = CRERR_NO_RTE;
break; break;
...@@ -792,20 +797,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) ...@@ -792,20 +797,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */ /* Whole-row reference? */
if (IsA(field4, A_Star)) if (IsA(field4, A_Star))
{ {
node = transformWholeRowRef(pstate, rte, cref->location); node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
break; break;
} }
Assert(IsA(field4, String)); Assert(IsA(field4, String));
colname = strVal(field4); colname = strVal(field4);
/* Try to identify as a column of the RTE */ /* Try to identify as a column of the nsitem */
node = scanRTEForColumn(pstate, rte, colname, cref->location, node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
0, NULL); cref->location);
if (node == NULL) if (node == NULL)
{ {
/* Try it as a function call on the whole row */ /* Try it as a function call on the whole row */
node = transformWholeRowRef(pstate, rte, cref->location); node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
node = ParseFuncOrColumn(pstate, node = ParseFuncOrColumn(pstate,
list_make1(makeString(colname)), list_make1(makeString(colname)),
list_make1(node), list_make1(node),
...@@ -2648,14 +2655,9 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b) ...@@ -2648,14 +2655,9 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
static Node * static Node *
transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr) transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
{ {
int sublevels_up;
/* CURRENT OF can only appear at top level of UPDATE/DELETE */ /* CURRENT OF can only appear at top level of UPDATE/DELETE */
Assert(pstate->p_target_rangetblentry != NULL); Assert(pstate->p_target_rtindex > 0);
cexpr->cvarno = RTERangeTablePosn(pstate, cexpr->cvarno = pstate->p_target_rtindex;
pstate->p_target_rangetblentry,
&sublevels_up);
Assert(sublevels_up == 0);
/* /*
* Check to see if the cursor name matches a parameter of type REFCURSOR. * Check to see if the cursor name matches a parameter of type REFCURSOR.
...@@ -2703,14 +2705,10 @@ transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr) ...@@ -2703,14 +2705,10 @@ transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
* Construct a whole-row reference to represent the notation "relation.*". * Construct a whole-row reference to represent the notation "relation.*".
*/ */
static Node * static Node *
transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location) transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem,
int sublevels_up, int location)
{ {
Var *result; Var *result;
int vnum;
int sublevels_up;
/* Find the RTE's rangetable location */
vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
/* /*
* Build the appropriate referencing node. Note that if the RTE is a * Build the appropriate referencing node. Note that if the RTE is a
...@@ -2720,13 +2718,14 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location) ...@@ -2720,13 +2718,14 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
* historically. One argument for it is that "rel" and "rel.*" mean the * historically. One argument for it is that "rel" and "rel.*" mean the
* same thing for composite relations, so why not for scalar functions... * same thing for composite relations, so why not for scalar functions...
*/ */
result = makeWholeRowVar(rte, vnum, sublevels_up, true); result = makeWholeRowVar(nsitem->p_rte, nsitem->p_rtindex,
sublevels_up, true);
/* location is not filled in by makeWholeRowVar */ /* location is not filled in by makeWholeRowVar */
result->location = location; result->location = location;
/* mark relation as requiring whole-row SELECT access */ /* mark relation as requiring whole-row SELECT access */
markVarForSelectPriv(pstate, result, rte); markVarForSelectPriv(pstate, result, nsitem->p_rte);
return (Node *) result; return (Node *) result;
} }
......
...@@ -1913,13 +1913,15 @@ ParseComplexProjection(ParseState *pstate, const char *funcname, Node *first_arg ...@@ -1913,13 +1913,15 @@ ParseComplexProjection(ParseState *pstate, const char *funcname, Node *first_arg
if (IsA(first_arg, Var) && if (IsA(first_arg, Var) &&
((Var *) first_arg)->varattno == InvalidAttrNumber) ((Var *) first_arg)->varattno == InvalidAttrNumber)
{ {
RangeTblEntry *rte; ParseNamespaceItem *nsitem;
rte = GetRTEByRangeTablePosn(pstate, nsitem = GetNSItemByRangeTablePosn(pstate,
((Var *) first_arg)->varno, ((Var *) first_arg)->varno,
((Var *) first_arg)->varlevelsup); ((Var *) first_arg)->varlevelsup);
/* Return a Var if funcname matches a column, else NULL */ /* Return a Var if funcname matches a column, else NULL */
return scanRTEForColumn(pstate, rte, funcname, location, 0, NULL); return scanNSItemForColumn(pstate, nsitem,
((Var *) first_arg)->varlevelsup,
funcname, location);
} }
/* /*
......
...@@ -180,27 +180,6 @@ pcb_error_callback(void *arg) ...@@ -180,27 +180,6 @@ pcb_error_callback(void *arg)
} }
/*
* make_var
* Build a Var node for an attribute identified by RTE and attrno
*/
Var *
make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location)
{
Var *result;
int vnum,
sublevels_up;
Oid vartypeid;
int32 type_mod;
Oid varcollid;
vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod, &varcollid);
result = makeVar(vnum, attrno, vartypeid, type_mod, varcollid, sublevels_up);
result->location = location;
return result;
}
/* /*
* transformContainerType() * transformContainerType()
* Identify the types involved in a subscripting operation for container * Identify the types involved in a subscripting operation for container
......
This diff is collapsed.
...@@ -62,8 +62,9 @@ static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, ...@@ -62,8 +62,9 @@ static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
static List *ExpandAllTables(ParseState *pstate, int location); static List *ExpandAllTables(ParseState *pstate, int location);
static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind, static List *ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind,
bool make_target_entry, ParseExprKind exprKind); bool make_target_entry, ParseExprKind exprKind);
static List *ExpandSingleTable(ParseState *pstate, RangeTblEntry *rte, static List *ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
int location, bool make_target_entry); int sublevels_up, int location,
bool make_target_entry);
static List *ExpandRowReference(ParseState *pstate, Node *expr, static List *ExpandRowReference(ParseState *pstate, Node *expr,
bool make_target_entry); bool make_target_entry);
static int FigureColnameInternal(Node *node, char **name); static int FigureColnameInternal(Node *node, char **name);
...@@ -548,10 +549,13 @@ transformAssignedExpr(ParseState *pstate, ...@@ -548,10 +549,13 @@ transformAssignedExpr(ParseState *pstate,
/* /*
* Build a Var for the column to be updated. * Build a Var for the column to be updated.
*/ */
colVar = (Node *) make_var(pstate, Var *var;
pstate->p_target_rangetblentry,
attrno, var = makeVar(pstate->p_target_rtindex, attrno,
location); attrtype, attrtypmod, attrcollation, 0);
var->location = location;
colVar = (Node *) var;
} }
expr = (Expr *) expr = (Expr *)
...@@ -1127,7 +1131,7 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, ...@@ -1127,7 +1131,7 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
*/ */
char *nspname = NULL; char *nspname = NULL;
char *relname = NULL; char *relname = NULL;
RangeTblEntry *rte = NULL; ParseNamespaceItem *nsitem = NULL;
int levels_up; int levels_up;
enum enum
{ {
...@@ -1153,16 +1157,16 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, ...@@ -1153,16 +1157,16 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
{ {
case 2: case 2:
relname = strVal(linitial(fields)); relname = strVal(linitial(fields));
rte = refnameRangeTblEntry(pstate, nspname, relname, nsitem = refnameNamespaceItem(pstate, nspname, relname,
cref->location, cref->location,
&levels_up); &levels_up);
break; break;
case 3: case 3:
nspname = strVal(linitial(fields)); nspname = strVal(linitial(fields));
relname = strVal(lsecond(fields)); relname = strVal(lsecond(fields));
rte = refnameRangeTblEntry(pstate, nspname, relname, nsitem = refnameNamespaceItem(pstate, nspname, relname,
cref->location, cref->location,
&levels_up); &levels_up);
break; break;
case 4: case 4:
{ {
...@@ -1178,9 +1182,9 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, ...@@ -1178,9 +1182,9 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
} }
nspname = strVal(lsecond(fields)); nspname = strVal(lsecond(fields));
relname = strVal(lthird(fields)); relname = strVal(lthird(fields));
rte = refnameRangeTblEntry(pstate, nspname, relname, nsitem = refnameNamespaceItem(pstate, nspname, relname,
cref->location, cref->location,
&levels_up); &levels_up);
break; break;
} }
default: default:
...@@ -1193,17 +1197,19 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, ...@@ -1193,17 +1197,19 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
* bit by passing the RangeTblEntry, not a Var, as the planned * bit by passing the RangeTblEntry, not a Var, as the planned
* translation. (A single Var wouldn't be strictly correct anyway. * translation. (A single Var wouldn't be strictly correct anyway.
* This convention allows hooks that really care to know what is * This convention allows hooks that really care to know what is
* happening.) * happening. It might be better to pass the nsitem, but we'd have to
* promote that struct to a full-fledged Node type so that callees
* could identify its type.)
*/ */
if (pstate->p_post_columnref_hook != NULL) if (pstate->p_post_columnref_hook != NULL)
{ {
Node *node; Node *node;
node = pstate->p_post_columnref_hook(pstate, cref, node = pstate->p_post_columnref_hook(pstate, cref,
(Node *) rte); (Node *) (nsitem ? nsitem->p_rte : NULL));
if (node != NULL) if (node != NULL)
{ {
if (rte != NULL) if (nsitem != NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_COLUMN), (errcode(ERRCODE_AMBIGUOUS_COLUMN),
errmsg("column reference \"%s\" is ambiguous", errmsg("column reference \"%s\" is ambiguous",
...@@ -1216,7 +1222,7 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, ...@@ -1216,7 +1222,7 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
/* /*
* Throw error if no translation found. * Throw error if no translation found.
*/ */
if (rte == NULL) if (nsitem == NULL)
{ {
switch (crserr) switch (crserr)
{ {
...@@ -1242,9 +1248,10 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref, ...@@ -1242,9 +1248,10 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref,
} }
/* /*
* OK, expand the RTE into fields. * OK, expand the nsitem into fields.
*/ */
return ExpandSingleTable(pstate, rte, cref->location, make_target_entry); return ExpandSingleTable(pstate, nsitem, levels_up, cref->location,
make_target_entry);
} }
} }
...@@ -1269,7 +1276,6 @@ ExpandAllTables(ParseState *pstate, int location) ...@@ -1269,7 +1276,6 @@ ExpandAllTables(ParseState *pstate, 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 table-only items */ /* Ignore table-only items */
if (!nsitem->p_cols_visible) if (!nsitem->p_cols_visible)
...@@ -1280,12 +1286,10 @@ ExpandAllTables(ParseState *pstate, int location) ...@@ -1280,12 +1286,10 @@ ExpandAllTables(ParseState *pstate, int location)
found_table = true; found_table = true;
target = list_concat(target, target = list_concat(target,
expandRelAttrs(pstate, expandNSItemAttrs(pstate,
rte, nsitem,
RTERangeTablePosn(pstate, rte, 0,
NULL), location));
0,
location));
} }
/* /*
...@@ -1341,26 +1345,21 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind, ...@@ -1341,26 +1345,21 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind,
* The referenced columns are marked as requiring SELECT access. * The referenced columns are marked as requiring SELECT access.
*/ */
static List * static List *
ExpandSingleTable(ParseState *pstate, RangeTblEntry *rte, ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
int location, bool make_target_entry) int sublevels_up, int location, bool make_target_entry)
{ {
int sublevels_up;
int rtindex;
rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up);
if (make_target_entry) if (make_target_entry)
{ {
/* expandRelAttrs handles permissions marking */ /* expandNSItemAttrs handles permissions marking */
return expandRelAttrs(pstate, rte, rtindex, sublevels_up, return expandNSItemAttrs(pstate, nsitem, sublevels_up, location);
location);
} }
else else
{ {
RangeTblEntry *rte = nsitem->p_rte;
List *vars; List *vars;
ListCell *l; ListCell *l;
expandRTE(rte, rtindex, sublevels_up, location, false, expandRTE(rte, nsitem->p_rtindex, sublevels_up, location, false,
NULL, &vars); NULL, &vars);
/* /*
...@@ -1411,10 +1410,10 @@ ExpandRowReference(ParseState *pstate, Node *expr, ...@@ -1411,10 +1410,10 @@ ExpandRowReference(ParseState *pstate, Node *expr,
((Var *) expr)->varattno == InvalidAttrNumber) ((Var *) expr)->varattno == InvalidAttrNumber)
{ {
Var *var = (Var *) expr; Var *var = (Var *) expr;
RangeTblEntry *rte; ParseNamespaceItem *nsitem;
rte = GetRTEByRangeTablePosn(pstate, var->varno, var->varlevelsup); nsitem = GetNSItemByRangeTablePosn(pstate, var->varno, var->varlevelsup);
return ExpandSingleTable(pstate, rte, var->location, make_target_entry); return ExpandSingleTable(pstate, nsitem, var->varlevelsup, var->location, make_target_entry);
} }
/* /*
......
...@@ -134,6 +134,8 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param, ...@@ -134,6 +134,8 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param,
* *
* p_target_rangetblentry: target relation's entry in the rtable list. * p_target_rangetblentry: target relation's entry in the rtable list.
* *
* p_target_rtindex: target relation's index in the rtable list.
*
* p_is_insert: true to process assignment expressions like INSERT, false * p_is_insert: true to process assignment expressions like INSERT, false
* to process them like UPDATE. (Note this can change intra-statement, for * to process them like UPDATE. (Note this can change intra-statement, for
* cases like INSERT ON CONFLICT UPDATE.) * cases like INSERT ON CONFLICT UPDATE.)
...@@ -185,7 +187,8 @@ struct ParseState ...@@ -185,7 +187,8 @@ struct ParseState
List *p_future_ctes; /* common table exprs not yet in namespace */ List *p_future_ctes; /* common table exprs not yet in namespace */
CommonTableExpr *p_parent_cte; /* this query's containing CTE */ CommonTableExpr *p_parent_cte; /* this query's containing CTE */
Relation p_target_relation; /* INSERT/UPDATE/DELETE target rel */ Relation p_target_relation; /* INSERT/UPDATE/DELETE target rel */
RangeTblEntry *p_target_rangetblentry; /* target rel's RTE */ RangeTblEntry *p_target_rangetblentry; /* target rel's RTE, or NULL */
int p_target_rtindex; /* target rel's RT index, or 0 */
bool p_is_insert; /* process assignment like INSERT not UPDATE */ bool p_is_insert; /* process assignment like INSERT not UPDATE */
List *p_windowdefs; /* raw representations of window clauses */ List *p_windowdefs; /* raw representations of window clauses */
ParseExprKind p_expr_kind; /* what kind of expression we're parsing */ ParseExprKind p_expr_kind; /* what kind of expression we're parsing */
...@@ -249,6 +252,7 @@ struct ParseState ...@@ -249,6 +252,7 @@ struct ParseState
typedef struct ParseNamespaceItem typedef struct ParseNamespaceItem
{ {
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 */
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? */
bool p_lateral_only; /* Is only visible to LATERAL expressions? */ bool p_lateral_only; /* Is only visible to LATERAL expressions? */
...@@ -272,8 +276,6 @@ extern void setup_parser_errposition_callback(ParseCallbackState *pcbstate, ...@@ -272,8 +276,6 @@ extern void setup_parser_errposition_callback(ParseCallbackState *pcbstate,
ParseState *pstate, int location); ParseState *pstate, int location);
extern void cancel_parser_errposition_callback(ParseCallbackState *pcbstate); extern void cancel_parser_errposition_callback(ParseCallbackState *pcbstate);
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno,
int location);
extern Oid transformContainerType(Oid *containerType, int32 *containerTypmod); extern Oid transformContainerType(Oid *containerType, int32 *containerTypmod);
extern SubscriptingRef *transformContainerSubscripts(ParseState *pstate, extern SubscriptingRef *transformContainerSubscripts(ParseState *pstate,
......
...@@ -17,45 +17,28 @@ ...@@ -17,45 +17,28 @@
#include "parser/parse_node.h" #include "parser/parse_node.h"
/* extern ParseNamespaceItem *refnameNamespaceItem(ParseState *pstate,
* Support for fuzzily matching column. const char *schemaname,
* const char *refname,
* This is for building diagnostic messages, where non-exact matching int location,
* attributes are suggested to the user. The struct's fields may be facets of int *sublevels_up);
* a particular RTE, or of an entire range table, depending on context.
*/
typedef struct
{
int distance; /* Weighted distance (lowest so far) */
RangeTblEntry *rfirst; /* RTE of first */
AttrNumber first; /* Closest attribute so far */
RangeTblEntry *rsecond; /* RTE of second */
AttrNumber second; /* Second closest attribute so far */
} FuzzyAttrMatchState;
extern RangeTblEntry *refnameRangeTblEntry(ParseState *pstate,
const char *schemaname,
const char *refname,
int location,
int *sublevels_up);
extern CommonTableExpr *scanNameSpaceForCTE(ParseState *pstate, extern CommonTableExpr *scanNameSpaceForCTE(ParseState *pstate,
const char *refname, const char *refname,
Index *ctelevelsup); Index *ctelevelsup);
extern bool scanNameSpaceForENR(ParseState *pstate, const char *refname); extern bool scanNameSpaceForENR(ParseState *pstate, const char *refname);
extern void checkNameSpaceConflicts(ParseState *pstate, List *namespace1, extern void checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
List *namespace2); List *namespace2);
extern int RTERangeTablePosn(ParseState *pstate, extern ParseNamespaceItem *GetNSItemByRangeTablePosn(ParseState *pstate,
RangeTblEntry *rte, int varno,
int *sublevels_up); int sublevels_up);
extern RangeTblEntry *GetRTEByRangeTablePosn(ParseState *pstate, extern RangeTblEntry *GetRTEByRangeTablePosn(ParseState *pstate,
int varno, int varno,
int sublevels_up); int sublevels_up);
extern CommonTableExpr *GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte, extern CommonTableExpr *GetCTEForRTE(ParseState *pstate, RangeTblEntry *rte,
int rtelevelsup); int rtelevelsup);
extern Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, extern Node *scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
const char *colname, int location, int sublevels_up, const char *colname,
int fuzzy_rte_penalty, FuzzyAttrMatchState *fuzzystate); int location);
extern Node *colNameToVar(ParseState *pstate, const char *colname, bool localonly, extern Node *colNameToVar(ParseState *pstate, const char *colname, bool localonly,
int location); int location);
extern void markVarForSelectPriv(ParseState *pstate, Var *var, extern void markVarForSelectPriv(ParseState *pstate, Var *var,
...@@ -122,8 +105,8 @@ extern void errorMissingColumn(ParseState *pstate, ...@@ -122,8 +105,8 @@ extern void errorMissingColumn(ParseState *pstate,
extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
int location, bool include_dropped, int location, bool include_dropped,
List **colnames, List **colvars); List **colnames, List **colvars);
extern List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte, extern List *expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem,
int rtindex, int sublevels_up, int location); int sublevels_up, int location);
extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK); extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK);
extern const NameData *attnumAttName(Relation rd, int attid); extern const NameData *attnumAttName(Relation rd, int attid);
extern Oid attnumTypeId(Relation rd, int attid); extern Oid attnumTypeId(Relation rd, int attid);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment