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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers