Support ALTER TYPE RENAME. Petr Jelinek
authorTom Lane
Wed, 19 Mar 2008 18:38:30 +0000 (18:38 +0000)
committerTom Lane
Wed, 19 Mar 2008 18:38:30 +0000 (18:38 +0000)
doc/src/sgml/ref/alter_type.sgml
src/backend/catalog/pg_type.c
src/backend/commands/alter.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/parser/gram.y
src/backend/tcop/utility.c
src/include/catalog/pg_type.h
src/include/commands/tablecmds.h
src/include/commands/typecmds.h

index c4f9edd399a454ca01b5adfa0a274650861d0127..6f16da6242507b92a2a81fa78e36196d3a1dde0b 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -24,6 +24,7 @@ PostgreSQL documentation
 
  
   
+ALTER TYPE name RENAME TO new_name
 ALTER TYPE name OWNER TO new_owner 
 ALTER TYPE name SET SCHEMA new_schema
   
@@ -34,8 +35,6 @@ ALTER TYPE name SET SCHEMA 
 
   
    ALTER TYPE changes the definition of an existing type.
-   The only currently available capabilities are changing the owner and schema
-   of a type.
   
 
   
@@ -65,6 +64,15 @@ ALTER TYPE name SET SCHEMA 
       
      
 
+     
+      new_name
+      
+       
+        The new name for the type.
+       
+      
+     
+
      
       new_owner
       
@@ -91,7 +99,14 @@ ALTER TYPE name SET SCHEMA 
   Examples
 
    
-   To change the owner of the user-defined type email
+   To rename a data type:
+   
+ALTER TYPE electronic_mail RENAME TO email;
+   
+  
+
+   
+   To change the owner of the type email
    to joe:
    
 ALTER TYPE email OWNER TO joe;
@@ -99,7 +114,7 @@ ALTER TYPE email OWNER TO joe;
   
 
   
-   To change the schema of the user-defined type email
+   To change the schema of the type email
    to customers:
    
 ALTER TYPE email SET SCHEMA customers;
index 780d5134d9e946a0215362a1b95f7901b4b6d846..a654f19dbbd87b7df06ff1a66f8ce44827e0678b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.115 2008/01/01 19:45:48 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.116 2008/03/19 18:38:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -552,15 +552,16 @@ GenerateTypeDependencies(Oid typeNamespace,
 }
 
 /*
- * TypeRename
+ * RenameTypeInternal
  *     This renames a type, as well as any associated array type.
  *
- * Note: this isn't intended to be a user-exposed function; it doesn't check
- * permissions etc.  (Perhaps TypeRenameInternal would be a better name.)
- * Currently this is only used for renaming table rowtypes.
+ * Caller must have already checked privileges.
+ *
+ * Currently this is used for renaming table rowtypes and for
+ * ALTER TYPE RENAME TO command.
  */
 void
-TypeRename(Oid typeOid, const char *newTypeName, Oid typeNamespace)
+RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
 {
    Relation    pg_type_desc;
    HeapTuple   tuple;
@@ -606,7 +607,7 @@ TypeRename(Oid typeOid, const char *newTypeName, Oid typeNamespace)
    {
        char       *arrname = makeArrayTypeName(newTypeName, typeNamespace);
 
-       TypeRename(arrayOid, arrname, typeNamespace);
+       RenameTypeInternal(arrayOid, arrname, typeNamespace);
        pfree(arrname);
    }
 }
@@ -706,7 +707,7 @@ moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
    newname = makeArrayTypeName(typeName, typeNamespace);
 
    /* Apply the rename */
