1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Remove lc_ctype_is_c().

Instead always fetch the locale and look at the ctype_is_c field.

hba.c relies on regexes working for the C locale without needing
catalog access, which worked before due to a special case for
C_COLLATION_OID in lc_ctype_is_c(). Move the special case to
pg_set_regex_collation() now that lc_ctype_is_c() is gone.

Author: Andreas Karlsson
Discussion: https://postgr.es/m/60929555-4709-40a7-b136-bcb44cff5a3c@proxel.se
This commit is contained in:
Jeff Davis
2024-09-06 13:23:21 -07:00
parent 129a2f6679
commit 51edc4ca54
7 changed files with 39 additions and 61 deletions

View File

@ -246,9 +246,13 @@ pg_set_regex_collation(Oid collation)
errhint("Use the COLLATE clause to set the collation explicitly."))); errhint("Use the COLLATE clause to set the collation explicitly.")));
} }
if (lc_ctype_is_c(collation)) if (collation == C_COLLATION_OID)
{ {
/* C/POSIX collations use this path regardless of database encoding */ /*
* Some callers expect regexes to work for C_COLLATION_OID before
* catalog access is available, so we can't call
* pg_newlocale_from_collation().
*/
strategy = PG_REGEX_STRATEGY_C; strategy = PG_REGEX_STRATEGY_C;
collation = C_COLLATION_OID; collation = C_COLLATION_OID;
} }
@ -261,7 +265,17 @@ pg_set_regex_collation(Oid collation)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("nondeterministic collations are not supported for regular expressions"))); errmsg("nondeterministic collations are not supported for regular expressions")));
if (locale->provider == COLLPROVIDER_BUILTIN) if (locale->ctype_is_c)
{
/*
* C/POSIX collations use this path regardless of database
* encoding
*/
strategy = PG_REGEX_STRATEGY_C;
locale = 0;
collation = C_COLLATION_OID;
}
else if (locale->provider == COLLPROVIDER_BUILTIN)
{ {
Assert(GetDatabaseEncoding() == PG_UTF8); Assert(GetDatabaseEncoding() == PG_UTF8);
strategy = PG_REGEX_STRATEGY_BUILTIN; strategy = PG_REGEX_STRATEGY_BUILTIN;
@ -274,6 +288,7 @@ pg_set_regex_collation(Oid collation)
#endif #endif
else else
{ {
Assert(locale->provider == COLLPROVIDER_LIBC);
if (GetDatabaseEncoding() == PG_UTF8) if (GetDatabaseEncoding() == PG_UTF8)
strategy = PG_REGEX_STRATEGY_LIBC_WIDE; strategy = PG_REGEX_STRATEGY_LIBC_WIDE;
else else

View File

@ -1636,6 +1636,7 @@ char *
str_tolower(const char *buff, size_t nbytes, Oid collid) str_tolower(const char *buff, size_t nbytes, Oid collid)
{ {
char *result; char *result;
pg_locale_t mylocale;
if (!buff) if (!buff)
return NULL; return NULL;
@ -1653,17 +1654,15 @@ str_tolower(const char *buff, size_t nbytes, Oid collid)
errhint("Use the COLLATE clause to set the collation explicitly."))); errhint("Use the COLLATE clause to set the collation explicitly.")));
} }
mylocale = pg_newlocale_from_collation(collid);
/* C/POSIX collations use this path regardless of database encoding */ /* C/POSIX collations use this path regardless of database encoding */
if (lc_ctype_is_c(collid)) if (mylocale->ctype_is_c)
{ {
result = asc_tolower(buff, nbytes); result = asc_tolower(buff, nbytes);
} }
else else
{ {
pg_locale_t mylocale;
mylocale = pg_newlocale_from_collation(collid);
#ifdef USE_ICU #ifdef USE_ICU
if (mylocale->provider == COLLPROVIDER_ICU) if (mylocale->provider == COLLPROVIDER_ICU)
{ {
@ -1774,6 +1773,7 @@ char *
str_toupper(const char *buff, size_t nbytes, Oid collid) str_toupper(const char *buff, size_t nbytes, Oid collid)
{ {
char *result; char *result;
pg_locale_t mylocale;
if (!buff) if (!buff)
return NULL; return NULL;
@ -1791,17 +1791,15 @@ str_toupper(const char *buff, size_t nbytes, Oid collid)
errhint("Use the COLLATE clause to set the collation explicitly."))); errhint("Use the COLLATE clause to set the collation explicitly.")));
} }
mylocale = pg_newlocale_from_collation(collid);
/* C/POSIX collations use this path regardless of database encoding */ /* C/POSIX collations use this path regardless of database encoding */
if (lc_ctype_is_c(collid)) if (mylocale->ctype_is_c)
{ {
result = asc_toupper(buff, nbytes); result = asc_toupper(buff, nbytes);
} }
else else
{ {
pg_locale_t mylocale;
mylocale = pg_newlocale_from_collation(collid);
#ifdef USE_ICU #ifdef USE_ICU
if (mylocale->provider == COLLPROVIDER_ICU) if (mylocale->provider == COLLPROVIDER_ICU)
{ {
@ -1954,6 +1952,7 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
{ {
char *result; char *result;
int wasalnum = false; int wasalnum = false;
pg_locale_t mylocale;
if (!buff) if (!buff)
return NULL; return NULL;
@ -1971,17 +1970,15 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
errhint("Use the COLLATE clause to set the collation explicitly."))); errhint("Use the COLLATE clause to set the collation explicitly.")));
} }
mylocale = pg_newlocale_from_collation(collid);
/* C/POSIX collations use this path regardless of database encoding */ /* C/POSIX collations use this path regardless of database encoding */
if (lc_ctype_is_c(collid)) if (mylocale->ctype_is_c)
{ {
result = asc_initcap(buff, nbytes); result = asc_initcap(buff, nbytes);
} }
else else
{ {
pg_locale_t mylocale;
mylocale = pg_newlocale_from_collation(collid);
#ifdef USE_ICU #ifdef USE_ICU
if (mylocale->provider == COLLPROVIDER_ICU) if (mylocale->provider == COLLPROVIDER_ICU)
{ {

View File

@ -147,7 +147,7 @@ SB_lower_char(unsigned char c, pg_locale_t locale, bool locale_is_c)
static inline int static inline int
GenericMatchText(const char *s, int slen, const char *p, int plen, Oid collation) GenericMatchText(const char *s, int slen, const char *p, int plen, Oid collation)
{ {
if (collation && !lc_ctype_is_c(collation)) if (collation)
{ {
pg_locale_t locale = pg_newlocale_from_collation(collation); pg_locale_t locale = pg_newlocale_from_collation(collation);

View File

@ -100,7 +100,7 @@ static Selectivity regex_selectivity(const char *patt, int pattlen,
bool case_insensitive, bool case_insensitive,
int fixed_prefix_len); int fixed_prefix_len);
static int pattern_char_isalpha(char c, bool is_multibyte, static int pattern_char_isalpha(char c, bool is_multibyte,
pg_locale_t locale, bool locale_is_c); pg_locale_t locale);
static Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc, static Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc,
Oid collation); Oid collation);
static Datum string_to_datum(const char *str, Oid datatype); static Datum string_to_datum(const char *str, Oid datatype);
@ -1000,7 +1000,6 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation,
match_pos; match_pos;
bool is_multibyte = (pg_database_encoding_max_length() > 1); bool is_multibyte = (pg_database_encoding_max_length() > 1);
pg_locale_t locale = 0; pg_locale_t locale = 0;
bool locale_is_c = false;
/* the right-hand const is type text or bytea */ /* the right-hand const is type text or bytea */
Assert(typeid == BYTEAOID || typeid == TEXTOID); Assert(typeid == BYTEAOID || typeid == TEXTOID);
@ -1024,11 +1023,7 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation,
errhint("Use the COLLATE clause to set the collation explicitly."))); errhint("Use the COLLATE clause to set the collation explicitly.")));
} }
/* If case-insensitive, we need locale info */ locale = pg_newlocale_from_collation(collation);
if (lc_ctype_is_c(collation))
locale_is_c = true;
else
locale = pg_newlocale_from_collation(collation);
} }
if (typeid != BYTEAOID) if (typeid != BYTEAOID)
@ -1065,7 +1060,7 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation,
/* Stop if case-varying character (it's sort of a wildcard) */ /* Stop if case-varying character (it's sort of a wildcard) */
if (case_insensitive && if (case_insensitive &&
pattern_char_isalpha(patt[pos], is_multibyte, locale, locale_is_c)) pattern_char_isalpha(patt[pos], is_multibyte, locale))
break; break;
match[match_pos++] = patt[pos]; match[match_pos++] = patt[pos];
@ -1499,16 +1494,16 @@ regex_selectivity(const char *patt, int pattlen, bool case_insensitive,
*/ */
static int static int
pattern_char_isalpha(char c, bool is_multibyte, pattern_char_isalpha(char c, bool is_multibyte,
pg_locale_t locale, bool locale_is_c) pg_locale_t locale)
{ {
if (locale_is_c) if (locale->ctype_is_c)
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
else if (is_multibyte && IS_HIGHBIT_SET(c)) else if (is_multibyte && IS_HIGHBIT_SET(c))
return true; return true;
else if (locale && locale->provider == COLLPROVIDER_ICU) else if (locale->provider == COLLPROVIDER_ICU)
return IS_HIGHBIT_SET(c) || return IS_HIGHBIT_SET(c) ||
(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
else if (locale && locale->provider == COLLPROVIDER_LIBC) else if (locale->provider == COLLPROVIDER_LIBC)
return isalpha_l((unsigned char) c, locale->info.lt); return isalpha_l((unsigned char) c, locale->info.lt);
else else
return isalpha((unsigned char) c); return isalpha((unsigned char) c);

View File

@ -1266,32 +1266,6 @@ lookup_collation_cache(Oid collation)
return cache_entry; return cache_entry;
} }
/*
* Detect whether collation's LC_CTYPE property is C
*/
bool
lc_ctype_is_c(Oid collation)
{
/*
* If we're asked about "collation 0", return false, so that the code will
* go into the non-C path and report that the collation is bogus.
*/
if (!OidIsValid(collation))
return false;
/*
* If we're asked about the built-in C/POSIX collations, we know that.
*/
if (collation == C_COLLATION_OID ||
collation == POSIX_COLLATION_OID)
return true;
/*
* Otherwise, we have to consult pg_collation, but we cache that.
*/
return pg_newlocale_from_collation(collation)->ctype_is_c;
}
/* simple subroutine for reporting errors from newlocale() */ /* simple subroutine for reporting errors from newlocale() */
static void static void
report_newlocale_failure(const char *localename) report_newlocale_failure(const char *localename)

View File

@ -19,8 +19,7 @@
descr => 'standard C collation', descr => 'standard C collation',
collname => 'C', collprovider => 'c', collencoding => '-1', collname => 'C', collprovider => 'c', collencoding => '-1',
collcollate => 'C', collctype => 'C' }, collcollate => 'C', collctype => 'C' },
{ oid => '951', oid_symbol => 'POSIX_COLLATION_OID', { oid => '951', descr => 'standard POSIX collation',
descr => 'standard POSIX collation',
collname => 'POSIX', collprovider => 'c', collencoding => '-1', collname => 'POSIX', collprovider => 'c', collencoding => '-1',
collcollate => 'POSIX', collctype => 'POSIX' }, collcollate => 'POSIX', collctype => 'POSIX' },
{ oid => '962', descr => 'sorts by Unicode code point, C character semantics', { oid => '962', descr => 'sorts by Unicode code point, C character semantics',

View File

@ -54,8 +54,6 @@ extern PGDLLIMPORT bool database_ctype_is_c;
extern bool check_locale(int category, const char *locale, char **canonname); extern bool check_locale(int category, const char *locale, char **canonname);
extern char *pg_perm_setlocale(int category, const char *locale); extern char *pg_perm_setlocale(int category, const char *locale);
extern bool lc_ctype_is_c(Oid collation);
/* /*
* Return the POSIX lconv struct (contains number/money formatting * Return the POSIX lconv struct (contains number/money formatting
* information) with locale information for all categories. * information) with locale information for all categories.