mirror of
https://github.com/postgres/postgres.git
synced 2025-10-09 00:05:07 -04:00
Improve error message for duplicate labels when creating an enum type.
Previously, duplicate labels in CREATE TYPE AS ENUM were caught by the unique index on pg_enum, resulting in a generic error message. While this was evidently intentional, it's not terribly user-friendly, nor consistent with the ALTER TYPE cases which take more care with such errors. This patch adds an explicit check to produce a more user-friendly and descriptive error message. A potential objection to this implementation is that it adds O(N^2) work to the creation operation. However, quick testing finds that that's pretty negligible below 1000 enum labels, and tolerable even at 10000. So it doesn't really seem worth being smarter. Author: Yugo Nagata <nagata@sraoss.co.jp> Reviewed-by: Rahila Syed <rahilasyed90@gmail.com> Reviewed-by: Jim Jones <jim.jones@uni-muenster.de> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/20250704000402.37e605ab0c59c300965a17ee@sraoss.co.jp
This commit is contained in:
parent
eccba079c2
commit
1b1960c8c9
@ -110,12 +110,6 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
|
||||
|
||||
num_elems = list_length(vals);
|
||||
|
||||
/*
|
||||
* We do not bother to check the list of values for duplicates --- if you
|
||||
* have any, you'll get a less-than-friendly unique-index violation. It is
|
||||
* probably not worth trying harder.
|
||||
*/
|
||||
|
||||
pg_enum = table_open(EnumRelationId, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
@ -164,6 +158,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
|
||||
{
|
||||
char *lab = strVal(lfirst(lc));
|
||||
Name enumlabel = palloc0(NAMEDATALEN);
|
||||
ListCell *lc2;
|
||||
|
||||
/*
|
||||
* labels are stored in a name field, for easier syscache lookup, so
|
||||
@ -176,6 +171,24 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
|
||||
errdetail("Labels must be %d bytes or less.",
|
||||
NAMEDATALEN - 1)));
|
||||
|
||||
/*
|
||||
* Check for duplicate labels. The unique index on pg_enum would catch
|
||||
* that anyway, but we prefer a friendlier error message.
|
||||
*/
|
||||
foreach(lc2, vals)
|
||||
{
|
||||
/* Only need to compare lc to earlier entries */
|
||||
if (lc2 == lc)
|
||||
break;
|
||||
|
||||
if (strcmp(lab, strVal(lfirst(lc2))) == 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
||||
errmsg("enum label \"%s\" used more than once",
|
||||
lab)));
|
||||
}
|
||||
|
||||
/* OK, construct a tuple for this label */
|
||||
ExecClearTuple(slot[slotCount]);
|
||||
|
||||
memset(slot[slotCount]->tts_isnull, false,
|
||||
|
@ -52,6 +52,9 @@ hint |
|
||||
sql_error_code | 22P02
|
||||
|
||||
\x
|
||||
-- check for duplicate enum entries
|
||||
CREATE TYPE dup_enum AS ENUM ('foo','bar','foo');
|
||||
ERROR: enum label "foo" used more than once
|
||||
--
|
||||
-- adding new values
|
||||
--
|
||||
|
@ -23,6 +23,9 @@ SELECT * FROM pg_input_error_info('mauve', 'rainbow');
|
||||
SELECT * FROM pg_input_error_info(repeat('too_long', 32), 'rainbow');
|
||||
\x
|
||||
|
||||
-- check for duplicate enum entries
|
||||
CREATE TYPE dup_enum AS ENUM ('foo','bar','foo');
|
||||
|
||||
--
|
||||
-- adding new values
|
||||
--
|
||||
|
Loading…
x
Reference in New Issue
Block a user