* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.16 2002/04/30 01:26:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.17 2002/05/01 23:06:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_shadow.h"
+#include "catalog/pg_type.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
}
/*
+ * RelationIsVisible
+ * Determine whether a relation (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified relation name".
+ */
+bool
+RelationIsVisible(Oid relid)
+{
+ HeapTuple reltup;
+ Form_pg_class relform;
+ Oid relnamespace;
+ bool visible;
+
+ recomputeNamespacePath();
+
+ reltup = SearchSysCache(RELOID,
+ ObjectIdGetDatum(relid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(reltup))
+ elog(ERROR, "Cache lookup failed for relation %u", relid);
+ relform = (Form_pg_class) GETSTRUCT(reltup);
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible.
+ */
+ relnamespace = relform->relnamespace;
+ if (relnamespace != myTempNamespace &&
+ relnamespace != PG_CATALOG_NAMESPACE &&
+ !intMember(relnamespace, namespaceSearchPath))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another relation of the same name earlier in the path.
+ * So we must do a slow check to see if this rel would be found by
+ * RelnameGetRelid.
+ */
+ char *relname = NameStr(relform->relname);
+
+ visible = (RelnameGetRelid(relname) == relid);
+ }
+
+ ReleaseSysCache(reltup);
+
+ return visible;
+}
+
+
+/*
* TypenameGetTypid
* Try to resolve an unqualified datatype name.
* Returns OID if type found in search path, else InvalidOid.
}
/*
- * OpclassnameGetOpcid
- * Try to resolve an unqualified index opclass name.
- * Returns OID if opclass found in search path, else InvalidOid.
- *
- * This is essentially the same as TypenameGetTypid, but we have to have
- * an extra argument for the index AM OID.
+ * TypeIsVisible
+ * Determine whether a type (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified type name".
*/
-Oid
-OpclassnameGetOpcid(Oid amid, const char *opcname)
+bool
+TypeIsVisible(Oid typid)
{
- Oid opcid;
- List *lptr;
+ HeapTuple typtup;
+ Form_pg_type typform;
+ Oid typnamespace;
+ bool visible;
recomputeNamespacePath();
- /*
- * If system namespace is not in path, implicitly search it before path
- */
- if (!pathContainsSystemNamespace)
- {
- opcid = GetSysCacheOid(CLAAMNAMENSP,
- ObjectIdGetDatum(amid),
- PointerGetDatum(opcname),
- ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
- 0);
- if (OidIsValid(opcid))
- return opcid;
- }
+ typtup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(typid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(typtup))
+ elog(ERROR, "Cache lookup failed for type %u", typid);
+ typform = (Form_pg_type) GETSTRUCT(typtup);
/*
- * Else search the path
+ * Quick check: if it ain't in the path at all, it ain't visible.
*/
- foreach(lptr, namespaceSearchPath)
+ typnamespace = typform->typnamespace;
+ if (typnamespace != PG_CATALOG_NAMESPACE &&
+ !intMember(typnamespace, namespaceSearchPath))
+ visible = false;
+ else
{
- Oid namespaceId = (Oid) lfirsti(lptr);
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another type of the same name earlier in the path.
+ * So we must do a slow check to see if this type would be found by
+ * TypenameGetTypid.
+ */
+ char *typname = NameStr(typform->typname);
- opcid = GetSysCacheOid(CLAAMNAMENSP,
- ObjectIdGetDatum(amid),
- PointerGetDatum(opcname),
- ObjectIdGetDatum(namespaceId),
- 0);
- if (OidIsValid(opcid))
- return opcid;
+ visible = (TypenameGetTypid(typname) == typid);
}
- /* Not found in path */
- return InvalidOid;
+ ReleaseSysCache(typtup);
+
+ return visible;
}
+
/*
* FuncnameGetCandidates
* Given a possibly-qualified function name and argument count,
}
/*
+ * FunctionIsVisible
+ * Determine whether a function (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified function name with exact argument matches".
+ */
+bool
+FunctionIsVisible(Oid funcid)
+{
+ HeapTuple proctup;
+ Form_pg_proc procform;
+ Oid pronamespace;
+ bool visible;
+
+ recomputeNamespacePath();
+
+ proctup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(proctup))
+ elog(ERROR, "Cache lookup failed for procedure %u", funcid);
+ procform = (Form_pg_proc) GETSTRUCT(proctup);
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible.
+ */
+ pronamespace = procform->pronamespace;
+ if (pronamespace != PG_CATALOG_NAMESPACE &&
+ !intMember(pronamespace, namespaceSearchPath))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another proc of the same name and arguments earlier
+ * in the path. So we must do a slow check to see if this is the
+ * same proc that would be found by FuncnameGetCandidates.
+ */
+ char *proname = NameStr(procform->proname);
+ int nargs = procform->pronargs;
+ FuncCandidateList clist;
+
+ visible = false;
+
+ clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs);
+
+ for (; clist; clist = clist->next)
+ {
+ if (memcmp(clist->args, procform->proargtypes,
+ nargs * sizeof(Oid)) == 0)
+ {
+ /* Found the expected entry; is it the right proc? */
+ visible = (clist->oid == funcid);
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(proctup);
+
+ return visible;
+}
+
+
+/*
* OpernameGetCandidates
* Given a possibly-qualified operator name and operator kind,
* retrieve a list of the possible matches.
}
/*
+ * OperatorIsVisible
+ * Determine whether an operator (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified operator name with exact argument matches".
+ */
+bool
+OperatorIsVisible(Oid oprid)
+{
+ HeapTuple oprtup;
+ Form_pg_operator oprform;
+ Oid oprnamespace;
+ bool visible;
+
+ recomputeNamespacePath();
+
+ oprtup = SearchSysCache(OPEROID,
+ ObjectIdGetDatum(oprid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(oprtup))
+ elog(ERROR, "Cache lookup failed for operator %u", oprid);
+ oprform = (Form_pg_operator) GETSTRUCT(oprtup);
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible.
+ */
+ oprnamespace = oprform->oprnamespace;
+ if (oprnamespace != PG_CATALOG_NAMESPACE &&
+ !intMember(oprnamespace, namespaceSearchPath))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another operator of the same name and arguments earlier
+ * in the path. So we must do a slow check to see if this is the
+ * same operator that would be found by OpernameGetCandidates.
+ */
+ char *oprname = NameStr(oprform->oprname);
+ FuncCandidateList clist;
+
+ visible = false;
+
+ clist = OpernameGetCandidates(makeList1(makeString(oprname)),
+ oprform->oprkind);
+
+ for (; clist; clist = clist->next)
+ {
+ if (clist->args[0] == oprform->oprleft &&
+ clist->args[1] == oprform->oprright)
+ {
+ /* Found the expected entry; is it the right op? */
+ visible = (clist->oid == oprid);
+ break;
+ }
+ }
+ }
+
+ ReleaseSysCache(oprtup);
+
+ return visible;
+}
+
+
+/*
* OpclassGetCandidates
* Given an index access method OID, retrieve a list of all the
* opclasses for that AM that are visible in the search path.
return resultList;
}
+/*
+ * OpclassnameGetOpcid
+ * Try to resolve an unqualified index opclass name.
+ * Returns OID if opclass found in search path, else InvalidOid.
+ *
+ * This is essentially the same as TypenameGetTypid, but we have to have
+ * an extra argument for the index AM OID.
+ */
+Oid
+OpclassnameGetOpcid(Oid amid, const char *opcname)
+{
+ Oid opcid;
+ List *lptr;
+
+ recomputeNamespacePath();
+
+ /*
+ * If system namespace is not in path, implicitly search it before path
+ */
+ if (!pathContainsSystemNamespace)
+ {
+ opcid = GetSysCacheOid(CLAAMNAMENSP,
+ ObjectIdGetDatum(amid),
+ PointerGetDatum(opcname),
+ ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
+ 0);
+ if (OidIsValid(opcid))
+ return opcid;
+ }
+
+ /*
+ * Else search the path
+ */
+ foreach(lptr, namespaceSearchPath)
+ {
+ Oid namespaceId = (Oid) lfirsti(lptr);
+
+ opcid = GetSysCacheOid(CLAAMNAMENSP,
+ ObjectIdGetDatum(amid),
+ PointerGetDatum(opcname),
+ ObjectIdGetDatum(namespaceId),
+ 0);
+ if (OidIsValid(opcid))
+ return opcid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+}
+
+/*
+ * OpclassIsVisible
+ * Determine whether an opclass (identified by OID) is visible in the
+ * current search path. Visible means "would be found by searching
+ * for the unqualified opclass name".
+ */
+bool
+OpclassIsVisible(Oid opcid)
+{
+ HeapTuple opctup;
+ Form_pg_opclass opcform;
+ Oid opcnamespace;
+ bool visible;
+
+ recomputeNamespacePath();
+
+ opctup = SearchSysCache(CLAOID,
+ ObjectIdGetDatum(opcid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(opctup))
+ elog(ERROR, "Cache lookup failed for opclass %u", opcid);
+ opcform = (Form_pg_opclass) GETSTRUCT(opctup);
+
+ /*
+ * Quick check: if it ain't in the path at all, it ain't visible.
+ */
+ opcnamespace = opcform->opcnamespace;
+ if (opcnamespace != PG_CATALOG_NAMESPACE &&
+ !intMember(opcnamespace, namespaceSearchPath))
+ visible = false;
+ else
+ {
+ /*
+ * If it is in the path, it might still not be visible; it could be
+ * hidden by another opclass of the same name earlier in the path.
+ * So we must do a slow check to see if this opclass would be found by
+ * OpclassnameGetOpcid.
+ */
+ char *opcname = NameStr(opcform->opcname);
+
+ visible = (OpclassnameGetOpcid(opcform->opcamid, opcname) == opcid);
+ }
+
+ ReleaseSysCache(opctup);
+
+ return visible;
+}
+
/*
* QualifiedNameGetCreationNamespace
return false;
}
+
/*
* recomputeNamespacePath - recompute path derived variables if needed.
*/
}
}
+
/*
* Routines for handling the GUC variable 'search_path'.
*/
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.28 2002/03/20 19:44:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.29 2002/05/01 23:06:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include <ctype.h>
-#include "fmgr.h"
+#include "catalog/namespace.h"
#include "catalog/pg_type.h"
+#include "fmgr.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
#include "utils/numeric.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
* pg_attribute.atttypmod. This function will get the type name and
* format it and the modifier to canonical SQL format, if the type is
* a standard type. Otherwise you just get pg_type.typname back,
- * double quoted if it contains funny characters.
+ * double quoted if it contains funny characters or matches a keyword.
*
* If typemod is NULL then we are formatting a type name in a context where
* no typemod is available, eg a function argument or result type. This
{
bool with_typemod = typemod_given && (typemod >= 0);
HeapTuple tuple;
+ Form_pg_type typeform;
Oid array_base_type;
- int16 typlen;
- char typtype;
bool is_array;
- char *name;
char *buf;
if (type_oid == InvalidOid && allow_invalid)
elog(ERROR, "could not locate data type with oid %u in catalog",
type_oid);
}
+ typeform = (Form_pg_type) GETSTRUCT(tuple);
/*
* Check if it's an array (and not a domain --- we don't want to show
* the substructure of a domain type). Fixed-length array types such
* as "name" shouldn't get deconstructed either.
*/
- array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
- typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
- typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
+ array_base_type = typeform->typelem;
- if (array_base_type != InvalidOid && typlen < 0 && typtype != 'd')
+ if (array_base_type != InvalidOid &&
+ typeform->typlen < 0 &&
+ typeform->typtype != 'd')
{
/* Switch our attention to the array element type */
ReleaseSysCache(tuple);
elog(ERROR, "could not locate data type with oid %u in catalog",
type_oid);
}
- is_array = true;
+ typeform = (Form_pg_type) GETSTRUCT(tuple);
type_oid = array_base_type;
+ is_array = true;
}
else
is_array = false;
+ /*
+ * See if we want to special-case the output for certain built-in types.
+ * Note that these special cases should all correspond to special
+ * productions in gram.y, to ensure that the type name will be taken as
+ * a system type, not a user type of the same name.
+ *
+ * If we do not provide a special-case output here, the type name will
+ * be handled the same way as a user type name --- in particular, it
+ * will be double-quoted if it matches any lexer keyword. This behavior
+ * is essential for some cases, such as types "bit" and "char".
+ */
+ buf = NULL; /* flag for no special case */
+
switch (type_oid)
{
case BITOID:
* BIT(1) per SQL spec. Report it as the quoted typename
* so that parser will not assign a bogus typmod.
*/
- buf = pstrdup("\"bit\"");
}
else
buf = pstrdup("bit");
* which means CHARACTER(1) per SQL spec. Report it as
* bpchar so that parser will not assign a bogus typmod.
*/
- buf = pstrdup("bpchar");
}
else
buf = pstrdup("character");
break;
- case CHAROID:
- /*
- * This char type is the single-byte version. You have to
- * double-quote it to get at it in the parser.
- */
- buf = pstrdup("\"char\"");
- break;
-
case FLOAT4OID:
buf = pstrdup("real");
break;
else
buf = pstrdup("character varying");
break;
+ }
- default:
- name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
- /*
- * Double-quote the name if it's not a standard identifier.
- * Note this is *necessary* for ruleutils.c's use.
- */
- if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
- || isdigit((unsigned char) name[0]))
- buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
- else
- buf = pstrdup(name);
- break;
+ if (buf == NULL)
+ {
+ /*
+ * Default handling: report the name as it appears in the catalog.
+ * Here, we must qualify the name if it is not visible in the search
+ * path, and we must double-quote it if it's not a standard identifier
+ * or if it matches any keyword.
+ */
+ char *nspname;
+ char *typname;
+
+ if (TypeIsVisible(type_oid))
+ nspname = NULL;
+ else
+ nspname = get_namespace_name(typeform->typnamespace);
+
+ typname = NameStr(typeform->typname);
+
+ buf = quote_qualified_identifier(nspname, typname);
}
if (is_array)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.66 2002/04/25 02:56:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.67 2002/05/01 23:06:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int nargs = procform->pronargs;
int i;
char *nspname;
- FuncCandidateList clist;
StringInfoData buf;
/* XXX no support here for bootstrap mode */
+ initStringInfo(&buf);
+
/*
* Would this proc be found (given the right args) by regprocedurein?
* If not, we need to qualify it.
*/
- clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs);
-
- for (; clist; clist = clist->next)
- {
- if (memcmp(clist->args, procform->proargtypes,
- nargs * sizeof(Oid)) == 0)
- break;
- }
-
- if (clist != NULL && clist->oid == proid)
+ if (FunctionIsVisible(proid))
nspname = NULL;
else
nspname = get_namespace_name(procform->pronamespace);
- initStringInfo(&buf);
-
appendStringInfo(&buf, "%s(",
quote_qualified_identifier(nspname, proname));
for (i = 0; i < nargs; i++)
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
char *oprname = NameStr(operform->oprname);
char *nspname;
- FuncCandidateList clist;
StringInfoData buf;
/* XXX no support here for bootstrap mode */
+ initStringInfo(&buf);
+
/*
* Would this oper be found (given the right args) by regoperatorin?
* If not, we need to qualify it.
*/
- clist = OpernameGetCandidates(makeList1(makeString(oprname)),
- operform->oprkind);
-
- for (; clist; clist = clist->next)
- {
- if (clist->args[0] == operform->oprleft &&
- clist->args[1] == operform->oprright)
- break;
- }
-
- initStringInfo(&buf);
-
- if (clist == NULL || clist->oid != oprid)
+ if (!OperatorIsVisible(oprid))
{
nspname = get_namespace_name(operform->oprnamespace);
appendStringInfo(&buf, "%s.",
* Would this class be found by regclassin?
* If not, qualify it.
*/
- if (RelnameGetRelid(classname) == classid)
+ if (RelationIsVisible(classid))
nspname = NULL;
else
nspname = get_namespace_name(classform->relnamespace);
if (HeapTupleIsValid(typetup))
{
Form_pg_type typeform = (Form_pg_type) GETSTRUCT(typetup);
- char *typname = NameStr(typeform->typname);
/*
* In bootstrap mode, skip the fancy namespace stuff and just
*/
if (IsBootstrapProcessingMode())
{
+ char *typname = NameStr(typeform->typname);
+
result = pstrdup(typname);
}
else
{
- char *nspname;
-
- /*
- * Would this type be found by regtypein?
- * If not, qualify it.
- *
- * XXX shouldn't we use format_type instead?
- */
- if (TypenameGetTypid(typname) == typid)
- nspname = NULL;
- else
- nspname = get_namespace_name(typeform->typnamespace);
-
- result = quote_qualified_identifier(nspname, typname);
+ result = format_type_be(typid);
}
ReleaseSysCache(typetup);