Skip to content

Commit a2f17f0

Browse files
committed
Control collation behavior with a method table.
Previously, behavior branched based on the provider. A method table is less error-prone and more flexible. The ctype behavior will be addressed in an upcoming commit. Reviewed-by: Andreas Karlsson Discussion: https://postgr.es/m/2830211e1b6e6a2e26d845780b03e125281ea17b.camel%40j-davis.com
1 parent 4f5cef2 commit a2f17f0

File tree

4 files changed

+180
-176
lines changed

4 files changed

+180
-176
lines changed

src/backend/utils/adt/pg_locale.c

Lines changed: 16 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -92,27 +92,12 @@ extern char *get_collation_actual_version_builtin(const char *collcollate);
9292
/* pg_locale_icu.c */
9393
#ifdef USE_ICU
9494
extern UCollator *pg_ucol_open(const char *loc_str);
95-
extern int strncoll_icu(const char *arg1, ssize_t len1,
96-
const char *arg2, ssize_t len2,
97-
pg_locale_t locale);
98-
extern size_t strnxfrm_icu(char *dest, size_t destsize,
99-
const char *src, ssize_t srclen,
100-
pg_locale_t locale);
101-
extern size_t strnxfrm_prefix_icu(char *dest, size_t destsize,
102-
const char *src, ssize_t srclen,
103-
pg_locale_t locale);
10495
extern char *get_collation_actual_version_icu(const char *collcollate);
10596
#endif
10697
extern pg_locale_t create_pg_locale_icu(Oid collid, MemoryContext context);
10798

10899
/* pg_locale_libc.c */
109100
extern pg_locale_t create_pg_locale_libc(Oid collid, MemoryContext context);
110-
extern int strncoll_libc(const char *arg1, ssize_t len1,
111-
const char *arg2, ssize_t len2,
112-
pg_locale_t locale);
113-
extern size_t strnxfrm_libc(char *dest, size_t destsize,
114-
const char *src, ssize_t srclen,
115-
pg_locale_t locale);
116101
extern char *get_collation_actual_version_libc(const char *collcollate);
117102

118103
extern size_t strlower_builtin(char *dst, size_t dstsize, const char *src,
@@ -1244,6 +1229,9 @@ create_pg_locale(Oid collid, MemoryContext context)
12441229

12451230
result->is_default = false;
12461231

1232+
Assert((result->collate_is_c && result->collate == NULL) ||
1233+
(!result->collate_is_c && result->collate != NULL));
1234+
12471235
datum = SysCacheGetAttr(COLLOID, tp, Anum_pg_collation_collversion,
12481236
&isnull);
12491237
if (!isnull)
@@ -1467,19 +1455,7 @@ pg_strupper(char *dst, size_t dstsize, const char *src, ssize_t srclen,
14671455
int
14681456
pg_strcoll(const char *arg1, const char *arg2, pg_locale_t locale)
14691457
{
1470-
int result;
1471-
1472-
if (locale->provider == COLLPROVIDER_LIBC)
1473-
result = strncoll_libc(arg1, -1, arg2, -1, locale);
1474-
#ifdef USE_ICU
1475-
else if (locale->provider == COLLPROVIDER_ICU)
1476-
result = strncoll_icu(arg1, -1, arg2, -1, locale);
1477-
#endif
1478-
else
1479-
/* shouldn't happen */
1480-
PGLOCALE_SUPPORT_ERROR(locale->provider);
1481-
1482-
return result;
1458+
return locale->collate->strncoll(arg1, -1, arg2, -1, locale);
14831459
}
14841460

14851461
/*
@@ -1500,51 +1476,25 @@ int
15001476
pg_strncoll(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2,
15011477
pg_locale_t locale)
15021478
{
1503-
int result;
1504-
1505-
if (locale->provider == COLLPROVIDER_LIBC)
1506-
result = strncoll_libc(arg1, len1, arg2, len2, locale);
1507-
#ifdef USE_ICU
1508-
else if (locale->provider == COLLPROVIDER_ICU)
1509-
result = strncoll_icu(arg1, len1, arg2, len2, locale);
1510-
#endif
1511-
else
1512-
/* shouldn't happen */
1513-
PGLOCALE_SUPPORT_ERROR(locale->provider);
1514-
1515-
return result;
1479+
return locale->collate->strncoll(arg1, len1, arg2, len2, locale);
15161480
}
15171481

15181482
/*
15191483
* Return true if the collation provider supports pg_strxfrm() and
15201484
* pg_strnxfrm(); otherwise false.
15211485
*
1522-
* Unfortunately, it seems that strxfrm() for non-C collations is broken on
1523-
* many common platforms; testing of multiple versions of glibc reveals that,
1524-
* for many locales, strcoll() and strxfrm() do not return consistent
1525-
* results. While no other libc other than Cygwin has so far been shown to
1526-
* have a problem, we take the conservative course of action for right now and
1527-
* disable this categorically. (Users who are certain this isn't a problem on
1528-
* their system can define TRUST_STRXFRM.)
15291486
*
15301487
* No similar problem is known for the ICU provider.
15311488
*/
15321489
bool
15331490
pg_strxfrm_enabled(pg_locale_t locale)
15341491
{
1535-
if (locale->provider == COLLPROVIDER_LIBC)
1536-
#ifdef TRUST_STRXFRM
1537-
return true;
1538-
#else
1539-
return false;
1540-
#endif
1541-
else if (locale->provider == COLLPROVIDER_ICU)
1542-
return true;
1543-
else
1544-
/* shouldn't happen */
1545-
PGLOCALE_SUPPORT_ERROR(locale->provider);
1546-
1547-
return false; /* keep compiler quiet */
1492+
/*
1493+
* locale->collate->strnxfrm is still a required method, even if it may
1494+
* have the wrong behavior, because the planner uses it for estimates in
1495+
* some cases.
1496+
*/
1497+
return locale->collate->strxfrm_is_safe;
15481498
}
15491499

15501500
/*
@@ -1555,19 +1505,7 @@ pg_strxfrm_enabled(pg_locale_t locale)
15551505
size_t
15561506
pg_strxfrm(char *dest, const char *src, size_t destsize, pg_locale_t locale)
15571507
{
1558-
size_t result = 0; /* keep compiler quiet */
1559-
1560-
if (locale->provider == COLLPROVIDER_LIBC)
1561-
result = strnxfrm_libc(dest, destsize, src, -1, locale);
1562-
#ifdef USE_ICU
1563-
else if (locale->provider == COLLPROVIDER_ICU)
1564-
result = strnxfrm_icu(dest, destsize, src, -1, locale);
1565-
#endif
1566-
else
1567-
/* shouldn't happen */
1568-
PGLOCALE_SUPPORT_ERROR(locale->provider);
1569-
1570-
return result;
1508+
return locale->collate->strnxfrm(dest, destsize, src, -1, locale);
15711509
}
15721510

