1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-25 13:17:41 +03:00

Make parser rely more heavily on the ParseNamespaceItem data structure.

When I added the ParseNamespaceItem data structure (in commit 5ebaaa494),
it wasn't very tightly integrated into the parser's APIs.  In the wake of
adding p_rtindex to that struct (commit b541e9acc), there is a good reason
to make more use of it: by passing around ParseNamespaceItem pointers
instead of bare RTE pointers, we can get rid of various messy methods for
passing back or deducing the rangetable index of an RTE during parsing.
Hence, refactor the addRangeTableEntryXXX functions to build and return
a ParseNamespaceItem struct, not just the RTE proper; and replace
addRTEtoQuery with addNSItemToQuery, which is passed a ParseNamespaceItem
rather than building one internally.

Also, add per-column data (a ParseNamespaceColumn array) to each
ParseNamespaceItem.  These arrays are built during addRangeTableEntryXXX,
where we have column type data at hand so that it's nearly free to fill
the data structure.  Later, when we need to build Vars referencing RTEs,
we can use the ParseNamespaceColumn info to avoid the rather expensive
operations done in get_rte_attribute_type() or expandRTE().
get_rte_attribute_type() is indeed dead code now, so I've removed it.
This makes for a useful improvement in parse analysis speed, around 20%
in one moderately-complex test query.

The ParseNamespaceColumn structs also include Var identity information
(varno/varattno).  That info isn't actually being used in this patch,
except that p_varno == 0 is a handy test for a dropped column.
A follow-on patch will make more use of it.

Discussion: https://postgr.es/m/2461.1577764221@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2020-01-02 11:29:01 -05:00
parent 198c7153dc
commit 5815696bc6
20 changed files with 923 additions and 790 deletions

View File

