Centralize some ALTER <whatever> .. SET SCHEMA checks.
authorRobert Haas <rhaas@postgresql.org>
Tue, 23 Nov 2010 00:46:15 +0000 (19:46 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 23 Nov 2010 00:53:34 +0000 (19:53 -0500)
Any flavor of ALTER <whatever> .. 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
src/backend/catalog/namespace.c
src/backend/commands/functioncmds.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/include/catalog/dependency.h
src/include/catalog/namespace.h

index c4ccb5fb2aa21c6ac4cefe8d5976b0c6ea7bb6a0..a912971abae9a26e049a8a1d79664f737d95909b 100644 (file)
@@ -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
  */
index 3727146ea01374f10d5928a901571b75f72bed65..653c9ada118c061e4d2cce168aca6ccc92499c6f 100644 (file)
@@ -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
index 4b6801ac540cabc222eb9e09e9a4c5c6acf1c782..62a21102512a324b44244f903e70fc198cf83112 100644 (file)
@@ -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,
index b22bcf0d66379ca360d39ce0cc669f308d3f979d..11171eaa9901c322511d5508d2f64961a43c4af2 100644 (file)
@@ -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);
index 2f21451abdccd89cf85efd0f73cb7967df899c1c..583bba37f577893662f3df8039509fd395a8cd3f 100644 (file)
@@ -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,
index ccde371f6a17357b93ed0b91b698bda689f36f1b..87f853d0e5e7ce54980274de43a0a0b7ccd41500 100644 (file)
@@ -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);
 
index c6672e955eee7e2facba8adc2b15bda4b5740a2c..a842ea7ee6eaa1fe869225a3f29bd226466102ab 100644 (file)
@@ -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);