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 c4ccb5fb2a..a912971aba 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 3727146ea0..653c9ada11 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 4b6801ac54..62a2110251 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 b22bcf0d66..11171eaa99 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 2f21451abd..583bba37f5 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 ccde371f6a..87f853d0e5 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 c6672e955e..a842ea7ee6 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