diff --git a/doc/src/sgml/ref/create_database.sgml b/doc/src/sgml/ref/create_database.sgml index 6c1fd95602..a839a8568c 100644 --- a/doc/src/sgml/ref/create_database.sgml +++ b/doc/src/sgml/ref/create_database.sgml @@ -29,6 +29,7 @@ CREATE DATABASE name [ LOCALE [=] locale ] [ LC_COLLATE [=] lc_collate ] [ LC_CTYPE [=] lc_ctype ] + [ BUILTIN_LOCALE [=] builtin_locale ] [ ICU_LOCALE [=] icu_locale ] [ ICU_RULES [=] icu_rules ] [ LOCALE_PROVIDER [=] locale_provider ] @@ -216,6 +217,23 @@ CREATE DATABASE name + + builtin_locale + + + Specifies the builtin provider locale for the database default + collation order and character classification, overriding the setting + . The locale provider must + be builtin. The default is the setting of if specified; otherwise the same + setting as the template database. Currently, the only available + locale for the builtin provider is + C. + + + + icu_locale diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index 9059f8b3ef..63ef9a0841 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -318,7 +318,7 @@ DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_e if (collprovider == COLLPROVIDER_BUILTIN) { - collencoding = GetDatabaseEncoding(); + collencoding = builtin_locale_encoding(colllocale); } else if (collprovider == COLLPROVIDER_ICU) { diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 364716bcec..f793f50b98 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -1270,14 +1270,8 @@ lookup_collation_cache(Oid collation, bool set_flags) if (collform->collprovider == COLLPROVIDER_BUILTIN) { - Datum datum; - const char *colllocale; - - datum = SysCacheGetAttrNotNull(COLLOID, tp, Anum_pg_collation_colllocale); - colllocale = TextDatumGetCString(datum); - cache_entry->collate_is_c = true; - cache_entry->ctype_is_c = (strcmp(colllocale, "C") == 0); + cache_entry->ctype_is_c = true; } else if (collform->collprovider == COLLPROVIDER_LIBC) { @@ -2501,6 +2495,26 @@ pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, return result; } +/* + * Return required encoding ID for the given locale, or -1 if any encoding is + * valid for the locale. + * + * The only supported locale for the builtin provider is "C", and it's + * available for any encoding. + */ +int +builtin_locale_encoding(const char *locale) +{ + if (strcmp(locale, "C") == 0) + return -1; + else + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("invalid locale name \"%s\" for builtin provider", + locale))); +} + + /* * Validate the locale and encoding combination, and return the canonical form * of the locale name. diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 8d53ef4a1f..c2daff1717 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -2455,7 +2455,8 @@ usage(const char *progname) " set default locale in the respective category for\n" " new databases (default taken from environment)\n")); printf(_(" --no-locale equivalent to --locale=C\n")); - printf(_(" --builtin-locale=LOCALE set builtin locale name for new databases\n")); + printf(_(" --builtin-locale=LOCALE\n" + " set builtin locale name for new databases\n")); printf(_(" --locale-provider={builtin|libc|icu}\n" " set default locale provider for new databases\n")); printf(_(" --pwfile=FILE read password for the new superuser from file\n")); @@ -2618,9 +2619,9 @@ setup_locale_encoding(void) else { printf(_("The database cluster will be initialized with this locale configuration:\n")); - printf(_(" default collation provider: %s\n"), collprovider_name(locale_provider)); + printf(_(" locale provider: %s\n"), collprovider_name(locale_provider)); if (locale_provider != COLLPROVIDER_LIBC) - printf(_(" default collation locale: %s\n"), datlocale); + printf(_(" default collation: %s\n"), datlocale); printf(_(" LC_COLLATE: %s\n" " LC_CTYPE: %s\n" " LC_MESSAGES: %s\n" diff --git a/src/bin/initdb/t/001_initdb.pl b/src/bin/initdb/t/001_initdb.pl index e719f70dae..3478f58b02 100644 --- a/src/bin/initdb/t/001_initdb.pl +++ b/src/bin/initdb/t/001_initdb.pl @@ -138,7 +138,7 @@ if ($ENV{with_icu} eq 'yes') '--lc-monetary=C', '--lc-time=C', "$tempdir/data4" ], - qr/^\s+default collation locale:\s+und\n/ms, + qr/^\s+default collation:\s+und\n/ms, 'options --locale-provider=icu --locale=und --lc-*=C'); command_fails_like( diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 43a9a70709..6fb22007ed 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202403172 +#define CATALOG_VERSION_NO 202403181 #endif diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h index 3d949d5112..205aa20067 100644 --- a/src/include/utils/pg_locale.h +++ b/src/include/utils/pg_locale.h @@ -117,6 +117,7 @@ extern size_t pg_strxfrm_prefix(char *dest, const char *src, size_t destsize, extern size_t pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src, size_t srclen, pg_locale_t locale); +extern int builtin_locale_encoding(const char *loc_str); extern const char *builtin_validate_locale(int encoding, const char *loc_str); extern void icu_validate_locale(const char *loc_str); extern char *icu_language_tag(const char *loc_str, int elevel); diff --git a/src/test/icu/t/010_database.pl b/src/test/icu/t/010_database.pl index 5f8ef16803..88d91cca39 100644 --- a/src/test/icu/t/010_database.pl +++ b/src/test/icu/t/010_database.pl @@ -62,8 +62,18 @@ is( $node1->psql( 0, "C locale works for ICU"); +# Test that LOCALE works for ICU locales if LC_COLLATE and LC_CTYPE +# are specified +is( $node1->psql( + 'postgres', + q{CREATE DATABASE dbicu2 LOCALE_PROVIDER icu LOCALE '@colStrength=primary' + LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0 ENCODING UTF8} + ), + 0, + "LOCALE works for ICU locales if LC_COLLATE and LC_CTYPE are specified"); + my ($ret, $stdout, $stderr) = $node1->psql('postgres', - q{CREATE DATABASE dbicu LOCALE_PROVIDER builtin LOCALE 'C' TEMPLATE dbicu} + q{CREATE DATABASE dbicu3 LOCALE_PROVIDER builtin LOCALE 'C' TEMPLATE dbicu} ); isnt($ret, 0, "locale provider must match template: exit code not 0"); like(