1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Add routines in namespace.c to determine whether objects are visible

in the search path.  (We might want to make these available as SQL
functions too, but I haven't done that yet.)  Fix format_type to be
schema-aware.
This commit is contained in:
Tom Lane
2002-05-01 23:06:41 +00:00
parent a829cbb877
commit 0041a3d72f
4 changed files with 378 additions and 120 deletions

View File

@@ -8,7 +8,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@@ -17,11 +17,13 @@
#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"
@@ -47,7 +49,7 @@ __attribute__((format(printf, 2, 3)));
* 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
@@ -121,11 +123,9 @@ format_type_internal(Oid type_oid, int32 typemod,
{
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)
@@ -142,17 +142,18 @@ format_type_internal(Oid type_oid, int32 typemod,
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);
@@ -167,12 +168,26 @@ format_type_internal(Oid type_oid, int32 typemod,
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:
@@ -186,7 +201,6 @@ format_type_internal(Oid type_oid, int32 typemod,
* 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");
@@ -207,20 +221,11 @@ format_type_internal(Oid type_oid, int32 typemod,
* 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;
@@ -365,19 +370,27 @@ format_type_internal(Oid type_oid, int32 typemod,
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)

View File

@@ -13,7 +13,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@@ -307,31 +307,21 @@ regprocedureout(PG_FUNCTION_ARGS)
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++)
@@ -632,28 +622,17 @@ regoperatorout(PG_FUNCTION_ARGS)
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.",
@@ -815,7 +794,7 @@ regclassout(PG_FUNCTION_ARGS)
* 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);
@@ -947,7 +926,6 @@ regtypeout(PG_FUNCTION_ARGS)
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
@@ -956,24 +934,13 @@ regtypeout(PG_FUNCTION_ARGS)
*/
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);