Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+16-107
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)