-   TypeRename(typeOid, newname, typeNamespace);
+   RenameTypeInternal(typeOid, newname, typeNamespace);
 
    /*
     * We must bump the command counter so that any subsequent use of
index 8cf833a921894420f7db03efd6c17f10e70003d0..63acefa527dc1627ec58fd110190c53012932250 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.27 2008/02/07 21:07:55 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.28 2008/03/19 18:38:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -117,7 +117,7 @@ ExecRenameStmt(RenameStmt *stmt)
                                aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                                            get_namespace_name(namespaceId));
 
-                           renamerel(relid, stmt->newname, stmt->renameType);
+                           RenameRelation(relid, stmt->newname, stmt->renameType);
                            break;
                        }
                    case OBJECT_COLUMN:
@@ -154,6 +154,10 @@ ExecRenameStmt(RenameStmt *stmt)
            RenameTSConfiguration(stmt->object, stmt->newname);
            break;
 
+       case OBJECT_TYPE:
+           RenameType(stmt->object, stmt->newname);
+           break;
+
        default:
            elog(ERROR, "unrecognized rename stmt type: %d",
                 (int) stmt->renameType);
index 027fe51eca4761c1caf16bff3d0088e419a41e97..bd7786a918d9528db5557ad7b8e68cda9aaaa0e7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.242 2008/02/07 17:09:51 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.243 2008/03/19 18:38:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1612,26 +1612,18 @@ renameatt(Oid myrelid,
    relation_close(targetrelation, NoLock);     /* close rel but keep lock */
 }
 
+
 /*
- *     renamerel       - change the name of a relation
+ * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW RENAME
  *
- *     XXX - When renaming sequences, we don't bother to modify the
- *           sequence name that is stored within the sequence itself
- *           (this would cause problems with MVCC). In the future,
- *           the sequence name should probably be removed from the
- *           sequence, AFAIK there's no need for it to be there.
+ * Caller has already done permissions checks.
  */
 void
-renamerel(Oid myrelid, const char *newrelname, ObjectType reltype)
+RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
 {
    Relation    targetrelation;
-   Relation    relrelation;    /* for RELATION relation */
-   HeapTuple   reltup;
-   Form_pg_class relform;
    Oid         namespaceId;
-   char       *oldrelname;
    char        relkind;
-   bool        relhastriggers;
 
    /*
     * Grab an exclusive lock on the target table, index, sequence or view,
@@ -1639,20 +1631,13 @@ renamerel(Oid myrelid, const char *newrelname, ObjectType reltype)
     */
    targetrelation = relation_open(myrelid, AccessExclusiveLock);
 
-   oldrelname = pstrdup(RelationGetRelationName(targetrelation));
    namespaceId = RelationGetNamespace(targetrelation);
-
-   if (!allowSystemTableMods && IsSystemRelation(targetrelation))
-       ereport(ERROR,
-               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                errmsg("permission denied: \"%s\" is a system catalog",
-                       RelationGetRelationName(targetrelation))));
+   relkind = targetrelation->rd_rel->relkind;
 
    /*
     * For compatibility with prior releases, we don't complain if ALTER TABLE
     * or ALTER INDEX is used to rename a sequence or view.
     */
-   relkind = targetrelation->rd_rel->relkind;
    if (reltype == OBJECT_SEQUENCE && relkind != RELKIND_SEQUENCE)
        ereport(ERROR,
                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -1665,7 +1650,48 @@ renamerel(Oid myrelid, const char *newrelname, ObjectType reltype)
                 errmsg("\"%s\" is not a view",
                        RelationGetRelationName(targetrelation))));
 
