]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix t_isspace(), etc., when datlocprovider=i and datctype=C.
authorJeff Davis <jdavis@postgresql.org>
Fri, 17 Mar 2023 18:47:35 +0000 (11:47 -0700)
committerJeff Davis <jdavis@postgresql.org>
Fri, 17 Mar 2023 19:07:47 +0000 (12:07 -0700)
Check whether the datctype is C to determine whether t_isspace() and
related functions use isspace() or iswspace().

Previously, t_isspace() checked whether the database default collation
was C; which is incorrect when the default collation uses the ICU
provider.

Discussion: https://postgr.es/m/79e4354d9eccfdb00483146a6b9f6295202e7890.camel@j-davis.com
Reviewed-by: Peter Eisentraut
Backpatch-through: 15

src/backend/tsearch/ts_locale.c
src/backend/tsearch/wparser_def.c
src/backend/utils/adt/pg_locale.c
src/backend/utils/init/postinit.c
src/include/utils/pg_locale.h

index e0aa570bf5e60f17e05e50b4a79541662186f271..3a475a0f5fcb738c3e4ff88b80dbf26d70e71614 100644 (file)
@@ -38,10 +38,9 @@ t_isdigit(const char *ptr)
 {
        int                     clen = pg_mblen(ptr);
        wchar_t         character[WC_BUF_LEN];
-       Oid                     collation = DEFAULT_COLLATION_OID;      /* TODO */
        pg_locale_t mylocale = 0;       /* TODO */
 
-       if (clen == 1 || lc_ctype_is_c(collation))
+       if (clen == 1 || database_ctype_is_c)
                return isdigit(TOUCHAR(ptr));
 
        char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale);
@@ -54,10 +53,9 @@ t_isspace(const char *ptr)
 {
        int                     clen = pg_mblen(ptr);
        wchar_t         character[WC_BUF_LEN];
-       Oid                     collation = DEFAULT_COLLATION_OID;      /* TODO */
        pg_locale_t mylocale = 0;       /* TODO */
 
-       if (clen == 1 || lc_ctype_is_c(collation))
+       if (clen == 1 || database_ctype_is_c)
                return isspace(TOUCHAR(ptr));
 
        char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale);
@@ -70,10 +68,9 @@ t_isalpha(const char *ptr)
 {
        int                     clen = pg_mblen(ptr);
        wchar_t         character[WC_BUF_LEN];
-       Oid                     collation = DEFAULT_COLLATION_OID;      /* TODO */
        pg_locale_t mylocale = 0;       /* TODO */
 
-       if (clen == 1 || lc_ctype_is_c(collation))
+       if (clen == 1 || database_ctype_is_c)
                return isalpha(TOUCHAR(ptr));
 
        char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale);
@@ -86,10 +83,9 @@ t_isprint(const char *ptr)
 {
        int                     clen = pg_mblen(ptr);
        wchar_t         character[WC_BUF_LEN];
-       Oid                     collation = DEFAULT_COLLATION_OID;      /* TODO */
        pg_locale_t mylocale = 0;       /* TODO */
 
-       if (clen == 1 || lc_ctype_is_c(collation))
+       if (clen == 1 || database_ctype_is_c)
                return isprint(TOUCHAR(ptr));
 
        char2wchar(character, WC_BUF_LEN, ptr, clen, mylocale);
@@ -257,7 +253,6 @@ char *
 lowerstr_with_len(const char *str, int len)
 {
        char       *out;
-       Oid                     collation = DEFAULT_COLLATION_OID;      /* TODO */
        pg_locale_t mylocale = 0;       /* TODO */
 
        if (len == 0)
@@ -269,7 +264,7 @@ lowerstr_with_len(const char *str, int len)
         * Also, for a C locale there is no need to process as multibyte. From
         * backend/utils/adt/oracle_compat.c Teodor
         */
-       if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c(collation))
+       if (pg_database_encoding_max_length() > 1 && !database_ctype_is_c)
        {
                wchar_t    *wstr,
                                   *wptr;
index 2323a3b90860808efccbb052b8a0ab4cd9f7cfdb..de6ff79489a327e80d2771c058eb87a71e07ebb2 100644 (file)
@@ -297,11 +297,10 @@ TParserInit(char *str, int len)
         */
        if (prs->charmaxlen > 1)
        {
-               Oid                     collation = DEFAULT_COLLATION_OID;      /* TODO */
                pg_locale_t mylocale = 0;       /* TODO */
 
                prs->usewide = true;
-               if (lc_ctype_is_c(collation))
+               if (database_ctype_is_c)
                {
                        /*
                         * char2wchar doesn't work for C-locale and sizeof(pg_wchar) could
index a0490a752244411ca1676231ae4a2c35884a941d..3c8fbe63a61deb2a87087eb4e7ac6cb66eafacd2 100644 (file)
@@ -99,6 +99,9 @@ char     *localized_full_days[7 + 1];
 char      *localized_abbrev_months[12 + 1];
 char      *localized_full_months[12 + 1];
 
+/* is the databases's LC_CTYPE the C locale? */
+bool           database_ctype_is_c = false;
+
 /* indicates whether locale information cache is valid */
 static bool CurrentLocaleConvValid = false;
 static bool CurrentLCTimeValid = false;
index 28d5e19848afb8d3759f8cd74853435ea80c63fc..ae03706d84010b683f3836fcd96b637ae85f37c3 100644 (file)
@@ -418,6 +418,10 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect
                                                   " which is not recognized by setlocale().", ctype),
                                 errhint("Recreate the database with another locale or install the missing locale.")));
 
+       if (strcmp(ctype, "C") == 0 ||
+               strcmp(ctype, "POSIX") == 0)
+               database_ctype_is_c = true;
+
        if (dbform->datlocprovider == COLLPROVIDER_ICU)
        {
                datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_daticulocale, &isnull);
index e7385faef862c1b3ea94a5ce70cf8658cf54eeea..de7c5e30d2d7633f4cdf84ed1c25af58ebe45547 100644 (file)
@@ -49,6 +49,8 @@ extern PGDLLIMPORT char *localized_full_days[];
 extern PGDLLIMPORT char *localized_abbrev_months[];
 extern PGDLLIMPORT char *localized_full_months[];
 
+/* is the databases's LC_CTYPE the C locale? */
+extern PGDLLIMPORT bool        database_ctype_is_c;
 
 extern bool check_locale_messages(char **newval, void **extra, GucSource source);
 extern void assign_locale_messages(const char *newval, void *extra);