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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user