Commit 31510194 authored by Tom Lane's avatar Tom Lane

Minor corrections for ALTER TYPE ADD VALUE IF NOT EXISTS patch.

Produce a NOTICE when the label already exists, for consistency with other
CREATE IF NOT EXISTS commands.  Also, fix the code so it produces something
more user-friendly than an index violation when the label already exists.
This not incidentally enables making a regression test that the previous
patch didn't make for fear of exposing an unpredictable OID in the results.
Also some wordsmithing on the documentation.
parent fcc15766
...@@ -109,15 +109,16 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE [ IF NOT ...@@ -109,15 +109,16 @@ ALTER TYPE <replaceable class="PARAMETER">name</replaceable> ADD VALUE [ IF NOT
<term><literal>ADD VALUE [ IF NOT EXISTS ] [ BEFORE | AFTER ]</literal></term> <term><literal>ADD VALUE [ IF NOT EXISTS ] [ BEFORE | AFTER ]</literal></term>
<listitem> <listitem>
<para> <para>
This form adds a new value to an enum type. If the new value's place in This form adds a new value to an enum type. The new value's place in
the enum's ordering is not specified using <literal>BEFORE</literal> or the enum's ordering can be specified as being <literal>BEFORE</literal>
<literal>AFTER</literal>, then the new item is placed at the end of the or <literal>AFTER</literal> one of the existing values. Otherwise,
list of values. the new item is added at the end of the list of values.
</para> </para>
<para> <para>
If <literal>IF NOT EXISTS</literal> is used, it is not an error if the If <literal>IF NOT EXISTS</literal> is specified, it is not an error if
type already contains the new value, and no action is taken. Otherwise, the type already contains the new value: a notice is issued but no other
an error will occur if the new value is already present. action is taken. Otherwise, an error will occur if the new value is
already present.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
...@@ -212,19 +212,30 @@ AddEnumLabel(Oid enumTypeOid, ...@@ -212,19 +212,30 @@ AddEnumLabel(Oid enumTypeOid,
*/ */
LockDatabaseObject(TypeRelationId, enumTypeOid, 0, ExclusiveLock); LockDatabaseObject(TypeRelationId, enumTypeOid, 0, ExclusiveLock);
/* Do the "IF NOT EXISTS" test if specified */ /*
if (skipIfExists) * Check if label is already in use. The unique index on pg_enum would
* catch this anyway, but we prefer a friendlier error message, and
* besides we need a check to support IF NOT EXISTS.
*/
enum_tup = SearchSysCache2(ENUMTYPOIDNAME,
ObjectIdGetDatum(enumTypeOid),
CStringGetDatum(newVal));
if (HeapTupleIsValid(enum_tup))
{ {
HeapTuple tup; ReleaseSysCache(enum_tup);
if (skipIfExists)
tup = SearchSysCache2(ENUMTYPOIDNAME,
ObjectIdGetDatum(enumTypeOid),
CStringGetDatum(newVal));
if (HeapTupleIsValid(tup))
{ {
ReleaseSysCache(tup); ereport(NOTICE,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("enum label \"%s\" already exists, skipping",
newVal)));
return; return;
} }
else
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("enum label \"%s\" already exists",
newVal)));
} }
pg_enum = heap_open(EnumRelationId, RowExclusiveLock); pg_enum = heap_open(EnumRelationId, RowExclusiveLock);
......
...@@ -2306,7 +2306,7 @@ typedef struct AlterEnumStmt ...@@ -2306,7 +2306,7 @@ typedef struct AlterEnumStmt
char *newVal; /* new enum value's name */ char *newVal; /* new enum value's name */
char *newValNeighbor; /* neighboring enum value, if specified */ char *newValNeighbor; /* neighboring enum value, if specified */
bool newValIsAfter; /* place new enum value after neighbor? */ bool newValIsAfter; /* place new enum value after neighbor? */
bool skipIfExists; /* ignore statement if label already exists */ bool skipIfExists; /* no error if label already exists */
} AlterEnumStmt; } AlterEnumStmt;
/* ---------------------- /* ----------------------
......
...@@ -97,11 +97,11 @@ ALTER TYPE planets ADD VALUE 'pluto' AFTER 'zeus'; ...@@ -97,11 +97,11 @@ ALTER TYPE planets ADD VALUE 'pluto' AFTER 'zeus';
ERROR: "zeus" is not an existing enum label ERROR: "zeus" is not an existing enum label
-- if not exists tests -- if not exists tests
-- existing value gives error -- existing value gives error
-- We can't do this test because the error contains the ALTER TYPE planets ADD VALUE 'mercury';
-- offending Oid value, which is unpredictable. ERROR: enum label "mercury" already exists
-- ALTER TYPE planets ADD VALUE 'mercury';
-- unless IF NOT EXISTS is specified -- unless IF NOT EXISTS is specified
ALTER TYPE planets ADD VALUE IF NOT EXISTS 'mercury'; ALTER TYPE planets ADD VALUE IF NOT EXISTS 'mercury';
NOTICE: enum label "mercury" already exists, skipping
-- should be neptune, not mercury -- should be neptune, not mercury
SELECT enum_last(NULL::planets); SELECT enum_last(NULL::planets);
enum_last enum_last
......
...@@ -57,10 +57,7 @@ ALTER TYPE planets ADD VALUE 'pluto' AFTER 'zeus'; ...@@ -57,10 +57,7 @@ ALTER TYPE planets ADD VALUE 'pluto' AFTER 'zeus';
-- if not exists tests -- if not exists tests
-- existing value gives error -- existing value gives error
ALTER TYPE planets ADD VALUE 'mercury';
-- We can't do this test because the error contains the
-- offending Oid value, which is unpredictable.
-- ALTER TYPE planets ADD VALUE 'mercury';
-- unless IF NOT EXISTS is specified -- unless IF NOT EXISTS is specified
ALTER TYPE planets ADD VALUE IF NOT EXISTS 'mercury'; ALTER TYPE planets ADD VALUE IF NOT EXISTS 'mercury';
...@@ -73,7 +70,6 @@ ALTER TYPE planets ADD VALUE IF NOT EXISTS 'pluto'; ...@@ -73,7 +70,6 @@ ALTER TYPE planets ADD VALUE IF NOT EXISTS 'pluto';
-- should be pluto, i.e. the new value -- should be pluto, i.e. the new value
SELECT enum_last(NULL::planets); SELECT enum_last(NULL::planets);
-- --
-- Test inserting so many values that we have to renumber -- Test inserting so many values that we have to renumber
-- --
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment