Skip to content

Commit 51edc4c

Browse files
committed
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
1 parent 129a2f6 commit 51edc4c

File tree

7 files changed

+39
-61
lines changed

7 files changed

+39
-61
lines changed

src/backend/regex/regc_pg_locale.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,13 @@ pg_set_regex_collation(Oid collation)
246246
errhint("Use the COLLATE clause to set the collation explicitly.")));
247247
}
248248

249-
if (lc_ctype_is_c(collation))
249+
if (collation == C_COLLATION_OID)
250250
{
251-
/* C/POSIX collations use this path regardless of database encoding */
251+
/*
252+
* Some callers expect regexes to work for C_COLLATION_OID before
253+
* catalog access is available, so we can't call
254+
* pg_newlocale_from_collation().
255+
*/
252256
strategy = PG_REGEX_STRATEGY_C;
253257
collation = C_COLLATION_OID;
254258
}
@@ -261,7 +265,17 @@ pg_set_regex_collation(Oid collation)
261265
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
262266
errmsg("nondeterministic collations are not supported for regular expressions")));
263267

264-
if (locale->provider == COLLPROVIDER_BUILTIN)
268+
if (locale->ctype_is_c)
269+
{
270+
/*
271+
* C/POSIX collations use this path regardless of database
272+
* encoding
273+
*/
274+
strategy = PG_REGEX_STRATEGY_C;
275+
locale = 0;
276+
collation = C_COLLATION_OID;
277+
}
278+
else if (locale->provider == COLLPROVIDER_BUILTIN)
265279
{
266280
Assert(GetDatabaseEncoding() == PG_UTF8);
267281
strategy = PG_REGEX_STRATEGY_BUILTIN;
@@ -274,6 +288,7 @@ pg_set_regex_collation(Oid collation)
274288
#endif
275289
else
276290
{
291+
Assert(locale->provider == COLLPROVIDER_LIBC);
277292
if (GetDatabaseEncoding() == PG_UTF8)
278293
strategy = PG_REGEX_STRATEGY_LIBC_WIDE;
279294
else

src/backend/utils/adt/formatting.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,7 @@ char *
16361636
str_tolower(const char *buff, size_t nbytes, Oid collid)
16371637
{
16381638
char *result;
1639+
pg_locale_t mylocale;
16391640

16401641
if (!buff)
16411642
return NULL;
@@ -1653,17 +1654,15 @@ str_tolower(const char *buff, size_t nbytes, Oid collid)
16531654
errhint("Use the COLLATE clause to set the collation explicitly.")));
16541655
}
16551656

1657+
mylocale = pg_newlocale_from_collation(collid);
1658+
16561659
/* C/POSIX collations use this path regardless of database encoding */
1657-
if (lc_ctype_is_c(collid))
1660+
if (mylocale->ctype_is_c)
16581661
{
16591662
result = asc_tolower(buff, nbytes);
16601663
}
16611664
else
16621665
{
1663-
pg_locale_t mylocale;
1664-
1665-
mylocale = pg_newlocale_from_collation(collid);
1666-
16671666
#ifdef USE_ICU
16681667
if (mylocale->provider == COLLPROVIDER_ICU)
16691668
{
@@ -1774,6 +1773,7 @@ char *
17741773
str_toupper(const char *buff, size_t nbytes, Oid collid)
17751774
{
17761775
char *result;
1776+
pg_locale_t mylocale;
17771777

17781778
if (!buff)
17791779
return NULL;
@@ -1791,17 +1791,15 @@ str_toupper(const char *buff, size_t nbytes, Oid collid)
17911791
errhint("Use the COLLATE clause to set the collation explicitly.")));
17921792
}
17931793

1794+
mylocale = pg_newlocale_from_collation(collid);
1795+
17941796
/* C/POSIX collations use this path regardless of database encoding */
1795-
if (lc_ctype_is_c(collid))
1797+
if (mylocale->ctype_is_c)
17961798
{
17971799
result = asc_toupper(buff, nbytes);
17981800
}
17991801
else
18001802
{
1801-
pg_locale_t mylocale;
1802-
1803-
mylocale = pg_newlocale_from_collation(collid);
1804-
18051803
#ifdef USE_ICU
18061804
if (mylocale->provider == COLLPROVIDER_ICU)
18071805
{
@@ -1954,6 +1952,7 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
19541952
{
19551953
char *result;
19561954
int wasalnum = false;
1955+
pg_locale_t mylocale;
19571956

19581957
if (!buff)
19591958
return NULL;
@@ -1971,17 +1970,15 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
19711970
errhint("Use the COLLATE clause to set the collation explicitly.")));
19721971
}
19731972

