Address more review comments on commit 2d819a08a1.

Based on comments from Peter Eisentraut.

 * Document CREATE DATABASE ... BUILTIN_LOCALE.
 * Determine required encoding based on locale name for CREATE
   COLLATION. Use -1 for "C" (requires catversion bump).
 * initdb output fixups.
 * Make ctype_is_c a constant true for now.
 * Fixups to ICU 010_create_database.pl test.

Discussion: https://postgr.es/m/4135cf11-206d-40ed-96c0-9363c1232379@eisentraut.org
This commit is contained in:
Jeff Davis 2024-03-18 11:56:45 -07:00
parent 66ab9371a2
commit 846311051e
8 changed files with 58 additions and 14 deletions

View File

@ -29,6 +29,7 @@ CREATE DATABASE <replaceable class="parameter">name</replaceable>
[ LOCALE [=] <replaceable class="parameter">locale</replaceable> ]
[ LC_COLLATE [=] <replaceable class="parameter">lc_collate</replaceable> ]
[ LC_CTYPE [=] <replaceable class="parameter">lc_ctype</replaceable> ]
[ BUILTIN_LOCALE [=] <replaceable class="parameter">builtin_locale</replaceable> ]
[ ICU_LOCALE [=] <replaceable class="parameter">icu_locale</replaceable> ]
[ ICU_RULES [=] <replaceable class="parameter">icu_rules</replaceable> ]
[ LOCALE_PROVIDER [=] <replaceable class="parameter">locale_provider</replaceable> ]
@ -216,6 +217,23 @@ CREATE DATABASE <replaceable class="parameter">name</replaceable>
</listitem>
</varlistentry>
<varlistentry id="create-database-builtin-locale">
<term><replaceable class="parameter">builtin_locale</replaceable></term>
<listitem>
<para>
Specifies the builtin provider locale for the database default
collation order and character classification, overriding the setting
<xref linkend="create-database-locale"/>. The <link
linkend="create-database-locale-provider">locale provider</link> must
be <literal>builtin</literal>. The default is the setting of <xref
linkend="create-database-locale"/> if specified; otherwise the same
setting as the template database. Currently, the only available
locale for the <literal>builtin</literal> provider is
<literal>C</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry id="create-database-icu-locale">
<term><replaceable class="parameter">icu_locale</replaceable></term>
<listitem>

View File

@ -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)
{

View File

@ -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.

View File

@ -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"

View File

@ -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(

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202403172
#define CATALOG_VERSION_NO 202403181
#endif

View File

@ -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);

View File

@ -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(