Index: doc/src/sgml/ref/alter_type.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/alter_type.sgml,v retrieving revision 1.4 diff -c -r1.4 alter_type.sgml *** doc/src/sgml/ref/alter_type.sgml 16 Sep 2006 00:30:16 -0000 1.4 --- doc/src/sgml/ref/alter_type.sgml 29 Sep 2007 05:43:14 -0000 *************** *** 26,31 **** --- 26,32 ---- ALTER TYPE name OWNER TO new_owner ALTER TYPE name SET SCHEMA new_schema + ALTER TYPE name RNAME TO new_name *************** *** 83,88 **** --- 84,98 ---- + + new_name + + + The new name for the type. + + + + Index: src/backend/catalog/pg_type.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_type.c,v retrieving revision 1.113 diff -c -r1.113 pg_type.c *** src/backend/catalog/pg_type.c 12 May 2007 00:54:59 -0000 1.113 --- src/backend/catalog/pg_type.c 30 Sep 2007 04:20:03 -0000 *************** *** 552,566 **** } /* ! * TypeRename * 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. */ void ! TypeRename(Oid typeOid, const char *newTypeName, Oid typeNamespace) { Relation pg_type_desc; HeapTuple tuple; --- 552,567 ---- } /* ! * RenameTypeInternal * This renames a type, as well as any associated array type. * ! * Caller must have already checked privileges. ! * ! * Currently this is used for renaming table rowtypes and for ! * ALTER TYPE RENAME TO command. */ void ! RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace) { Relation pg_type_desc; HeapTuple tuple; *************** *** 606,612 **** { char *arrname = makeArrayTypeName(newTypeName, typeNamespace); ! TypeRename(arrayOid, arrname, typeNamespace); pfree(arrname); } } --- 607,613 ---- { char *arrname = makeArrayTypeName(newTypeName, typeNamespace); ! RenameTypeInternal(arrayOid, arrname, typeNamespace); pfree(arrname); } } *************** *** 706,712 **** newname = makeArrayTypeName(typeName, typeNamespace); /* Apply the rename */ ! TypeRename(typeOid, newname, typeNamespace); /* * We must bump the command counter so that any subsequent use of --- 707,713 ---- newname = makeArrayTypeName(typeName, typeNamespace); /* Apply the rename */ ! RenameTypeInternal(typeOid, newname, typeNamespace); /* * We must bump the command counter so that any subsequent use of Index: src/backend/commands/alter.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/alter.c,v retrieving revision 1.25 diff -c -r1.25 alter.c *** src/backend/commands/alter.c 21 Aug 2007 01:11:14 -0000 1.25 --- src/backend/commands/alter.c 30 Sep 2007 03:53:05 -0000 *************** *** 117,123 **** aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(namespaceId)); ! renamerel(relid, stmt->newname, stmt->renameType); break; } case OBJECT_COLUMN: --- 117,123 ---- aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(namespaceId)); ! RenameRelation(relid, stmt->newname, stmt->renameType); break; } case OBJECT_COLUMN: *************** *** 154,159 **** --- 154,164 ---- RenameTSConfiguration(stmt->object, stmt->newname); break; + case OBJECT_TYPE: + case OBJECT_DOMAIN: + RenameType(stmt->object, stmt->newname); + break; + default: elog(ERROR, "unrecognized rename stmt type: %d", (int) stmt->renameType); Index: src/backend/commands/tablecmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/tablecmds.c,v retrieving revision 1.233 diff -c -r1.233 tablecmds.c *** src/backend/commands/tablecmds.c 29 Sep 2007 17:18:58 -0000 1.233 --- src/backend/commands/tablecmds.c 30 Sep 2007 03:55:31 -0000 *************** *** 1612,1637 **** relation_close(targetrelation, NoLock); /* close rel but keep lock */ } /* ! * renamerel - 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 ! renamerel(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 --- 1612,1627 ---- relation_close(targetrelation, NoLock); /* close rel but keep lock */ } + /* ! * Execute ALTER TABLE/VIEW/SEQUENCE RENAME */ void ! RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype) { Relation targetrelation; Oid namespaceId; char relkind; /* * Grab an exclusive lock on the target table, index, sequence or *************** *** 1639,1645 **** */ targetrelation = relation_open(myrelid, AccessExclusiveLock); - oldrelname = pstrdup(RelationGetRelationName(targetrelation)); namespaceId = RelationGetNamespace(targetrelation); if (!allowSystemTableMods && IsSystemRelation(targetrelation)) --- 1629,1634 ---- *************** *** 1654,1672 **** * view. */ relkind = targetrelation->rd_rel->relkind; ! if (reltype == OBJECT_SEQUENCE && relkind != 'S') ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a sequence", RelationGetRelationName(targetrelation)))); ! if (reltype == OBJECT_VIEW && relkind != 'v') ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a view", RelationGetRelationName(targetrelation)))); ! relhastriggers = (targetrelation->rd_rel->reltriggers > 0); /* * Find relation's pg_class tuple, and make sure newrelname isn't in use. --- 1643,1702 ---- * view. */ relkind = targetrelation->rd_rel->relkind; ! if (reltype == OBJECT_SEQUENCE && relkind != RELKIND_SEQUENCE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a sequence", RelationGetRelationName(targetrelation)))); ! if (reltype == OBJECT_VIEW && relkind != RELKIND_VIEW) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a view", RelationGetRelationName(targetrelation)))); ! /* ! * 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 RENAME TO 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. *************** *** 1704,1710 **** * Also rename the associated type, if any. */ if (OidIsValid(targetrelation->rd_rel->reltype)) ! TypeRename(targetrelation->rd_rel->reltype, newrelname, namespaceId); /* * Close rel, but keep exclusive lock! --- 1734,1740 ---- * Also rename the associated type, if any. */ if (OidIsValid(targetrelation->rd_rel->reltype)) ! RenameTypeInternal(targetrelation->rd_rel->reltype, newrelname, namespaceId); /* * Close rel, but keep exclusive lock! Index: src/backend/commands/typecmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/typecmds.c,v retrieving revision 1.108 diff -c -r1.108 typecmds.c *** src/backend/commands/typecmds.c 29 Sep 2007 17:18:58 -0000 1.108 --- src/backend/commands/typecmds.c 30 Sep 2007 04:36:08 -0000 *************** *** 2654,2656 **** --- 2654,2723 ---- if (OidIsValid(arrayOid)) AlterTypeNamespaceInternal(arrayOid, nspOid, true, true); } + + + /* + * 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); + + /* 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", + TypeNameToString(typename)))); + + /* 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 type we need to rename associated relation 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); + } Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.603 diff -c -r2.603 gram.y *** src/backend/parser/gram.y 24 Sep 2007 01:29:28 -0000 2.603 --- src/backend/parser/gram.y 29 Sep 2007 05:13:21 -0000 *************** *** 4748,4753 **** --- 4748,4761 ---- 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: src/include/catalog/pg_type.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_type.h,v retrieving revision 1.188 diff -c -r1.188 pg_type.h *** src/include/catalog/pg_type.h 3 Sep 2007 02:30:45 -0000 1.188 --- src/include/catalog/pg_type.h 29 Sep 2007 23:04:57 -0000 *************** *** 678,684 **** Node *defaultExpr, bool rebuild); ! extern void TypeRename(Oid typeOid, const char *newTypeName, Oid typeNamespace); extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace); --- 678,684 ---- Node *defaultExpr, bool rebuild); ! extern void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace); extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace); Index: src/include/commands/tablecmds.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/commands/tablecmds.h,v retrieving revision 1.34 diff -c -r1.34 tablecmds.h *** src/include/commands/tablecmds.h 3 Jul 2007 01:30:37 -0000 1.34 --- src/include/commands/tablecmds.h 30 Sep 2007 03:49:44 -0000 *************** *** 42,51 **** bool recurse, bool recursing); ! extern void renamerel(Oid myrelid, const char *newrelname, ObjectType reltype); extern void find_composite_type_dependencies(Oid typeOid, const char *origTblName, const char *origTypeName); --- 42,55 ---- bool recurse, bool recursing); ! 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: src/include/commands/typecmds.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/commands/typecmds.h,v retrieving revision 1.19 diff -c -r1.19 typecmds.h *** src/include/commands/typecmds.h 11 May 2007 17:57:14 -0000 1.19 --- src/include/commands/typecmds.h 29 Sep 2007 05:11:57 -0000 *************** *** 43,46 **** --- 43,48 ---- bool isImplicitArray, bool errorOnTableType); + extern void RenameType(List *names, const char *newTypeName); + #endif /* TYPECMDS_H */