1973+
mylocale = pg_newlocale_from_collation(collid);
1974+
19741975
/* C/POSIX collations use this path regardless of database encoding */
1975-
if (lc_ctype_is_c(collid))
1976+
if (mylocale->ctype_is_c)
19761977
{
19771978
result = asc_initcap(buff, nbytes);
19781979
}
19791980
else
19801981
{
1981-
pg_locale_t mylocale;
1982-
1983-
mylocale = pg_newlocale_from_collation(collid);
1984-
19851982
#ifdef USE_ICU
19861983
if (mylocale->provider == COLLPROVIDER_ICU)
19871984
{

src/backend/utils/adt/like.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ SB_lower_char(unsigned char c, pg_locale_t locale, bool locale_is_c)
147147
static inline int
148148
GenericMatchText(const char *s, int slen, const char *p, int plen, Oid collation)
149149
{
150-
if (collation && !lc_ctype_is_c(collation))
150+
if (collation)
151151
{
152152
pg_locale_t locale = pg_newlocale_from_collation(collation);
153153

src/backend/utils/adt/like_support.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static Selectivity regex_selectivity(const char *patt, int pattlen,
100100
bool case_insensitive,
101101
int fixed_prefix_len);
102102
static int pattern_char_isalpha(char c, bool is_multibyte,
103-
pg_locale_t locale, bool locale_is_c);
103+
pg_locale_t locale);
104104
static Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc,
105105
Oid collation);
106106
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,
10001000
match_pos;
10011001
bool is_multibyte = (pg_database_encoding_max_length() > 1);
10021002
pg_locale_t locale = 0;
1003-
bool locale_is_c = false;
10041003

10051004
/* the right-hand const is type text or bytea */
10061005
Assert(typeid == BYTEAOID || typeid == TEXTOID);
@@ -1024,11 +1023,7 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation,
10241023
errhint("Use the COLLATE clause to set the collation explicitly.")));
10251024
}
10261025

1027-
/* If case-insensitive, we need locale info */
1028-
if (lc_ctype_is_c(collation))
1029-
locale_is_c = true;
1030-
else
1031-
locale = pg_newlocale_from_collation(collation);
1026+
locale = pg_newlocale_from_collation(collation);
10321027
}
10331028

10341029
if (typeid != BYTEAOID)
@@ -1065,7 +1060,7 @@ like_fixed_prefix(Const *patt_const, bool case_insensitive, Oid collation,
10651060

10661061
/* Stop if case-varying character (it's sort of a wildcard) */
10671062
if (case_insensitive &&
1068-
pattern_char_isalpha(patt[pos], is_multibyte, locale, locale_is_c))
1063+
pattern_char_isalpha(patt[pos], is_multibyte, locale))
10691064
break;
10701065

10711066
match[match_pos++] = patt[pos];
@@ -1499,16 +1494,16 @@ regex_selectivity(const char *patt, int pattlen, bool case_insensitive,
14991494
*/
15001495
static int
15011496
pattern_char_isalpha(char c, bool is_multibyte,
1502-
pg_locale_t locale, bool locale_is_c)
1497+
pg_locale_t locale)
15031498
{
1504-
if (locale_is_c)
1499+
if (locale->ctype_is_c)
15051500
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
15061501
else if (is_multibyte && IS_HIGHBIT_SET(c))
15071502
return true;
1508-
else if (locale && locale->provider == COLLPROVIDER_ICU)
1503+
else if (locale->provider == COLLPROVIDER_ICU)
15091504
return IS_HIGHBIT_SET(c) ||
15101505
(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
1511-
else if (locale && locale->provider == COLLPROVIDER_LIBC)
1506+
else if (locale->provider == COLLPROVIDER_LIBC)
15121507
return isalpha_l((unsigned char) c, locale->info.lt);
15131508
else
15141509
return isalpha((unsigned char) c);

src/backend/utils/adt/pg_locale.c

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,32 +1266,6 @@ lookup_collation_cache(Oid collation)
12661266
return cache_entry;
12671267
}
12681268

1269-
/*
1270-
* Detect whether collation's LC_CTYPE property is C
1271-
*/
1272-
bool
1273-
lc_ctype_is_c(Oid collation)
1274-
{
1275-
/*
1276-
* If we're asked about "collation 0", return false, so that the code will
1277-
* go into the non-C path and report that the collation is bogus.
1278-
*/
1279-
if (!OidIsValid(collation))
1280-
return false;
1281-
1282-
/*
1283-
* If we're asked about the built-in C/POSIX collations, we know that.
1284-
*/
1285-
if (collation == C_COLLATION_OID ||
1286-
collation == POSIX_COLLATION_OID)
1287-
return true;
1288-
1289-
/*
1290-
* Otherwise, we have to consult pg_collation, but we cache that.
1291-
*/
1292-
return pg_newlocale_from_collation(collation)->ctype_is_c;
1293-
}
1294-
12951269
/* simple subroutine for reporting errors from newlocale() */
12961270
static void
12971271
report_newlocale_failure(const char *localename)

src/include/catalog/pg_collation.dat

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
descr => 'standard C collation',
2020
collname => 'C', collprovider => 'c', collencoding => '-1',
2121
collcollate => 'C', collctype => 'C' },
22-
{ oid => '951', oid_symbol => 'POSIX_COLLATION_OID',
23-
descr => 'standard POSIX collation',
22+
{ oid => '951', descr => 'standard POSIX collation',
2423
collname => 'POSIX', collprovider => 'c', collencoding => '-1',
2524
collcollate => 'POSIX', collctype => 'POSIX' },
2625
{ oid => '962', descr => 'sorts by Unicode code point, C character semantics',

src/include/utils/pg_locale.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ extern PGDLLIMPORT bool database_ctype_is_c;
5454
extern bool check_locale(int category, const char *locale, char **canonname);
5555
extern char *pg_perm_setlocale(int category, const char *locale);
5656

57-
extern bool lc_ctype_is_c(Oid collation);
58-
5957
/*
6058
* Return the POSIX lconv struct (contains number/money formatting
6159
* information) with locale information for all categories.

0 commit comments

Comments
 (0)