In commit 9aa3c782c93, Tom fixed a bug in which creating a table _foo when an array type of that name already existed would make the array type change its name to get out of the way. But it missed a trick in that renaming a table would still cause a conflict.
Steps to reproduce: postgres=# create table foo (id int); CREATE TABLE postgres=# create table bar (id int); CREATE TABLE postgres=# alter table bar rename to _foo; ERROR: type "_foo" already exists Attached is a patch that fixes this bug. One interesting thing to note however, is that if you rename a table to its own array's name (which was my case when I found this bug), the new array name will be ___foo instead of just __foo. I don't know if it's worth worrying about that. -- Vik Fearing +33 6 46 75 15 36 http://2ndQuadrant.fr PostgreSQL : Expertise, Formation et Support
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 04c10c6347..9e4e46f9f5 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -695,6 +695,7 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace) HeapTuple tuple; Form_pg_type typ; Oid arrayOid; + Oid typoid; pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock); @@ -708,10 +709,22 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace) arrayOid = typ->typarray; + typoid = GetSysCacheOid2(TYPENAMENSP, + CStringGetDatum(newTypeName), + ObjectIdGetDatum(typeNamespace)); + + /* + * See if it's an autogenerated array type, and if so + * rename it out of the way. + */ + if (OidIsValid(typoid) && get_typisdefined(typoid)) + { + if (moveArrayTypeName(typoid, newTypeName, typeNamespace)) + typoid = InvalidOid; + } + /* Just to give a more friendly error than unique-index violation */ - if (SearchSysCacheExists2(TYPENAMENSP, - CStringGetDatum(newTypeName), - ObjectIdGetDatum(typeNamespace))) + if (OidIsValid(typoid)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists", newTypeName))); diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index c88fd76848..142a782bff 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -128,6 +128,15 @@ SELECT * FROM tmp_new2; DROP TABLE tmp_new; DROP TABLE tmp_new2; +-- renaming to an array's autogenerated name (the array's name should get out of the way) +CREATE TABLE tmp_array (id int); +CREATE TABLE tmp_array2 (id int); +ALTER TABLE tmp_array2 RENAME TO _tmp_array; +DROP TABLE _tmp_array; +DROP TABLE tmp_array; +CREATE TABLE tmp_array (id int); +ALTER TABLE tmp_array RENAME TO _tmp_array; +DROP TABLE _tmp_array; -- ALTER TABLE ... RENAME on non-table relations -- renaming indexes (FIXME: this should probably test the index's functionality) ALTER INDEX IF EXISTS __onek_unique1 RENAME TO tmp_onek_unique1; diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql index c0e29720dc..1a893e9e2c 100644 --- a/src/test/regress/sql/alter_table.sql +++ b/src/test/regress/sql/alter_table.sql @@ -165,6 +165,16 @@ SELECT * FROM tmp_new2; DROP TABLE tmp_new; DROP TABLE tmp_new2; +-- renaming to an array's autogenerated name (the array's name should get out of the way) +CREATE TABLE tmp_array (id int); +CREATE TABLE tmp_array2 (id int); +ALTER TABLE tmp_array2 RENAME TO _tmp_array; +DROP TABLE _tmp_array; +DROP TABLE tmp_array; + +CREATE TABLE tmp_array (id int); +ALTER TABLE tmp_array RENAME TO _tmp_array; +DROP TABLE _tmp_array; -- ALTER TABLE ... RENAME on non-table relations -- renaming indexes (FIXME: this should probably test the index's functionality)
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers