diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c new file mode 100644 index ebb0994..c6a6ed3 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -88,17 +88,41 @@ DefineCollation(ParseState *pstate, List if (strcmp(defel->defname, "from") == 0) defelp = &fromEl; else if (strcmp(defel->defname, "locale") == 0) + { + if (localeEl) + errorConflictingDefElem(defel, pstate); defelp = &localeEl; + } else if (strcmp(defel->defname, "lc_collate") == 0) + { + if (lccollateEl) + errorConflictingDefElem(defel, pstate); defelp = &lccollateEl; + } else if (strcmp(defel->defname, "lc_ctype") == 0) + { + if (lcctypeEl) + errorConflictingDefElem(defel, pstate); defelp = &lcctypeEl; + } else if (strcmp(defel->defname, "provider") == 0) + { + if (providerEl) + errorConflictingDefElem(defel, pstate); defelp = &providerEl; + } else if (strcmp(defel->defname, "deterministic") == 0) + { + if (deterministicEl) + errorConflictingDefElem(defel, pstate); defelp = &deterministicEl; + } else if (strcmp(defel->defname, "version") == 0) + { + if (versionEl) + errorConflictingDefElem(defel, pstate); defelp = &versionEl; + } else { ereport(ERROR, @@ -112,11 +136,17 @@ DefineCollation(ParseState *pstate, List *defelp = defel; } - if ((localeEl && (lccollateEl || lcctypeEl)) - || (fromEl && list_length(parameters) != 1)) + if (localeEl && (lccollateEl || lcctypeEl)) ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting or redundant options"))); + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"), + errdetail("LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE.")); + + if (fromEl && list_length(parameters) != 1) + ereport(ERROR, + errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"), + errdetail("FROM cannot be specified together with any other options.")); if (fromEl) { diff --git a/src/test/regress/expected/collate.out b/src/test/regress/expected/collate.out new file mode 100644 index 0b60b55..2468325 --- a/src/test/regress/expected/collate.out +++ b/src/test/regress/expected/collate.out @@ -701,6 +701,53 @@ View definition: SELECT ss.c1 + 1 AS c1p FROM ( SELECT 4 AS c1) ss; +-- Check conflicting or redundant options in CREATE COLLATION +-- LC_COLLATE +CREATE COLLATION coll_dup_chk (LC_COLLATE = "POSIX", LC_COLLATE = "NONSENSE", LC_CTYPE = "POSIX"); +ERROR: conflicting or redundant options +LINE 1: ...ATE COLLATION coll_dup_chk (LC_COLLATE = "POSIX", LC_COLLATE... + ^ +-- LC_CTYPE +CREATE COLLATION coll_dup_chk (LC_CTYPE = "POSIX", LC_CTYPE = "NONSENSE", LC_COLLATE = "POSIX"); +ERROR: conflicting or redundant options +LINE 1: ...REATE COLLATION coll_dup_chk (LC_CTYPE = "POSIX", LC_CTYPE =... + ^ +-- PROVIDER +CREATE COLLATION coll_dup_chk (PROVIDER = icu, PROVIDER = NONSENSE, LC_COLLATE = "POSIX", LC_CTYPE = "POSIX"); +ERROR: conflicting or redundant options +LINE 1: CREATE COLLATION coll_dup_chk (PROVIDER = icu, PROVIDER = NO... + ^ +-- LOCALE +CREATE COLLATION case_sensitive (LOCALE = '', LOCALE = "NONSENSE"); +ERROR: conflicting or redundant options +LINE 1: CREATE COLLATION case_sensitive (LOCALE = '', LOCALE = "NONS... + ^ +-- DETERMINISTIC +CREATE COLLATION coll_dup_chk (DETERMINISTIC = TRUE, DETERMINISTIC = NONSENSE, LOCALE = ''); +ERROR: conflicting or redundant options +LINE 1: ...ATE COLLATION coll_dup_chk (DETERMINISTIC = TRUE, DETERMINIS... + ^ +-- VERSION +CREATE COLLATION coll_dup_chk (VERSION = '1', VERSION = "NONSENSE", LOCALE = ''); +ERROR: conflicting or redundant options +LINE 1: CREATE COLLATION coll_dup_chk (VERSION = '1', VERSION = "NON... + ^ +-- LOCALE conflicts with LC_COLLATE and LC_CTYPE +CREATE COLLATION coll_dup_chk (LC_COLLATE = "POSIX", LC_CTYPE = "POSIX", LOCALE = ''); +ERROR: conflicting or redundant options +DETAIL: LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE. +-- LOCALE conflicts with LC_COLLATE +CREATE COLLATION coll_dup_chk (LC_COLLATE = "POSIX", LOCALE = ''); +ERROR: conflicting or redundant options +DETAIL: LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE. +-- LOCALE conflicts with LC_CTYPE +CREATE COLLATION coll_dup_chk (LC_CTYPE = "POSIX", LOCALE = ''); +ERROR: conflicting or redundant options +DETAIL: LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE. +-- FROM conflicts with any other option +CREATE COLLATION coll_dup_chk (FROM = "C", VERSION = "1"); +ERROR: conflicting or redundant options +DETAIL: FROM cannot be specified together with any other options. -- -- Clean up. Many of these table names will be re-used if the user is -- trying to run any platform-specific collation tests later, so we diff --git a/src/test/regress/sql/collate.sql b/src/test/regress/sql/collate.sql new file mode 100644 index 30f811b..c3d40fc --- a/src/test/regress/sql/collate.sql +++ b/src/test/regress/sql/collate.sql @@ -272,6 +272,27 @@ SELECT c1+1 AS c1p FROM (SELECT ('4' COLLATE "C")::INT AS c1) ss; \d+ collate_on_int +-- Check conflicting or redundant options in CREATE COLLATION +-- LC_COLLATE +CREATE COLLATION coll_dup_chk (LC_COLLATE = "POSIX", LC_COLLATE = "NONSENSE", LC_CTYPE = "POSIX"); +-- LC_CTYPE +CREATE COLLATION coll_dup_chk (LC_CTYPE = "POSIX", LC_CTYPE = "NONSENSE", LC_COLLATE = "POSIX"); +-- PROVIDER +CREATE COLLATION coll_dup_chk (PROVIDER = icu, PROVIDER = NONSENSE, LC_COLLATE = "POSIX", LC_CTYPE = "POSIX"); +-- LOCALE +CREATE COLLATION case_sensitive (LOCALE = '', LOCALE = "NONSENSE"); +-- DETERMINISTIC +CREATE COLLATION coll_dup_chk (DETERMINISTIC = TRUE, DETERMINISTIC = NONSENSE, LOCALE = ''); +-- VERSION +CREATE COLLATION coll_dup_chk (VERSION = '1', VERSION = "NONSENSE", LOCALE = ''); +-- LOCALE conflicts with LC_COLLATE and LC_CTYPE +CREATE COLLATION coll_dup_chk (LC_COLLATE = "POSIX", LC_CTYPE = "POSIX", LOCALE = ''); +-- LOCALE conflicts with LC_COLLATE +CREATE COLLATION coll_dup_chk (LC_COLLATE = "POSIX", LOCALE = ''); +-- LOCALE conflicts with LC_CTYPE +CREATE COLLATION coll_dup_chk (LC_CTYPE = "POSIX", LOCALE = ''); +-- FROM conflicts with any other option +CREATE COLLATION coll_dup_chk (FROM = "C", VERSION = "1"); -- -- Clean up. Many of these table names will be re-used if the user is