15731511
/*
@@ -1593,19 +1531,7 @@ size_t
15931531
pg_strnxfrm(char *dest, size_t destsize, const char *src, ssize_t srclen,
15941532
pg_locale_t locale)
15951533
{
1596-
size_t result = 0; /* keep compiler quiet */
1597-
1598-
if (locale->provider == COLLPROVIDER_LIBC)
1599-
result = strnxfrm_libc(dest, destsize, src, srclen, locale);
1600-
#ifdef USE_ICU
1601-
else if (locale->provider == COLLPROVIDER_ICU)
1602-
result = strnxfrm_icu(dest, destsize, src, srclen, locale);
1603-
#endif
1604-
else
1605-
/* shouldn't happen */
1606-
PGLOCALE_SUPPORT_ERROR(locale->provider);
1607-
1608-
return result;
1534+
return locale->collate->strnxfrm(dest, destsize, src, srclen, locale);
16091535
}
16101536

16111537
/*
@@ -1615,15 +1541,7 @@ pg_strnxfrm(char *dest, size_t destsize, const char *src, ssize_t srclen,
16151541
bool
16161542
pg_strxfrm_prefix_enabled(pg_locale_t locale)
16171543
{
1618-
if (locale->provider == COLLPROVIDER_LIBC)
1619-
return false;
1620-
else if (locale->provider == COLLPROVIDER_ICU)
1621-
return true;
1622-
else
1623-
/* shouldn't happen */
1624-
PGLOCALE_SUPPORT_ERROR(locale->provider);
1625-
1626-
return false; /* keep compiler quiet */
1544+
return (locale->collate->strnxfrm_prefix != NULL);
16271545
}
16281546

16291547
/*
@@ -1635,7 +1553,7 @@ size_t
16351553
pg_strxfrm_prefix(char *dest, const char *src, size_t destsize,
16361554
pg_locale_t locale)
16371555
{
1638-
return pg_strnxfrm_prefix(dest, destsize, src, -1, locale);
1556+
return locale->collate->strnxfrm_prefix(dest, destsize, src, -1, locale);
16391557
}
16401558

16411559
/*
@@ -1660,16 +1578,7 @@ size_t
16601578
pg_strnxfrm_prefix(char *dest, size_t destsize, const char *src,
16611579
ssize_t srclen, pg_locale_t locale)
16621580
{
1663-
size_t result = 0; /* keep compiler quiet */
1664-
1665-
#ifdef USE_ICU
1666-
if (locale->provider == COLLPROVIDER_ICU)
1667-
result = strnxfrm_prefix_icu(dest, destsize, src, -1, locale);
1668-
else
1669-
#endif
1670-
PGLOCALE_SUPPORT_ERROR(locale->provider);
1671-
1672-
return result;
1581+
return locale->collate->strnxfrm_prefix(dest, destsize, src, srclen, locale);
16731582
}
16741583

16751584
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy