*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.284 2005/04/14 20:03:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.285 2005/06/05 00:38:07 tgl Exp $
*
*
* INTERFACE ROUTINES
NULL,
false,
true);
- addRTEtoQuery(pstate, rte, true, true);
+ addRTEtoQuery(pstate, rte, true, true, true);
/*
* Process column default expressions.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.159 2005/05/30 07:20:58 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.160 2005/06/05 00:38:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
NULL,
false,
true);
- addRTEtoQuery(pstate, rte, false, true);
+ addRTEtoQuery(pstate, rte, false, true, true);
transform = transformExpr(pstate, cmd->transform);
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.321 2005/04/28 21:47:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.322 2005/06/05 00:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Query *qry = makeNode(Query);
Query *selectQuery = NULL;
List *sub_rtable;
- List *sub_namespace;
+ List *sub_relnamespace;
+ List *sub_varnamespace;
List *icolumns;
List *attrnos;
ListCell *icols;
* SELECT. This can only happen if we are inside a CREATE RULE, and
* in that case we want the rule's OLD and NEW rtable entries to
* appear as part of the SELECT's rtable, not as outer references for
- * it. (Kluge!) The SELECT's joinlist is not affected however. We
+ * it. (Kluge!) The SELECT's joinlist is not affected however. We
* must do this before adding the target table to the INSERT's rtable.
*/
if (stmt->selectStmt)
{
sub_rtable = pstate->p_rtable;
pstate->p_rtable = NIL;
- sub_namespace = pstate->p_namespace;
- pstate->p_namespace = NIL;
+ sub_relnamespace = pstate->p_relnamespace;
+ pstate->p_relnamespace = NIL;
+ sub_varnamespace = pstate->p_varnamespace;
+ pstate->p_varnamespace = NIL;
}
else
{
sub_rtable = NIL; /* not used, but keep compiler quiet */
- sub_namespace = NIL;
+ sub_relnamespace = NIL;
+ sub_varnamespace = NIL;
}
/*
* through 6.5 had bugs of just that nature...)
*/
sub_pstate->p_rtable = sub_rtable;
- sub_pstate->p_namespace = sub_namespace;
+ sub_pstate->p_relnamespace = sub_relnamespace;
+ sub_pstate->p_varnamespace = sub_varnamespace;
/*
* Note: we are not expecting that extras_before and extras_after
rte = addRangeTableEntryForSubquery(pstate,
selectQuery,
makeAlias("*SELECT*", NIL),
- true);
+ false);
rtr = makeNode(RangeTblRef);
/* assume new rte is at end */
rtr->rtindex = list_length(pstate->p_rtable);
*/
rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true);
- /* no to join list, yes to namespace */
- addRTEtoQuery(pstate, rte, false, true);
+ /* no to join list, yes to namespaces */
+ addRTEtoQuery(pstate, rte, false, true, true);
stmt->whereClause = transformWhereClause(pstate, stmt->whereClause,
"WHERE");
{
rte = addRangeTableEntry(pstate, stmt->relation, NULL,
false, true);
- /* no to join list, yes to namespace */
- addRTEtoQuery(pstate, rte, false, true);
+ /* no to join list, yes to namespaces */
+ addRTEtoQuery(pstate, rte, false, true, true);
}
ielem->expr = transformExpr(pstate, ielem->expr);
Assert(pstate->p_rtable == NIL);
oldrte = addRangeTableEntryForRelation(pstate, rel,
makeAlias("*OLD*", NIL),
- false, true);
+ false, false);
newrte = addRangeTableEntryForRelation(pstate, rel,
makeAlias("*NEW*", NIL),
- false, true);
+ false, false);
/* Must override addRangeTableEntry's default access-check flags */
oldrte->requiredPerms = 0;
newrte->requiredPerms = 0;
* the one(s) that are relevant for the current kind of rule. In an
* UPDATE rule, quals must refer to OLD.field or NEW.field to be
* unambiguous, but there's no need to be so picky for INSERT &
- * DELETE. (Note we marked the RTEs "inFromCl = true" above to allow
- * unqualified references to their fields.) We do not add them to the
- * joinlist.
+ * DELETE. We do not add them to the joinlist.
*/
switch (stmt->event)
{
case CMD_SELECT:
- addRTEtoQuery(pstate, oldrte, false, true);
+ addRTEtoQuery(pstate, oldrte, false, true, true);
break;
case CMD_UPDATE:
- addRTEtoQuery(pstate, oldrte, false, true);
- addRTEtoQuery(pstate, newrte, false, true);
+ addRTEtoQuery(pstate, oldrte, false, true, true);
+ addRTEtoQuery(pstate, newrte, false, true, true);
break;
case CMD_INSERT:
- addRTEtoQuery(pstate, newrte, false, true);
+ addRTEtoQuery(pstate, newrte, false, true, true);
break;
case CMD_DELETE:
- addRTEtoQuery(pstate, oldrte, false, true);
+ addRTEtoQuery(pstate, oldrte, false, true, true);
break;
default:
elog(ERROR, "unrecognized event type: %d",
/*
* Set up OLD/NEW in the rtable for this statement. The
- * entries are marked not inFromCl because we don't want them
- * to be referred to by unqualified field names nor "*" in the
- * rule actions. We must add them to the namespace, however,
- * or they won't be accessible at all. We decide later
+ * entries are added only to relnamespace, not varnamespace,
+ * because we don't want them to be referred to by unqualified
+ * field names nor "*" in the rule actions. We decide later
* whether to put them in the joinlist.
*/
oldrte = addRangeTableEntryForRelation(sub_pstate, rel,
false, false);
oldrte->requiredPerms = 0;
newrte->requiredPerms = 0;
- addRTEtoQuery(sub_pstate, oldrte, false, true);
- addRTEtoQuery(sub_pstate, newrte, false, true);
+ addRTEtoQuery(sub_pstate, oldrte, false, true, false);
+ addRTEtoQuery(sub_pstate, newrte, false, true, false);
/* Transform the rule action statement */
top_subqry = transformStmt(sub_pstate, action,
/* 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);
+ addRTEtoQuery(sub_pstate, oldrte, true, false, false);
sub_qry->jointree->fromlist = sub_pstate->p_joinlist;
}
*dtlist;
List *targetvars,
*targetnames,
- *sv_namespace,
+ *sv_relnamespace,
+ *sv_varnamespace,
*sv_rtable;
RangeTblEntry *jrte;
- RangeTblRef *jrtr;
int tllen;
qry->commandType = CMD_SELECT;
/*
* As a first step towards supporting sort clauses that are
- * expressions using the output columns, generate a namespace entry
+ * expressions using the output columns, generate a varnamespace entry
* that makes the output columns visible. A Join RTE node is handy
* for this, since we can easily control the Vars generated upon
* matches.
JOIN_INNER,
targetvars,
NULL,
- true);
- jrtr = makeNode(RangeTblRef);
- jrtr->rtindex = 1; /* only entry in dummy rtable */
+ false);
sv_rtable = pstate->p_rtable;
pstate->p_rtable = list_make1(jrte);
- sv_namespace = pstate->p_namespace;
- pstate->p_namespace = list_make1(jrtr);
+ sv_relnamespace = pstate->p_relnamespace;
+ pstate->p_relnamespace = NIL; /* no qualified names allowed */
+
+ sv_varnamespace = pstate->p_varnamespace;
+ pstate->p_varnamespace = list_make1(jrte);
/*
* For now, we don't support resjunk sort clauses on the output of a
&qry->targetList,
false /* no unknowns expected */ );
- pstate->p_namespace = sv_namespace;
pstate->p_rtable = sv_rtable;
+ pstate->p_relnamespace = sv_relnamespace;
+ pstate->p_varnamespace = sv_varnamespace;
if (tllen != list_length(qry->targetList))
ereport(ERROR,
* happen because the namespace will be empty, but it could happen
* if we are inside a rule.
*/
- if (pstate->p_namespace)
+ if (pstate->p_relnamespace || pstate->p_varnamespace)
{
if (contain_vars_of_level((Node *) selectQuery, 1))
ereport(ERROR,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.141 2005/06/04 19:19:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.142 2005/06/05 00:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static Node *transformJoinUsingClause(ParseState *pstate,
List *leftVars, List *rightVars);
static Node *transformJoinOnClause(ParseState *pstate, JoinExpr *j,
- List *containedRels);
-static RangeTblRef *transformTableEntry(ParseState *pstate, RangeVar *r);
-static RangeTblRef *transformRangeSubselect(ParseState *pstate,
+ RangeTblEntry *l_rte,
+ RangeTblEntry *r_rte,
+ List *relnamespace,
+ Relids containedRels);
+static RangeTblEntry *transformTableEntry(ParseState *pstate, RangeVar *r);
+static RangeTblEntry *transformRangeSubselect(ParseState *pstate,
RangeSubselect *r);
-static RangeTblRef *transformRangeFunction(ParseState *pstate,
+static RangeTblEntry *transformRangeFunction(ParseState *pstate,
RangeFunction *r);
static Node *transformFromClauseItem(ParseState *pstate, Node *n,
- List **containedRels);
+ RangeTblEntry **top_rte, int *top_rti,
+ List **relnamespace,
+ Relids *containedRels);
static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
Var *l_colvar, Var *r_colvar);
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
/*
* transformFromClause -
* Process the FROM clause and add items to the query's range table,
- * joinlist, and namespace.
+ * joinlist, and namespaces.
*
- * Note: we assume that pstate's p_rtable, p_joinlist, and p_namespace lists
- * were initialized to NIL when the pstate was created. We will add onto
- * any entries already present --- this is needed for rule processing, as
- * well as for UPDATE and DELETE.
+ * Note: we assume that pstate's p_rtable, p_joinlist, p_relnamespace, and
+ * p_varnamespace lists were initialized to NIL when the pstate was created.
+ * We will add onto any entries already present --- this is needed for rule
+ * processing, as well as for UPDATE and DELETE.
*
* The range table may grow still further when we transform the expressions
* in the query's quals and target list. (This is possible because in
* The grammar will have produced a list of RangeVars,
* RangeSubselects, RangeFunctions, and/or JoinExprs. Transform each
* one (possibly adding entries to the rtable), check for duplicate
- * refnames, and then add it to the joinlist and namespace.
+ * refnames, and then add it to the joinlist and namespaces.
*/
foreach(fl, frmList)
{
Node *n = lfirst(fl);
- List *containedRels;
-
- n = transformFromClauseItem(pstate, n, &containedRels);
- checkNameSpaceConflicts(pstate, (Node *) pstate->p_namespace, n);
+ RangeTblEntry *rte;
+ int rtindex;
+ List *relnamespace;
+ Relids containedRels;
+
+ n = transformFromClauseItem(pstate, n,
+ &rte,
+ &rtindex,
+ &relnamespace,
+ &containedRels);
+ checkNameSpaceConflicts(pstate, pstate->p_relnamespace, relnamespace);
pstate->p_joinlist = lappend(pstate->p_joinlist, n);
- pstate->p_namespace = lappend(pstate->p_namespace, n);
+ pstate->p_relnamespace = list_concat(pstate->p_relnamespace,
+ relnamespace);
+ pstate->p_varnamespace = lappend(pstate->p_varnamespace, rte);
+ bms_free(containedRels);
}
}
rte->requiredPerms = requiredPerms;
/*
- * If UPDATE/DELETE, add table to joinlist and namespace.
+ * If UPDATE/DELETE, add table to joinlist and namespaces.
*/
if (alsoSource)
- addRTEtoQuery(pstate, rte, true, true);
+ addRTEtoQuery(pstate, rte, true, true, true);
return rtindex;
}
*/
static Node *
transformJoinOnClause(ParseState *pstate, JoinExpr *j,
- List *containedRels)
+ RangeTblEntry *l_rte,
+ RangeTblEntry *r_rte,
+ List *relnamespace,
+ Relids containedRels)
{
Node *result;
- List *save_namespace;
+ List *save_relnamespace;
+ List *save_varnamespace;
Relids clause_varnos;
int varno;
* can't legally alter the namespace by causing implicit relation refs
* to be added.
*/
- save_namespace = pstate->p_namespace;
- pstate->p_namespace = list_make2(j->larg, j->rarg);
+ save_relnamespace = pstate->p_relnamespace;
+ save_varnamespace = pstate->p_varnamespace;
+
+ pstate->p_relnamespace = relnamespace;
+ pstate->p_varnamespace = list_make2(l_rte, r_rte);
result = transformWhereClause(pstate, j->quals, "JOIN/ON");
- pstate->p_namespace = save_namespace;
+ pstate->p_relnamespace = save_relnamespace;
+ pstate->p_varnamespace = save_varnamespace;
/*
* Second, we need to check that the ON condition doesn't refer to any
* here.)
*/
clause_varnos = pull_varnos(result);
- while ((varno = bms_first_member(clause_varnos)) >= 0)
+ clause_varnos = bms_del_members(clause_varnos, containedRels);
+ if ((varno = bms_first_member(clause_varnos)) >= 0)
{
- if (!list_member_int(containedRels, varno))
- {
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
- errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN",
- rt_fetch(varno, pstate->p_rtable)->eref->aliasname)));
- }
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
+ errmsg("JOIN/ON clause refers to \"%s\", which is not part of JOIN",
+ rt_fetch(varno, pstate->p_rtable)->eref->aliasname)));
}
bms_free(clause_varnos);
/*
* transformTableEntry --- transform a RangeVar (simple relation reference)
*/
-static RangeTblRef *
+static RangeTblEntry *
transformTableEntry(ParseState *pstate, RangeVar *r)
{
RangeTblEntry *rte;
- RangeTblRef *rtr;
/*
* mark this entry to indicate it comes from the FROM clause. In SQL,
rte = addRangeTableEntry(pstate, r, r->alias,
interpretInhOption(r->inhOpt), true);
- /*
- * We create a RangeTblRef, but we do not add it to the joinlist or
- * namespace; our caller must do that if appropriate.
- */
- 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));
-
- return rtr;
+ return rte;
}
/*
* transformRangeSubselect --- transform a sub-SELECT appearing in FROM
*/
-static RangeTblRef *
+static RangeTblEntry *
transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
{
List *parsetrees;
Query *query;
RangeTblEntry *rte;
- RangeTblRef *rtr;
/*
* We require user to supply an alias for a subselect, per SQL92. To
* visible in the current query. Also note that outer references are
* OK.
*/
- if (pstate->p_namespace)
+ if (pstate->p_relnamespace || pstate->p_varnamespace)
{
if (contain_vars_of_level((Node *) query, 1))
ereport(ERROR,
*/
rte = addRangeTableEntryForSubquery(pstate, query, r->alias, true);
- /*
- * We create a RangeTblRef, but we do not add it to the joinlist or
- * namespace; our caller must do that if appropriate.
- */
- 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));
-
- return rtr;
+ return rte;
}
/*
* transformRangeFunction --- transform a function call appearing in FROM
*/
-static RangeTblRef *
+static RangeTblEntry *
transformRangeFunction(ParseState *pstate, RangeFunction *r)
{
Node *funcexpr;
char *funcname;
RangeTblEntry *rte;
- RangeTblRef *rtr;
/*
* Get function name for possible use as alias. We use the same
* XXX this will need further work to support SQL99's LATERAL() feature,
* wherein such references would indeed be legal.
*/
- if (pstate->p_namespace)
+ if (pstate->p_relnamespace || pstate->p_varnamespace)
{
if (contain_vars_of_level(funcexpr, 0))
ereport(ERROR,
rte = addRangeTableEntryForFunction(pstate, funcname, funcexpr,
r, true);
- /*
- * We create a RangeTblRef, but we do not add it to the joinlist or
- * namespace; our caller must do that if appropriate.
- */
- 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));
-
- return rtr;
+ return rte;
}
* transformFromClauseItem -
* Transform a FROM-clause item, adding any required entries to the
* range table list being built in the ParseState, and return the
- * transformed item ready to include in the joinlist and namespace.
+ * transformed item ready to include in the joinlist and namespaces.
* This routine can recurse to handle SQL92 JOIN expressions.
*
- * Aside from the primary return value (the transformed joinlist item)
- * this routine also returns an integer list of the rangetable indexes
- * of all the base and join relations represented in the joinlist item.
- * This list is needed for checking JOIN/ON conditions in higher levels.
+ * 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.)
+ *
+ * *relnamespace: receives a List of the RTEs exposed as relation names
+ * by this item.
+ *
+ * *containedRels: receives a bitmap set of the rangetable indexes
+ * of all the base and join relations represented in this jointree item.
+ * This is needed for checking JOIN/ON conditions in higher levels.
+ *
+ * We do not need to pass back an explicit varnamespace value, because
+ * in all cases the varnamespace contribution is exactly top_rte.
*/
static Node *
-transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
+transformFromClauseItem(ParseState *pstate, Node *n,
+ RangeTblEntry **top_rte, int *top_rti,
+ List **relnamespace,
+ Relids *containedRels)
{
if (IsA(n, RangeVar))
{
/* Plain relation reference */
RangeTblRef *rtr;
+ RangeTblEntry *rte;
+ int rtindex;
- rtr = transformTableEntry(pstate, (RangeVar *) n);
- *containedRels = list_make1_int(rtr->rtindex);
+ rte = transformTableEntry(pstate, (RangeVar *) 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;
+ *relnamespace = list_make1(rte);
+ *containedRels = bms_make_singleton(rtindex);
+ rtr = makeNode(RangeTblRef);
+ rtr->rtindex = rtindex;
return (Node *) rtr;
}
else if (IsA(n, RangeSubselect))
{
/* sub-SELECT is like a plain relation */
RangeTblRef *rtr;
+ RangeTblEntry *rte;
+ int rtindex;
- rtr = transformRangeSubselect(pstate, (RangeSubselect *) n);
- *containedRels = list_make1_int(rtr->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;
+ *relnamespace = list_make1(rte);
+ *containedRels = bms_make_singleton(rtindex);
+ rtr = makeNode(RangeTblRef);
+ rtr->rtindex = rtindex;
return (Node *) rtr;
}
else if (IsA(n, RangeFunction))
{
/* function is like a plain relation */
RangeTblRef *rtr;
+ RangeTblEntry *rte;
+ int rtindex;
- rtr = transformRangeFunction(pstate, (RangeFunction *) n);
- *containedRels = list_make1_int(rtr->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;
+ *relnamespace = list_make1(rte);
+ *containedRels = bms_make_singleton(rtindex);
+ rtr = makeNode(RangeTblRef);
+ rtr->rtindex = rtindex;
return (Node *) rtr;
}
else if (IsA(n, JoinExpr))
{
/* A newfangled join expression */
JoinExpr *j = (JoinExpr *) n;
- List *my_containedRels,
- *l_containedRels,
- *r_containedRels,
+ RangeTblEntry *l_rte;
+ RangeTblEntry *r_rte;
+ int l_rtindex;
+ int r_rtindex;
+ Relids l_containedRels,
+ r_containedRels,
+ my_containedRels;
+ List *l_relnamespace,
+ *r_relnamespace,
+ *my_relnamespace,
*l_colnames,
*r_colnames,
*res_colnames,
*l_colvars,
*r_colvars,
*res_colvars;
- Index leftrti,
- rightrti;
RangeTblEntry *rte;
/*
* Recursively process the left and right subtrees
*/
- j->larg = transformFromClauseItem(pstate, j->larg, &l_containedRels);
- j->rarg = transformFromClauseItem(pstate, j->rarg, &r_containedRels);
-
- /*
- * Generate combined list of relation indexes for possible use by
- * transformJoinOnClause below.
- */
- my_containedRels = list_concat(l_containedRels, r_containedRels);
+ j->larg = transformFromClauseItem(pstate, j->larg,
+ &l_rte,
+ &l_rtindex,
+ &l_relnamespace,
+ &l_containedRels);
+ j->rarg = transformFromClauseItem(pstate, j->rarg,
+ &r_rte,
+ &r_rtindex,
+ &r_relnamespace,
+ &r_containedRels);
/*
* Check for conflicting refnames in left and right subtrees. Must
* do this because higher levels will assume I hand back a self-
* consistent namespace subtree.
*/
- checkNameSpaceConflicts(pstate, j->larg, j->rarg);
+ checkNameSpaceConflicts(pstate, l_relnamespace, r_relnamespace);
+
+ /*
+ * Generate combined relation membership info for possible use by
+ * transformJoinOnClause below.
+ */
+ my_relnamespace = list_concat(l_relnamespace, r_relnamespace);
+ my_containedRels = bms_join(l_containedRels, r_containedRels);
+
+ pfree(r_relnamespace); /* free unneeded list header */
/*
* Extract column name and var lists from both subtrees
*
* Note: expandRTE returns new lists, safe for me to modify
*/
- if (IsA(j->larg, RangeTblRef))
- leftrti = ((RangeTblRef *) j->larg)->rtindex;
- else if (IsA(j->larg, JoinExpr))
- leftrti = ((JoinExpr *) j->larg)->rtindex;
- else
- {
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(j->larg));
- leftrti = 0; /* keep compiler quiet */
- }
- rte = rt_fetch(leftrti, pstate->p_rtable);
- expandRTE(rte, leftrti, 0, false,
+ expandRTE(l_rte, l_rtindex, 0, false,
&l_colnames, &l_colvars);
-
- if (IsA(j->rarg, RangeTblRef))
- rightrti = ((RangeTblRef *) j->rarg)->rtindex;
- else if (IsA(j->rarg, JoinExpr))
- rightrti = ((JoinExpr *) j->rarg)->rtindex;
- else
- {
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(j->rarg));
- rightrti = 0; /* keep compiler quiet */
- }
- rte = rt_fetch(rightrti, pstate->p_rtable);
- expandRTE(rte, rightrti, 0, false,
+ expandRTE(r_rte, r_rtindex, 0, false,
&r_colnames, &r_colvars);
/*
else if (j->quals)
{
/* User-written ON-condition; transform it */
- j->quals = transformJoinOnClause(pstate, j, my_containedRels);
+ j->quals = transformJoinOnClause(pstate, j,
+ l_rte, r_rte,
+ my_relnamespace,
+ my_containedRels);
}
else
{
j->rtindex = list_length(pstate->p_rtable);
Assert(rte == rt_fetch(j->rtindex, pstate->p_rtable));
+ *top_rte = rte;
+ *top_rti = j->rtindex;
+
+ /*
+ * Prepare returned namespace list. If the JOIN has an alias
+ * then it hides the contained RTEs as far as the relnamespace
+ * goes; otherwise, put the contained RTEs and *not* the JOIN
+ * into relnamespace.
+ */
+ if (j->alias)
+ {
+ *relnamespace = list_make1(rte);
+ list_free(my_relnamespace);
+ }
+ else
+ *relnamespace = my_relnamespace;
+
/*
- * Include join RTE in returned containedRels list
+ * Include join RTE in returned containedRels set
*/
- *containedRels = lcons_int(j->rtindex, my_containedRels);
+ *containedRels = bms_add_member(my_containedRels, j->rtindex);
return (Node *) j;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.110 2005/06/04 19:19:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.111 2005/06/05 00:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* GUC parameter */
bool add_missing_from;
-static Node *scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
- const char *refname);
-static Node *scanNameSpaceForRelid(ParseState *pstate, Node *nsnode,
- Oid relid);
-static void scanNameSpaceForConflict(ParseState *pstate, Node *nsnode,
- RangeTblEntry *rte1, const char *aliasname1);
+static RangeTblEntry *scanNameSpaceForRefname(ParseState *pstate,
+ const char *refname);
+static RangeTblEntry *scanNameSpaceForRelid(ParseState *pstate, Oid relid);
static bool isLockedRel(ParseState *pstate, char *refname);
static void expandRelation(Oid relid, Alias *eref,
int rtindex, int sublevels_up,
while (pstate != NULL)
{
- Node *nsnode;
+ RangeTblEntry *result;
if (OidIsValid(relId))
- nsnode = scanNameSpaceForRelid(pstate,
- (Node *) pstate->p_namespace,
- relId);
+ result = scanNameSpaceForRelid(pstate, relId);
else
- nsnode = scanNameSpaceForRefname(pstate,
- (Node *) pstate->p_namespace,
- refname);
+ result = scanNameSpaceForRefname(pstate, refname);
- if (nsnode)
- {
- /* should get an RTE or JoinExpr */
- if (IsA(nsnode, RangeTblEntry))
- return (RangeTblEntry *) nsnode;
- Assert(IsA(nsnode, JoinExpr));
- return rt_fetch(((JoinExpr *) nsnode)->rtindex, pstate->p_rtable);
- }
+ if (result)
+ return result;
- pstate = pstate->parentParseState;
if (sublevels_up)
(*sublevels_up)++;
else
break;
+
+ pstate = pstate->parentParseState;
}
return NULL;
}
/*
- * Recursively search a namespace for an RTE or joinexpr matching the
- * given unqualified refname. Return the node if a unique match, or NULL
+ * Search the query's table namespace for an RTE matching the
+ * given unqualified refname. Return the RTE if a unique match, or NULL
* if no match. Raise error if multiple matches.
- *
- * The top level of p_namespace is a list, and we recurse into any joins
- * that are not subqueries.
*/
-static Node *
-scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
- const char *refname)
+static RangeTblEntry *
+scanNameSpaceForRefname(ParseState *pstate, const char *refname)
{
- Node *result = NULL;
- Node *newresult;
+ RangeTblEntry *result = NULL;
+ ListCell *l;
- if (nsnode == NULL)
- return NULL;
- if (IsA(nsnode, RangeTblRef))
+ foreach(l, pstate->p_relnamespace)
{
- int varno = ((RangeTblRef *) nsnode)->rtindex;
- RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
if (strcmp(rte->eref->aliasname, refname) == 0)
- result = (Node *) rte;
- }
- else if (IsA(nsnode, JoinExpr))
- {
- JoinExpr *j = (JoinExpr *) nsnode;
-
- if (j->alias)
{
- if (strcmp(j->alias->aliasname, refname) == 0)
- return (Node *) j; /* matched a join alias */
-
- /*
- * Tables within an aliased join are invisible from outside
- * the join, according to the scope rules of SQL92 (the join
- * is considered a subquery). So, stop here.
- */
- return NULL;
- }
- result = scanNameSpaceForRefname(pstate, j->larg, refname);
- newresult = scanNameSpaceForRefname(pstate, j->rarg, refname);
- if (!result)
- result = newresult;
- else if (newresult)
- ereport(ERROR,
- (errcode(ERRCODE_AMBIGUOUS_ALIAS),
- errmsg("table reference \"%s\" is ambiguous",
- refname)));
- }
- else if (IsA(nsnode, List))
- {
- ListCell *l;
-
- foreach(l, (List *) nsnode)
- {
- newresult = scanNameSpaceForRefname(pstate, lfirst(l), refname);
- if (!result)
- result = newresult;
- else if (newresult)
+ if (result)
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_ALIAS),
errmsg("table reference \"%s\" is ambiguous",
refname)));
+ result = rte;
}
}
- else
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(nsnode));
return result;
}
/*
- * Recursively search a namespace for a relation RTE matching the
- * given relation OID. Return the node if a unique match, or NULL
+ * Search the query's table namespace for a relation RTE matching the
+ * given relation OID. Return the RTE if a unique match, or NULL
* if no match. Raise error if multiple matches (which shouldn't
* happen if the namespace was checked correctly when it was created).
*
- * The top level of p_namespace is a list, and we recurse into any joins
- * that are not subqueries.
- *
* See the comments for refnameRangeTblEntry to understand why this
* acts the way it does.
*/
-static Node *
-scanNameSpaceForRelid(ParseState *pstate, Node *nsnode, Oid relid)
+static RangeTblEntry *
+scanNameSpaceForRelid(ParseState *pstate, Oid relid)
{
- Node *result = NULL;
- Node *newresult;
+ RangeTblEntry *result = NULL;
+ ListCell *l;
- if (nsnode == NULL)
- return NULL;
- if (IsA(nsnode, RangeTblRef))
+ foreach(l, pstate->p_relnamespace)
{
- int varno = ((RangeTblRef *) nsnode)->rtindex;
- RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
/* yes, the test for alias==NULL should be there... */
if (rte->rtekind == RTE_RELATION &&
rte->relid == relid &&
rte->alias == NULL)
- result = (Node *) rte;
- }
- else if (IsA(nsnode, JoinExpr))
- {
- JoinExpr *j = (JoinExpr *) nsnode;
-
- if (j->alias)
{
- /*
- * Tables within an aliased join are invisible from outside
- * the join, according to the scope rules of SQL92 (the join
- * is considered a subquery). So, stop here.
- */
- return NULL;
- }
- result = scanNameSpaceForRelid(pstate, j->larg, relid);
- newresult = scanNameSpaceForRelid(pstate, j->rarg, relid);
- if (!result)
- result = newresult;
- else if (newresult)
- ereport(ERROR,
- (errcode(ERRCODE_AMBIGUOUS_ALIAS),
- errmsg("table reference %u is ambiguous",
- relid)));
- }
- else if (IsA(nsnode, List))
- {
- ListCell *l;
-
- foreach(l, (List *) nsnode)
- {
- newresult = scanNameSpaceForRelid(pstate, lfirst(l), relid);
- if (!result)
- result = newresult;
- else if (newresult)
+ if (result)
ereport(ERROR,
(errcode(ERRCODE_AMBIGUOUS_ALIAS),
errmsg("table reference %u is ambiguous",
relid)));
+ result = rte;
}
}
- else
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(nsnode));
return result;
}
/*
- * Recursively check for name conflicts between two namespaces or
- * namespace subtrees. Raise an error if any is found.
- *
- * Works by recursively scanning namespace1 for RTEs and join nodes,
- * and for each one recursively scanning namespace2 for a match.
+ * Check for relation-name conflicts between two relnamespace lists.
+ * Raise an error if any is found.
*
* Note: we assume that each given argument does not contain conflicts
* itself; we just want to know if the two can be merged together.
* are for different relation OIDs (implying they are in different schemas).
*/
void
-checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
- Node *namespace2)
+checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
+ List *namespace2)
{
- if (namespace1 == NULL)
- return;
- if (IsA(namespace1, RangeTblRef))
- {
- int varno = ((RangeTblRef *) namespace1)->rtindex;
- RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
-
- if (rte->rtekind == RTE_RELATION && rte->alias == NULL)
- scanNameSpaceForConflict(pstate, namespace2,
- rte, rte->eref->aliasname);
- else
- scanNameSpaceForConflict(pstate, namespace2,
- NULL, rte->eref->aliasname);
- }
- else if (IsA(namespace1, JoinExpr))
- {
- JoinExpr *j = (JoinExpr *) namespace1;
-
- if (j->alias)
- {
- scanNameSpaceForConflict(pstate, namespace2,
- NULL, j->alias->aliasname);
-
- /*
- * Tables within an aliased join are invisible from outside
- * the join, according to the scope rules of SQL92 (the join
- * is considered a subquery). So, stop here.
- */
- return;
- }
- checkNameSpaceConflicts(pstate, j->larg, namespace2);
- checkNameSpaceConflicts(pstate, j->rarg, namespace2);
- }
- else if (IsA(namespace1, List))
- {
- ListCell *l;
-
- foreach(l, (List *) namespace1)
- checkNameSpaceConflicts(pstate, lfirst(l), namespace2);
- }
- else
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(namespace1));
-}
+ ListCell *l1;
-/*
- * Subroutine for checkNameSpaceConflicts: scan namespace2
- */
-static void
-scanNameSpaceForConflict(ParseState *pstate, Node *nsnode,
- RangeTblEntry *rte1, const char *aliasname1)
-{
- if (nsnode == NULL)
- return;
- if (IsA(nsnode, RangeTblRef))
+ foreach(l1, namespace1)
{
- int varno = ((RangeTblRef *) nsnode)->rtindex;
- RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
-
- if (strcmp(rte->eref->aliasname, aliasname1) != 0)
- return; /* definitely no conflict */
- if (rte->rtekind == RTE_RELATION && rte->alias == NULL &&
- rte1 != NULL && rte->relid != rte1->relid)
- return; /* no conflict per SQL92 rule */
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_ALIAS),
- errmsg("table name \"%s\" specified more than once",
- aliasname1)));
- }
- else if (IsA(nsnode, JoinExpr))
- {
- JoinExpr *j = (JoinExpr *) nsnode;
+ RangeTblEntry *rte1 = (RangeTblEntry *) lfirst(l1);
+ const char *aliasname1 = rte1->eref->aliasname;
+ ListCell *l2;
- if (j->alias)
+ foreach(l2, namespace2)
{
- if (strcmp(j->alias->aliasname, aliasname1) == 0)
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_ALIAS),
+ RangeTblEntry *rte2 = (RangeTblEntry *) lfirst(l2);
+
+ if (strcmp(rte2->eref->aliasname, aliasname1) != 0)
+ continue; /* definitely no conflict */
+ if (rte1->rtekind == RTE_RELATION && rte1->alias == NULL &&
+ rte2->rtekind == RTE_RELATION && rte2->alias == NULL &&
+ rte1->relid != rte2->relid)
+ continue; /* no conflict per SQL92 rule */
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_ALIAS),
errmsg("table name \"%s\" specified more than once",
aliasname1)));
-
- /*
- * Tables within an aliased join are invisible from outside
- * the join, according to the scope rules of SQL92 (the join
- * is considered a subquery). So, stop here.
- */
- return;
}
- scanNameSpaceForConflict(pstate, j->larg, rte1, aliasname1);
- scanNameSpaceForConflict(pstate, j->rarg, rte1, aliasname1);
}
- else if (IsA(nsnode, List))
- {
- ListCell *l;
-
- foreach(l, (List *) nsnode)
- scanNameSpaceForConflict(pstate, lfirst(l), rte1, aliasname1);
- }
- else
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(nsnode));
}
/*
{
Node *result = NULL;
ParseState *orig_pstate = pstate;
- int levels_up = 0;
while (pstate != NULL)
{
- ListCell *ns;
-
- /*
- * We need to look only at top-level namespace items, and even for
- * those, ignore RTEs that are marked as not inFromCl and not the
- * query's target relation.
- */
- foreach(ns, pstate->p_namespace)
- {
- Node *nsnode = (Node *) lfirst(ns);
- Node *newresult = NULL;
-
- if (IsA(nsnode, RangeTblRef))
- {
- int varno = ((RangeTblRef *) nsnode)->rtindex;
- RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
-
- if (!rte->inFromCl &&
- rte != pstate->p_target_rangetblentry)
- continue;
-
- /* use orig_pstate here to get the right sublevels_up */
- newresult = scanRTEForColumn(orig_pstate, rte, colname);
- }
- else if (IsA(nsnode, JoinExpr))
- {
- int varno = ((JoinExpr *) nsnode)->rtindex;
- RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
+ ListCell *l;
- /* joins are always inFromCl, so no need to check */
- Assert(rte->inFromCl);
+ foreach(l, pstate->p_varnamespace)
+ {
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
+ Node *newresult;
- /* use orig_pstate here to get the right sublevels_up */
- newresult = scanRTEForColumn(orig_pstate, rte, colname);
- }
- else
- elog(ERROR, "unrecognized node type: %d",
- (int) nodeTag(nsnode));
+ /* use orig_pstate here to get the right sublevels_up */
+ newresult = scanRTEForColumn(orig_pstate, rte, colname);
if (newresult)
{
break; /* found, or don't want to look at parent */
pstate = pstate->parentParseState;
- levels_up++;
}
return result;
/*
* Add the given RTE as a top-level entry in the pstate's join list
- * and/or name space list. (We assume caller has checked for any
- * namespace conflict.)
+ * and/or name space lists. (We assume caller has checked for any
+ * namespace conflicts.)
*/
void
addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
- bool addToJoinList, bool addToNameSpace)
+ bool addToJoinList,
+ bool addToRelNameSpace, bool addToVarNameSpace)
{
- int rtindex = RTERangeTablePosn(pstate, rte, NULL);
- RangeTblRef *rtr = makeNode(RangeTblRef);
-
- rtr->rtindex = rtindex;
-
if (addToJoinList)
+ {
+ int rtindex = RTERangeTablePosn(pstate, rte, NULL);
+ RangeTblRef *rtr = makeNode(RangeTblRef);
+
+ rtr->rtindex = rtindex;
pstate->p_joinlist = lappend(pstate->p_joinlist, rtr);
- if (addToNameSpace)
- pstate->p_namespace = lappend(pstate->p_namespace, rtr);
+ }
+ if (addToRelNameSpace)
+ pstate->p_relnamespace = lappend(pstate->p_relnamespace, rte);
+ if (addToVarNameSpace)
+ pstate->p_varnamespace = lappend(pstate->p_varnamespace, rte);
}
/*
RangeTblEntry *rte;
rte = addRangeTableEntry(pstate, relation, NULL, false, false);
- addRTEtoQuery(pstate, rte, true, true);
+ /* Add to joinlist and relnamespace, but not varnamespace */
+ addRTEtoQuery(pstate, rte, true, true, false);
warnAutoRange(pstate, relation);
return rte;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.135 2005/06/04 19:19:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.136 2005/06/05 00:38:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* ExpandAllTables()
* Turns '*' (in the target list) into a list of targetlist entries.
*
- * tlist entries are generated for each relation appearing at the top level
- * of the query's namespace, except for RTEs marked not inFromCl. (These
- * may include NEW/OLD pseudo-entries, implicit RTEs, etc.)
+ * tlist entries are generated for each relation appearing in the query's
+ * varnamespace. We do not consider relnamespace because that would include
+ * input tables of aliasless JOINs, NEW/OLD pseudo-entries, implicit RTEs,
+ * etc.
*/
static List *
ExpandAllTables(ParseState *pstate)
{
List *target = NIL;
- bool found_table = false;
- ListCell *ns;
-
- foreach(ns, pstate->p_namespace)
- {
- Node *n = (Node *) lfirst(ns);
- int rtindex;
- RangeTblEntry *rte;
+ ListCell *l;
- if (IsA(n, RangeTblRef))
- rtindex = ((RangeTblRef *) n)->rtindex;
- else if (IsA(n, JoinExpr))
- rtindex = ((JoinExpr *) n)->rtindex;
- else
- {
- elog(ERROR, "unrecognized node type: %d", (int) nodeTag(n));
- rtindex = 0; /* keep compiler quiet */
- }
+ /* Check for SELECT *; */
+ if (!pstate->p_varnamespace)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("SELECT * with no tables specified is not valid")));
- /*
- * Ignore added-on relations that were not listed in the FROM
- * clause.
- */
- rte = rt_fetch(rtindex, pstate->p_rtable);
- if (!rte->inFromCl)
- continue;
+ foreach(l, pstate->p_varnamespace)
+ {
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
+ int rtindex = RTERangeTablePosn(pstate, rte, NULL);
- found_table = true;
target = list_concat(target,
expandRelAttrs(pstate, rte, rtindex, 0));
}
- /* Check for SELECT *; */
- if (!found_table)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("SELECT * with no tables specified is not valid")));
-
return target;
}
* back to source text
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.199 2005/06/03 23:05:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.200 2005/06/05 00:38:10 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
* We use the query's jointree as a guide to what to print. However,
* we must ignore auto-added RTEs that are marked not inFromCl. (These
* can only appear at the top level of the jointree, so it's
- * sufficient to check here.) Also ignore the rule pseudo-RTEs for NEW
- * and OLD.
+ * sufficient to check here.) This check also ensures we ignore
+ * the rule pseudo-RTEs for NEW and OLD.
*/
foreach(l, query->jointree->fromlist)
{
if (!rte->inFromCl)
continue;
- if (strcmp(rte->eref->aliasname, "*NEW*") == 0)
- continue;
- if (strcmp(rte->eref->aliasname, "*OLD*") == 0)
- continue;
}
if (first)
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.279 2005/06/03 23:05:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.280 2005/06/05 00:38:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* FROM clause, but POSTQUEL allows you to refer to tables not listed,
* in which case a range table entry will be generated. We still support
* this POSTQUEL feature, although there is some doubt whether it's
- * convenient or merely confusing. The flag is needed since an
- * implicitly-added RTE shouldn't change the namespace for unqualified
- * column names processed later, and it also shouldn't affect the
- * expansion of '*'.
+ * convenient or merely confusing. The flag is not actually needed
+ * anymore during parsing, since the parser uses a separate "namespace"
+ * data structure to control visibility, but it is needed by ruleutils.c
+ * to determine whether RTEs should be included in decompiled queries.
*
* requiredPerms and checkAsUser specify run-time access permissions
* checks to be performed at query startup. The user must have *all*
Alias *alias; /* user-written alias clause, if any */
Alias *eref; /* expanded reference names */
bool inh; /* inheritance requested? */
- bool inFromCl; /* present in FROM clause */
+ bool inFromCl; /* present in FROM clause? */
AclMode requiredPerms; /* bitmask of required access permissions */
AclId checkAsUser; /* if not zero, check access as this user */
} RangeTblEntry;
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.43 2005/04/28 21:47:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.44 2005/06/05 00:38:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* p_joinlist: list of join items (RangeTblRef and JoinExpr nodes) that
* will become the fromlist of the query's top-level FromExpr node.
*
- * p_namespace: list of join items that represents the current namespace
- * for table and column lookup. This may be just a subset of the rtable +
- * joinlist, and/or may contain entries that are not yet added to the main
- * joinlist. Note that an RTE that is present in p_namespace, but does not
- * have its inFromCl flag set, is accessible only with an explicit qualifier;
- * lookups of unqualified column names should ignore it.
+ * p_relnamespace: list of RTEs that represents the current namespace for
+ * table lookup, ie, those RTEs that are accessible by qualified names.
+ * This may be just a subset of the rtable + joinlist, and/or may contain
+ * entries that are not yet added to the main joinlist.
+ *
+ * p_varnamespace: list of RTEs that represents the current namespace for
+ * column lookup, ie, those RTEs that are accessible by unqualified names.
+ * This is different from p_relnamespace because a JOIN without an alias does
+ * not hide the contained tables (so they must still be in p_relnamespace)
+ * but it does hide their columns (unqualified references to the columns must
+ * refer to the JOIN, not the member tables). Also, we put POSTQUEL-style
+ * implicit RTEs into p_relnamespace but not p_varnamespace, so that they
+ * do not affect the set of columns available for unqualified references.
*
* p_paramtypes: an array of p_numparams type OIDs for $n parameter symbols
* (zeroth entry in array corresponds to $1). If p_variableparams is true, the
List *p_rtable; /* range table so far */
List *p_joinlist; /* join items so far (will become FromExpr
* node's fromlist) */
- List *p_namespace; /* current lookup namespace (join items) */
+ List *p_relnamespace; /* current namespace for relations */
+ List *p_varnamespace; /* current namespace for columns */
Oid *p_paramtypes; /* OIDs of types for $n parameter symbols */
int p_numparams; /* allocated size of p_paramtypes[] */
int p_next_resno; /* next targetlist resno to assign */
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.50 2005/06/04 19:19:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.51 2005/06/05 00:38:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
const char *schemaname,
const char *refname,
int *sublevels_up);
-extern void checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
- Node *namespace2);
+extern void checkNameSpaceConflicts(ParseState *pstate, List *namespace1,
+ List *namespace2);
extern int RTERangeTablePosn(ParseState *pstate,
RangeTblEntry *rte,
int *sublevels_up);
Alias *alias,
bool inFromCl);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
- bool addToJoinList, bool addToNameSpace);
+ bool addToJoinList,
+ bool addToRelNameSpace, bool addToVarNameSpace);
extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation);
extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
bool include_dropped,