-   relhastriggers = (targetrelation->rd_rel->reltriggers > 0);
+   /*
+    * Don't allow ALTER TABLE on composite types.
+    * We want people to use ALTER TYPE for that.
+    */
+   if (relkind == RELKIND_COMPOSITE_TYPE)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("\"%s\" is a composite type",
+                       RelationGetRelationName(targetrelation)),
+                errhint("Use ALTER TYPE instead.")));
+
+   /* Do the work */
+   RenameRelationInternal(myrelid, newrelname, namespaceId);
+
+   /*
+    * Close rel, but keep exclusive lock!
+    */
+   relation_close(targetrelation, NoLock);
+}
+
+/*
+ *     RenameRelationInternal - change the name of a relation
+ *
+ *     XXX - When renaming sequences, we don't bother to modify the
+ *           sequence name that is stored within the sequence itself
+ *           (this would cause problems with MVCC). In the future,
+ *           the sequence name should probably be removed from the
+ *           sequence, AFAIK there's no need for it to be there.
+ */
+void
+RenameRelationInternal(Oid myrelid, const char *newrelname, Oid namespaceId)
+{
+   Relation    targetrelation;
+   Relation    relrelation;    /* for RELATION relation */
+   HeapTuple   reltup;
+   Form_pg_class relform;
+
+   /*
+    * Grab an exclusive lock on the target table, index, sequence or
+    * view, which we will NOT release until end of transaction.
+    */
+   targetrelation = relation_open(myrelid, AccessExclusiveLock);
 
    /*
     * Find relation's pg_class tuple, and make sure newrelname isn't in use.
@@ -1703,12 +1729,13 @@ renamerel(Oid myrelid, const char *newrelname, ObjectType reltype)
     * Also rename the associated type, if any.
     */
    if (OidIsValid(targetrelation->rd_rel->reltype))
-       TypeRename(targetrelation->rd_rel->reltype, newrelname, namespaceId);
+       RenameTypeInternal(targetrelation->rd_rel->reltype,
+                          newrelname, namespaceId);
 
    /*
     * Also rename the associated constraint, if any.
     */
-   if (relkind == RELKIND_INDEX)
+   if (targetrelation->rd_rel->relkind == RELKIND_INDEX)
    {
        Oid         constraintId = get_index_constraint(myrelid);
 
index 9528b58c5682f4c481d86e11a4ab91e80457be88..982588e04a616c60b1f4bf12f59ef45e14051d17 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.113 2008/01/01 19:45:49 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.114 2008/03/19 18:38:30 tgl Exp $
  *
  * DESCRIPTION
  *   The "DefineFoo" routines take the parse tree and pick out the
@@ -2339,6 +2339,76 @@ GetDomainConstraints(Oid typeOid)
    return result;
 }
 
+
+/*
+ * Execute ALTER TYPE RENAME
+ */
+void
+RenameType(List *names, const char *newTypeName)
+{
+   TypeName   *typename;
+   Oid         typeOid;
+   Relation    rel;
+   HeapTuple   tup;
+   Form_pg_type typTup;
+
+   /* Make a TypeName so we can use standard type lookup machinery */
+   typename = makeTypeNameFromNameList(names);
+   typeOid = typenameTypeId(NULL, typename, NULL);
+
+   /* Look up the type in the type table */
+   rel = heap_open(TypeRelationId, RowExclusiveLock);
+
+   tup = SearchSysCacheCopy(TYPEOID,
+                            ObjectIdGetDatum(typeOid),
+                            0, 0, 0);
+   if (!HeapTupleIsValid(tup))
+       elog(ERROR, "cache lookup failed for type %u", typeOid);
+   typTup = (Form_pg_type) GETSTRUCT(tup);
+
+   /* check permissions on type */
+   if (!pg_type_ownercheck(typeOid, GetUserId()))
+       aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
+                      format_type_be(typeOid));
+
+   /*
+    * If it's a composite type, we need to check that it really is a
+    * free-standing composite type, and not a table's rowtype. We
+    * want people to use ALTER TABLE not ALTER TYPE for that case.
+    */
+   if (typTup->typtype == TYPTYPE_COMPOSITE &&
+       get_rel_relkind(typTup->typrelid) != RELKIND_COMPOSITE_TYPE)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("%s is a table's row type",
+                       format_type_be(typeOid)),
+                errhint("Use ALTER TABLE instead.")));
+
+   /* don't allow direct alteration of array types, either */
+   if (OidIsValid(typTup->typelem) &&
+       get_array_type(typTup->typelem) == typeOid)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("cannot alter array type %s",
+                       format_type_be(typeOid)),
+                errhint("You can alter type %s, which will alter the array type as well.",
+                        format_type_be(typTup->typelem))));
+
+   /* 
+    * If type is composite we need to rename associated pg_class entry too.
+    * RenameRelationInternal will call RenameTypeInternal automatically.
+    */
+   if (typTup->typtype == TYPTYPE_COMPOSITE)
+       RenameRelationInternal(typTup->typrelid, newTypeName,
+                              typTup->typnamespace);
+   else
+       RenameTypeInternal(typeOid, newTypeName,
+                          typTup->typnamespace);
+
+   /* Clean up */
+   heap_close(rel, RowExclusiveLock);
+}
+
 /*
  * Change the owner of a type.
  */
