Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b541e9a

Browse files
committed
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
1 parent 044b319 commit b541e9a

File tree

9 files changed

+332
-289
lines changed

9 files changed

+332
-289
lines changed

src/backend/parser/analyze.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -1344,7 +1344,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
13441344
int sublist_length = -1;
13451345
bool lateral = false;
13461346
RangeTblEntry *rte;
1347-
int rtindex;
1347+
ParseNamespaceItem *nsitem;
13481348
ListCell *lc;
13491349
ListCell *lc2;
13501350
int i;
@@ -1516,15 +1516,15 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
15161516
NULL, lateral, true);
15171517
addRTEtoQuery(pstate, rte, true, true, true);
15181518

1519-
/* assume new rte is at end */
1520-
rtindex = list_length(pstate->p_rtable);
1521-
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
1519+
/* grab the namespace item made by addRTEtoQuery */
1520+
nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
1521+
Assert(rte == nsitem->p_rte);
15221522

15231523
/*
15241524
* Generate a targetlist as though expanding "*"
15251525
*/
15261526
Assert(pstate->p_next_resno == 1);
1527-
qry->targetList = expandRelAttrs(pstate, rte, rtindex, 0, -1);
1527+
qry->targetList = expandNSItemAttrs(pstate, nsitem, 0, -1);
15281528

15291529
/*
15301530
* The grammar allows attaching ORDER BY, LIMIT, and FOR UPDATE to a

src/backend/parser/parse_clause.c

+15-8
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
#include "utils/syscache.h"
5353

5454
/* Convenience macro for the most common makeNamespaceItem() case */
55-
#define makeDefaultNSItem(rte) makeNamespaceItem(rte, true, true, false, true)
55+
#define makeDefaultNSItem(rte, rti) \
56+
makeNamespaceItem(rte, rti, true, true, false, true)
5657

5758
static void extractRemainingColumns(List *common_colnames,
5859
List *src_colnames, List *src_colvars,
@@ -78,7 +79,7 @@ static Node *transformFromClauseItem(ParseState *pstate, Node *n,
7879
List **namespace);
7980
static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
8081
Var *l_colvar, Var *r_colvar);
81-
static ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte,
82+
static ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte, int rtindex,
8283
bool rel_visible, bool cols_visible,
8384
bool lateral_only, bool lateral_ok);
8485
static void setNamespaceColumnVisibility(List *namespace, bool cols_visible);
@@ -216,12 +217,15 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
216217
rte = addRangeTableEntryForRelation(pstate, pstate->p_target_relation,
217218
RowExclusiveLock,
218219
relation->alias, inh, false);
219-
pstate->p_target_rangetblentry = rte;
220220

221221
/* assume new rte is at end */
222222
rtindex = list_length(pstate->p_rtable);
223223
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
224224

