aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_expr.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-12-26 11:16:42 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2019-12-26 11:16:42 -0500
commitb541e9accb28c90656388a3f827ca3a68dd2a308 (patch)
treef0aa0a43e27556d05eeb0e847d7bcf066bf98637 /src/backend/parser/parse_expr.c
parent044b319cd77c589507291f9591994093ad30931d (diff)
downloadpostgresql-b541e9accb28c90656388a3f827ca3a68dd2a308.tar.gz
postgresql-b541e9accb28c90656388a3f827ca3a68dd2a308.zip
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
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r--src/backend/parser/parse_expr.c105
1 files changed, 52 insertions, 53 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index eb91da2d87a..25e92de0b33 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -114,8 +114,9 @@ static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs);
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr);
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
-static Node *transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte,
- int location);
+static Node *transformWholeRowRef(ParseState *pstate,
+ ParseNamespaceItem *nsitem,
+ int sublevels_up, int location);
static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
@@ -510,7 +511,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
char *nspname = NULL;
char *relname = NULL;
char *colname = NULL;
- RangeTblEntry *rte;
+ ParseNamespaceItem *nsitem;
int levels_up;
enum
{
@@ -653,11 +654,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
* PostQUEL-inspired syntax. The preferred form now is
* "rel.*".
*/
- rte = refnameRangeTblEntry(pstate, NULL, colname,
- cref->location,
- &levels_up);
- if (rte)
- node = transformWholeRowRef(pstate, rte,
+ nsitem = refnameNamespaceItem(pstate, NULL, colname,
+ cref->location,
+ &levels_up);
+ if (nsitem)
+ node = transformWholeRowRef(pstate, nsitem, levels_up,
cref->location);
}
break;
@@ -670,11 +671,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
Assert(IsA(field1, String));
relname = strVal(field1);
- /* Locate the referenced RTE */
- rte = refnameRangeTblEntry(pstate, nspname, relname,
- cref->location,
- &levels_up);
- if (rte == NULL)
+ /* Locate the referenced nsitem */
+ nsitem = refnameNamespaceItem(pstate, nspname, relname,
+ cref->location,
+ &levels_up);
+ if (nsitem == NULL)
{
crerr = CRERR_NO_RTE;
break;
@@ -683,20 +684,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */
if (IsA(field2, A_Star))
{
- node = transformWholeRowRef(pstate, rte, cref->location);
+ node = transformWholeRowRef(pstate, nsitem, levels_up,
+ cref->location);
break;
}
Assert(IsA(field2, String));
colname = strVal(field2);
- /* Try to identify as a column of the RTE */
- node = scanRTEForColumn(pstate, rte, colname, cref->location,
- 0, NULL);
+ /* Try to identify as a column of the nsitem */
+ node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
+ cref->location);
if (node == NULL)
{
/* 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,
list_make1(makeString(colname)),
list_make1(node),
@@ -718,11 +721,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
Assert(IsA(field2, String));
relname = strVal(field2);
- /* Locate the referenced RTE */
- rte = refnameRangeTblEntry(pstate, nspname, relname,
- cref->location,
- &levels_up);
- if (rte == NULL)
+ /* Locate the referenced nsitem */
+ nsitem = refnameNamespaceItem(pstate, nspname, relname,
+ cref->location,
+ &levels_up);
+ if (nsitem == NULL)
{
crerr = CRERR_NO_RTE;
break;
@@ -731,20 +734,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */
if (IsA(field3, A_Star))
{
- node = transformWholeRowRef(pstate, rte, cref->location);
+ node = transformWholeRowRef(pstate, nsitem, levels_up,
+ cref->location);
break;
}
Assert(IsA(field3, String));
colname = strVal(field3);
- /* Try to identify as a column of the RTE */
- node = scanRTEForColumn(pstate, rte, colname, cref->location,
- 0, NULL);
+ /* Try to identify as a column of the nsitem */
+ node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
+ cref->location);
if (node == NULL)
{
/* 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,
list_make1(makeString(colname)),
list_make1(node),
@@ -779,11 +784,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
break;
}
- /* Locate the referenced RTE */
- rte = refnameRangeTblEntry(pstate, nspname, relname,
- cref->location,
- &levels_up);
- if (rte == NULL)
+ /* Locate the referenced nsitem */
+ nsitem = refnameNamespaceItem(pstate, nspname, relname,
+ cref->location,
+ &levels_up);
+ if (nsitem == NULL)
{
crerr = CRERR_NO_RTE;
break;
@@ -792,20 +797,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
/* Whole-row reference? */
if (IsA(field4, A_Star))
{
- node = transformWholeRowRef(pstate, rte, cref->location);
+ node = transformWholeRowRef(pstate, nsitem, levels_up,
+ cref->location);
break;
}
Assert(IsA(field4, String));
colname = strVal(field4);
- /* Try to identify as a column of the RTE */
- node = scanRTEForColumn(pstate, rte, colname, cref->location,
- 0, NULL);
+ /* Try to identify as a column of the nsitem */
+ node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
+ cref->location);
if (node == NULL)
{
/* 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,
list_make1(makeString(colname)),
list_make1(node),
@@ -2648,14 +2655,9 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
static Node *
transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
{
- int sublevels_up;
-
/* CURRENT OF can only appear at top level of UPDATE/DELETE */
- Assert(pstate->p_target_rangetblentry != NULL);
- cexpr->cvarno = RTERangeTablePosn(pstate,
- pstate->p_target_rangetblentry,
- &sublevels_up);
- Assert(sublevels_up == 0);
+ Assert(pstate->p_target_rtindex > 0);
+ cexpr->cvarno = pstate->p_target_rtindex;
/*
* Check to see if the cursor name matches a parameter of type REFCURSOR.
@@ -2703,14 +2705,10 @@ transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
* Construct a whole-row reference to represent the notation "relation.*".
*/
static Node *
-transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
+transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem,
+ int sublevels_up, int location)
{
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
@@ -2720,13 +2718,14 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
* historically. One argument for it is that "rel" and "rel.*" mean the
* 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 */
result->location = location;
/* mark relation as requiring whole-row SELECT access */
- markVarForSelectPriv(pstate, result, rte);
+ markVarForSelectPriv(pstate, result, nsitem->p_rte);
return (Node *) result;
}