diff options
-rw-r--r-- | src/backend/utils/adt/pg_locale.c | 34 | ||||
-rw-r--r-- | src/bin/initdb/initdb.c | 2 | ||||
-rw-r--r-- | src/test/regress/expected/collate.icu.utf8.out | 7 | ||||
-rw-r--r-- | src/test/regress/sql/collate.icu.utf8.sql | 2 |
4 files changed, 44 insertions, 1 deletions
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index dd0786dff52..42b6ad45cb8 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -2503,6 +2503,7 @@ pg_ucol_open(const char *loc_str) { UCollator *collator; UErrorCode status; + char *fixed_str = NULL; /* * Must never open default collator, because it depends on the environment @@ -2517,6 +2518,36 @@ pg_ucol_open(const char *loc_str) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("opening default collator is not supported"))); + /* + * In ICU versions 54 and earlier, "und" is not a recognized spelling of + * the root locale. If the first component of the locale is "und", replace + * with "root" before opening. + */ + if (U_ICU_VERSION_MAJOR_NUM < 55) + { + char lang[ULOC_LANG_CAPACITY]; + + status = U_ZERO_ERROR; + uloc_getLanguage(loc_str, lang, ULOC_LANG_CAPACITY, &status); + if (U_FAILURE(status)) + { + ereport(ERROR, + (errmsg("could not get language from locale \"%s\": %s", + loc_str, u_errorName(status)))); + } + + if (strcmp(lang, "und") == 0) + { + const char *remainder = loc_str + strlen("und"); + + fixed_str = palloc(strlen("root") + strlen(remainder) + 1); + strcpy(fixed_str, "root"); + strcat(fixed_str, remainder); + + loc_str = fixed_str; + } + } + status = U_ZERO_ERROR; collator = ucol_open(loc_str, &status); if (U_FAILURE(status)) @@ -2527,6 +2558,9 @@ pg_ucol_open(const char *loc_str) if (U_ICU_VERSION_MAJOR_NUM < 54) icu_set_collation_attributes(collator, loc_str); + if (fixed_str != NULL) + pfree(fixed_str); + return collator; } diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 3c0bf5c0a89..bae97539fc8 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -1701,7 +1701,7 @@ setup_collation(FILE *cmdfd) * that they win if libc defines a locale with the same name. */ PG_CMD_PRINTF("INSERT INTO pg_collation (oid, collname, collnamespace, collowner, collprovider, collisdeterministic, collencoding, colliculocale)" - "VALUES (pg_nextoid('pg_catalog.pg_collation', 'oid', 'pg_catalog.pg_collation_oid_index'), 'unicode', 'pg_catalog'::regnamespace, %u, '%c', true, -1, '');\n\n", + "VALUES (pg_nextoid('pg_catalog.pg_collation', 'oid', 'pg_catalog.pg_collation_oid_index'), 'unicode', 'pg_catalog'::regnamespace, %u, '%c', true, -1, 'und');\n\n", BOOTSTRAP_SUPERUSERID, COLLPROVIDER_ICU); PG_CMD_PRINTF("INSERT INTO pg_collation (oid, collname, collnamespace, collowner, collprovider, collisdeterministic, collencoding, collcollate, collctype)" diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out index 6225b575cea..f135200c997 100644 --- a/src/test/regress/expected/collate.icu.utf8.out +++ b/src/test/regress/expected/collate.icu.utf8.out @@ -1312,6 +1312,13 @@ SELECT 'aBcD' COLLATE lt_insensitive = 'AbCd' COLLATE lt_insensitive; t (1 row) +CREATE COLLATION lt_upperfirst (provider = icu, locale = 'und-u-kf-upper'); +SELECT 'Z' COLLATE lt_upperfirst < 'z' COLLATE lt_upperfirst; + ?column? +---------- + t +(1 row) + CREATE TABLE test1cs (x text COLLATE case_sensitive); CREATE TABLE test2cs (x text COLLATE case_sensitive); CREATE TABLE test3cs (x text COLLATE case_sensitive); diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql index 64cbfd0a5bd..8105ebc8ae1 100644 --- a/src/test/regress/sql/collate.icu.utf8.sql +++ b/src/test/regress/sql/collate.icu.utf8.sql @@ -521,6 +521,8 @@ SELECT 'abc' <= 'ABC' COLLATE case_insensitive, 'abc' >= 'ABC' COLLATE case_inse -- test language tags CREATE COLLATION lt_insensitive (provider = icu, locale = 'en-u-ks-level1', deterministic = false); SELECT 'aBcD' COLLATE lt_insensitive = 'AbCd' COLLATE lt_insensitive; +CREATE COLLATION lt_upperfirst (provider = icu, locale = 'und-u-kf-upper'); +SELECT 'Z' COLLATE lt_upperfirst < 'z' COLLATE lt_upperfirst; CREATE TABLE test1cs (x text COLLATE case_sensitive); CREATE TABLE test2cs (x text COLLATE case_sensitive); |