TupleConstr *oldconstr;
int numoldchecks;
ParseState *pstate;
- RangeTblEntry *rte;
+ ParseNamespaceItem *nsitem;
int numchecks;
List *checknames;
ListCell *cell;
*/
pstate = make_parsestate(NULL);
pstate->p_sourcetext = queryString;
- 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);
/*
* Process column default expressions.
if (stmt->relation)
{
LOCKMODE lockmode = is_from ? RowExclusiveLock : AccessShareLock;
+ ParseNamespaceItem *nsitem;
RangeTblEntry *rte;
TupleDesc tupDesc;
List *attnums;
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);
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);
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);
ArrayType *role_ids;
ParseState *qual_pstate;
ParseState *with_check_pstate;
- RangeTblEntry *rte;
+ ParseNamespaceItem *nsitem;
Node *qual;
Node *with_check_qual;
ScanKeyData skey[2];
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),
/* 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,
/* 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),
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);
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);
defaultPartOid;
Relation parent,
defaultRel = NULL;
- RangeTblEntry *rte;
+ ParseNamespaceItem *nsitem;
/* Already have strong enough lock on the parent */
parent = table_open(parentId, NoLock);
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);
/*
{
PartitionSpec *newspec;
ParseState *pstate;
- RangeTblEntry *rte;
+ ParseNamespaceItem *nsitem;
ListCell *l;
newspec = makeNode(PartitionSpec);
* 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)
if (!whenClause && stmt->whenClause)
{
ParseState *pstate;
- RangeTblEntry *rte;
+ ParseNamespaceItem *nsitem;
List *varList;
ListCell *lc;
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,
{
Relation viewRel;
List *new_rt;
+ ParseNamespaceItem *nsitem;
RangeTblEntry *rt_entry1,
*rt_entry2;
ParseState *pstate;
* 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;
Query *subselect = (Query *) sublink->subselect;
Relids upper_varnos;
int rtindex;
+ ParseNamespaceItem *nsitem;
RangeTblEntry *rte;
RangeTblRef *rtr;
List *subquery_vars;
* below). Therefore this is a lot easier than what pull_up_subqueries has
* to go through.
*/
- rte = addRangeTableEntryForSubquery(pstate,
- subselect,
- makeAlias("ANY_subquery", NIL),
- false,
- false);
+ 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);
stmt->relation->inh,
true,
ACL_DELETE);
-
- /* grab the namespace item made by setTargetTable */
- nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
+ nsitem = pstate->p_target_nsitem;
/* there's no DISTINCT in DELETE */
qry->distinctClause = NIL;
List *sub_namespace;
List *icolumns;
List *attrnos;
+ ParseNamespaceItem *nsitem;
RangeTblEntry *rte;
- RangeTblRef *rtr;
ListCell *icols;
ListCell *attnos;
ListCell *lc;
/*
* Make the source be a subquery in the INSERT's rangetable, and add
- * it to the INSERT's joinlist.
+ * it to the INSERT's joinlist (but not the namespace).
*/
- rte = addRangeTableEntryForSubquery(pstate,
- selectQuery,
- makeAlias("*SELECT*", NIL),
- false,
- false);
- rtr = makeNode(RangeTblRef);
- /* assume new rte is at end */
- rtr->rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
- pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
+ nsitem = addRangeTableEntryForSubquery(pstate,
+ selectQuery,
+ makeAlias("*SELECT*", NIL),
+ false,
+ false);
+ addNSItemToQuery(pstate, nsitem, true, false, false);
/*----------
* Generate an expression list for the INSERT that selects all the
expr = tle->expr;
else
{
- Var *var = makeVarFromTargetEntry(rtr->rtindex, tle);
+ Var *var = makeVarFromTargetEntry(nsitem->p_rtindex, tle);
var->location = exprLocation((Node *) tle->expr);
expr = (Expr *) var;
/*
* Generate the VALUES RTE
*/
- rte = addRangeTableEntryForValues(pstate, exprsLists,
- coltypes, coltypmods, colcollations,
- NULL, lateral, true);
- rtr = makeNode(RangeTblRef);
- /* assume new rte is at end */
- rtr->rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
- pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
+ nsitem = addRangeTableEntryForValues(pstate, exprsLists,
+ coltypes, coltypmods, colcollations,
+ NULL, lateral, true);
+ addNSItemToQuery(pstate, nsitem, true, false, false);
/*
* Generate list of Vars referencing the RTE
*/
- expandRTE(rte, rtr->rtindex, 0, -1, false, NULL, &exprList);
+ exprList = expandNSItemVars(nsitem, 0, -1, NULL);
/*
* Re-apply any indirection on the target column specs to the Vars
* Generate query's target list using the computed list of expressions.
* Also, mark all the target columns as needing insert permissions.
*/
- rte = pstate->p_target_rangetblentry;
+ rte = pstate->p_target_nsitem->p_rte;
qry->targetList = NIL;
Assert(list_length(exprList) <= list_length(icolumns));
forthree(lc, exprList, icols, icolumns, attnos, attrnos)
if (stmt->returningList)
{
pstate->p_namespace = NIL;
- addRTEtoQuery(pstate, pstate->p_target_rangetblentry,
- false, true, true);
+ addNSItemToQuery(pstate, pstate->p_target_nsitem,
+ false, true, true);
qry->returningList = transformReturningList(pstate,
stmt->returningList);
}
Oid arbiterConstraint;
List *onConflictSet = NIL;
Node *onConflictWhere = NULL;
- RangeTblEntry *exclRte = NULL;
int exclRelIndex = 0;
List *exclRelTlist = NIL;
OnConflictExpr *result;
if (onConflictClause->action == ONCONFLICT_UPDATE)
{
Relation targetrel = pstate->p_target_relation;
+ ParseNamespaceItem *exclNSItem;
+ RangeTblEntry *exclRte;
/*
* All INSERT expressions have been parsed, get ready for potentially
* relation, and no permission checks are required on it. (We'll
* check the actual target relation, instead.)
*/
- exclRte = addRangeTableEntryForRelation(pstate,
- targetrel,
- RowExclusiveLock,
- makeAlias("excluded", NIL),
- false, false);
+ exclNSItem = addRangeTableEntryForRelation(pstate,
+ targetrel,
+ RowExclusiveLock,
+ makeAlias("excluded", NIL),
+ false, false);
+ exclRte = exclNSItem->p_rte;
+ exclRelIndex = exclNSItem->p_rtindex;
+
exclRte->relkind = RELKIND_COMPOSITE_TYPE;
exclRte->requiredPerms = 0;
/* other permissions fields in exclRte are already empty */
- exclRelIndex = list_length(pstate->p_rtable);
-
/* Create EXCLUDED rel's targetlist for use by EXPLAIN */
exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
exclRelIndex);
* Add EXCLUDED and the target RTE to the namespace, so that they can
* be used in the UPDATE subexpressions.
*/
- addRTEtoQuery(pstate, exclRte, false, true, true);
- addRTEtoQuery(pstate, pstate->p_target_rangetblentry,
- false, true, true);
+ addNSItemToQuery(pstate, exclNSItem, false, true, true);
+ addNSItemToQuery(pstate, pstate->p_target_nsitem,
+ false, true, true);
/*
* Now transform the UPDATE subexpressions.
List **colexprs = NULL;
int sublist_length = -1;
bool lateral = false;
- RangeTblEntry *rte;
ParseNamespaceItem *nsitem;
ListCell *lc;
ListCell *lc2;
/*
* Generate the VALUES RTE
*/
- rte = addRangeTableEntryForValues(pstate, exprsLists,
- coltypes, coltypmods, colcollations,
- NULL, lateral, true);
- addRTEtoQuery(pstate, rte, true, true, true);
-
- /* grab the namespace item made by addRTEtoQuery */
- nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
- Assert(rte == nsitem->p_rte);
+ nsitem = addRangeTableEntryForValues(pstate, exprsLists,
+ coltypes, coltypmods, colcollations,
+ NULL, lateral, true);
+ addNSItemToQuery(pstate, nsitem, true, true, true);
/*
* Generate a targetlist as though expanding "*"
*targetnames,
*sv_namespace;
int sv_rtable_length;
- RangeTblEntry *jrte;
+ ParseNamespaceItem *jnsitem;
+ ParseNamespaceColumn *sortnscolumns;
+ int sortcolindex;
int tllen;
qry->commandType = CMD_SELECT;
qry->targetList = NIL;
targetvars = NIL;
targetnames = NIL;
+ sortnscolumns = (ParseNamespaceColumn *)
+ palloc0(list_length(sostmt->colTypes) * sizeof(ParseNamespaceColumn));
+ sortcolindex = 0;
forfour(lct, sostmt->colTypes,
lcm, sostmt->colTypmods,
qry->targetList = lappend(qry->targetList, tle);
targetvars = lappend(targetvars, var);
targetnames = lappend(targetnames, makeString(colName));
+ sortnscolumns[sortcolindex].p_varno = leftmostRTI;
+ sortnscolumns[sortcolindex].p_varattno = lefttle->resno;
+ sortnscolumns[sortcolindex].p_vartype = colType;
+ sortnscolumns[sortcolindex].p_vartypmod = colTypmod;
+ sortnscolumns[sortcolindex].p_varcollid = colCollation;
+ sortnscolumns[sortcolindex].p_varnosyn = leftmostRTI;
+ sortnscolumns[sortcolindex].p_varattnosyn = lefttle->resno;
+ sortcolindex++;
}
/*
*/
sv_rtable_length = list_length(pstate->p_rtable);
- jrte = addRangeTableEntryForJoin(pstate,
- targetnames,
- JOIN_INNER,
- targetvars,
- NULL,
- false);
+ jnsitem = addRangeTableEntryForJoin(pstate,
+ targetnames,
+ sortnscolumns,
+ JOIN_INNER,
+ targetvars,
+ NULL,
+ false);
sv_namespace = pstate->p_namespace;
pstate->p_namespace = NIL;
- /* add jrte to column namespace only */
- addRTEtoQuery(pstate, jrte, false, false, true);
+ /* add jnsitem to column namespace only */
+ addNSItemToQuery(pstate, jnsitem, false, false, true);
/*
* For now, we don't support resjunk sort clauses on the output of a
EXPR_KIND_ORDER_BY,
false /* allow SQL92 rules */ );
- /* restore namespace, remove jrte from rtable */
+ /* restore namespace, remove join RTE from rtable */
pstate->p_namespace = sv_namespace;
pstate->p_rtable = list_truncate(pstate->p_rtable, sv_rtable_length);
/* Process leaf SELECT */
Query *selectQuery;
char selectName[32];
- RangeTblEntry *rte PG_USED_FOR_ASSERTS_ONLY;
+ ParseNamespaceItem *nsitem;
RangeTblRef *rtr;
ListCell *tl;
*/
snprintf(selectName, sizeof(selectName), "*SELECT* %d",
list_length(pstate->p_rtable) + 1);
- rte = addRangeTableEntryForSubquery(pstate,
- selectQuery,
- makeAlias(selectName, NIL),
- false,
- false);
+ nsitem = addRangeTableEntryForSubquery(pstate,
+ selectQuery,
+ makeAlias(selectName, NIL),
+ false,
+ false);
/*
* Return a RangeTblRef to replace the SelectStmt in the set-op tree.
*/
rtr = makeNode(RangeTblRef);
- /* assume new rte is at end */
- rtr->rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtr->rtindex, pstate->p_rtable));
+ rtr->rtindex = nsitem->p_rtindex;
return (Node *) rtr;
}
else
stmt->relation->inh,
true,
ACL_UPDATE);
-
- /* grab the namespace item made by setTargetTable */
- nsitem = (ParseNamespaceItem *) llast(pstate->p_namespace);
+ nsitem = pstate->p_target_nsitem;
/* subqueries in FROM cannot access the result relation */
nsitem->p_lateral_only = true;
pstate->p_next_resno = RelationGetNumberOfAttributes(pstate->p_target_relation) + 1;
/* Prepare non-junk columns for assignment to target table */
- target_rte = pstate->p_target_rangetblentry;
+ target_rte = pstate->p_target_nsitem->p_rte;
orig_tl = list_head(origTlist);
foreach(tl, tlist)
#include "utils/rel.h"
#include "utils/syscache.h"
-/* Convenience macro for the most common makeNamespaceItem() case */
-#define makeDefaultNSItem(rte, rti) \
- makeNamespaceItem(rte, rti, true, true, false, true)
static void extractRemainingColumns(List *common_colnames,
List *src_colnames, List *src_colvars,
- List **res_colnames, List **res_colvars);
+ ParseNamespaceColumn *src_nscolumns,
+ List **res_colnames, List **res_colvars,
+ ParseNamespaceColumn *res_nscolumns);
static Node *transformJoinUsingClause(ParseState *pstate,
RangeTblEntry *leftRTE, RangeTblEntry *rightRTE,
List *leftVars, List *rightVars);
static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j,
List *namespace);
-static RangeTblEntry *getRTEForSpecialRelationTypes(ParseState *pstate,
- RangeVar *rv);
-static RangeTblEntry *transformTableEntry(ParseState *pstate, RangeVar *r);
-static RangeTblEntry *transformRangeSubselect(ParseState *pstate,
- RangeSubselect *r);
-static RangeTblEntry *transformRangeFunction(ParseState *pstate,
- RangeFunction *r);
-static RangeTblEntry *transformRangeTableFunc(ParseState *pstate,
- RangeTableFunc *t);
+static ParseNamespaceItem *transformTableEntry(ParseState *pstate, RangeVar *r);
+static ParseNamespaceItem *transformRangeSubselect(ParseState *pstate,
+ RangeSubselect *r);
+static ParseNamespaceItem *transformRangeFunction(ParseState *pstate,
+ RangeFunction *r);
+static ParseNamespaceItem *transformRangeTableFunc(ParseState *pstate,
+ RangeTableFunc *t);
static TableSampleClause *transformRangeTableSample(ParseState *pstate,
RangeTableSample *rts);
+static ParseNamespaceItem *getNSItemForSpecialRelationTypes(ParseState *pstate,
+ RangeVar *rv);
static Node *transformFromClauseItem(ParseState *pstate, Node *n,
- RangeTblEntry **top_rte, int *top_rti,
+ ParseNamespaceItem **top_nsitem,
List **namespace);
static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
Var *l_colvar, Var *r_colvar);
-static ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte, int rtindex,
- bool rel_visible, bool cols_visible,
- bool lateral_only, bool lateral_ok);
static void setNamespaceColumnVisibility(List *namespace, bool cols_visible);
static void setNamespaceLateralState(List *namespace,
bool lateral_only, bool lateral_ok);
foreach(fl, frmList)
{
Node *n = lfirst(fl);
- RangeTblEntry *rte;
- int rtindex;
+ ParseNamespaceItem *nsitem;
List *namespace;
n = transformFromClauseItem(pstate, n,
- &rte,
- &rtindex,
+ &nsitem,
&namespace);
checkNameSpaceConflicts(pstate, pstate->p_namespace, namespace);
setTargetTable(ParseState *pstate, RangeVar *relation,
bool inh, bool alsoSource, AclMode requiredPerms)
{
- RangeTblEntry *rte;
- int rtindex;
+ ParseNamespaceItem *nsitem;
/*
* ENRs hide tables of the same name, so we need to check for them first.
RowExclusiveLock);
/*
- * Now build an RTE.
+ * Now build an RTE and a ParseNamespaceItem.
*/
- rte = addRangeTableEntryForRelation(pstate, pstate->p_target_relation,
- RowExclusiveLock,
- relation->alias, inh, false);
+ nsitem = addRangeTableEntryForRelation(pstate, pstate->p_target_relation,
+ RowExclusiveLock,
+ relation->alias, inh, false);
- /* assume new rte is at end */
- rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
-
- /* remember the RTE as being the query target */
- pstate->p_target_rangetblentry = rte;
- pstate->p_target_rtindex = rtindex;
+ /* remember the RTE/nsitem as being the query target */
+ pstate->p_target_nsitem = nsitem;
/*
* Override addRangeTableEntry's default ACL_SELECT permissions check, and
* analysis, we will add the ACL_SELECT bit back again; see
* markVarForSelectPriv and its callers.
*/
- rte->requiredPerms = requiredPerms;
+ nsitem->p_rte->requiredPerms = requiredPerms;
/*
* If UPDATE/DELETE, add table to joinlist and namespace.
- *
- * Note: some callers know that they can find the new ParseNamespaceItem
- * at the end of the pstate->p_namespace list. This is a bit ugly but not
- * worth complicating this function's signature for.
*/
if (alsoSource)
- addRTEtoQuery(pstate, rte, true, true, true);
+ addNSItemToQuery(pstate, nsitem, true, true, true);
- return rtindex;
+ return nsitem->p_rtindex;
}
/*
* Extract all not-in-common columns from column lists of a source table
+ *
+ * We hand back new lists in *res_colnames and *res_colvars. But
+ * res_nscolumns points to a caller-allocated array that we fill in
+ * the next few entries in.
*/
static void
extractRemainingColumns(List *common_colnames,
List *src_colnames, List *src_colvars,
- List **res_colnames, List **res_colvars)
+ ParseNamespaceColumn *src_nscolumns,
+ List **res_colnames, List **res_colvars,
+ ParseNamespaceColumn *res_nscolumns)
{
List *new_colnames = NIL;
List *new_colvars = NIL;
bool match = false;
ListCell *cnames;
+ /*
+ * Ignore any dropped columns in the src_nscolumns input. (The list
+ * inputs won't contain entries for dropped columns.)
+ */
+ while (src_nscolumns->p_varno == 0)
+ src_nscolumns++;
+
+ /* is current src column already accounted for in common_colnames? */
foreach(cnames, common_colnames)
{
char *ccolname = strVal(lfirst(cnames));
if (!match)
{
+ /* Nope, so emit it as next output column */
new_colnames = lappend(new_colnames, lfirst(lnames));
new_colvars = lappend(new_colvars, lfirst(lvars));
+ /* Copy the input relation's nscolumn data for this column */
+ *res_nscolumns = *src_nscolumns;
+ res_nscolumns++;
}
+
+ src_nscolumns++;
}
*res_colnames = new_colnames;
/*
* transformTableEntry --- transform a RangeVar (simple relation reference)
*/
-static RangeTblEntry *
+static ParseNamespaceItem *
transformTableEntry(ParseState *pstate, RangeVar *r)
{
- RangeTblEntry *rte;
-
- /* We need only build a range table entry */
- rte = addRangeTableEntry(pstate, r, r->alias, r->inh, true);
-
- return rte;
+ /* addRangeTableEntry does all the work */
+ return addRangeTableEntry(pstate, r, r->alias, r->inh, true);
}
/*
* transformRangeSubselect --- transform a sub-SELECT appearing in FROM
*/
-static RangeTblEntry *
+static ParseNamespaceItem *
transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
{
Query *query;
- RangeTblEntry *rte;
/*
* We require user to supply an alias for a subselect, per SQL92. To relax
elog(ERROR, "unexpected non-SELECT command in subquery in FROM");
/*
- * OK, build an RTE for the subquery.
+ * OK, build an RTE and nsitem for the subquery.
*/
- rte = addRangeTableEntryForSubquery(pstate,
- query,
- r->alias,
- r->lateral,
- true);
-
- return rte;
+ return addRangeTableEntryForSubquery(pstate,
+ query,
+ r->alias,
+ r->lateral,
+ true);
}
/*
* transformRangeFunction --- transform a function call appearing in FROM
*/
-static RangeTblEntry *
+static ParseNamespaceItem *
transformRangeFunction(ParseState *pstate, RangeFunction *r)
{
List *funcexprs = NIL;
List *funcnames = NIL;
List *coldeflists = NIL;
bool is_lateral;
- RangeTblEntry *rte;
ListCell *lc;
/*
is_lateral = r->lateral || contain_vars_of_level((Node *) funcexprs, 0);
/*
- * OK, build an RTE for the function.
+ * OK, build an RTE and nsitem for the function.
*/
- rte = addRangeTableEntryForFunction(pstate,
- funcnames, funcexprs, coldeflists,
- r, is_lateral, true);
-
- return rte;
+ return addRangeTableEntryForFunction(pstate,
+ funcnames, funcexprs, coldeflists,
+ r, is_lateral, true);
}
/*
* row-generating expression, the column-generating expressions, and the
* default value expressions.
*/
-static RangeTblEntry *
+static ParseNamespaceItem *
transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
{
TableFunc *tf = makeNode(TableFunc);
const char *constructName;
Oid docType;
- RangeTblEntry *rte;
bool is_lateral;
ListCell *col;
char **names;
*/
is_lateral = rtf->lateral || contain_vars_of_level((Node *) tf, 0);
- rte = addRangeTableEntryForTableFunc(pstate,
- tf, rtf->alias, is_lateral, true);
-
- return rte;
+ return addRangeTableEntryForTableFunc(pstate,
+ tf, rtf->alias, is_lateral, true);
}
/*
}
/*
- * getRTEForSpecialRelationTypes
+ * getNSItemForSpecialRelationTypes
*
* If given RangeVar refers to a CTE or an EphemeralNamedRelation,
- * build and return an appropriate RTE, otherwise return NULL
+ * build and return an appropriate ParseNamespaceItem, otherwise return NULL
*/
-static RangeTblEntry *
-getRTEForSpecialRelationTypes(ParseState *pstate, RangeVar *rv)
+static ParseNamespaceItem *
+getNSItemForSpecialRelationTypes(ParseState *pstate, RangeVar *rv)
{
+ ParseNamespaceItem *nsitem;
CommonTableExpr *cte;
Index levelsup;
- RangeTblEntry *rte;
/*
* if it is a qualified name, it can't be a CTE or tuplestore reference
cte = scanNameSpaceForCTE(pstate, rv->relname, &levelsup);
if (cte)
- rte = addRangeTableEntryForCTE(pstate, cte, levelsup, rv, true);
+ nsitem = addRangeTableEntryForCTE(pstate, cte, levelsup, rv, true);
else if (scanNameSpaceForENR(pstate, rv->relname))
- rte = addRangeTableEntryForENR(pstate, rv, true);
+ nsitem = addRangeTableEntryForENR(pstate, rv, true);
else
- rte = NULL;
+ nsitem = NULL;
- return rte;
+ return nsitem;
}
/*
* The function return value is the node to add to the jointree (a
* RangeTblRef or JoinExpr). Additional output parameters are:
*
- * *top_rte: receives the RTE corresponding to the jointree item.
- * (We could extract this from the function return node, but it saves cycles
- * to pass it back separately.)
- *
- * *top_rti: receives the rangetable index of top_rte. (Ditto.)
+ * *top_nsitem: receives the ParseNamespaceItem directly corresponding to the
+ * jointree item. (This is only used during internal recursion, not by
+ * outside callers.)
*
* *namespace: receives a List of ParseNamespaceItems for the RTEs exposed
* as table/column names by this item. (The lateral_only flags in these items
*/
static Node *
transformFromClauseItem(ParseState *pstate, Node *n,
- RangeTblEntry **top_rte, int *top_rti,
+ ParseNamespaceItem **top_nsitem,
List **namespace)
{
if (IsA(n, RangeVar))
/* Plain relation reference, or perhaps a CTE reference */
RangeVar *rv = (RangeVar *) n;
RangeTblRef *rtr;
- RangeTblEntry *rte;
- int rtindex;
+ ParseNamespaceItem *nsitem;
/* Check if it's a CTE or tuplestore reference */
- rte = getRTEForSpecialRelationTypes(pstate, rv);
+ nsitem = getNSItemForSpecialRelationTypes(pstate, rv);
/* if not found above, must be a table reference */
- if (!rte)
- rte = transformTableEntry(pstate, rv);
-
- /* assume new rte is at end */
- rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
- *top_rte = rte;
- *top_rti = rtindex;
- *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
+ if (!nsitem)
+ nsitem = transformTableEntry(pstate, rv);
+
+ *top_nsitem = nsitem;
+ *namespace = list_make1(nsitem);
rtr = makeNode(RangeTblRef);
- rtr->rtindex = rtindex;
+ rtr->rtindex = nsitem->p_rtindex;
return (Node *) rtr;
}
else if (IsA(n, RangeSubselect))
{
/* sub-SELECT is like a plain relation */
RangeTblRef *rtr;
- RangeTblEntry *rte;
- int rtindex;
-
- rte = transformRangeSubselect(pstate, (RangeSubselect *) n);
- /* assume new rte is at end */
- rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
- *top_rte = rte;
- *top_rti = rtindex;
- *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
+ ParseNamespaceItem *nsitem;
+
+ nsitem = transformRangeSubselect(pstate, (RangeSubselect *) n);
+ *top_nsitem = nsitem;
+ *namespace = list_make1(nsitem);
rtr = makeNode(RangeTblRef);
- rtr->rtindex = rtindex;
+ rtr->rtindex = nsitem->p_rtindex;
return (Node *) rtr;
}
else if (IsA(n, RangeFunction))
{
/* function is like a plain relation */
RangeTblRef *rtr;
- RangeTblEntry *rte;
- int rtindex;
-
- rte = transformRangeFunction(pstate, (RangeFunction *) n);
- /* assume new rte is at end */
- rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
- *top_rte = rte;
- *top_rti = rtindex;
- *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
+ ParseNamespaceItem *nsitem;
+
+ nsitem = transformRangeFunction(pstate, (RangeFunction *) n);
+ *top_nsitem = nsitem;
+ *namespace = list_make1(nsitem);
rtr = makeNode(RangeTblRef);
- rtr->rtindex = rtindex;
+ rtr->rtindex = nsitem->p_rtindex;
return (Node *) rtr;
}
else if (IsA(n, RangeTableFunc))
{
/* table function is like a plain relation */
RangeTblRef *rtr;
- RangeTblEntry *rte;
- int rtindex;
-
- rte = transformRangeTableFunc(pstate, (RangeTableFunc *) n);
- /* assume new rte is at end */
- rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
- *top_rte = rte;
- *top_rti = rtindex;
- *namespace = list_make1(makeDefaultNSItem(rte, rtindex));
+ ParseNamespaceItem *nsitem;
+
+ nsitem = transformRangeTableFunc(pstate, (RangeTableFunc *) n);
+ *top_nsitem = nsitem;
+ *namespace = list_make1(nsitem);
rtr = makeNode(RangeTblRef);
- rtr->rtindex = rtindex;
+ rtr->rtindex = nsitem->p_rtindex;
return (Node *) rtr;
}
else if (IsA(n, RangeTableSample))
/* TABLESAMPLE clause (wrapping some other valid FROM node) */
RangeTableSample *rts = (RangeTableSample *) n;
Node *rel;
- RangeTblRef *rtr;
RangeTblEntry *rte;
/* Recursively transform the contained relation */
rel = transformFromClauseItem(pstate, rts->relation,
- top_rte, top_rti, namespace);
- /* Currently, grammar could only return a RangeVar as contained rel */
- rtr = castNode(RangeTblRef, rel);
- rte = rt_fetch(rtr->rtindex, pstate->p_rtable);
+ top_nsitem, namespace);
+ rte = (*top_nsitem)->p_rte;
/* We only support this on plain relations and matviews */
- if (rte->relkind != RELKIND_RELATION &&
- rte->relkind != RELKIND_MATVIEW &&
- rte->relkind != RELKIND_PARTITIONED_TABLE)
+ if (rte->rtekind != RTE_RELATION ||
+ (rte->relkind != RELKIND_RELATION &&
+ rte->relkind != RELKIND_MATVIEW &&
+ rte->relkind != RELKIND_PARTITIONED_TABLE))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("TABLESAMPLE clause can only be applied to tables and materialized views"),
/* Transform TABLESAMPLE details and attach to the RTE */
rte->tablesample = transformRangeTableSample(pstate, rts);
- return (Node *) rtr;
+ return rel;
}
else if (IsA(n, JoinExpr))
{
/* A newfangled join expression */
JoinExpr *j = (JoinExpr *) n;
- RangeTblEntry *l_rte;
- RangeTblEntry *r_rte;
- int l_rtindex;
- int r_rtindex;
+ ParseNamespaceItem *nsitem;
+ ParseNamespaceItem *l_nsitem;
+ ParseNamespaceItem *r_nsitem;
List *l_namespace,
*r_namespace,
*my_namespace,
*l_colvars,
*r_colvars,
*res_colvars;
+ ParseNamespaceColumn *res_nscolumns;
+ int res_colindex;
bool lateral_ok;
int sv_namespace_length;
- RangeTblEntry *rte;
int k;
/*
* it in this order for correct visibility of LATERAL references.
*/
j->larg = transformFromClauseItem(pstate, j->larg,
- &l_rte,
- &l_rtindex,
+ &l_nsitem,
&l_namespace);
/*
/* And now we can process the RHS */
j->rarg = transformFromClauseItem(pstate, j->rarg,
- &r_rte,
- &r_rtindex,
+ &r_nsitem,
&r_namespace);
/* Remove the left-side RTEs from the namespace list again */
/*
* Extract column name and var lists from both subtrees
*
- * Note: expandRTE returns new lists, safe for me to modify
+ * Note: expandNSItemVars returns new lists, safe for me to modify
*/
- expandRTE(l_rte, l_rtindex, 0, -1, false,
- &l_colnames, &l_colvars);
- expandRTE(r_rte, r_rtindex, 0, -1, false,
- &r_colnames, &r_colvars);
+ l_colvars = expandNSItemVars(l_nsitem, 0, -1, &l_colnames);
+ r_colvars = expandNSItemVars(r_nsitem, 0, -1, &r_colnames);
/*
* Natural join does not explicitly specify columns; must generate
res_colnames = NIL;
res_colvars = NIL;
+ /* this may be larger than needed, but it's not worth being exact */
+ res_nscolumns = (ParseNamespaceColumn *)
+ palloc0((list_length(l_colnames) + list_length(r_colnames)) *
+ sizeof(ParseNamespaceColumn));
+ res_colindex = 0;
+
if (j->usingClause)
{
/*
int r_index = -1;
Var *l_colvar,
*r_colvar;
+ Node *u_colvar;
+ ParseNamespaceColumn *res_nscolumn;
/* Check for USING(foo,foo) */
foreach(col, res_colnames)
r_usingvars = lappend(r_usingvars, r_colvar);
res_colnames = lappend(res_colnames, lfirst(ucol));
- res_colvars = lappend(res_colvars,
- buildMergedJoinVar(pstate,
- j->jointype,
- l_colvar,
- r_colvar));
+ u_colvar = buildMergedJoinVar(pstate,
+ j->jointype,
+ l_colvar,
+ r_colvar);
+ res_colvars = lappend(res_colvars, u_colvar);
+ res_nscolumn = res_nscolumns + res_colindex;
+ res_colindex++;
+ if (u_colvar == (Node *) l_colvar)
+ {
+ /* Merged column is equivalent to left input */
+ res_nscolumn->p_varno = l_colvar->varno;
+ res_nscolumn->p_varattno = l_colvar->varattno;
+ res_nscolumn->p_vartype = l_colvar->vartype;
+ res_nscolumn->p_vartypmod = l_colvar->vartypmod;
+ res_nscolumn->p_varcollid = l_colvar->varcollid;
+ /* XXX these are not quite right, but doesn't matter yet */
+ res_nscolumn->p_varnosyn = l_colvar->varno;
+ res_nscolumn->p_varattnosyn = l_colvar->varattno;
+ }
+ else if (u_colvar == (Node *) r_colvar)
+ {
+ /* Merged column is equivalent to right input */
+ res_nscolumn->p_varno = r_colvar->varno;
+ res_nscolumn->p_varattno = r_colvar->varattno;
+ res_nscolumn->p_vartype = r_colvar->vartype;
+ res_nscolumn->p_vartypmod = r_colvar->vartypmod;
+ res_nscolumn->p_varcollid = r_colvar->varcollid;
+ /* XXX these are not quite right, but doesn't matter yet */
+ res_nscolumn->p_varnosyn = r_colvar->varno;
+ res_nscolumn->p_varattnosyn = r_colvar->varattno;
+ }
+ else
+ {
+ /*
+ * Merged column is not semantically equivalent to either
+ * input, so it needs to be referenced as the join output
+ * column. We don't know the join's varno yet, so we'll
+ * replace these zeroes below.
+ */
+ res_nscolumn->p_varno = 0;
+ res_nscolumn->p_varattno = res_colindex;
+ res_nscolumn->p_vartype = exprType(u_colvar);
+ res_nscolumn->p_vartypmod = exprTypmod(u_colvar);
+ res_nscolumn->p_varcollid = exprCollation(u_colvar);
+ res_nscolumn->p_varnosyn = 0;
+ res_nscolumn->p_varattnosyn = res_colindex;
+ }
}
j->quals = transformJoinUsingClause(pstate,
- l_rte,
- r_rte,
+ l_nsitem->p_rte,
+ r_nsitem->p_rte,
l_usingvars,
r_usingvars);
}
/* Add remaining columns from each side to the output columns */
extractRemainingColumns(res_colnames,
l_colnames, l_colvars,
- &l_colnames, &l_colvars);
+ l_nsitem->p_nscolumns,
+ &l_colnames, &l_colvars,
+ res_nscolumns + res_colindex);
+ res_colindex += list_length(l_colvars);
extractRemainingColumns(res_colnames,
r_colnames, r_colvars,
- &r_colnames, &r_colvars);
+ r_nsitem->p_nscolumns,
+ &r_colnames, &r_colvars,
+ res_nscolumns + res_colindex);
+ res_colindex += list_length(r_colvars);
res_colnames = list_concat(res_colnames, l_colnames);
res_colvars = list_concat(res_colvars, l_colvars);
res_colnames = list_concat(res_colnames, r_colnames);
}
/*
- * Now build an RTE for the result of the join
+ * Now build an RTE and nsitem for the result of the join.
+ * res_nscolumns isn't totally done yet, but that's OK because
+ * addRangeTableEntryForJoin doesn't examine it, only store a pointer.
*/
- rte = addRangeTableEntryForJoin(pstate,
- res_colnames,
- j->jointype,
- res_colvars,
- j->alias,
- true);
+ nsitem = addRangeTableEntryForJoin(pstate,
+ res_colnames,
+ res_nscolumns,
+ j->jointype,
+ res_colvars,
+ j->alias,
+ true);
- /* assume new rte is at end */
- j->rtindex = list_length(pstate->p_rtable);
- Assert(rte == rt_fetch(j->rtindex, pstate->p_rtable));
+ j->rtindex = nsitem->p_rtindex;
- *top_rte = rte;
- *top_rti = j->rtindex;
+ /*
+ * Now that we know the join RTE's rangetable index, we can fix up the
+ * res_nscolumns data in places where it should contain that.
+ */
+ Assert(res_colindex == list_length(nsitem->p_rte->eref->colnames));
+ for (k = 0; k < res_colindex; k++)
+ {
+ ParseNamespaceColumn *nscol = res_nscolumns + k;
+
+ /* fill in join RTI for merged columns */
+ if (nscol->p_varno == 0)
+ nscol->p_varno = j->rtindex;
+ if (nscol->p_varnosyn == 0)
+ nscol->p_varnosyn = j->rtindex;
+ /* if join has an alias, it syntactically hides all inputs */
+ if (j->alias)
+ {
+ nscol->p_varnosyn = j->rtindex;
+ nscol->p_varattnosyn = k + 1;
+ }
+ }
/* make a matching link to the JoinExpr for later use */
for (k = list_length(pstate->p_joinexprs) + 1; k < j->rtindex; k++)
* The join RTE itself is always made visible for unqualified column
* names. It's visible as a relation name only if it has an alias.
*/
- *namespace = lappend(my_namespace,
- makeNamespaceItem(rte,
- j->rtindex,
- (j->alias != NULL),
- true,
- false,
- true));
+ nsitem->p_rel_visible = (j->alias != NULL);
+ nsitem->p_cols_visible = true;
+ nsitem->p_lateral_only = false;
+ nsitem->p_lateral_ok = true;
+
+ *top_nsitem = nsitem;
+ *namespace = lappend(my_namespace, nsitem);
return (Node *) j;
}
return res_node;
}
-/*
- * makeNamespaceItem -
- * Convenience subroutine to construct a ParseNamespaceItem.
- */
-static ParseNamespaceItem *
-makeNamespaceItem(RangeTblEntry *rte, int rtindex,
- bool rel_visible, bool cols_visible,
- bool lateral_only, bool lateral_ok)
-{
- ParseNamespaceItem *nsitem;
-
- nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
- nsitem->p_rte = rte;
- nsitem->p_rtindex = rtindex;
- nsitem->p_rel_visible = rel_visible;
- nsitem->p_cols_visible = cols_visible;
- nsitem->p_lateral_only = lateral_only;
- nsitem->p_lateral_ok = lateral_ok;
- return nsitem;
-}
-
/*
* setNamespaceColumnVisibility -
* Convenience subroutine to update cols_visible flags in a namespace list.
*/
save_namespace = pstate->p_namespace;
pstate->p_namespace = NIL;
- addRTEtoQuery(pstate, pstate->p_target_rangetblentry,
- false, false, true);
+ addNSItemToQuery(pstate, pstate->p_target_nsitem,
+ false, false, true);
if (infer->indexElems)
*arbiterExpr = resolve_unique_index_expr(pstate, infer,
if (infer->conname)
{
Oid relid = RelationGetRelid(pstate->p_target_relation);
- RangeTblEntry *rte = pstate->p_target_rangetblentry;
+ RangeTblEntry *rte = pstate->p_target_nsitem->p_rte;
Bitmapset *conattnos;
conattnos = get_relation_constraint_attnos(relid, infer->conname,
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,
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.
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("invalid reference to FROM-clause entry for table \"%s\"",
refname),
- (rte == pstate->p_target_rangetblentry) ?
+ (pstate->p_target_nsitem != NULL &&
+ rte == pstate->p_target_nsitem->p_rte) ?
errhint("There is an entry for table \"%s\", but it cannot be referenced from this part of the query.",
refname) :
errdetail("The combining JOIN type must be INNER or LEFT for a LATERAL reference."),
RangeTblEntry *rte = nsitem->p_rte;
int attnum;
Var *var;
- Oid vartypeid;
- int32 vartypmod;
- Oid varcollid;
/*
* Scan the RTE's column names (or aliases) for a match. Complain if
parser_errposition(pstate, location)));
/* Found a valid match, so build a Var */
- get_rte_attribute_type(rte, attnum,
- &vartypeid, &vartypmod, &varcollid);
- var = makeVar(nsitem->p_rtindex, attnum,
- vartypeid, vartypmod, varcollid,
- sublevels_up);
+ if (attnum > InvalidAttrNumber)
+ {
+ /* Get attribute data from the ParseNamespaceColumn array */
+ ParseNamespaceColumn *nscol = &nsitem->p_nscolumns[attnum - 1];
+
+ /* Complain if dropped column. See notes in scanRTEForColumn. */
+ if (nscol->p_varno == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_COLUMN),
+ errmsg("column \"%s\" of relation \"%s\" does not exist",
+ colname,
+ rte->eref->aliasname)));
+
+ var = makeVar(nsitem->p_rtindex,
+ attnum,
+ nscol->p_vartype,
+ nscol->p_vartypmod,
+ nscol->p_varcollid,
+ sublevels_up);
+ }
+ else
+ {
+ /* System column, so use predetermined type data */
+ const FormData_pg_attribute *sysatt;
+
+ sysatt = SystemAttributeDefinition(attnum);
+ var = makeVar(nsitem->p_rtindex,
+ attnum,
+ sysatt->atttypid,
+ sysatt->atttypmod,
+ sysatt->attcollation,
+ sublevels_up);
+ }
var->location = location;
/* Require read access to the column */
* don't bother to test for that case here.
*
* Should this somehow go wrong and we try to access a dropped column,
- * we'll still catch it by virtue of the checks in
- * get_rte_attribute_type(), which is called by scanNSItemForColumn().
- * That routine has to do a cache lookup anyway, so the check there is
- * cheap. Callers interested in finding match with shortest distance need
- * to defend against this directly, though.
+ * we'll still catch it by virtue of the check in scanNSItemForColumn().
+ * Callers interested in finding match with shortest distance need to
+ * defend against this directly, though.
*/
foreach(c, rte->eref->colnames)
{
return funcname;
}
+/*
+ * buildNSItemFromTupleDesc
+ * Build a ParseNamespaceItem, given a tupdesc describing the columns.
+ *
+ * rte: the new RangeTblEntry for the rel
+ * rtindex: its index in the rangetable list
+ * tupdesc: the physical column information
+ */
+static ParseNamespaceItem *
+buildNSItemFromTupleDesc(RangeTblEntry *rte, Index rtindex, TupleDesc tupdesc)
+{
+ ParseNamespaceItem *nsitem;
+ ParseNamespaceColumn *nscolumns;
+ int maxattrs = tupdesc->natts;
+ int varattno;
+
+ /* colnames must have the same number of entries as the nsitem */
+ Assert(maxattrs == list_length(rte->eref->colnames));
+
+ /* extract per-column data from the tupdesc */
+ nscolumns = (ParseNamespaceColumn *)
+ palloc0(maxattrs * sizeof(ParseNamespaceColumn));
+
+ for (varattno = 0; varattno < maxattrs; varattno++)
+ {
+ Form_pg_attribute attr = TupleDescAttr(tupdesc, varattno);
+
+ /* For a dropped column, just leave the entry as zeroes */
+ if (attr->attisdropped)
+ continue;
+
+ nscolumns[varattno].p_varno = rtindex;
+ nscolumns[varattno].p_varattno = varattno + 1;
+ nscolumns[varattno].p_vartype = attr->atttypid;
+ nscolumns[varattno].p_vartypmod = attr->atttypmod;
+ nscolumns[varattno].p_varcollid = attr->attcollation;
+ nscolumns[varattno].p_varnosyn = rtindex;
+ nscolumns[varattno].p_varattnosyn = varattno + 1;
+ }
+
+ /* ... and build the nsitem */
+ nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+ nsitem->p_rte = rte;
+ nsitem->p_rtindex = rtindex;
+ nsitem->p_nscolumns = nscolumns;
+ /* set default visibility flags; might get changed later */
+ nsitem->p_rel_visible = true;
+ nsitem->p_cols_visible = true;
+ nsitem->p_lateral_only = false;
+ nsitem->p_lateral_ok = true;
+
+ return nsitem;
+}
+
+/*
+ * buildNSItemFromLists
+ * Build a ParseNamespaceItem, given column type information in lists.
+ *
+ * rte: the new RangeTblEntry for the rel
+ * rtindex: its index in the rangetable list
+ * coltypes: per-column datatype OIDs
+ * coltypmods: per-column type modifiers
+ * colcollation: per-column collation OIDs
+ */
+static ParseNamespaceItem *
+buildNSItemFromLists(RangeTblEntry *rte, Index rtindex,
+ List *coltypes, List *coltypmods, List *colcollations)
+{
+ ParseNamespaceItem *nsitem;
+ ParseNamespaceColumn *nscolumns;
+ int maxattrs = list_length(coltypes);
+ int varattno;
+ ListCell *lct;
+ ListCell *lcm;
+ ListCell *lcc;
+
+ /* colnames must have the same number of entries as the nsitem */
+ Assert(maxattrs == list_length(rte->eref->colnames));
+
+ Assert(maxattrs == list_length(coltypmods));
+ Assert(maxattrs == list_length(colcollations));
+
+ /* extract per-column data from the lists */
+ nscolumns = (ParseNamespaceColumn *)
+ palloc0(maxattrs * sizeof(ParseNamespaceColumn));
+
+ varattno = 0;
+ forthree(lct, coltypes,
+ lcm, coltypmods,
+ lcc, colcollations)
+ {
+ nscolumns[varattno].p_varno = rtindex;
+ nscolumns[varattno].p_varattno = varattno + 1;
+ nscolumns[varattno].p_vartype = lfirst_oid(lct);
+ nscolumns[varattno].p_vartypmod = lfirst_int(lcm);
+ nscolumns[varattno].p_varcollid = lfirst_oid(lcc);
+ nscolumns[varattno].p_varnosyn = rtindex;
+ nscolumns[varattno].p_varattnosyn = varattno + 1;
+ varattno++;
+ }
+
+ /* ... and build the nsitem */
+ nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+ nsitem->p_rte = rte;
+ nsitem->p_rtindex = rtindex;
+ nsitem->p_nscolumns = nscolumns;
+ /* set default visibility flags; might get changed later */
+ nsitem->p_rel_visible = true;
+ nsitem->p_cols_visible = true;
+ nsitem->p_lateral_only = false;
+ nsitem->p_lateral_ok = true;
+
+ return nsitem;
+}
+
/*
* Open a table during parse analysis
*
/*
* Add an entry for a relation to the pstate's range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
+ *
+ * We do not link the ParseNamespaceItem into the pstate here; it's the
+ * caller's job to do that in the appropriate way.
*
* Note: formerly this checked for refname conflicts, but that's wrong.
* Caller is responsible for checking for conflicts in the appropriate scope.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntry(ParseState *pstate,
RangeVar *relation,
Alias *alias,
char *refname = alias ? alias->aliasname : relation->relname;
LOCKMODE lockmode;
Relation rel;
+ ParseNamespaceItem *nsitem;
Assert(pstate != NULL);
rte->eref = makeAlias(refname, NIL);
buildRelationAliases(rel->rd_att, alias, rte->eref);
- /*
- * Drop the rel refcount, but keep the access lock till end of transaction
- * so that the table can't be deleted or have its schema modified
- * underneath us.
- */
- table_close(rel, NoLock);
-
/*
* Set flags and access permissions.
*
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ nsitem = buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
+ rel->rd_att);
+
+ /*
+ * Drop the rel refcount, but keep the access lock till end of transaction
+ * so that the table can't be deleted or have its schema modified
+ * underneath us.
+ */
+ table_close(rel, NoLock);
+
+ return nsitem;
}
/*
* Add an entry for a relation to the pstate's range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
*
* This is just like addRangeTableEntry() except that it makes an RTE
* given an already-open relation instead of a RangeVar reference.
* would require importing storage/lock.h into parse_relation.h. Since
* LOCKMODE is typedef'd as int anyway, that seems like overkill.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForRelation(ParseState *pstate,
Relation rel,
int lockmode,
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
+ rel->rd_att);
}
/*
* Add an entry for a subquery to the pstate's range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
*
- * This is just like addRangeTableEntry() except that it makes a subquery RTE.
+ * This is much like addRangeTableEntry() except that it makes a subquery RTE.
* Note that an alias clause *must* be supplied.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery,
Alias *alias,
char *refname = alias->aliasname;
Alias *eref;
int numaliases;
+ List *coltypes,
+ *coltypmods,
+ *colcollations;
int varattno;
ListCell *tlistitem;
eref = copyObject(alias);
numaliases = list_length(eref->colnames);
- /* fill in any unspecified alias columns */
+ /* fill in any unspecified alias columns, and extract column type info */
+ coltypes = coltypmods = colcollations = NIL;
varattno = 0;
foreach(tlistitem, subquery->targetList)
{
attrname = pstrdup(te->resname);
eref->colnames = lappend(eref->colnames, makeString(attrname));
}
+ coltypes = lappend_oid(coltypes,
+ exprType((Node *) te->expr));
+ coltypmods = lappend_int(coltypmods,
+ exprTypmod((Node *) te->expr));
+ colcollations = lappend_oid(colcollations,
+ exprCollation((Node *) te->expr));
}
if (varattno < numaliases)
ereport(ERROR,
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ return buildNSItemFromLists(rte, list_length(pstate->p_rtable),
+ coltypes, coltypmods, colcollations);
}
/*
* Add an entry for a function (or functions) to the pstate's range table
- * (p_rtable).
+ * (p_rtable). Then, construct and return a ParseNamespaceItem for the new RTE.
*
- * This is just like addRangeTableEntry() except that it makes a function RTE.
+ * This is much like addRangeTableEntry() except that it makes a function RTE.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForFunction(ParseState *pstate,
List *funcnames,
List *funcexprs,
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
+ tupdesc);
}
/*
* Add an entry for a table function to the pstate's range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
*
* This is much like addRangeTableEntry() except that it makes a tablefunc RTE.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForTableFunc(ParseState *pstate,
TableFunc *tf,
Alias *alias,
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ return buildNSItemFromLists(rte, list_length(pstate->p_rtable),
+ rte->coltypes, rte->coltypmods,
+ rte->colcollations);
}
/*
* Add an entry for a VALUES list to the pstate's range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
*
* This is much like addRangeTableEntry() except that it makes a values RTE.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForValues(ParseState *pstate,
List *exprs,
List *coltypes,
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ return buildNSItemFromLists(rte, list_length(pstate->p_rtable),
+ rte->coltypes, rte->coltypmods,
+ rte->colcollations);
}
/*
* Add an entry for a join to the pstate's range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
*
* This is much like addRangeTableEntry() except that it makes a join RTE.
+ * Also, it's more convenient for the caller to construct the
+ * ParseNamespaceColumn array, so we pass that in.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForJoin(ParseState *pstate,
List *colnames,
+ ParseNamespaceColumn *nscolumns,
JoinType jointype,
List *aliasvars,
Alias *alias,
RangeTblEntry *rte = makeNode(RangeTblEntry);
Alias *eref;
int numaliases;
+ ParseNamespaceItem *nsitem;
Assert(pstate != NULL);
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
+ nsitem->p_rte = rte;
+ nsitem->p_rtindex = list_length(pstate->p_rtable);
+ nsitem->p_nscolumns = nscolumns;
+ /* set default visibility flags; might get changed later */
+ nsitem->p_rel_visible = true;
+ nsitem->p_cols_visible = true;
+ nsitem->p_lateral_only = false;
+ nsitem->p_lateral_ok = true;
+
+ return nsitem;
}
/*
* Add an entry for a CTE reference to the pstate's range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
*
* This is much like addRangeTableEntry() except that it makes a CTE RTE.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForCTE(ParseState *pstate,
CommonTableExpr *cte,
Index levelsup,
rte->extraUpdatedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ return buildNSItemFromLists(rte, list_length(pstate->p_rtable),
+ rte->coltypes, rte->coltypmods,
+ rte->colcollations);
}
/*
* Add an entry for an ephemeral named relation reference to the pstate's
* range table (p_rtable).
+ * Then, construct and return a ParseNamespaceItem for the new RTE.
*
* It is expected that the RangeVar, which up until now is only known to be an
* ephemeral named relation, will (in conjunction with the QueryEnvironment in
* This is much like addRangeTableEntry() except that it makes an RTE for an
* ephemeral named relation.
*/
-RangeTblEntry *
+ParseNamespaceItem *
addRangeTableEntryForENR(ParseState *pstate,
RangeVar *rv,
bool inFromCl)
rte->selectedCols = NULL;
/*
- * Add completed RTE to pstate's range table list, but not to join list
- * nor namespace --- caller must do that if appropriate.
+ * Add completed RTE to pstate's range table list, so that we know its
+ * index. But we don't add it to the join list --- caller must do that if
+ * appropriate.
*/
pstate->p_rtable = lappend(pstate->p_rtable, rte);
- return rte;
+ /*
+ * Build a ParseNamespaceItem, but don't add it to the pstate's namespace
+ * list --- caller must do that if appropriate.
+ */
+ return buildNSItemFromTupleDesc(rte, list_length(pstate->p_rtable),
+ tupdesc);
}
}
/*
- * Add the given RTE as a top-level entry in the pstate's join list
+ * Add the given nsitem/RTE as a top-level entry in the pstate's join list
* and/or namespace list. (We assume caller has checked for any
- * namespace conflicts.) The RTE is always marked as unconditionally
+ * namespace conflicts.) The nsitem is always marked as unconditionally
* visible, that is, not LATERAL-only.
- *
- * Note: some callers know that they can find the new ParseNamespaceItem
- * at the end of the pstate->p_namespace list. This is a bit ugly but not
- * worth complicating this function's signature for.
*/
void
-addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
- bool addToJoinList,
- bool addToRelNameSpace, bool addToVarNameSpace)
+addNSItemToQuery(ParseState *pstate, ParseNamespaceItem *nsitem,
+ bool addToJoinList,
+ bool addToRelNameSpace, bool addToVarNameSpace)
{
- int rtindex;
-
- /*
- * Most callers have just added the RTE to the rangetable, so it's likely
- * to be the last entry. Hence, it's a good idea to search the rangetable
- * back-to-front.
- */
- for (rtindex = list_length(pstate->p_rtable); rtindex > 0; rtindex--)
- {
- if (rte == rt_fetch(rtindex, pstate->p_rtable))
- break;
- }
- if (rtindex <= 0)
- elog(ERROR, "RTE not found (internal error)");
-
if (addToJoinList)
{
RangeTblRef *rtr = makeNode(RangeTblRef);
- rtr->rtindex = rtindex;
+ rtr->rtindex = nsitem->p_rtindex;
pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
}
if (addToRelNameSpace || addToVarNameSpace)
{
- ParseNamespaceItem *nsitem;
-
- nsitem = (ParseNamespaceItem *) palloc(sizeof(ParseNamespaceItem));
- nsitem->p_rte = rte;
- nsitem->p_rtindex = rtindex;
+ /* Set the new nsitem's visibility flags correctly */
nsitem->p_rel_visible = addToRelNameSpace;
nsitem->p_cols_visible = addToVarNameSpace;
nsitem->p_lateral_only = false;
}
}
+/*
+ * expandNSItemVars
+ * Produce a list of Vars, and optionally a list of column names,
+ * for the non-dropped columns of the nsitem.
+ *
+ * The emitted Vars are marked with the given sublevels_up and location.
+ *
+ * If colnames isn't NULL, a list of String items for the columns is stored
+ * there; note that it's just a subset of the RTE's eref list, and hence
+ * the list elements mustn't be modified.
+ */
+List *
+expandNSItemVars(ParseNamespaceItem *nsitem,
+ int sublevels_up, int location,
+ List **colnames)
+{
+ List *result = NIL;
+ int colindex;
+ ListCell *lc;
+
+ if (colnames)
+ *colnames = NIL;
+ colindex = 0;
+ foreach(lc, nsitem->p_rte->eref->colnames)
+ {
+ Value *colnameval = (Value *) lfirst(lc);
+ const char *colname = strVal(colnameval);
+ ParseNamespaceColumn *nscol = nsitem->p_nscolumns + colindex;
+
+ if (colname[0])
+ {
+ Var *var;
+
+ Assert(nscol->p_varno > 0);
+ var = makeVar(nsitem->p_rtindex,
+ colindex + 1,
+ nscol->p_vartype,
+ nscol->p_vartypmod,
+ nscol->p_varcollid,
+ sublevels_up);
+ var->location = location;
+ result = lappend(result, var);
+ if (colnames)
+ *colnames = lappend(*colnames, colnameval);
+ }
+ else
+ {
+ /* dropped column, ignore */
+ Assert(nscol->p_varno == 0);
+ }
+ colindex++;
+ }
+ return result;
+}
+
/*
* expandNSItemAttrs -
* Workhorse for "*" expansion: produce a list of targetentries
*var;
List *te_list = NIL;
- expandRTE(rte, nsitem->p_rtindex, sublevels_up, location, false,
- &names, &vars);
+ vars = expandNSItemVars(nsitem, sublevels_up, location, &names);
/*
* Require read access to the table. This is normally redundant with the
return NULL; /* keep compiler quiet */
}
-/*
- * get_rte_attribute_type
- * Get attribute type/typmod/collation information from a RangeTblEntry
- */
-void
-get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
- Oid *vartype, int32 *vartypmod, Oid *varcollid)
-{
- switch (rte->rtekind)
- {
- case RTE_RELATION:
- {
- /* Plain relation RTE --- get the attribute's type info */
- HeapTuple tp;
- Form_pg_attribute att_tup;
-
- tp = SearchSysCache2(ATTNUM,
- ObjectIdGetDatum(rte->relid),
- Int16GetDatum(attnum));
- if (!HeapTupleIsValid(tp)) /* shouldn't happen */
- elog(ERROR, "cache lookup failed for attribute %d of relation %u",
- attnum, rte->relid);
- att_tup = (Form_pg_attribute) GETSTRUCT(tp);
-
- /*
- * If dropped column, pretend it ain't there. See notes in
- * scanRTEForColumn.
- */
- if (att_tup->attisdropped)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column \"%s\" of relation \"%s\" does not exist",
- NameStr(att_tup->attname),
- get_rel_name(rte->relid))));
- *vartype = att_tup->atttypid;
- *vartypmod = att_tup->atttypmod;
- *varcollid = att_tup->attcollation;
- ReleaseSysCache(tp);
- }
- break;
- case RTE_SUBQUERY:
- {
- /* Subselect RTE --- get type info from subselect's tlist */
- TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
- attnum);
-
- if (te == NULL || te->resjunk)
- elog(ERROR, "subquery %s does not have attribute %d",
- rte->eref->aliasname, attnum);
- *vartype = exprType((Node *) te->expr);
- *vartypmod = exprTypmod((Node *) te->expr);
- *varcollid = exprCollation((Node *) te->expr);
- }
- break;
- case RTE_FUNCTION:
- {
- /* Function RTE */
- ListCell *lc;
- int atts_done = 0;
-
- /* Identify which function covers the requested column */
- foreach(lc, rte->functions)
- {
- RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
-
- if (attnum > atts_done &&
- attnum <= atts_done + rtfunc->funccolcount)
- {
- TypeFuncClass functypclass;
- Oid funcrettype;
- TupleDesc tupdesc;
-
- attnum -= atts_done; /* now relative to this func */
- functypclass = get_expr_result_type(rtfunc->funcexpr,
- &funcrettype,
- &tupdesc);
-
- if (functypclass == TYPEFUNC_COMPOSITE ||
- functypclass == TYPEFUNC_COMPOSITE_DOMAIN)
- {
- /* Composite data type, e.g. a table's row type */
- Form_pg_attribute att_tup;
-
- Assert(tupdesc);
- Assert(attnum <= tupdesc->natts);
- att_tup = TupleDescAttr(tupdesc, attnum - 1);
-
- /*
- * If dropped column, pretend it ain't there. See
- * notes in scanRTEForColumn.
- */
- if (att_tup->attisdropped)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column \"%s\" of relation \"%s\" does not exist",
- NameStr(att_tup->attname),
- rte->eref->aliasname)));
- *vartype = att_tup->atttypid;
- *vartypmod = att_tup->atttypmod;
- *varcollid = att_tup->attcollation;
- }
- else if (functypclass == TYPEFUNC_SCALAR)
- {
- /* Base data type, i.e. scalar */
- *vartype = funcrettype;
- *vartypmod = -1;
- *varcollid = exprCollation(rtfunc->funcexpr);
- }
- else if (functypclass == TYPEFUNC_RECORD)
- {
- *vartype = list_nth_oid(rtfunc->funccoltypes,
- attnum - 1);
- *vartypmod = list_nth_int(rtfunc->funccoltypmods,
- attnum - 1);
- *varcollid = list_nth_oid(rtfunc->funccolcollations,
- attnum - 1);
- }
- else
- {
- /*
- * addRangeTableEntryForFunction should've caught
- * this
- */
- elog(ERROR, "function in FROM has unsupported return type");
- }
- return;
- }
- atts_done += rtfunc->funccolcount;
- }
-
- /* If we get here, must be looking for the ordinality column */
- if (rte->funcordinality && attnum == atts_done + 1)
- {
- *vartype = INT8OID;
- *vartypmod = -1;
- *varcollid = InvalidOid;
- return;
- }
-
- /* this probably can't happen ... */
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column %d of relation \"%s\" does not exist",
- attnum,
- rte->eref->aliasname)));
- }
- break;
- case RTE_JOIN:
- {
- /*
- * Join RTE --- get type info from join RTE's alias variable
- */
- Node *aliasvar;
-
- Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars));
- aliasvar = (Node *) list_nth(rte->joinaliasvars, attnum - 1);
- Assert(aliasvar != NULL);
- *vartype = exprType(aliasvar);
- *vartypmod = exprTypmod(aliasvar);
- *varcollid = exprCollation(aliasvar);
- }
- break;
- case RTE_TABLEFUNC:
- case RTE_VALUES:
- case RTE_CTE:
- case RTE_NAMEDTUPLESTORE:
- {
- /*
- * tablefunc, VALUES, CTE, or ENR RTE --- get type info from
- * lists in the RTE
- */
- Assert(attnum > 0 && attnum <= list_length(rte->coltypes));
- *vartype = list_nth_oid(rte->coltypes, attnum - 1);
- *vartypmod = list_nth_int(rte->coltypmods, attnum - 1);
- *varcollid = list_nth_oid(rte->colcollations, attnum - 1);
-
- /* For ENR, better check for dropped column */
- if (!OidIsValid(*vartype))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column %d of relation \"%s\" does not exist",
- attnum,
- rte->eref->aliasname)));
- }
- break;
- case RTE_RESULT:
- /* this probably can't happen ... */
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column %d of relation \"%s\" does not exist",
- attnum,
- rte->eref->aliasname)));
- break;
- default:
- elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind);
- }
-}
-
/*
* get_rte_attribute_is_dropped
* Check whether attempted attribute ref is to a dropped column
*/
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;
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
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;
transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
{
ParseState *pstate;
- RangeTblEntry *rte;
+ ParseNamespaceItem *nsitem;
ListCell *l;
Relation rel;
* relation, but we still need to open it.
*/
rel = relation_open(relid, NoLock);
- rte = addRangeTableEntryForRelation(pstate, rel,
- AccessShareLock,
- NULL, false, true);
+ 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)
{
Relation rel;
ParseState *pstate;
- RangeTblEntry *oldrte;
- RangeTblEntry *newrte;
+ ParseNamespaceItem *oldnsitem;
+ ParseNamespaceItem *newnsitem;
/*
* To avoid deadlock, make sure the first thing we do is grab
/*
* 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,
- AccessShareLock,
- makeAlias("old", NIL),
- false, false);
- newrte = addRangeTableEntryForRelation(pstate, rel,
- AccessShareLock,
- makeAlias("new", NIL),
- false, false);
+ oldnsitem = addRangeTableEntryForRelation(pstate, rel,
+ AccessShareLock,
+ makeAlias("old", NIL),
+ false, false);
+ 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
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",
* nor "*" in the rule actions. We decide later whether to put
* them in the joinlist.
*/
- oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
- AccessShareLock,
- makeAlias("old", NIL),
- false, false);
- newrte = 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 = addRangeTableEntryForRelation(sub_pstate, rel,
+ AccessShareLock,
+ makeAlias("old", NIL),
+ false, false);
+ newnsitem = addRangeTableEntryForRelation(sub_pstate, rel,
+ AccessShareLock,
+ makeAlias("new", NIL),
+ false, 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,
*/
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
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);
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
/* Set up pstate */
pstate = make_parsestate(NULL);
pstate->p_sourcetext = queryString;
- rte = addRangeTableEntryForRelation(pstate,
- rel,
- AccessShareLock,
- NULL,
- false,
- true);
- addRTEtoQuery(pstate, rte, false, true, true);
+ nsitem = addRangeTableEntryForRelation(pstate,
+ rel,
+ AccessShareLock,
+ NULL,
+ false,
+ true);
+ addNSItemToQuery(pstate, nsitem, false, true, true);
/* Set up CreateStmtContext */
cxt.pstate = pstate;
copybuf = makeStringInfo();
pstate = make_parsestate(NULL);
- addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
- NULL, false, false);
+ (void) addRangeTableEntryForRelation(pstate, rel, AccessShareLock,
+ NULL, false, false);
attnamelist = make_copy_attnamelist(relmapentry);
cstate = BeginCopyFrom(pstate, rel, NULL, false, copy_read_data, attnamelist, NIL);
{
Index old_exclRelIndex,
new_exclRelIndex;
+ ParseNamespaceItem *new_exclNSItem;
RangeTblEntry *new_exclRte;
List *tmp_tlist;
*/
old_exclRelIndex = parsetree->onConflict->exclRelIndex;
- new_exclRte = addRangeTableEntryForRelation(make_parsestate(NULL),
- base_rel,
- RowExclusiveLock,
- makeAlias("excluded", NIL),
- false, false);
+ 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 */
#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,
/*
* 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);
*
* 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
*/
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 */
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 */
/*
* 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
* 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
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);
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);
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)
qual_pstate = make_parsestate(NULL);
- rte = addRangeTableEntryForRelation(qual_pstate, relation, AccessShareLock,
- NULL, false, false);
- addRTEtoQuery(qual_pstate, rte, false, true, true);
+ nsitem = addRangeTableEntryForRelation(qual_pstate,
+ relation, AccessShareLock,
+ NULL, false, false);
+ addNSItemToQuery(qual_pstate, nsitem, false, true, true);
role = ObjectIdGetDatum(ACL_ID_PUBLIC);
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)
qual_pstate = make_parsestate(NULL);
- rte = addRangeTableEntryForRelation(qual_pstate, relation, AccessShareLock,
- NULL, false, false);
- addRTEtoQuery(qual_pstate, rte, false, true, true);
+ nsitem = addRangeTableEntryForRelation(qual_pstate,
+ relation, AccessShareLock,
+ NULL, false, false);
+ addNSItemToQuery(qual_pstate, nsitem, false, true, true);
role = ObjectIdGetDatum(ACL_ID_PUBLIC);