Commit 5815696b authored by Tom Lane's avatar Tom Lane

Make parser rely more heavily on the ParseNamespaceItem data structure.

When I added the ParseNamespaceItem data structure (in commit 5ebaaa49),
it wasn't very tightly integrated into the parser's APIs.  In the wake of
adding p_rtindex to that struct (commit b541e9ac), 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
parent 198c7153
......@@ -2531,7 +2531,7 @@ AddRelationNewConstraints(Relation rel,
TupleConstr *oldconstr;
int numoldchecks;
ParseState *pstate;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
int numchecks;
List *checknames;
ListCell *cell;
......@@ -2554,13 +2554,13 @@ AddRelationNewConstraints(Relation rel,
*/
pstate = make_parsestate(NULL);
pstate->p_sourcetext = queryString;
rte = addRangeTableEntryForRelation(pstate,
nsitem = addRangeTableEntryForRelation(pstate,
rel,
AccessShareLock,
NULL,
false,
true);
addRTEtoQuery(pstate, rte, true, true, true);
addNSItemToQuery(pstate, nsitem, true, true, true);
/*
* Process column default expressions.
......
......@@ -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,
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);
......
......@@ -568,7 +568,7 @@ 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,
(void) addRangeTableEntryForRelation(qual_pstate, rel,
AccessShareLock,
NULL, false, false);
......@@ -592,7 +592,7 @@ 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,
(void) addRangeTableEntryForRelation(with_check_pstate, rel,
AccessShareLock,
NULL, false, false);
......@@ -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,
nsitem = addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
addRTEtoQuery(qual_pstate, rte, false, true, true);
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
/* Add for the with-check quals */
rte = addRangeTableEntryForRelation(with_check_pstate, target_table,
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);
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,
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,
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,7 +1107,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
qual = stringToNode(qual_value);
/* Add this rel to the parsestate's rangetable, for dependencies */
addRangeTableEntryForRelation(qual_pstate, target_table,
(void) addRangeTableEntryForRelation(qual_pstate, target_table,
AccessShareLock,
NULL, false, false);
......@@ -1149,7 +1149,8 @@ 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,
(void) addRangeTableEntryForRelation(with_check_pstate,
target_table,
AccessShareLock,
NULL, false, false);
......
......@@ -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,
nsitem = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
NULL, false, false);
addRTEtoQuery(pstate, rte, false, true, true);
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,
nsitem = addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
NULL, false, true);
addRTEtoQuery(pstate, rte, true, true, true);
addNSItemToQuery(pstate, nsitem, true, true, true);
/* take care of any partition expressions */
foreach(l, partspec->partParams)
......
......@@ -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,
nsitem = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
addRTEtoQuery(pstate, rte, false, true, true);
rte = addRangeTableEntryForRelation(pstate, rel,
addNSItemToQuery(pstate, nsitem, false, true, true);
nsitem = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("new", NIL),
false, false);
addRTEtoQuery(pstate, rte, false, true, true);
addNSItemToQuery(pstate, nsitem, false, true, true);
/* Transform expression. Copy to be sure we don't modify original */
whenClause = transformWhereClause(pstate,
......
......@@ -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,
nsitem = addRangeTableEntryForRelation(pstate, viewRel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
rt_entry2 = addRangeTableEntryForRelation(pstate, viewRel,
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;
......
......@@ -1217,6 +1217,7 @@ convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
Query *subselect = (Query *) sublink->subselect;
Relids upper_varnos;
int rtindex;
ParseNamespaceItem *nsitem;
RangeTblEntry *rte;
RangeTblRef *rtr;
List *subquery_vars;
......@@ -1264,11 +1265,12 @@ convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink,
* below). Therefore this is a lot easier than what pull_up_subqueries has
* to go through.
*/
rte = addRangeTableEntryForSubquery(pstate,
nsitem = addRangeTableEntryForSubquery(pstate,
subselect,
makeAlias("ANY_subquery", NIL),
false,
false);
rte = nsitem->p_rte;
parse->rtable = lappend(parse->rtable, rte);
rtindex = list_length(parse->rtable);
......
This diff is collapsed.
This diff is collapsed.
......@@ -1010,11 +1010,10 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
int rtindex = ((Var *) node)->varno;
int sublevels_up = ((Var *) node)->varlevelsup;
int vlocation = ((Var *) node)->location;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
rte = GetRTEByRangeTablePosn(pstate, rtindex, sublevels_up);
expandRTE(rte, rtindex, sublevels_up, vlocation, false,
NULL, &args);
nsitem = GetNSItemByRangeTablePosn(pstate, rtindex, sublevels_up);
args = expandNSItemVars(nsitem, sublevels_up, vlocation, NULL);
}
else
ereport(ERROR,
......
......@@ -2656,8 +2656,8 @@ static Node *
transformCurrentOfExpr(ParseState *pstate, CurrentOfExpr *cexpr)
{
/* CURRENT OF can only appear at top level of UPDATE/DELETE */
Assert(pstate->p_target_rtindex > 0);
cexpr->cvarno = pstate->p_target_rtindex;
Assert(pstate->p_target_nsitem != NULL);
cexpr->cvarno = pstate->p_target_nsitem->p_rtindex;
/*
* Check to see if the cursor name matches a parameter of type REFCURSOR.
......
This diff is collapsed.
......@@ -551,7 +551,7 @@ transformAssignedExpr(ParseState *pstate,
*/
Var *var;
var = makeVar(pstate->p_target_rtindex, attrno,
var = makeVar(pstate->p_target_nsitem->p_rtindex, attrno,
attrtype, attrtypmod, attrcollation, 0);
var->location = location;
......@@ -1359,8 +1359,7 @@ ExpandSingleTable(ParseState *pstate, ParseNamespaceItem *nsitem,
List *vars;
ListCell *l;
expandRTE(rte, nsitem->p_rtindex, sublevels_up, location, false,
NULL, &vars);
vars = expandNSItemVars(nsitem, sublevels_up, location, NULL);
/*
* Require read access to the table. This is normally redundant with
......@@ -1496,6 +1495,12 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
Assert(IsA(var, Var));
Assert(var->vartype == RECORDOID);
/*
* Note: it's tempting to use GetNSItemByRangeTablePosn here so that we
* can use expandNSItemVars instead of expandRTE; but that does not work
* for some of the recursion cases below, where we have consed up a
* ParseState that lacks p_namespace data.
*/
netlevelsup = var->varlevelsup + levelsup;
rte = GetRTEByRangeTablePosn(pstate, var->varno, netlevelsup);
attnum = var->varattno;
......
......@@ -2598,7 +2598,7 @@ IndexStmt *
transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
{
ParseState *pstate;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
ListCell *l;
Relation rel;
......@@ -2622,12 +2622,12 @@ transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
* relation, but we still need to open it.
*/
rel = relation_open(relid, NoLock);
rte = addRangeTableEntryForRelation(pstate, rel,
nsitem = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
NULL, false, true);
/* no to join list, yes to namespaces */
addRTEtoQuery(pstate, rte, false, true, true);
addNSItemToQuery(pstate, nsitem, false, true, true);
/* take care of the where clause */
if (stmt->whereClause)
......@@ -2707,8 +2707,8 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
{
Relation rel;
ParseState *pstate;
RangeTblEntry *oldrte;
RangeTblEntry *newrte;
ParseNamespaceItem *oldnsitem;
ParseNamespaceItem *newnsitem;
/*
* To avoid deadlock, make sure the first thing we do is grab
......@@ -2729,20 +2729,20 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
/*
* NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to 2.
* Set up their RTEs in the main pstate for use in parsing the rule
* qualification.
* Set up their ParseNamespaceItems in the main pstate for use in parsing
* the rule qualification.
*/
oldrte = addRangeTableEntryForRelation(pstate, rel,
oldnsitem = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
newrte = addRangeTableEntryForRelation(pstate, rel,
newnsitem = addRangeTableEntryForRelation(pstate, rel,
AccessShareLock,
makeAlias("new", NIL),
false, false);
/* Must override addRangeTableEntry's default access-check flags */
oldrte->requiredPerms = 0;
newrte->requiredPerms = 0;
oldnsitem->p_rte->requiredPerms = 0;
newnsitem->p_rte->requiredPerms = 0;
/*
* They must be in the namespace too for lookup purposes, but only add the
......@@ -2754,17 +2754,17 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
switch (stmt->event)
{
case CMD_SELECT:
addRTEtoQuery(pstate, oldrte, false, true, true);
addNSItemToQuery(pstate, oldnsitem, false, true, true);
break;
case CMD_UPDATE:
addRTEtoQuery(pstate, oldrte, false, true, true);
addRTEtoQuery(pstate, newrte, false, true, true);
addNSItemToQuery(pstate, oldnsitem, false, true, true);
addNSItemToQuery(pstate, newnsitem, false, true, true);
break;
case CMD_INSERT:
addRTEtoQuery(pstate, newrte, false, true, true);
addNSItemToQuery(pstate, newnsitem, false, true, true);
break;
case CMD_DELETE:
addRTEtoQuery(pstate, oldrte, false, true, true);
addNSItemToQuery(pstate, oldnsitem, false, true, true);
break;
default:
elog(ERROR, "unrecognized event type: %d",
......@@ -2832,18 +2832,18 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
* nor "*" in the rule actions. We decide later whether to put
* them in the joinlist.
*/
oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
oldnsitem = addRangeTableEntryForRelation(sub_pstate, rel,
AccessShareLock,
makeAlias("old", NIL),
false, false);
newrte = addRangeTableEntryForRelation(sub_pstate, rel,
newnsitem = addRangeTableEntryForRelation(sub_pstate, rel,
AccessShareLock,
makeAlias("new", NIL),
false, false);
oldrte->requiredPerms = 0;
newrte->requiredPerms = 0;
addRTEtoQuery(sub_pstate, oldrte, false, true, false);
addRTEtoQuery(sub_pstate, newrte, false, true, false);
oldnsitem->p_rte->requiredPerms = 0;
newnsitem->p_rte->requiredPerms = 0;
addNSItemToQuery(sub_pstate, oldnsitem, false, true, false);
addNSItemToQuery(sub_pstate, newnsitem, false, true, false);
/* Transform the rule action statement */
top_subqry = transformStmt(sub_pstate,
......@@ -2967,6 +2967,8 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
*/
if (has_old || (has_new && stmt->event == CMD_UPDATE))
{
RangeTblRef *rtr;
/*
* If sub_qry is a setop, manipulating its jointree will do no
* good at all, because the jointree is dummy. (This should be
......@@ -2976,11 +2978,11 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
/* hack so we can use addRTEtoQuery() */
sub_pstate->p_rtable = sub_qry->rtable;
sub_pstate->p_joinlist = sub_qry->jointree->fromlist;
addRTEtoQuery(sub_pstate, oldrte, true, false, false);
sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
/* hackishly add OLD to the already-built FROM clause */
rtr = makeNode(RangeTblRef);
rtr->rtindex = oldnsitem->p_rtindex;
sub_qry->jointree->fromlist =
lappend(sub_qry->jointree->fromlist, rtr);
}
newactions = lappend(newactions, top_subqry);
......@@ -3025,7 +3027,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
List *newcmds = NIL;
bool skipValidation = true;
AlterTableCmd *newcmd;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
/*
* We must not scribble on the passed-in AlterTableStmt, so copy it. (This
......@@ -3040,13 +3042,13 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
/* Set up pstate */
pstate = make_parsestate(NULL);
pstate->p_sourcetext = queryString;
rte = addRangeTableEntryForRelation(pstate,
nsitem = addRangeTableEntryForRelation(pstate,
rel,
AccessShareLock,
NULL,
false,
true);
addRTEtoQuery(pstate, rte, false, true, true);
addNSItemToQuery(pstate, nsitem, false, true, true);
/* Set up CreateStmtContext */
cxt.pstate = pstate;
......
......@@ -777,7 +777,7 @@ copy_table(Relation rel)
copybuf = makeStringInfo();
pstate = make_parsestate(NULL);
addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
(void) addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
NULL, false, false);
attnamelist = make_copy_attnamelist(relmapentry);
......
......@@ -3227,6 +3227,7 @@ rewriteTargetView(Query *parsetree, Relation view)
{
Index old_exclRelIndex,
new_exclRelIndex;
ParseNamespaceItem *new_exclNSItem;
RangeTblEntry *new_exclRte;
List *tmp_tlist;
......@@ -3261,11 +3262,12 @@ rewriteTargetView(Query *parsetree, Relation view)
*/
old_exclRelIndex = parsetree->onConflict->exclRelIndex;
new_exclRte = addRangeTableEntryForRelation(make_parsestate(NULL),
new_exclNSItem = addRangeTableEntryForRelation(make_parsestate(NULL),
base_rel,
RowExclusiveLock,
makeAlias("excluded", NIL),
false, false);
new_exclRte = new_exclNSItem->p_rte;
new_exclRte->relkind = RELKIND_COMPOSITE_TYPE;
new_exclRte->requiredPerms = 0;
/* other permissions fields in new_exclRte are already empty */
......
......@@ -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
......
......@@ -45,30 +45,30 @@ extern void markVarForSelectPriv(ParseState *pstate, Var *var,
RangeTblEntry *rte);
extern Relation parserOpenTable(ParseState *pstate, const RangeVar *relation,
int lockmode);
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntry(ParseState *pstate,
RangeVar *relation,
Alias *alias,
bool inh,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForRelation(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForRelation(ParseState *pstate,
Relation rel,
int lockmode,
Alias *alias,
bool inh,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery,
Alias *alias,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForFunction(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForFunction(ParseState *pstate,
List *funcnames,
List *funcexprs,
List *coldeflists,
RangeFunction *rangefunc,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForValues(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
List *coltypes,
List *coltypmods,
......@@ -76,27 +76,28 @@ extern RangeTblEntry *addRangeTableEntryForValues(ParseState *pstate,
Alias *alias,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForTableFunc(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForTableFunc(ParseState *pstate,
TableFunc *tf,
Alias *alias,
bool lateral,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForJoin(ParseState *pstate,
List *colnames,
ParseNamespaceColumn *nscolumns,
JoinType jointype,
List *aliasvars,
Alias *alias,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForCTE(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForCTE(ParseState *pstate,
CommonTableExpr *cte,
Index levelsup,
RangeVar *rv,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForENR(ParseState *pstate,
extern ParseNamespaceItem *addRangeTableEntryForENR(ParseState *pstate,
RangeVar *rv,
bool inFromCl);
extern bool isLockedRefname(ParseState *pstate, const char *refname);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
extern void addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem,
bool addToJoinList,
bool addToRelNameSpace, bool addToVarNameSpace);
extern void errorMissingRTE(ParseState *pstate, RangeVar *relation) pg_attribute_noreturn();
......@@ -105,6 +106,9 @@ extern void errorMissingColumn(ParseState *pstate,
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);
......
......@@ -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);
......
......@@ -70,7 +70,7 @@ test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
Node *e;
ColumnRef *c;
ParseState *qual_pstate;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
if (strcmp(RelationGetRelationName(relation), "rls_test_permissive") != 0 &&
strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
......@@ -78,9 +78,10 @@ test_rls_hooks_permissive(CmdType cmdtype, Relation relation)
qual_pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(qual_pstate, relation, AccessShareLock,
nsitem = addRangeTableEntryForRelation(qual_pstate,
relation, AccessShareLock,
NULL, false, false);
addRTEtoQuery(qual_pstate, rte, false, true, true);
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
role = ObjectIdGetDatum(ACL_ID_PUBLIC);
......@@ -134,8 +135,7 @@ test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
Node *e;
ColumnRef *c;
ParseState *qual_pstate;
RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
if (strcmp(RelationGetRelationName(relation), "rls_test_restrictive") != 0 &&
strcmp(RelationGetRelationName(relation), "rls_test_both") != 0)
......@@ -143,9 +143,10 @@ test_rls_hooks_restrictive(CmdType cmdtype, Relation relation)
qual_pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(qual_pstate, relation, AccessShareLock,
nsitem = addRangeTableEntryForRelation(qual_pstate,
relation, AccessShareLock,
NULL, false, false);
addRTEtoQuery(qual_pstate, rte, false, true, true);
addNSItemToQuery(qual_pstate, nsitem, false, true, true);
role = ObjectIdGetDatum(ACL_ID_PUBLIC);
......
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