mirror of
https://github.com/postgres/postgres.git
synced 2025-05-24 00:03:23 -04: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:
parent
a829cbb877
commit
0041a3d72f
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -31,6 +31,7 @@
|
|||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_shadow.h"
|
#include "catalog/pg_shadow.h"
|
||||||
|
#include "catalog/pg_type.h"
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
@ -296,6 +297,56 @@ RelnameGetRelid(const char *relname)
|
|||||||
return InvalidOid;
|
return InvalidOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* TypenameGetTypid
|
||||||
* Try to resolve an unqualified datatype name.
|
* Try to resolve an unqualified datatype name.
|
||||||
@ -346,55 +397,54 @@ TypenameGetTypid(const char *typname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OpclassnameGetOpcid
|
* TypeIsVisible
|
||||||
* Try to resolve an unqualified index opclass name.
|
* Determine whether a type (identified by OID) is visible in the
|
||||||
* Returns OID if opclass found in search path, else InvalidOid.
|
* current search path. Visible means "would be found by searching
|
||||||
*
|
* for the unqualified type name".
|
||||||
* This is essentially the same as TypenameGetTypid, but we have to have
|
|
||||||
* an extra argument for the index AM OID.
|
|
||||||
*/
|
*/
|
||||||
Oid
|
bool
|
||||||
OpclassnameGetOpcid(Oid amid, const char *opcname)
|
TypeIsVisible(Oid typid)
|
||||||
{
|
{
|
||||||
Oid opcid;
|
HeapTuple typtup;
|
||||||
List *lptr;
|
Form_pg_type typform;
|
||||||
|
Oid typnamespace;
|
||||||
|
bool visible;
|
||||||
|
|
||||||
recomputeNamespacePath();
|
recomputeNamespacePath();
|
||||||
|
|
||||||
/*
|
typtup = SearchSysCache(TYPEOID,
|
||||||
* If system namespace is not in path, implicitly search it before path
|
ObjectIdGetDatum(typid),
|
||||||
*/
|
0, 0, 0);
|
||||||
if (!pathContainsSystemNamespace)
|
if (!HeapTupleIsValid(typtup))
|
||||||
{
|
elog(ERROR, "Cache lookup failed for type %u", typid);
|
||||||
opcid = GetSysCacheOid(CLAAMNAMENSP,
|
typform = (Form_pg_type) GETSTRUCT(typtup);
|
||||||
ObjectIdGetDatum(amid),
|
|
||||||
PointerGetDatum(opcname),
|
|
||||||
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
|
|
||||||
0);
|
|
||||||
if (OidIsValid(opcid))
|
|
||||||
return opcid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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,
|
visible = (TypenameGetTypid(typname) == typid);
|
||||||
ObjectIdGetDatum(amid),
|
|
||||||
PointerGetDatum(opcname),
|
|
||||||
ObjectIdGetDatum(namespaceId),
|
|
||||||
0);
|
|
||||||
if (OidIsValid(opcid))
|
|
||||||
return opcid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Not found in path */
|
ReleaseSysCache(typtup);
|
||||||
return InvalidOid;
|
|
||||||
|
return visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FuncnameGetCandidates
|
* FuncnameGetCandidates
|
||||||
* Given a possibly-qualified function name and argument count,
|
* Given a possibly-qualified function name and argument count,
|
||||||
@ -582,6 +632,70 @@ FuncnameGetCandidates(List *names, int nargs)
|
|||||||
return resultList;
|
return resultList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* OpernameGetCandidates
|
||||||
* Given a possibly-qualified operator name and operator kind,
|
* Given a possibly-qualified operator name and operator kind,
|
||||||
@ -765,6 +879,70 @@ OpernameGetCandidates(List *names, char oprkind)
|
|||||||
return resultList;
|
return resultList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* OpclassGetCandidates
|
||||||
* Given an index access method OID, retrieve a list of all the
|
* Given an index access method OID, retrieve a list of all the
|
||||||
@ -883,6 +1061,104 @@ OpclassGetCandidates(Oid amid)
|
|||||||
return resultList;
|
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
|
* QualifiedNameGetCreationNamespace
|
||||||
@ -1016,6 +1292,7 @@ isTempNamespace(Oid namespaceId)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* recomputeNamespacePath - recompute path derived variables if needed.
|
* recomputeNamespacePath - recompute path derived variables if needed.
|
||||||
*/
|
*/
|
||||||
@ -1453,6 +1730,7 @@ RemoveTempRelationsCallback(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines for handling the GUC variable 'search_path'.
|
* Routines for handling the GUC variable 'search_path'.
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 <ctype.h>
|
||||||
|
|
||||||
#include "fmgr.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
#include "fmgr.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/datetime.h"
|
#include "utils/datetime.h"
|
||||||
#include "utils/numeric.h"
|
#include "utils/numeric.h"
|
||||||
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#ifdef MULTIBYTE
|
#ifdef MULTIBYTE
|
||||||
#include "mb/pg_wchar.h"
|
#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
|
* pg_attribute.atttypmod. This function will get the type name and
|
||||||
* format it and the modifier to canonical SQL format, if the type is
|
* format it and the modifier to canonical SQL format, if the type is
|
||||||
* a standard type. Otherwise you just get pg_type.typname back,
|
* 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
|
* 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
|
* 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);
|
bool with_typemod = typemod_given && (typemod >= 0);
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
|
Form_pg_type typeform;
|
||||||
Oid array_base_type;
|
Oid array_base_type;
|
||||||
int16 typlen;
|
|
||||||
char typtype;
|
|
||||||
bool is_array;
|
bool is_array;
|
||||||
char *name;
|
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
if (type_oid == InvalidOid && allow_invalid)
|
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",
|
elog(ERROR, "could not locate data type with oid %u in catalog",
|
||||||
type_oid);
|
type_oid);
|
||||||
}
|
}
|
||||||
|
typeform = (Form_pg_type) GETSTRUCT(tuple);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if it's an array (and not a domain --- we don't want to show
|
* 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
|
* the substructure of a domain type). Fixed-length array types such
|
||||||
* as "name" shouldn't get deconstructed either.
|
* as "name" shouldn't get deconstructed either.
|
||||||
*/
|
*/
|
||||||
array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
|
array_base_type = typeform->typelem;
|
||||||
typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
|
|
||||||
typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
|
|
||||||
|
|
||||||
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 */
|
/* Switch our attention to the array element type */
|
||||||
ReleaseSysCache(tuple);
|
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",
|
elog(ERROR, "could not locate data type with oid %u in catalog",
|
||||||
type_oid);
|
type_oid);
|
||||||
}
|
}
|
||||||
is_array = true;
|
typeform = (Form_pg_type) GETSTRUCT(tuple);
|
||||||
type_oid = array_base_type;
|
type_oid = array_base_type;
|
||||||
|
is_array = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
is_array = false;
|
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)
|
switch (type_oid)
|
||||||
{
|
{
|
||||||
case BITOID:
|
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
|
* BIT(1) per SQL spec. Report it as the quoted typename
|
||||||
* so that parser will not assign a bogus typmod.
|
* so that parser will not assign a bogus typmod.
|
||||||
*/
|
*/
|
||||||
buf = pstrdup("\"bit\"");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf = pstrdup("bit");
|
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
|
* which means CHARACTER(1) per SQL spec. Report it as
|
||||||
* bpchar so that parser will not assign a bogus typmod.
|
* bpchar so that parser will not assign a bogus typmod.
|
||||||
*/
|
*/
|
||||||
buf = pstrdup("bpchar");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buf = pstrdup("character");
|
buf = pstrdup("character");
|
||||||
break;
|
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:
|
case FLOAT4OID:
|
||||||
buf = pstrdup("real");
|
buf = pstrdup("real");
|
||||||
break;
|
break;
|
||||||
@ -365,19 +370,27 @@ format_type_internal(Oid type_oid, int32 typemod,
|
|||||||
else
|
else
|
||||||
buf = pstrdup("character varying");
|
buf = pstrdup("character varying");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
if (buf == NULL)
|
||||||
name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
|
{
|
||||||
/*
|
/*
|
||||||
* Double-quote the name if it's not a standard identifier.
|
* Default handling: report the name as it appears in the catalog.
|
||||||
* Note this is *necessary* for ruleutils.c's use.
|
* 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.
|
||||||
*/
|
*/
|
||||||
if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
|
char *nspname;
|
||||||
|| isdigit((unsigned char) name[0]))
|
char *typname;
|
||||||
buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
|
|
||||||
|
if (TypeIsVisible(type_oid))
|
||||||
|
nspname = NULL;
|
||||||
else
|
else
|
||||||
buf = pstrdup(name);
|
nspname = get_namespace_name(typeform->typnamespace);
|
||||||
break;
|
|
||||||
|
typname = NameStr(typeform->typname);
|
||||||
|
|
||||||
|
buf = quote_qualified_identifier(nspname, typname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array)
|
if (is_array)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 nargs = procform->pronargs;
|
||||||
int i;
|
int i;
|
||||||
char *nspname;
|
char *nspname;
|
||||||
FuncCandidateList clist;
|
|
||||||
StringInfoData buf;
|
StringInfoData buf;
|
||||||
|
|
||||||
/* XXX no support here for bootstrap mode */
|
/* XXX no support here for bootstrap mode */
|
||||||
|
|
||||||
|
initStringInfo(&buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Would this proc be found (given the right args) by regprocedurein?
|
* Would this proc be found (given the right args) by regprocedurein?
|
||||||
* If not, we need to qualify it.
|
* If not, we need to qualify it.
|
||||||
*/
|
*/
|
||||||
clist = FuncnameGetCandidates(makeList1(makeString(proname)), nargs);
|
if (FunctionIsVisible(proid))
|
||||||
|
|
||||||
for (; clist; clist = clist->next)
|
|
||||||
{
|
|
||||||
if (memcmp(clist->args, procform->proargtypes,
|
|
||||||
nargs * sizeof(Oid)) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clist != NULL && clist->oid == proid)
|
|
||||||
nspname = NULL;
|
nspname = NULL;
|
||||||
else
|
else
|
||||||
nspname = get_namespace_name(procform->pronamespace);
|
nspname = get_namespace_name(procform->pronamespace);
|
||||||
|
|
||||||
initStringInfo(&buf);
|
|
||||||
|
|
||||||
appendStringInfo(&buf, "%s(",
|
appendStringInfo(&buf, "%s(",
|
||||||
quote_qualified_identifier(nspname, proname));
|
quote_qualified_identifier(nspname, proname));
|
||||||
for (i = 0; i < nargs; i++)
|
for (i = 0; i < nargs; i++)
|
||||||
@ -632,28 +622,17 @@ regoperatorout(PG_FUNCTION_ARGS)
|
|||||||
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
|
Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup);
|
||||||
char *oprname = NameStr(operform->oprname);
|
char *oprname = NameStr(operform->oprname);
|
||||||
char *nspname;
|
char *nspname;
|
||||||
FuncCandidateList clist;
|
|
||||||
StringInfoData buf;
|
StringInfoData buf;
|
||||||
|
|
||||||
/* XXX no support here for bootstrap mode */
|
/* XXX no support here for bootstrap mode */
|
||||||
|
|
||||||
|
initStringInfo(&buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Would this oper be found (given the right args) by regoperatorin?
|
* Would this oper be found (given the right args) by regoperatorin?
|
||||||
* If not, we need to qualify it.
|
* If not, we need to qualify it.
|
||||||
*/
|
*/
|
||||||
clist = OpernameGetCandidates(makeList1(makeString(oprname)),
|
if (!OperatorIsVisible(oprid))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
nspname = get_namespace_name(operform->oprnamespace);
|
nspname = get_namespace_name(operform->oprnamespace);
|
||||||
appendStringInfo(&buf, "%s.",
|
appendStringInfo(&buf, "%s.",
|
||||||
@ -815,7 +794,7 @@ regclassout(PG_FUNCTION_ARGS)
|
|||||||
* Would this class be found by regclassin?
|
* Would this class be found by regclassin?
|
||||||
* If not, qualify it.
|
* If not, qualify it.
|
||||||
*/
|
*/
|
||||||
if (RelnameGetRelid(classname) == classid)
|
if (RelationIsVisible(classid))
|
||||||
nspname = NULL;
|
nspname = NULL;
|
||||||
else
|
else
|
||||||
nspname = get_namespace_name(classform->relnamespace);
|
nspname = get_namespace_name(classform->relnamespace);
|
||||||
@ -947,7 +926,6 @@ regtypeout(PG_FUNCTION_ARGS)
|
|||||||
if (HeapTupleIsValid(typetup))
|
if (HeapTupleIsValid(typetup))
|
||||||
{
|
{
|
||||||
Form_pg_type typeform = (Form_pg_type) GETSTRUCT(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
|
* In bootstrap mode, skip the fancy namespace stuff and just
|
||||||
@ -956,24 +934,13 @@ regtypeout(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
if (IsBootstrapProcessingMode())
|
if (IsBootstrapProcessingMode())
|
||||||
{
|
{
|
||||||
|
char *typname = NameStr(typeform->typname);
|
||||||
|
|
||||||
result = pstrdup(typname);
|
result = pstrdup(typname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *nspname;
|
result = format_type_be(typid);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseSysCache(typetup);
|
ReleaseSysCache(typetup);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: namespace.h,v 1.11 2002/04/26 01:24:08 tgl Exp $
|
* $Id: namespace.h,v 1.12 2002/05/01 23:06:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -49,25 +49,25 @@ typedef struct _OpclassCandidateList
|
|||||||
|
|
||||||
|
|
||||||
extern Oid RangeVarGetRelid(const RangeVar *relation, bool failOK);
|
extern Oid RangeVarGetRelid(const RangeVar *relation, bool failOK);
|
||||||
|
|
||||||
extern Oid RangeVarGetCreationNamespace(const RangeVar *newRelation);
|
extern Oid RangeVarGetCreationNamespace(const RangeVar *newRelation);
|
||||||
|
|
||||||
extern Oid RelnameGetRelid(const char *relname);
|
extern Oid RelnameGetRelid(const char *relname);
|
||||||
|
extern bool RelationIsVisible(Oid relid);
|
||||||
|
|
||||||
extern Oid TypenameGetTypid(const char *typname);
|
extern Oid TypenameGetTypid(const char *typname);
|
||||||
|
extern bool TypeIsVisible(Oid typid);
|
||||||
extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname);
|
|
||||||
|
|
||||||
extern FuncCandidateList FuncnameGetCandidates(List *names, int nargs);
|
extern FuncCandidateList FuncnameGetCandidates(List *names, int nargs);
|
||||||
|
extern bool FunctionIsVisible(Oid funcid);
|
||||||
|
|
||||||
extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
|
extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
|
||||||
|
extern bool OperatorIsVisible(Oid oprid);
|
||||||
|
|
||||||
extern OpclassCandidateList OpclassGetCandidates(Oid amid);
|
extern OpclassCandidateList OpclassGetCandidates(Oid amid);
|
||||||
|
extern Oid OpclassnameGetOpcid(Oid amid, const char *opcname);
|
||||||
|
extern bool OpclassIsVisible(Oid opcid);
|
||||||
|
|
||||||
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
|
extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p);
|
||||||
|
|
||||||
extern RangeVar *makeRangeVarFromNameList(List *names);
|
extern RangeVar *makeRangeVarFromNameList(List *names);
|
||||||
|
|
||||||
extern char *NameListToString(List *names);
|
extern char *NameListToString(List *names);
|
||||||
|
|
||||||
extern bool isTempNamespace(Oid namespaceId);
|
extern bool isTempNamespace(Oid namespaceId);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user