225+
/* remember the RTE as being the query target */
226+
pstate->p_target_rangetblentry = rte;
227+
pstate->p_target_rtindex = rtindex;
228+
225229
/*
226230
* Override addRangeTableEntry's default ACL_SELECT permissions check, and
227231
* instead mark target table as requiring exactly the specified
@@ -1084,7 +1088,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
10841088
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
10851089
*top_rte = rte;
10861090
*top_rti = rtindex;
1087-
*namespace = list_make1(makeDefaultNSItem(rte));
1091+
*namespace = list_make1(makeDefaultNSItem(rte, rtindex));
10881092
rtr = makeNode(RangeTblRef);
10891093
rtr->rtindex = rtindex;
10901094
return (Node *) rtr;
@@ -1102,7 +1106,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
11021106
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
11031107
*top_rte = rte;
11041108
*top_rti = rtindex;
1105-
*namespace = list_make1(makeDefaultNSItem(rte));
1109+
*namespace = list_make1(makeDefaultNSItem(rte, rtindex));
11061110
rtr = makeNode(RangeTblRef);
11071111
rtr->rtindex = rtindex;
11081112
return (Node *) rtr;
@@ -1120,7 +1124,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
11201124
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
11211125
*top_rte = rte;
11221126
*top_rti = rtindex;
1123-
*namespace = list_make1(makeDefaultNSItem(rte));
1127+
*namespace = list_make1(makeDefaultNSItem(rte, rtindex));
11241128
rtr = makeNode(RangeTblRef);
11251129
rtr->rtindex = rtindex;
11261130
return (Node *) rtr;
@@ -1138,7 +1142,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
11381142
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
11391143
*top_rte = rte;
11401144
*top_rti = rtindex;
1141-
*namespace = list_make1(makeDefaultNSItem(rte));
1145+
*namespace = list_make1(makeDefaultNSItem(rte, rtindex));
11421146
rtr = makeNode(RangeTblRef);
11431147
rtr->rtindex = rtindex;
11441148
return (Node *) rtr;
@@ -1481,6 +1485,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
14811485
*/
14821486
*namespace = lappend(my_namespace,
14831487
makeNamespaceItem(rte,
1488+
j->rtindex,
14841489
(j->alias != NULL),
14851490
true,
14861491
false,
@@ -1617,13 +1622,15 @@ buildMergedJoinVar(ParseState *pstate, JoinType jointype,
16171622
* Convenience subroutine to construct a ParseNamespaceItem.
16181623
*/
16191624
static ParseNamespaceItem *
1620-
makeNamespaceItem(RangeTblEntry *rte, bool rel_visible, bool cols_visible,
1625+
makeNamespaceItem(RangeTblEntry *rte, int rtindex,
1626+
bool rel_visible, bool cols_visible,
16211627
bool lateral_only, bool lateral_ok)
16221628
{
16231629
ParseNamespaceItem *nsitem;
16241630

16251631
nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
16261632
nsitem->p_rte = rte;
1633+
nsitem->p_rtindex = rtindex;
16271634
nsitem->p_rel_visible = rel_visible;
16281635
nsitem->p_cols_visible = cols_visible;
16291636
nsitem->p_lateral_only = lateral_only;

src/backend/parser/parse_expr.c

+52-53
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,9 @@ static Node *transformXmlSerialize(ParseState *pstate, XmlSerialize *xs);
114114
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
115115
static Node *transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr);
116116
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
117-
static Node *transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte,
118-
int location);
117+
static Node *transformWholeRowRef(ParseState *pstate,
118+
ParseNamespaceItem *nsitem,
119+
int sublevels_up, int location);
119120
static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
120121
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
121122
static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
@@ -510,7 +511,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
510511
char *nspname = NULL;
511512
char *relname = NULL;
512513
char *colname = NULL;
513-
RangeTblEntry *rte;
514+
ParseNamespaceItem *nsitem;
514515
int levels_up;
515516
enum
516517
{
@@ -653,11 +654,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
653654
* PostQUEL-inspired syntax. The preferred form now is
654655
* "rel.*".
655656
*/
656-
rte = refnameRangeTblEntry(pstate, NULL, colname,
657-
cref->location,
658-
&levels_up);
659-
if (rte)
660-
node = transformWholeRowRef(pstate, rte,
657+
nsitem = refnameNamespaceItem(pstate, NULL, colname,
658+
cref->location,
659+
&levels_up);
660+
if (nsitem)
661+
node = transformWholeRowRef(pstate, nsitem, levels_up,
661662
cref->location);
662663
}
663664
break;
@@ -670,11 +671,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
670671
Assert(IsA(field1, String));
671672
relname = strVal(field1);
672673

673-
/* Locate the referenced RTE */
674-
rte = refnameRangeTblEntry(pstate, nspname, relname,
675-
cref->location,
676-
&levels_up);
677-
if (rte == NULL)
674+
/* Locate the referenced nsitem */
675+
nsitem = refnameNamespaceItem(pstate, nspname, relname,
676+
cref->location,
677+
&levels_up);
678+
if (nsitem == NULL)
678679
{
679680
crerr = CRERR_NO_RTE;
680681
break;
@@ -683,20 +684,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
683684
/* Whole-row reference? */
684685
if (IsA(field2, A_Star))
685686
{
686-
node = transformWholeRowRef(pstate, rte, cref->location);
687+
node = transformWholeRowRef(pstate, nsitem, levels_up,
688+
cref->location);
687689
break;
688690
}
689691

690692
Assert(IsA(field2, String));
691693
colname = strVal(field2);
692694

693-
/* Try to identify as a column of the RTE */
694-
node = scanRTEForColumn(pstate, rte, colname, cref->location,
695-
0, NULL);
695+
/* Try to identify as a column of the nsitem */
696+
node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
697+
cref->location);
696698
if (node == NULL)
697699
{
698700
/* Try it as a function call on the whole row */
699-
node = transformWholeRowRef(pstate, rte, cref->location);
701+
node = transformWholeRowRef(pstate, nsitem, levels_up,
702+
cref->location);
700703
node = ParseFuncOrColumn(pstate,
701704
list_make1(makeString(colname)),
702705
list_make1(node),
@@ -718,11 +721,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
718721
Assert(IsA(field2, String));
719722
relname = strVal(field2);
720723

721-
/* Locate the referenced RTE */
722-
rte = refnameRangeTblEntry(pstate, nspname, relname,
723-
cref->location,
724-
&levels_up);
725-
if (rte == NULL)
724+
/* Locate the referenced nsitem */
725+
nsitem = refnameNamespaceItem(pstate, nspname, relname,
726+
cref->location,
727+
&levels_up);
728+
if (nsitem == NULL)
726729
{
727730
crerr = CRERR_NO_RTE;
728731
break;
@@ -731,20 +734,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
731734
/* Whole-row reference? */
732735
if (IsA(field3, A_Star))
733736
{
734-
node = transformWholeRowRef(pstate, rte, cref->location);
737+
node = transformWholeRowRef(pstate, nsitem, levels_up,
738+
cref->location);
735739
break;
736740
}
737741

738742
Assert(IsA(field3, String));
739743
colname = strVal(field3);
740744

741-
/* Try to identify as a column of the RTE */
742-
node = scanRTEForColumn(pstate, rte, colname, cref->location,
743-
0, NULL);
745+
/* Try to identify as a column of the nsitem */
746+
node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
747+
cref->location);
744748
if (node == NULL)
745749
{
746750
/* Try it as a function call on the whole row */
747-
node = transformWholeRowRef(pstate, rte, cref->location);
751+
node = transformWholeRowRef(pstate, nsitem, levels_up,
752+
cref->location);
748753
node = ParseFuncOrColumn(pstate,
749754
list_make1(makeString(colname)),
750755
list_make1(node),
@@ -779,11 +784,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
779784
break;
780785
}
781786

782-
/* Locate the referenced RTE */
783-
rte = refnameRangeTblEntry(pstate, nspname, relname,
784-
cref->location,
785-
&levels_up);
786-
if (rte == NULL)
787+
/* Locate the referenced nsitem */
788+
nsitem = refnameNamespaceItem(pstate, nspname, relname,
789+
cref->location,
790+
&levels_up);
791+
if (nsitem == NULL)
787792
{
788793
crerr = CRERR_NO_RTE;
789794
break;
@@ -792,20 +797,22 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
792797
/* Whole-row reference? */
793798
if (IsA(field4, A_Star))
794799
{
795-
node = transformWholeRowRef(pstate, rte, cref->location);
800+
node = transformWholeRowRef(pstate, nsitem, levels_up,
801+
cref->location);
796802
break;
797803
}
798804

799805
Assert(IsA(field4, String));
800806
colname = strVal(field4);
801807

802-
/* Try to identify as a column of the RTE */
803-
node = scanRTEForColumn(pstate, rte, colname, cref->location,
804-
0, NULL);
808+
/* Try to identify as a column of the nsitem */
809+
node = scanNSItemForColumn(pstate, nsitem, levels_up, colname,
810+
cref->location);
805811
if (node == NULL)
806812
{
807813
/* Try it as a function call on the whole row */
808-
node = transformWholeRowRef(pstate, rte, cref->location);
814+
node = transformWholeRowRef(pstate, nsitem, levels_up,
815+
cref->location);
809816
node = ParseFuncOrColumn(pstate,
810817
list_make1(makeString(colname)),
811818
list_make1(node),
@@ -2648,14 +2655,9 @@ transformBooleanTest(ParseState *pstate, BooleanTest *b)
26482655
static Node *
26492656
transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
26502657
{
2651-
int sublevels_up;
2652-
26532658
/* CURRENT OF can only appear at top level of UPDATE/DELETE */
2654-
Assert(pstate->p_target_rangetblentry != NULL);
2655-
cexpr->cvarno = RTERangeTablePosn(pstate,
2656-
pstate->p_target_rangetblentry,
2657-
&sublevels_up);
2658-
Assert(sublevels_up == 0);
2659+
Assert(pstate->p_target_rtindex > 0);
2660+
cexpr->cvarno = pstate->p_target_rtindex;
26592661

26602662
/*
26612663
* Check to see if the cursor name matches a parameter of type REFCURSOR.
@@ -2703,14 +2705,10 @@ transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
27032705
* Construct a whole-row reference to represent the notation "relation.*".
27042706
*/
27052707
static Node *
2706-
transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
2708+
transformWholeRowRef(ParseState *pstate, ParseNamespaceItem *nsitem,
2709+
int sublevels_up, int location)
27072710
{
27082711
Var *result;
2709-
int vnum;
2710-
int sublevels_up;
2711-
2712-
/* Find the RTE's rangetable location */
2713-
vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
27142712

27152713
/*
27162714
* Build the appropriate referencing node. Note that if the RTE is a
@@ -2720,13 +2718,14 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
27202718
* historically. One argument for it is that "rel" and "rel.*" mean the
27212719
* same thing for composite relations, so why not for scalar functions...
27222720
*/
2723-
result = makeWholeRowVar(rte, vnum, sublevels_up, true);
2721+
result = makeWholeRowVar(nsitem->p_rte, nsitem->p_rtindex,
2722+
sublevels_up, true);
27242723

27252724
/* location is not filled in by makeWholeRowVar */
27262725
result->location = location;
27272726

27282727
/* mark relation as requiring whole-row SELECT access */
2729-
markVarForSelectPriv(pstate, result, rte);
2728+
markVarForSelectPriv(pstate, result, nsitem->p_rte);
27302729

27312730
return (Node *) result;
27322731
}

src/backend/parser/parse_func.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -1913,13 +1913,15 @@ ParseComplexProjection(ParseState *pstate, const char *funcname, Node *first_arg
19131913
if (IsA(first_arg, Var) &&
19141914
((Var *) first_arg)->varattno == InvalidAttrNumber)
19151915
{
1916-
RangeTblEntry *rte;
1916+
ParseNamespaceItem *nsitem;
19171917

1918-
rte = GetRTEByRangeTablePosn(pstate,
1919-
((Var *) first_arg)->varno,
1920-
((Var *) first_arg)->varlevelsup);
1918+
nsitem = GetNSItemByRangeTablePosn(pstate,
1919+
((Var *) first_arg)->varno,
1920+
((Var *) first_arg)->varlevelsup);
19211921
/* Return a Var if funcname matches a column, else NULL */
1922-
return scanRTEForColumn(pstate, rte, funcname, location, 0, NULL);
1922+
return scanNSItemForColumn(pstate, nsitem,
1923+
((Var *) first_arg)->varlevelsup,
1924+
funcname, location);
19231925
}
19241926

19251927
/*

src/backend/parser/parse_node.c

-21
Original file line numberDiff line numberDiff line change
@@ -180,27 +180,6 @@ pcb_error_callback(void *arg)
180180
}
181181

182182

183-
/*
184-
* make_var
185-
* Build a Var node for an attribute identified by RTE and attrno
186-
*/
187-
Var *
188-
make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location)
189-
{
190-
Var *result;
191-
int vnum,
192-
sublevels_up;
193-
Oid vartypeid;
194-
int32 type_mod;
195-
Oid varcollid;
196-
197-
vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
198-
get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod, &varcollid);
199-
result = makeVar(vnum, attrno, vartypeid, type_mod, varcollid, sublevels_up);
200-
result->location = location;
201-
return result;
202-
}
203-
204183
/*
205184
* transformContainerType()
206185
* Identify the types involved in a subscripting operation for container

0 commit comments

Comments
 (0)