Address more review comments on commit 2d819a08a1.
authorJeff Davis
Mon, 18 Mar 2024 18:56:45 +0000 (11:56 -0700)
committerJeff Davis
Mon, 18 Mar 2024 18:58:13 +0000 (11:58 -0700)
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

doc/src/sgml/ref/create_database.sgml
src/backend/commands/collationcmds.c
src/backend/utils/adt/pg_locale.c
src/bin/initdb/initdb.c
src/bin/initdb/t/001_initdb.pl
src/include/catalog/catversion.h
src/include/utils/pg_locale.h
src/test/icu/t/010_database.pl

index 6c1fd95602da2ea402ca288f28dd0f652e0eb18b..a839a8568cb06b73d35dd696fd9dadba9411b8c9 100644 (file)
@@ -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 
+        linkend="create-database-locale-provider">locale provider must
+        be builtin.  The default is the setting of 
+        linkend="create-database-locale"/> if specified; otherwise the same
+        setting as the template database.  Currently, the only available
+        locale for the builtin provider is
+        C.
+       
+      
+     
+
      
       icu_locale
       
index 9059f8b3efda33f11a120691115d5ede86b88fa6..63ef9a08411b0b4bb3e56caea0194e455158a137 100644 (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)
        {
index 364716bcec8692db16908f1987c971d58ec7c962..f793f50b98444297ade6ebd19f99f7b0ecbfa69f 100644 (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.
index 8d53ef4a1fc8923de24d83d5bcdf7ef53187b314..c2daff1717976de950c9ce60ce2ceef43d367269 100644 (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"
index e719f70dae285ebb33bb8c3f2d30527da88c31d3..3478f58b02a10a94bf6c5d73691c1e829755417e 100644 (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(
index 43a9a707094093a1753c534481f971149ba0f961..6fb22007ed007624b3e5af5df19128f3ee390132 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202403172
+#define CATALOG_VERSION_NO 202403181
 
 #endif
index 3d949d5112390436a04698e6f1d5bdb156e3bb77..205aa200672f6833ed0fb6e7c9115d0fce5122bd 100644 (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);
index 5f8ef16803423262a4a17868dab147046e2ae9c9..88d91cca39d4729b9d8178cb93b107c9f69294c0 100644 (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(