Hi,

Currently, when creating an enum type, duplicate labels are caught by a unique
index on pg_enum, resulting in a generic error message. 

 postgres=# create type t as enum ('a','b','a');
 ERROR:  duplicate key value violates unique constraint 
"pg_enum_typid_label_index"
 DETAIL:  Key (enumtypid, enumlabel)=(16418, a) already exists.

I propose adding an explicit check for duplicate labels during enum creation,
so that a more user-friendly and descriptive error message can be produced,
similar to what is already done in ALTER TYPE ... ADD VALUE
or ALTER TYPE ... RENAME VALUE .. TO ....
 
With the attached patch applied, the error message becomes:

ERROR:  label "a" used more than once

Regards,
Yugo Nagata


-- 
Yugo Nagata <nag...@sraoss.co.jp>
>From 0b7f148e9ea6d9d6851e71f7ca3dc91b30b377af Mon Sep 17 00:00:00 2001
From: Yugo Nagata <nag...@sraoss.co.jp>
Date: Thu, 3 Jul 2025 23:45:40 +0900
Subject: [PATCH] Improve error message for duplicate labels in enum types

Previously, duplicate labels in an enum type were caught by a unique
index on pg_enum, resulting in a generic error message. This adds an
explicit check beforehand to produce a more user-friendly and descriptive
error message.
---
 src/backend/catalog/pg_enum.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index a1634e58eec..9a4039d4669 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -164,6 +164,25 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	{
 		char	   *lab = strVal(lfirst(lc));
 		Name		enumlabel = palloc0(NAMEDATALEN);
+		ListCell   *lc2;
+
+		/*
+		 * Check for duplicate labels. The unique index on pg_enum would catch
+		 * that anyway, but we prefer a friendlier error message.
+		 */
+		foreach(lc2, vals)
+		{
+			char	   *lab2 = strVal(lfirst(lc2));
+
+			if (lc == lc2)
+				break;
+
+			if (strcmp(lab, lab2) == 0)
+				ereport(ERROR,
+						(errcode(ERRCODE_DUPLICATE_OBJECT),
+						 errmsg("label \"%s\" used more than once",
+								lab)));
+		}
 
 		/*
 		 * labels are stored in a name field, for easier syscache lookup, so
-- 
2.43.0

Reply via email to