1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-30 21:42:05 +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

@ -882,6 +882,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
if (stmt->relation)
{
LOCKMODE lockmode = is_from ? RowExclusiveLock : AccessShareLock;
ParseNamespaceItem *nsitem;
RangeTblEntry *rte;
TupleDesc tupDesc;
List *attnums;
@ -894,14 +895,15 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
relid = RelationGetRelid(rel);
rte = addRangeTableEntryForRelation(pstate, rel, lockmode,
NULL, false, false);
nsitem = addRangeTableEntryForRelation(pstate, rel, lockmode,
NULL, false, false);
rte = nsitem->p_rte;
rte->requiredPerms = (is_from ? ACL_INSERT : ACL_SELECT);
if (stmt->whereClause)
{
/* add rte to column namespace */
addRTEtoQuery(pstate, rte, false, true, true);
/* add nsitem to query namespace */
addNSItemToQuery(pstate, nsitem, false, true, true);
/* Transform the raw expression tree */
whereClause = transformExpr(pstate, stmt->whereClause, EXPR_KIND_COPY_WHERE);

View File

@ -568,9 +568,9 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
qual_expr = stringToNode(qual_value);
/* Add this rel to the parsestate's rangetable, for dependencies */
addRangeTableEntryForRelation(qual_pstate, rel,
AccessShareLock,
NULL, false, false);
(void) addRangeTableEntryForRelation(qual_pstate, rel,
AccessShareLock,
NULL, false, false);
qual_parse_rtable = qual_pstate->p_rtable;
free_parsestate(qual_pstate);
@ -592,9 +592,9 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
with_check_qual = stringToNode(with_check_value);
/* Add this rel to the parsestate's rangetable, for dependencies */
addRangeTableEntryForRelation(with_check_pstate, rel,
AccessShareLock,
NULL, false, false);
(void) addRangeTableEntryForRelation(with_check_pstate, rel,
AccessShareLock,
NULL, false, false);
with_check_parse_rtable = with_check_pstate->p_rtable;
free_parsestate(with_check_pstate);
@ -699,7 +699,7 @@ CreatePolicy(CreatePolicyStmt *stmt)
ArrayType *role_ids;
ParseState *qual_pstate;
ParseState *with_check_pstate;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
Node *qual;
Node *with_check_qual;
ScanKeyData skey[2];
@ -755,16 +755,16 @@ CreatePolicy(CreatePolicyStmt *stmt)
target_table = relation_open(table_id, NoLock);
/* Add for the regular security quals */
rte = addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
addRTEtoQuery(qual_pstate, rte, false, true, true);
nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
/* Add for the with-check quals */
rte = addRangeTableEntryForRelation(with_check_pstate, target_table,
AccessShareLock,
NULL, false, false);
addRTEtoQuery(with_check_pstate, rte, false, true, true);
nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
AccessShareLock,
NULL, false, false);
addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
qual = transformWhereClause(qual_pstate,
copyObject(stmt->qual),
@ -933,14 +933,14 @@ AlterPolicy(AlterPolicyStmt *stmt)
/* Parse the using policy clause */
if (stmt->qual)
{
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
ParseState *qual_pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
addRTEtoQuery(qual_pstate, rte, false, true, true);
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
qual = transformWhereClause(qual_pstate, copyObject(stmt->qual),
EXPR_KIND_POLICY,
@ -956,14 +956,14 @@ AlterPolicy(AlterPolicyStmt *stmt)
/* Parse the with-check policy clause */
if (stmt->with_check)
{
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
ParseState *with_check_pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(with_check_pstate, target_table,
AccessShareLock,
NULL, false, false);
nsitem = addRangeTableEntryForRelation(with_check_pstate, target_table,
AccessShareLock,
NULL, false, false);
addRTEtoQuery(with_check_pstate, rte, false, true, true);
addNSItemToQuery(with_check_pstate, nsitem, false, true, true);
with_check_qual = transformWhereClause(with_check_pstate,
copyObject(stmt->with_check),
@ -1107,9 +1107,9 @@ AlterPolicy(AlterPolicyStmt *stmt)
qual = stringToNode(qual_value);
/* Add this rel to the parsestate's rangetable, for dependencies */
addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
(void) addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
qual_parse_rtable = qual_pstate->p_rtable;
free_parsestate(qual_pstate);
@ -1149,9 +1149,10 @@ AlterPolicy(AlterPolicyStmt *stmt)
with_check_qual = stringToNode(with_check_value);
/* Add this rel to the parsestate's rangetable, for dependencies */
addRangeTableEntryForRelation(with_check_pstate, target_table,
AccessShareLock,
NULL, false, false);
(void) addRangeTableEntryForRelation(with_check_pstate,
target_table,
AccessShareLock,
NULL, false, false);
with_check_parse_rtable = with_check_pstate->p_rtable;
free_parsestate(with_check_pstate);

View File

@ -918,7 +918,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
defaultPartOid;
Relation parent,
defaultRel = NULL;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
/* Already have strong enough lock on the parent */
parent = table_open(parentId, NoLock);
@ -962,13 +962,14 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
pstate->p_sourcetext = queryString;
/*
* Add an RTE containing this relation, so that transformExpr called
* on partition bound expressions is able to report errors using a
* proper context.
* Add an nsitem containing this relation, so that transformExpr
* called on partition bound expressions is able to report errors
* using a proper context.
*/
rte = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
NULL, false, false);
addRTEtoQuery(pstate, rte, false, true, true);
nsitem = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
NULL, false, false);
addNSItemToQuery(pstate, nsitem, false, true, true);
bound = transformPartitionBound(pstate, parent, stmt->partbound);
/*
@ -14970,7 +14971,7 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
{
PartitionSpec *newspec;
ParseState *pstate;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
ListCell *l;
newspec = makeNode(PartitionSpec);
@ -15004,9 +15005,9 @@ transformPartitionSpec(Relation rel, PartitionSpec *partspec, char *strategy)
* rangetable entry. We need a ParseState for transformExpr.
*/
pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
NULL, false, true);
addRTEtoQuery(pstate, rte, true, true, true);
nsitem = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
NULL, false, true);
addNSItemToQuery(pstate, nsitem, true, true, true);
/* take care of any partition expressions */
foreach(l, partspec->partParams)

View File

@ -565,7 +565,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
if (!whenClause && stmt->whenClause)
{
ParseState *pstate;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
List *varList;
ListCell *lc;
@ -574,20 +574,20 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
pstate->p_sourcetext = queryString;
/*
* Set up RTEs for OLD and NEW references.
* Set up nsitems for OLD and NEW references.
*
* 'OLD' must always have varno equal to 1 and 'NEW' equal to 2.
*/
rte = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
addRTEtoQuery(pstate, rte, false, true, true);
rte = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("new", NIL),
false, false);
addRTEtoQuery(pstate, rte, false, true, true);
nsitem = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
addNSItemToQuery(pstate, nsitem, false, true, true);
nsitem = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("new", NIL),
false, false);
addNSItemToQuery(pstate, nsitem, false, true, true);
/* Transform expression. Copy to be sure we don't modify original */
whenClause = transformWhereClause(pstate,

View File

@ -341,6 +341,7 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
{
Relation viewRel;
List *new_rt;
ParseNamespaceItem *nsitem;
RangeTblEntry *rt_entry1,
*rt_entry2;
ParseState *pstate;
@ -365,14 +366,17 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
* Create the 2 new range table entries and form the new range table...
* OLD first, then NEW....
*/
rt_entry1 = addRangeTableEntryForRelation(pstate, viewRel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
rt_entry2 = addRangeTableEntryForRelation(pstate, viewRel,
AccessShareLock,
makeAlias("new", NIL),
false, false);
nsitem = addRangeTableEntryForRelation(pstate, viewRel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
rt_entry1 = nsitem->p_rte;
nsitem = addRangeTableEntryForRelation(pstate, viewRel,
AccessShareLock,
makeAlias("new", NIL),
false, false);
rt_entry2 = nsitem->p_rte;
/* Must override addRangeTableEntry's default access-check flags */
rt_entry1->requiredPerms = 0;
rt_entry2->requiredPerms = 0;