@@ -19,6 +19,11 @@
#include "utils/relcache.h"
/* Forward references for some structs declared below */
typedef struct ParseState ParseState;
typedef struct ParseNamespaceItem ParseNamespaceItem;
typedef struct ParseNamespaceColumn ParseNamespaceColumn;
/*
* Expression kinds distinguished by transformExpr(). Many of these are not
* semantically distinct so far as expression transformation goes; rather,
@@ -79,8 +84,6 @@ typedef enum ParseExprKind
/*
* Function signatures for parser hooks
*/
typedef struct ParseState ParseState;
typedef Node *(*PreParseColumnRefHook) (ParseState *pstate, ColumnRef *cref);
typedef Node *(*PostParseColumnRefHook) (ParseState *pstate, ColumnRef *cref, Node *var);
typedef Node *(*ParseParamRefHook) (ParseState *pstate, ParamRef *pref);
@@ -132,9 +135,7 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param,
*
* p_target_relation: target relation, if query is INSERT, UPDATE, or DELETE.
*
* p_target_rangetblentry: target relation's entry in the rtable list.
*
* p_target_rtindex: target relation's index in the rtable list.
* p_target_nsitem: target relation's ParseNamespaceItem.
*
* p_is_insert: true to process assignment expressions like INSERT, false
* to process them like UPDATE. (Note this can change intra-statement, for
@@ -174,7 +175,7 @@ typedef Node *(*CoerceParamHook) (ParseState *pstate, Param *param,
*/
struct ParseState
{
struct ParseState *parentParseState; /* stack link */
ParseState *parentParseState; /* stack link */
const char *p_sourcetext; /* source text, or NULL if not available */
List *p_rtable; /* range table so far */
List *p_joinexprs; /* JoinExprs for RTE_JOIN p_rtable entries */
@@ -187,8 +188,7 @@ struct ParseState
List *p_future_ctes; /* common table exprs not yet in namespace */
CommonTableExpr *p_parent_cte; /* this query's containing CTE */
Relation p_target_relation; /* INSERT/UPDATE/DELETE target rel */
RangeTblEntry *p_target_rangetblentry; /* target rel's RTE, or NULL */
int p_target_rtindex; /* target rel's RT index, or 0 */
ParseNamespaceItem *p_target_nsitem; /* target rel's NSItem, or NULL */
bool p_is_insert; /* process assignment like INSERT not UPDATE */
List *p_windowdefs; /* raw representations of window clauses */
ParseExprKind p_expr_kind; /* what kind of expression we're parsing */
@@ -225,6 +225,9 @@ struct ParseState
/*
* An element of a namespace list.
*
* The p_nscolumns array contains info showing how to construct Vars
* referencing corresponding elements of the RTE's 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
* accessible by unqualified names. These sets are different because a JOIN
@@ -249,15 +252,49 @@ struct ParseState
* are more complicated than "must have different alias names", so in practice
* code searching a namespace list has to check for ambiguous references.
*/
typedef struct ParseNamespaceItem
struct ParseNamespaceItem
{
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: */
ParseNamespaceColumn *p_nscolumns; /* per-column data */
bool p_rel_visible; /* Relation name is visible? */
bool p_cols_visible; /* Column names visible as unqualified refs? */
bool p_lateral_only; /* Is only visible to LATERAL expressions? */
bool p_lateral_ok; /* If so, does join type allow use? */
} ParseNamespaceItem;
};
/*
* Data about one column of a ParseNamespaceItem.
*
* We track the info needed to construct a Var referencing the column
* (but only for user-defined columns; system column references and
* whole-row references are handled separately).
*
* p_varno and p_varattno identify the semantic referent, which is a
* base-relation column unless the reference is to a join USING column that
* isn't semantically equivalent to either join input column (because it is a
* FULL join or the input column requires a type coercion). In those cases
* p_varno and p_varattno refer to the JOIN RTE.
*
* p_varnosyn and p_varattnosyn are either identical to p_varno/p_varattno,
* or they specify the column's position in an aliased JOIN RTE that hides
* the semantic referent RTE's refname. (That could be either the JOIN RTE
* in which this ParseNamespaceColumn entry exists, or some lower join level.)
*
* If an RTE contains a dropped column, its ParseNamespaceColumn struct
* is all-zeroes. (Conventionally, test for p_varno == 0 to detect this.)
*/
struct ParseNamespaceColumn
{
Index p_varno; /* rangetable index */
AttrNumber p_varattno; /* attribute number of the column */
Oid p_vartype; /* pg_type OID */
int32 p_vartypmod; /* type modifier value */
Oid p_varcollid; /* OID of collation, or InvalidOid */
Index p_varnosyn; /* rangetable index of syntactic referent */
AttrNumber p_varattnosyn; /* attribute number of syntactic referent */
};
/* Support for parser_errposition_callback function */
typedef struct ParseCallbackState

View File

@@ -45,66 +45,70 @@ extern void markVarForSelectPriv(ParseState *pstate, Var *var,
RangeTblEntry *rte);
extern Relation parserOpenTable(ParseState *pstate, const RangeVar *relation,
int lockmode);
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
RangeVar *relation,
Alias *alias,
bool inh,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForRelation(ParseState *pstate,
Relation rel,
int lockmode,
Alias *alias,
bool inh,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery,
Alias *alias,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForFunction(ParseState *pstate,
List *funcnames,
List *funcexprs,
List *coldeflists,
RangeFunction *rangefunc,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
List *coltypes,
List *coltypmods,
List *colcollations,
Alias *alias,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForTableFunc(ParseState *pstate,
TableFunc *tf,
extern ParseNamespaceItem *addRangeTableEntry(ParseState *pstate,
RangeVar *relation,
Alias *alias,
bool inh,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForRelation(ParseState *pstate,
Relation rel,
int lockmode,
Alias *alias,
bool inh,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery,
Alias *alias,
bool lateral,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForFunction(ParseState *pstate,
List *funcnames,
List *funcexprs,
List *coldeflists,
RangeFunction *rangefunc,
bool lateral,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
List *coltypes,
List *coltypmods,
List *colcollations,
Alias *alias,
bool lateral,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForTableFunc(ParseState *pstate,
TableFunc *tf,
Alias *alias,
bool lateral,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForJoin(ParseState *pstate,
List *colnames,
ParseNamespaceColumn *nscolumns,
JoinType jointype,
List *aliasvars,
Alias *alias,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
List *colnames,
JoinType jointype,
List *aliasvars,
Alias *alias,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForCTE(ParseState *pstate,
CommonTableExpr *cte,
Index levelsup,
RangeVar *rv,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForENR(ParseState *pstate,
RangeVar *rv,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForCTE(ParseState *pstate,
CommonTableExpr *cte,
Index levelsup,
RangeVar *rv,
bool inFromCl);
extern ParseNamespaceItem *addRangeTableEntryForENR(ParseState *pstate,
RangeVar *rv,
bool inFromCl);
extern bool isLockedRefname(ParseState *pstate, const char *refname);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList,
bool addToRelNameSpace, bool addToVarNameSpace);
extern void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem,
bool addToJoinList,
bool addToRelNameSpace, bool addToVarNameSpace);
extern void errorMissingRTE(ParseState *pstate, RangeVar *relation) pg_attribute_noreturn();
extern void errorMissingColumn(ParseState *pstate,
const char *relname, const char *colname, int location) pg_attribute_noreturn();
extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
int location, bool include_dropped,
List **colnames, List **colvars);
extern List *expandNSItemVars(ParseNamespaceItem *nsitem,
int sublevels_up, int location,
List **colnames);
extern List *expandNSItemAttrs(ParseState *pstate, ParseNamespaceItem *nsitem,
int sublevels_up, int location);
extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK);

View File

@@ -38,15 +38,7 @@
extern char *get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum);
/*
* Given an RTE and an attribute number, return the appropriate
* type and typemod info for that attribute of that RTE.
*/
extern void get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
Oid *vartype, int32 *vartypmod, Oid *varcollid);
/*
* Check whether an attribute of an RTE has been dropped (note that
* get_rte_attribute_type will fail on such an attr)
* Check whether an attribute of an RTE has been dropped
*/
extern bool get_rte_attribute_is_dropped(RangeTblEntry *rte,
AttrNumber attnum);