1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Support ALTER TYPE RENAME. Petr Jelinek

This commit is contained in:
Tom Lane
2008-03-19 18:38:30 +00:00
parent a9686591d7
commit 5507b22dfc
10 changed files with 180 additions and 47 deletions

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

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

View 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.
*/