From 9b7392f7e26af0c6464731c42adc5b8b91a011f7 Mon Sep 17 00:00:00 2001
From: Yugo Nagata <nagata@sraoss.co.jp>
Date: Thu, 3 Jul 2025 23:45:40 +0900
Subject: [PATCH v2] 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 +++++++++++++++++++
 src/test/regress/expected/enum.out |  3 +++
 src/test/regress/sql/enum.sql      |  3 +++
 3 files changed, 25 insertions(+)

diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index a1634e58eec..daa11d34976 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("enum label \"%s\" used more than once",
+								lab)));
+		}
 
 		/*
 		 * labels are stored in a name field, for easier syscache lookup, so
diff --git a/src/test/regress/expected/enum.out b/src/test/regress/expected/enum.out
index 4d9f36d0d36..09201489080 100644
--- a/src/test/regress/expected/enum.out
+++ b/src/test/regress/expected/enum.out
@@ -52,6 +52,9 @@ hint           |
 sql_error_code | 22P02
 
 \x
+-- check for duplicate enum entries
+CREATE TYPE den AS ENUM ('foo','bar','foo');
+ERROR:  enum label "foo" used more than once
 --
 -- adding new values
 --
diff --git a/src/test/regress/sql/enum.sql b/src/test/regress/sql/enum.sql
index ecc4878a678..8f744c71bea 100644
--- a/src/test/regress/sql/enum.sql
+++ b/src/test/regress/sql/enum.sql
@@ -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 den AS ENUM ('foo','bar','foo');
+
 --
 -- adding new values
 --
-- 
2.43.0

