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(