Skip to content

Commit 94aced8

Browse files
committed
Move autogenerated array types out of the way during ALTER ... RENAME.
Commit 9aa3c78 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
1 parent 0461b66 commit 94aced8

File tree

3 files changed

+98
-9
lines changed

3 files changed

+98
-9
lines changed

src/backend/catalog/pg_type.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,7 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
695695
HeapTuple tuple;
696696
Form_pg_type typ;
697697
Oid arrayOid;
698+
Oid oldTypeOid;
698699

699700
pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
700701

@@ -708,13 +709,28 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
708709

709710
arrayOid = typ->typarray;
710711

711-
/* Just to give a more friendly error than unique-index violation */
712-
if (SearchSysCacheExists2(TYPENAMENSP,
713-
CStringGetDatum(newTypeName),
714-
ObjectIdGetDatum(typeNamespace)))
715-
ereport(ERROR,
716-
(errcode(ERRCODE_DUPLICATE_OBJECT),
717-
errmsg("type \"%s\" already exists", newTypeName)));
712+
/* Check for a conflicting type name. */
713+
oldTypeOid = GetSysCacheOid2(TYPENAMENSP,
714+
CStringGetDatum(newTypeName),
715+
ObjectIdGetDatum(typeNamespace));
716+
717+
/*
718+
* If there is one, see if it's an autogenerated array type, and if so
719+
* rename it out of the way. (But we must skip that for a shell type
720+
* because moveArrayTypeName will do the wrong thing in that case.)
721+
* Otherwise, we can at least give a more friendly error than unique-index
722+
* violation.
723+
*/
724+
if (OidIsValid(oldTypeOid))
725+
{
726+
if (get_typisdefined(oldTypeOid) &&
727+
moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
728+
/* successfully dodged the problem */ ;
729+
else
730+
ereport(ERROR,
731+
(errcode(ERRCODE_DUPLICATE_OBJECT),
732+
errmsg("type \"%s\" already exists", newTypeName)));
733+
}
718734

719735
/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
720736
namestrcpy(&(typ->typname), newTypeName);
@@ -726,8 +742,12 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
726742
heap_freetuple(tuple);
727743
heap_close(pg_type_desc, RowExclusiveLock);
728744

729-
/* If the type has an array type, recurse to handle that */
730-
if (OidIsValid(arrayOid))
745+
/*
746+
* If the type has an array type, recurse to handle that. But we don't
747+
* need to do anything more if we already renamed that array type above
748+
* (which would happen when, eg, renaming "foo" to "_foo").
749+
*/
750+
if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
731751
{
732752
char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
733753

src/test/regress/expected/alter_table.out

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,55 @@ SELECT * FROM tmp_new2;
128128

129129
DROP TABLE tmp_new;
130130
DROP TABLE tmp_new2;
131+
--
132+
-- check renaming to a table's array type's autogenerated name
133+
-- (the array type's name should get out of the way)
134+
--
135+
CREATE TABLE tmp_array (id int);
136+
CREATE TABLE tmp_array2 (id int);
137+
SELECT typname FROM pg_type WHERE oid = 'tmp_array[]'::regtype;
138+
typname
139+
------------
140+
_tmp_array
141+
(1 row)
142+
143+
SELECT typname FROM pg_type WHERE oid = 'tmp_array2[]'::regtype;
144+
typname
145+
-------------
146+
_tmp_array2
147+
(1 row)
148+
149+
ALTER TABLE tmp_array2 RENAME TO _tmp_array;
150+
SELECT typname FROM pg_type WHERE oid = 'tmp_array[]'::regtype;
151+
typname
152+
-------------
153+
__tmp_array
154+
(1 row)
155+
156+
SELECT typname FROM pg_type WHERE oid = '_tmp_array[]'::regtype;
157+
typname
158+
--------------
159+
___tmp_array
160+
(1 row)
161+
162+
DROP TABLE _tmp_array;
163+
DROP TABLE tmp_array;
164+
-- renaming to table's own array type's name is an interesting corner case
165+
CREATE TABLE tmp_array (id int);
166+
SELECT typname FROM pg_type WHERE oid = 'tmp_array[]'::regtype;
167+
typname
168+
------------
169+
_tmp_array
170+
(1 row)
171+
172+
ALTER TABLE tmp_array RENAME TO _tmp_array;
173+
SELECT typname FROM pg_type WHERE oid = '_tmp_array[]'::regtype;
174+
typname
175+
-------------
176+
__tmp_array
177+
(1 row)
178+
179+
DROP TABLE _tmp_array;
131180
-- ALTER TABLE ... RENAME on non-table relations
132181
-- renaming indexes (FIXME: this should probably test the index's functionality)
133182
ALTER INDEX IF EXISTS __onek_unique1 RENAME TO tmp_onek_unique1;

src/test/regress/sql/alter_table.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,26 @@ SELECT * FROM tmp_new2;
165165
DROP TABLE tmp_new;
166166
DROP TABLE tmp_new2;
167167

168+
--
169+
-- check renaming to a table's array type's autogenerated name
170+
-- (the array type's name should get out of the way)
171+
--
172+
CREATE TABLE tmp_array (id int);
173+
CREATE TABLE tmp_array2 (id int);
174+
SELECT typname FROM pg_type WHERE oid = 'tmp_array[]'::regtype;
175+
SELECT typname FROM pg_type WHERE oid = 'tmp_array2[]'::regtype;
176+
ALTER TABLE tmp_array2 RENAME TO _tmp_array;
177+
SELECT typname FROM pg_type WHERE oid = 'tmp_array[]'::regtype;
178+
SELECT typname FROM pg_type WHERE oid = '_tmp_array[]'::regtype;
179+
DROP TABLE _tmp_array;
180+
DROP TABLE tmp_array;
181+
182+
-- renaming to table's own array type's name is an interesting corner case
183+
CREATE TABLE tmp_array (id int);
184+
SELECT typname FROM pg_type WHERE oid = 'tmp_array[]'::regtype;
185+
ALTER TABLE tmp_array RENAME TO _tmp_array;
186+
SELECT typname FROM pg_type WHERE oid = '_tmp_array[]'::regtype;
187+
DROP TABLE _tmp_array;
168188

169189
-- ALTER TABLE ... RENAME on non-table relations
170190
-- renaming indexes (FIXME: this should probably test the index's functionality)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy