* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.28 2002/08/06 05:40:44 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.29 2002/08/08 01:44:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* Returns the namespace OID. Raises elog if any problem.
*/
Oid
-LookupExplicitNamespace(char *nspname)
+LookupExplicitNamespace(const char *nspname)
{
Oid namespaceId;
AclResult aclresult;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.124 2002/08/04 06:46:12 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.125 2002/08/08 01:44:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Try to identify as an unqualified column */
node = colnameToVar(pstate, name);
+
if (node == NULL)
{
/*
* try to find the name as a relation ... but not if
* subscripts appear. Note also that only relations
* already entered into the rangetable will be recognized.
+ *
+ * This is a hack for backwards compatibility with PostQUEL-
+ * inspired syntax. The preferred form now is "rel.*".
*/
int levels_up;
if (cref->indirection == NIL &&
- refnameRangeTblEntry(pstate, name, &levels_up) != NULL)
+ refnameRangeTblEntry(pstate, NULL, name,
+ &levels_up) != NULL)
{
rv = makeNode(RangeVar);
rv->relname = name;
}
/* Try to identify as a once-qualified column */
- node = qualifiedNameToVar(pstate, name1, name2, true);
+ node = qualifiedNameToVar(pstate, NULL, name1, name2, true);
if (node == NULL)
{
/*
}
/* Try to identify as a twice-qualified column */
- /* XXX do something with schema name here */
- node = qualifiedNameToVar(pstate, name2, name3, true);
+ node = qualifiedNameToVar(pstate, name1, name2, name3, true);
if (node == NULL)
{
/* Try it as a function call */
}
/* Try to identify as a twice-qualified column */
- /* XXX do something with schema name here */
- node = qualifiedNameToVar(pstate, name3, name4, true);
+ node = qualifiedNameToVar(pstate, name2, name3, name4, true);
if (node == NULL)
{
/* Try it as a function call */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.133 2002/08/02 18:15:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.134 2002/08/08 01:44:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
static FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids,
FuncCandidateList candidates);
+static void unknown_attribute(const char *schemaname, const char *relname,
+ const char *attname);
/*
Oid funcid;
List *i;
Node *first_arg = NULL;
- char *refname;
int nargs = length(fargs);
int argn;
Oid oid_array[FUNC_MAX_ARGS];
if (IsA(first_arg, RangeVar))
{
/* First arg is a relation. This could be a projection. */
- refname = ((RangeVar *) first_arg)->relname;
-
- /* XXX WRONG: ignores possible qualification of argument */
- retval = qualifiedNameToVar(pstate, refname, cname, true);
+ retval = qualifiedNameToVar(pstate,
+ ((RangeVar *) first_arg)->schemaname,
+ ((RangeVar *) first_arg)->relname,
+ cname,
+ true);
if (retval)
return retval;
}
if (IsA(arg, RangeVar))
{
+ char *schemaname;
+ char *relname;
RangeTblEntry *rte;
int vnum;
int sublevels_up;
/*
- * a relation
+ * a relation: look it up in the range table, or add if needed
*/
- refname = ((RangeVar *) arg)->relname;
+ schemaname = ((RangeVar *) arg)->schemaname;
+ relname = ((RangeVar *) arg)->relname;
- rte = refnameRangeTblEntry(pstate, refname,
+ rte = refnameRangeTblEntry(pstate, schemaname, relname,
&sublevels_up);
if (rte == NULL)
* named tuple type
*/
if (is_column)
- elog(ERROR, "No such attribute %s.%s",
- refname, strVal(lfirst(funcname)));
+ unknown_attribute(schemaname, relname,
+ strVal(lfirst(funcname)));
else
elog(ERROR, "Cannot pass result of sub-select or join %s to a function",
- refname);
+ relname);
toid = InvalidOid; /* keep compiler quiet */
break;
}
Assert(nargs == 1);
if (IsA(first_arg, RangeVar))
- elog(ERROR, "No such attribute %s.%s",
- ((RangeVar *) first_arg)->relname, colname);
+ unknown_attribute(((RangeVar *) first_arg)->schemaname,
+ ((RangeVar *) first_arg)->relname,
+ colname);
relTypeId = exprType(first_arg);
if (!ISCOMPLEX(relTypeId))
elog(ERROR, "Attribute notation .%s applied to type %s, which is not a complex type",
}
/*
+ * Simple helper routine for delivering "No such attribute" error message
+ */
+static void
+unknown_attribute(const char *schemaname, const char *relname,
+ const char *attname)
+{
+ if (schemaname)
+ elog(ERROR, "No such attribute %s.%s.%s",
+ schemaname, relname, attname);
+ else
+ elog(ERROR, "No such attribute %s.%s",
+ relname, attname);
+}
+
+/*
* Error message when function lookup fails that gives details of the
* argument types
*/
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.75 2002/08/06 05:34:10 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.76 2002/08/08 01:44:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/heapam.h"
#include "access/htup.h"
#include "catalog/heap.h"
+#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "parser/parsetree.h"
static Node *scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
- char *refname);
+ 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 Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
char *colname);
static bool isForUpdate(ParseState *pstate, char *refname);
/*
* refnameRangeTblEntry
- * Given a refname, look to see if it matches any RTE.
- * If so, return a pointer to the RangeTblEntry.
- * Optionally get its nesting depth (0 = current). If sublevels_up
- * is NULL, only consider items at the current nesting level.
+ * Given a possibly-qualified refname, look to see if it matches any RTE.
+ * If so, return a pointer to the RangeTblEntry; else return NULL.
+ *
+ * Optionally get RTE's nesting depth (0 = current) into *sublevels_up.
+ * If sublevels_up is NULL, only consider items at the current nesting
+ * level.
+ *
+ * An unqualified refname (schemaname == NULL) can match any RTE with matching
+ * alias, or matching unqualified relname in the case of alias-less relation
+ * RTEs. It is possible that such a refname matches multiple RTEs in the
+ * nearest nesting level that has a match; if so, we report an error via elog.
+ *
+ * A qualified refname (schemaname != NULL) can only match a relation RTE
+ * that (a) has no alias and (b) is for the same relation identified by
+ * schemaname.refname. In this case we convert schemaname.refname to a
+ * relation OID and search by relid, rather than by alias name. This is
+ * peculiar, but it's what SQL92 says to do.
*/
RangeTblEntry *
refnameRangeTblEntry(ParseState *pstate,
- char *refname,
+ const char *schemaname,
+ const char *refname,
int *sublevels_up)
{
+ Oid relId = InvalidOid;
+
if (sublevels_up)
*sublevels_up = 0;
+ if (schemaname != NULL)
+ {
+ Oid namespaceId;
+
+ namespaceId = LookupExplicitNamespace(schemaname);
+ relId = get_relname_relid(refname, namespaceId);
+ if (!OidIsValid(relId))
+ return NULL;
+ }
+
while (pstate != NULL)
{
Node *nsnode;
- nsnode = scanNameSpaceForRefname(pstate,
- (Node *) pstate->p_namespace,
- refname);
+ if (OidIsValid(relId))
+ nsnode = scanNameSpaceForRelid(pstate,
+ (Node *) pstate->p_namespace,
+ relId);
+ else
+ nsnode = scanNameSpaceForRefname(pstate,
+ (Node *) pstate->p_namespace,
+ refname);
+
if (nsnode)
{
/* should get an RTE or JoinExpr */
}
/*
- * Recursively search a namespace for an RTE or joinexpr with given refname.
+ * Recursively search a namespace for an RTE or joinexpr matching the
+ * given unqualified refname. Return the node 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. It is also possible to pass an individual
- * join subtree (useful when checking for name conflicts within a scope).
- *
- * Note: we do not worry about the possibility of multiple matches;
- * we assume the code that built the namespace checked for duplicates.
+ * that are not subqueries.
*/
static Node *
scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
- char *refname)
+ const char *refname)
{
Node *result = NULL;
+ Node *newresult;
if (nsnode == NULL)
return NULL;
return NULL;
}
result = scanNameSpaceForRefname(pstate, j->larg, refname);
+ newresult = scanNameSpaceForRefname(pstate, j->rarg, refname);
if (!result)
- result = scanNameSpaceForRefname(pstate, j->rarg, refname);
+ result = newresult;
+ else if (newresult)
+ elog(ERROR, "Table reference \"%s\" is ambiguous", refname);
}
else if (IsA(nsnode, List))
{
foreach(l, (List *) nsnode)
{
- result = scanNameSpaceForRefname(pstate, lfirst(l), refname);
- if (result)
- break;
+ newresult = scanNameSpaceForRefname(pstate, lfirst(l), refname);
+ if (!result)
+ result = newresult;
+ else if (newresult)
+ elog(ERROR, "Table reference \"%s\" is ambiguous", refname);
}
}
else
return result;
}
-/* Convenience subroutine for checkNameSpaceConflicts */
-static void
-scanNameSpaceForConflict(ParseState *pstate, Node *nsnode,
- char *refname)
+/*
+ * Recursively search a namespace for a relation RTE matching the
+ * given relation OID. Return the node 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)
{
- if (scanNameSpaceForRefname(pstate, nsnode, refname) != NULL)
- elog(ERROR, "Table name \"%s\" specified more than once", refname);
+ Node *result = NULL;
+ Node *newresult;
+
+ if (nsnode == NULL)
+ return NULL;
+ if (IsA(nsnode, RangeTblRef))
+ {
+ int varno = ((RangeTblRef *) nsnode)->rtindex;
+ RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
+
+ /* 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)
+ elog(ERROR, "Table reference %u is ambiguous", relid);
+ }
+ else if (IsA(nsnode, List))
+ {
+ List *l;
+
+ foreach(l, (List *) nsnode)
+ {
+ newresult = scanNameSpaceForRelid(pstate, lfirst(l), relid);
+ if (!result)
+ result = newresult;
+ else if (newresult)
+ elog(ERROR, "Table reference %u is ambiguous", relid);
+ }
+ }
+ else
+ elog(ERROR, "scanNameSpaceForRelid: unexpected node type %d",
+ nodeTag(nsnode));
+ return result;
}
/*
- * Recursively check for refname conflicts between two namespaces or
+ * Recursively check for name conflicts between two namespaces or
* namespace subtrees. Raise an error if any is found.
*
- * Works by recursively scanning namespace1 in the same way that
- * scanNameSpaceForRefname does, and then looking in namespace2 for
- * a match to each refname found in namespace1.
+ * Works by recursively scanning namespace1 for RTEs and join nodes,
+ * and for each one recursively scanning namespace2 for a match.
*
* Note: we assume that each given argument does not contain conflicts
* itself; we just want to know if the two can be merged together.
+ *
+ * Per SQL92, two alias-less plain relation RTEs do not conflict even if
+ * they have the same eref->aliasname (ie, same relation name), if they
+ * are for different relation OIDs (implying they are in different schemas).
*/
void
checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
int varno = ((RangeTblRef *) namespace1)->rtindex;
RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
- scanNameSpaceForConflict(pstate, namespace2, rte->eref->aliasname);
+ 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))
{
if (j->alias)
{
- scanNameSpaceForConflict(pstate, namespace2, j->alias->aliasname);
+ scanNameSpaceForConflict(pstate, namespace2,
+ NULL, j->alias->aliasname);
/*
* Tables within an aliased join are invisible from outside
List *l;
foreach(l, (List *) namespace1)
+ {
checkNameSpaceConflicts(pstate, lfirst(l), namespace2);
+ }
}
else
elog(ERROR, "checkNameSpaceConflicts: unexpected node type %d",
}
/*
+ * 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))
+ {
+ 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 */
+ elog(ERROR, "Table name \"%s\" specified more than once",
+ aliasname1);
+ }
+ else if (IsA(nsnode, JoinExpr))
+ {
+ JoinExpr *j = (JoinExpr *) nsnode;
+
+ if (j->alias)
+ {
+ if (strcmp(j->alias->aliasname, aliasname1) == 0)
+ elog(ERROR, "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))
+ {
+ List *l;
+
+ foreach(l, (List *) nsnode)
+ {
+ scanNameSpaceForConflict(pstate, lfirst(l), rte1, aliasname1);
+ }
+ }
+ else
+ elog(ERROR, "scanNameSpaceForConflict: unexpected node type %d",
+ nodeTag(nsnode));
+}
+
+/*
* given an RTE, return RT index (starting with 1) of the entry,
* and optionally get its nesting depth (0 = current). If sublevels_up
* is NULL, only consider rels at the current nesting level.
/*
* qualifiedNameToVar
- * Search for a qualified column name (refname + column name).
+ * Search for a qualified column name: either refname.colname or
+ * schemaname.relname.colname.
+ *
* If found, return the appropriate Var node.
* If not found, return NULL. If the name proves ambiguous, raise error.
*/
Node *
-qualifiedNameToVar(ParseState *pstate, char *refname, char *colname,
+qualifiedNameToVar(ParseState *pstate,
+ char *schemaname,
+ char *refname,
+ char *colname,
bool implicitRTEOK)
{
RangeTblEntry *rte;
int sublevels_up;
- rte = refnameRangeTblEntry(pstate, refname, &sublevels_up);
+ rte = refnameRangeTblEntry(pstate, schemaname, refname, &sublevels_up);
if (rte == NULL)
{
if (!implicitRTEOK)
return NULL;
- rte = addImplicitRTE(pstate, makeRangeVar(NULL, refname));
+ rte = addImplicitRTE(pstate, makeRangeVar(schemaname, refname));
}
return scanRTEForColumn(pstate, rte, colname);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.86 2002/08/02 18:15:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.87 2002/08/08 01:44:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
break;
}
- /* XXX do something with schema name */
- rte = refnameRangeTblEntry(pstate, relname,
+ rte = refnameRangeTblEntry(pstate, schemaname, relname,
&sublevels_up);
if (rte == NULL)
- rte = addImplicitRTE(pstate, makeRangeVar(NULL, relname));
+ rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
+ relname));
p_target = nconc(p_target,
expandRelAttrs(pstate, rte));
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.112 2002/07/18 23:11:28 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.113 2002/08/08 01:44:31 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
bool force_colno,
deparse_context *context);
static void get_names_for_var(Var *var, deparse_context *context,
- char **refname, char **attname);
+ char **schemaname, char **refname, char **attname);
+static RangeTblEntry *find_rte_by_refname(const char *refname,
+ deparse_context *context);
static void get_rule_expr(Node *node, deparse_context *context);
static void get_oper_expr(Expr *expr, deparse_context *context);
static void get_func_expr(Expr *expr, deparse_context *context);
else
{
Var *var = (Var *) (tle->expr);
+ char *schemaname;
char *refname;
char *attname;
- get_names_for_var(var, context, &refname, &attname);
+ get_names_for_var(var, context, &schemaname, &refname, &attname);
tell_as = (attname == NULL ||
strcmp(attname, tle->resdom->resname) != 0);
}
/*
- * Get the relation refname and attname for a (possibly nonlocal) Var.
+ * Get the schemaname, refname and attname for a (possibly nonlocal) Var.
+ *
+ * schemaname is usually returned as NULL. It will be non-null only if
+ * use of the unqualified refname would find the wrong RTE.
*
* refname will be returned as NULL if the Var references an unnamed join.
* In this case the Var *must* be displayed without any qualification.
*
* attname will be returned as NULL if the Var represents a whole tuple
- * of the relation.
+ * of the relation. (Typically we'd want to display the Var as "foo.*",
+ * but it's convenient to return NULL to make it easier for callers to
+ * distinguish this case.)
*/
static void
get_names_for_var(Var *var, deparse_context *context,
- char **refname, char **attname)
+ char **schemaname, char **refname, char **attname)
{
List *nslist = context->namespaces;
int sup = var->varlevelsup;
var->varno);
/* Emit results */
- if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
- *refname = NULL;
- else
- *refname = rte->eref->aliasname;
+ *schemaname = NULL; /* default assumptions */
+ *refname = rte->eref->aliasname;
+
+ /* Exceptions occur only if the RTE is alias-less */
+ if (rte->alias == NULL)
+ {
+ if (rte->rtekind == RTE_RELATION)
+ {
+ /*
+ * It's possible that use of the bare refname would find another
+ * more-closely-nested RTE, or be ambiguous, in which case
+ * we need to specify the schemaname to avoid these errors.
+ */
+ if (find_rte_by_refname(rte->eref->aliasname, context) != rte)
+ *schemaname =
+ get_namespace_name(get_rel_namespace(rte->relid));
+ }
+ else if (rte->rtekind == RTE_JOIN)
+ {
+ /* Unnamed join has neither schemaname nor refname */
+ *refname = NULL;
+ }
+ }
if (var->varattno == InvalidAttrNumber)
*attname = NULL;
*attname = get_rte_attribute_name(rte, var->varattno);
}
+/*
+ * find_rte_by_refname - look up an RTE by refname in a deparse context
+ *
+ * Returns NULL if there is no matching RTE or the refname is ambiguous.
+ *
+ * NOTE: this code is not really correct since it does not take account of
+ * the fact that not all the RTEs in a rangetable may be visible from the
+ * point where a Var reference appears. For the purposes we need, however,
+ * the only consequence of a false match is that we might stick a schema
+ * qualifier on a Var that doesn't really need it. So it seems close
+ * enough.
+ */
+static RangeTblEntry *
+find_rte_by_refname(const char *refname, deparse_context *context)
+{
+ RangeTblEntry *result = NULL;
+ List *nslist;
+
+ foreach(nslist, context->namespaces)
+ {
+ deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist);
+ List *rtlist;
+
+ foreach(rtlist, dpns->rtable)
+ {
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(rtlist);
+
+ if (strcmp(rte->eref->aliasname, refname) == 0)
+ {
+ if (result)
+ return NULL; /* it's ambiguous */
+ result = rte;
+ }
+ }
+ if (dpns->outer_rte &&
+ strcmp(dpns->outer_rte->eref->aliasname, refname) == 0)
+ {
+ if (result)
+ return NULL; /* it's ambiguous */
+ result = dpns->outer_rte;
+ }
+ if (dpns->inner_rte &&
+ strcmp(dpns->inner_rte->eref->aliasname, refname) == 0)
+ {
+ if (result)
+ return NULL; /* it's ambiguous */
+ result = dpns->inner_rte;
+ }
+ if (result)
+ break;
+ }
+ return result;
+}
+
+
/* ----------
* get_rule_expr - Parse back an expression
* ----------
case T_Var:
{
Var *var = (Var *) node;
+ char *schemaname;
char *refname;
char *attname;
- get_names_for_var(var, context, &refname, &attname);
+ get_names_for_var(var, context,
+ &schemaname, &refname, &attname);
if (refname && (context->varprefix || attname == NULL))
{
+ if (schemaname)
+ appendStringInfo(buf, "%s.",
+ quote_identifier(schemaname));
+
if (strcmp(refname, "*NEW*") == 0)
- appendStringInfo(buf, "new");
+ appendStringInfo(buf, "new.");
else if (strcmp(refname, "*OLD*") == 0)
- appendStringInfo(buf, "old");
+ appendStringInfo(buf, "old.");
else
- appendStringInfo(buf, "%s",
+ appendStringInfo(buf, "%s.",
quote_identifier(refname));
- if (attname)
- appendStringInfoChar(buf, '.');
}
if (attname)
appendStringInfo(buf, "%s", quote_identifier(attname));
+ else
+ appendStringInfo(buf, "*");
}
break;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: namespace.h,v 1.18 2002/08/06 05:40:45 ishii Exp $
+ * $Id: namespace.h,v 1.19 2002/08/08 01:44:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void DeconstructQualifiedName(List *names,
char **nspname_p,
char **objname_p);
-extern Oid LookupExplicitNamespace(char *nspname);
+extern Oid LookupExplicitNamespace(const char *nspname);
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
extern RangeVar *makeRangeVarFromNameList(List *names);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_relation.h,v 1.37 2002/08/05 02:30:50 tgl Exp $
+ * $Id: parse_relation.h,v 1.38 2002/08/08 01:44:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "parser/parse_node.h"
extern RangeTblEntry *refnameRangeTblEntry(ParseState *pstate,
- char *refname,
+ const char *schemaname,
+ const char *refname,
int *sublevels_up);
extern void checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
Node *namespace2);
RangeTblEntry *rte,
int *sublevels_up);
extern Node *colnameToVar(ParseState *pstate, char *colname);
-extern Node *qualifiedNameToVar(ParseState *pstate, char *refname,
- char *colname, bool implicitRTEOK);
+extern Node *qualifiedNameToVar(ParseState *pstate,
+ char *schemaname,
+ char *refname,
+ char *colname,
+ bool implicitRTEOK);
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
RangeVar *relation,
Alias *alias,