From 44475e782f4674d257b9e5c1a3930218a4b4deea Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 22 Nov 2010 19:46:15 -0500 Subject: [PATCH] Centralize some ALTER .. SET SCHEMA checks. Any flavor of ALTER .. SET SCHEMA fails if (1) the object is already in the new schema, (2) either the old or new schema is a temp schema, or (3) either the old or new schema is the TOAST schema. Extraced from a patch by Dimitri Fontaine, with additional hacking by me. --- src/backend/catalog/dependency.c | 15 +++++++++++++ src/backend/catalog/namespace.c | 34 +++++++++++++++++++++++++++++ src/backend/commands/functioncmds.c | 20 ++--------------- src/backend/commands/tablecmds.c | 20 ++--------------- src/backend/commands/typecmds.c | 20 ++--------------- src/include/catalog/dependency.h | 1 + src/include/catalog/namespace.h | 2 ++ 7 files changed, 58 insertions(+), 54 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index c4ccb5fb2aa..a912971abae 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2684,6 +2684,21 @@ getObjectDescription(const ObjectAddress *object) return buffer.data; } +/* + * getObjectDescriptionOids: as above, except the object is specified by Oids + */ +char * +getObjectDescriptionOids(Oid classid, Oid objid) +{ + ObjectAddress address; + + address.classId = classid; + address.objectId = objid; + address.objectSubId = 0; + + return getObjectDescription(&address); +} + /* * subroutine for getObjectDescription: describe a relation */ diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 3727146ea01..653c9ada118 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -2339,6 +2339,40 @@ LookupCreationNamespace(const char *nspname) return namespaceId; } +/* + * Common checks on switching namespaces. + * + * We complain if (1) the old and new namespaces are the same, (2) either the + * old or new namespaces is a temporary schema (or temporary toast schema), or + * (3) either the old or new namespaces is the TOAST schema. + */ +void +CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid, Oid objid) +{ + if (oldNspOid == nspOid) + ereport(ERROR, + (classid == RelationRelationId ? + errcode(ERRCODE_DUPLICATE_TABLE) : + classid == ProcedureRelationId ? + errcode(ERRCODE_DUPLICATE_FUNCTION) : + errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("%s is already in schema \"%s\"", + getObjectDescriptionOids(classid, objid), + get_namespace_name(nspOid)))); + + /* disallow renaming into or out of temp schemas */ + if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot move objects into or out of temporary schemas"))); + + /* same for TOAST schema */ + if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot move objects into or out of TOAST schema"))); +} + /* * QualifiedNameGetCreationNamespace * Given a possibly-qualified name for an object (in List-of-Values diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 4b6801ac540..62a21102512 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -1899,24 +1899,8 @@ AlterFunctionNamespace(List *name, List *argtypes, bool isagg, /* get schema OID and check its permissions */ nspOid = LookupCreationNamespace(newschema); - if (oldNspOid == nspOid) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_FUNCTION), - errmsg("function \"%s\" is already in schema \"%s\"", - NameListToString(name), - newschema))); - - /* disallow renaming into or out of temp schemas */ - if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot move objects into or out of temporary schemas"))); - - /* same for TOAST schema */ - if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot move objects into or out of TOAST schema"))); + /* common checks on switching namespaces */ + CheckSetNamespace(oldNspOid, nspOid, ProcedureRelationId, procOid); /* check for duplicate name (more friendly than unique-index failure) */ if (SearchSysCacheExists3(PROCNAMEARGSNSP, diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b22bcf0d663..11171eaa990 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8114,24 +8114,8 @@ AlterTableNamespace(RangeVar *relation, const char *newschema, /* get schema OID and check its permissions */ nspOid = LookupCreationNamespace(newschema); - if (oldNspOid == nspOid) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_TABLE), - errmsg("relation \"%s\" is already in schema \"%s\"", - RelationGetRelationName(rel), - newschema))); - - /* disallow renaming into or out of temp schemas */ - if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot move objects into or out of temporary schemas"))); - - /* same for TOAST schema */ - if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot move objects into or out of TOAST schema"))); + /* common checks on switching namespaces */ + CheckSetNamespace(oldNspOid, nspOid, RelationRelationId, relid); /* OK, modify the pg_class row and pg_depend entry */ classRel = heap_open(RelationRelationId, RowExclusiveLock); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 2f21451abdc..583bba37f57 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -2828,24 +2828,8 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, oldNspOid = typform->typnamespace; arrayOid = typform->typarray; - if (oldNspOid == nspOid) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_OBJECT), - errmsg("type %s is already in schema \"%s\"", - format_type_be(typeOid), - get_namespace_name(nspOid)))); - - /* disallow renaming into or out of temp schemas */ - if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot move objects into or out of temporary schemas"))); - - /* same for TOAST schema */ - if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot move objects into or out of TOAST schema"))); + /* common checks on switching namespaces */ + CheckSetNamespace(oldNspOid, nspOid, TypeRelationId, typeOid); /* check for duplicate name (more friendly than unique-index failure) */ if (SearchSysCacheExists2(TYPENAMENSP, diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index ccde371f6a1..87f853d0e5e 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -165,6 +165,7 @@ extern void recordDependencyOnSingleRelExpr(const ObjectAddress *depender, extern ObjectClass getObjectClass(const ObjectAddress *object); extern char *getObjectDescription(const ObjectAddress *object); +extern char *getObjectDescriptionOids(Oid classid, Oid objid); extern ObjectAddresses *new_object_addresses(void); diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index c6672e955ee..a842ea7ee6e 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -94,6 +94,8 @@ extern Oid LookupExplicitNamespace(const char *nspname); extern Oid get_namespace_oid(const char *nspname, bool missing_ok); extern Oid LookupCreationNamespace(const char *nspname); +extern void CheckSetNamespace(Oid oldNspOid, Oid nspOid, Oid classid, + Oid objid); extern Oid QualifiedNameGetCreationNamespace(List *names, char **objname_p); extern RangeVar *makeRangeVarFromNameList(List *names); extern char *NameListToString(List *names); -- 2.39.5