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);