index 4688bc797789ade8ec4b69b872feb5728912b0eb..6d4df81a8a3b40a5094091cc279c7e2cfe385e6d 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.607 2008/02/15 22:17:06 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.608 2008/03/19 18:38:30 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -4734,6 +4734,14 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
                    n->newname = $8;
                    $$ = (Node *)n;
                }
+           | ALTER TYPE_P any_name RENAME TO name
+               {
+                   RenameStmt *n = makeNode(RenameStmt);
+                   n->renameType = OBJECT_TYPE;
+                   n->object = $3;
+                   n->newname = $6;
+                   $$ = (Node *)n;
+               }
        ;
 
 opt_column: COLUMN                                 { $$ = COLUMN; }
index fbd8f0d5643b5a6ad148044b949593e0add5b08d..df3887b1dc925cd53d55f23839ca84141057cca8 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.290 2008/03/14 17:25:58 alvherre Exp $
+ *   $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.291 2008/03/19 18:38:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1613,6 +1613,9 @@ CreateCommandTag(Node *parsetree)
                case OBJECT_TSCONFIGURATION:
                    tag = "ALTER TEXT SEARCH CONFIGURATION";
                    break;
+               case OBJECT_TYPE:
+                   tag = "ALTER TYPE";
+                   break;
                default:
                    tag = "???";
                    break;
index 7ece0af78c21fd7bc9724b6b739f68b420ab4f36..961f35e58976fa666a6e0649a8eb78796a19a993 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.191 2008/01/01 19:45:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.192 2008/03/19 18:38:30 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
@@ -682,7 +682,7 @@ extern void GenerateTypeDependencies(Oid typeNamespace,
                         Node *defaultExpr,
                         bool rebuild);
 
-extern void TypeRename(Oid typeOid, const char *newTypeName,
+extern void RenameTypeInternal(Oid typeOid, const char *newTypeName,
           Oid typeNamespace);
 
 extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace);
index e9c965439cee5511468e6314839897e4ffa2f406..700c1bd42eff52728c472d613dbf3e79d85e9c4b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.37 2008/01/30 19:46:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.38 2008/03/19 18:38:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,10 +44,14 @@ extern void renameatt(Oid myrelid,
          bool recurse,
          bool recursing);
 
-extern void renamerel(Oid myrelid,
+extern void RenameRelation(Oid myrelid,
          const char *newrelname,
          ObjectType reltype);
 
+extern void RenameRelationInternal(Oid myrelid,
+         const char *newrelname,
+         Oid namespaceId);
+
 extern void find_composite_type_dependencies(Oid typeOid,
                                 const char *origTblName,
                                 const char *origTypeName);
index 71d0ceefa813f98b815dfa794150dc5dd16c09d3..ce807b56d08c7992c6ec77f00af443e91bbc6912 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.22 2008/01/01 19:45:57 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.23 2008/03/19 18:38:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,7 @@ extern void AlterDomainDropConstraint(List *names, const char *constrName,
 
 extern List *GetDomainConstraints(Oid typeOid);
 
+extern void RenameType(List *names, const char *newTypeName);
 extern void AlterTypeOwner(List *names, Oid newOwnerId);
 extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
                       bool hasDependEntry);