1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-27 07:42:10 +03:00

Move autogenerated array types out of the way during ALTER ... RENAME.

Commit 9aa3c782c added code to allow CREATE TABLE/CREATE TYPE to not fail
when the desired type name conflicts with an autogenerated array type, by
dint of renaming the array type out of the way.  But I (tgl) overlooked
that the same case arises in ALTER TABLE/TYPE RENAME.  Fix that too.
Back-patch to all supported branches.

Report and patch by Vik Fearing, modified a bit by me

Discussion: https://postgr.es/m/0f4ade49-4f0b-a9a3-c120-7589f01d1eb8@2ndquadrant.com
This commit is contained in:
Tom Lane
2017-05-26 15:16:59 -04:00
parent a561254e4c
commit 525780c622
3 changed files with 98 additions and 9 deletions

View File

@@ -683,6 +683,7 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
HeapTuple tuple;
Form_pg_type typ;
Oid arrayOid;
Oid oldTypeOid;
pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
@@ -696,13 +697,28 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
arrayOid = typ->typarray;
/* Just to give a more friendly error than unique-index violation */
if (SearchSysCacheExists2(TYPENAMENSP,
CStringGetDatum(newTypeName),
ObjectIdGetDatum(typeNamespace)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("type \"%s\" already exists", newTypeName)));
/* Check for a conflicting type name. */
oldTypeOid = GetSysCacheOid2(TYPENAMENSP,
CStringGetDatum(newTypeName),
ObjectIdGetDatum(typeNamespace));
/*
* If there is one, see if it's an autogenerated array type, and if so
* rename it out of the way. (But we must skip that for a shell type
* because moveArrayTypeName will do the wrong thing in that case.)
* Otherwise, we can at least give a more friendly error than unique-index
* violation.
*/
if (OidIsValid(oldTypeOid))
{
if (get_typisdefined(oldTypeOid) &&
moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
/* successfully dodged the problem */ ;
else
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("type \"%s\" already exists", newTypeName)));
}
/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
namestrcpy(&(typ->typname), newTypeName);
@@ -717,8 +733,12 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
heap_freetuple(tuple);
heap_close(pg_type_desc, RowExclusiveLock);
/* If the type has an array type, recurse to handle that */
if (OidIsValid(arrayOid))
/*
* If the type has an array type, recurse to handle that. But we don't
* need to do anything more if we already renamed that array type above
* (which would happen when, eg, renaming "foo" to "_foo").
*/
if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
{
char *arrname = makeArrayTypeName(newTypeName, typeNamespace);