OSDN Git Service

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 c4ccb5f..a912971 100644 (file)
@@ -2685,6 +2685,21 @@ getObjectDescription(const ObjectAddress *object)
 }
 
 /*
+ * 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
  */
 static void
index 3727146..653c9ad 100644 (file)
@@ -2340,6 +2340,40 @@ LookupCreationNamespace(const char *nspname)
 }
 
 /*
+ * 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
  *             format), determine what namespace the object should be created in.
index 4b6801a..62a2110 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 b22bcf0..11171ea 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 2f21451..583bba3 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 ccde371..87f853d 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 c6672e9..a842ea7 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);