Skip to content

Commit ee71132

Browse files
committed
Added ICU patch combined from several commit in PGPRO 9.5
1 parent 5b22ab7 commit ee71132

File tree

10 files changed

+2485
-154
lines changed

10 files changed

+2485
-154
lines changed

configure

Lines changed: 1808 additions & 152 deletions
Large diffs are not rendered by default.

configure.in

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,16 @@ PGAC_ARG_BOOL(with, systemd, no, [build with systemd support],
729729
AC_SUBST(with_systemd)
730730
AC_MSG_RESULT([$with_systemd])
731731

732+
#
733+
# ICU
734+
#
735+
AC_MSG_CHECKING([whether to build with ICU support])
736+
PGAC_ARG_BOOL(with, icu, no, [ --with-icu build with ICU support],
737+
[AC_DEFINE([USE_ICU], 1, [Define to build with ICU support. (--with-icu)])])
738+
AC_MSG_RESULT([$with_icu])
739+
AC_SUBST(with_icu)
740+
741+
732742
#
733743
# Readline
734744
#
@@ -1120,6 +1130,67 @@ if test "$with_openssl" = yes ; then
11201130
AC_CHECK_FUNCS([SSL_get_current_compression])
11211131
fi
11221132

1133+
if test "$with_icu" = yes ; then
1134+
AC_SEARCH_LIBS(ucol_open_57, [icui18n icuin], [], [
1135+
AC_SEARCH_LIBS(ucol_open_56, [icui18n icuin], [], [
1136+
AC_SEARCH_LIBS(ucol_open_55, [icui18n icuin], [], [
1137+
AC_SEARCH_LIBS(ucol_open_54, [icui18n icuin], [], [
1138+
AC_SEARCH_LIBS(ucol_open_53, [icui18n icuin], [], [
1139+
AC_SEARCH_LIBS(ucol_open_52, [icui18n icuin], [], [
1140+
AC_SEARCH_LIBS(ucol_open_50, [icui18n icuin], [], [
1141+
AC_SEARCH_LIBS(ucol_open_48, [icui18n icuin], [], [
1142+
AC_SEARCH_LIBS(ucol_open_46, [icui18n icuin], [], [
1143+
AC_SEARCH_LIBS(ucol_open_44, [icui18n icuin], [], [
1144+
AC_SEARCH_LIBS(ucol_open_43, [icui18n icuin], [], [
1145+
AC_SEARCH_LIBS(ucol_open_4_2, [icui18n icuin], [], [
1146+
AC_SEARCH_LIBS(ucol_open_3_8, [icui18n icuin], [], [
1147+
AC_SEARCH_LIBS(ucol_open_3_6, [icui18n icuin], [], [
1148+
AC_SEARCH_LIBS(ucol_open_3_4, [icui18n icuin], [], [AC_MSG_ERROR([library 'icui18n' is required for ICU])])
1149+
])
1150+
])
1151+
])
1152+
])
1153+
])
1154+
])
1155+
])
1156+
])
1157+
])
1158+
])
1159+
])
1160+
])
1161+
])
1162+
])
1163+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_57, [], [
1164+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_56, [], [
1165+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_55, [], [
1166+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_54, [], [
1167+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_53, [], [
1168+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_52, [], [
1169+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_50, [], [
1170+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_48, [], [
1171+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_46, [], [
1172+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_44, [], [
1173+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_43, [], [
1174+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_4_2, [], [
1175+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_3_8, [], [
1176+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_3_6, [], [
1177+
AC_CHECK_LIB(icuuc, ucnv_fromUChars_3_4, [], [AC_MSG_ERROR([library 'icuuc' is required for ICU])])
1178+
])
1179+
])
1180+
])
1181+
])
1182+
])
1183+
])
1184+
])
1185+
])
1186+
])
1187+
])
1188+
])
1189+
])
1190+
])
1191+
])
1192+
fi
1193+
11231194
if test "$with_pam" = yes ; then
11241195
AC_CHECK_LIB(pam, pam_start, [], [AC_MSG_ERROR([library 'pam' is required for PAM])])
11251196
fi
@@ -1273,6 +1344,10 @@ if test "$with_openssl" = yes ; then
12731344
AC_CHECK_HEADER(openssl/err.h, [], [AC_MSG_ERROR([header file <openssl/err.h> is required for OpenSSL])])
12741345
fi
12751346

1347+
if test "$with_icu" = yes ; then
1348+
AC_CHECK_HEADER(unicode/utypes.h, [], [AC_MSG_ERROR([header file <unicode/utypes.h> is required for ICU])])
1349+
fi
1350+
12761351
if test "$with_pam" = yes ; then
12771352
AC_CHECK_HEADERS(security/pam_appl.h, [],
12781353
[AC_CHECK_HEADERS(pam/pam_appl.h, [],

src/backend/utils/adt/formatting.c

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@
9292
#include "utils/numeric.h"
9393
#include "utils/pg_locale.h"
9494

95+
#ifdef USE_ICU
96+
#include <unicode/utypes.h> /* Basic ICU data types */
97+
#include <unicode/ucnv.h> /* C Converter API */
98+
#include <unicode/ustring.h>
99+
#endif /* USE_ICU */
100+
95101
/* ----------
96102
* Routines type
97103
* ----------
@@ -940,6 +946,12 @@ typedef struct NUMProc
940946
} NUMProc;
941947

942948

949+
#ifdef USE_ICU
950+
static UConverter *conv = NULL;
951+
#define STACKBUFLEN 1024 / sizeof(UChar)
952+
#endif /* USE_ICU */
953+
954+
943955
/* ----------
944956
* Functions
945957
* ----------
@@ -1491,6 +1503,82 @@ str_tolower(const char *buff, size_t nbytes, Oid collid)
14911503
{
14921504
result = asc_tolower(buff, nbytes);
14931505
}
1506+
#ifdef USE_ICU
1507+
/* use ICU only when max encoding length > one */
1508+
if (pg_database_encoding_max_length() > 1)
1509+
{
1510+
UChar sourcebuf[STACKBUFLEN], destbuf[STACKBUFLEN];
1511+
UChar *source, *dest;
1512+
int buflen;
1513+
size_t result_size, usize;
1514+
UErrorCode status = U_ZERO_ERROR;
1515+
1516+
if (conv == NULL)
1517+
{
1518+
conv = ucnv_open(NULL, &status);
1519+
if (U_FAILURE(status))
1520+
{
1521+
ereport(ERROR,
1522+
(errcode(status),
1523+
errmsg("ICU error: oracle_compat.c, could not get converter for \"%s\"", ucnv_getDefaultName())));
1524+
}
1525+
}
1526+
1527+
if (nbytes >= STACKBUFLEN / sizeof(UChar))
1528+
{
1529+
buflen = (nbytes + 1) * sizeof(UChar);
1530+
source = palloc(buflen);
1531+
dest = palloc(buflen);
1532+
}
1533+
else
1534+
{
1535+
buflen = STACKBUFLEN;
1536+
source = sourcebuf;
1537+
dest = destbuf;
1538+
}
1539+
// convert to UTF-16
1540+
ucnv_toUChars(conv, source, buflen, buff, nbytes, &status);
1541+
if (U_FAILURE(status))
1542+
{
1543+
ereport(ERROR,
1544+
(errcode(status),
1545+
errmsg("ICU error: Could not convert string")));
1546+
}
1547+
1548+
// run desired function
1549+
buflen = u_strToLower(dest, buflen, source, -1, NULL, &status);
1550+
if (U_FAILURE(status))
1551+
{
1552+
ereport(ERROR,
1553+
(errcode(status),
1554+
errmsg("ICU error: Could not modify case")));
1555+
}
1556+
1557+
// and convert modified utf-16 string back to text
1558+
result_size = UCNV_GET_MAX_BYTES_FOR_STRING(buflen, ucnv_getMaxCharSize(conv));
1559+
result = palloc(result_size);
1560+
1561+
usize = ucnv_fromUChars(conv, result, result_size,
1562+
dest, buflen, &status);
1563+
1564+
if (U_FAILURE(status))
1565+
{
1566+
/* Invalid multibyte character encountered ... shouldn't happen */
1567+
ereport(ERROR,
1568+
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
1569+
errmsg("ICU: invalid multibyte character for locale")));
1570+
}
1571+
1572+
Assert(usize <= (size_t) (buflen * sizeof(UChar)));
1573+
1574+
if (nbytes >= STACKBUFLEN / sizeof(UChar))
1575+
{
1576+
pfree(source);
1577+
pfree(dest);
1578+
}
1579+
return result;
1580+
}
1581+
#else
14941582
#ifdef USE_WIDE_UPPER_LOWER
14951583
else if (pg_database_encoding_max_length() > 1)
14961584
{
@@ -1544,6 +1632,7 @@ str_tolower(const char *buff, size_t nbytes, Oid collid)
15441632
pfree(workspace);
15451633
}
15461634
#endif /* USE_WIDE_UPPER_LOWER */
1635+
#endif /* USE_ICU */
15471636
else
15481637
{
15491638
#ifdef HAVE_LOCALE_T
@@ -1611,6 +1700,82 @@ str_toupper(const char *buff, size_t nbytes, Oid collid)
16111700
{
16121701
result = asc_toupper(buff, nbytes);
16131702
}
1703+
#ifdef USE_ICU
1704+
/* use ICU only when max encoding length > one */
1705+
if (pg_database_encoding_max_length() > 1)
1706+
{
1707+
UChar sourcebuf[STACKBUFLEN], destbuf[STACKBUFLEN];
1708+
UChar *source, *dest;
1709+
int buflen;
1710+
size_t result_size, usize;
1711+
UErrorCode status = U_ZERO_ERROR;
1712+
1713+
if (conv == NULL)
1714+
{
1715+
conv = ucnv_open(NULL, &status);
1716+
if (U_FAILURE(status))
1717+
{
1718+
ereport(ERROR,
1719+
(errcode(status),
1720+
errmsg("ICU error: oracle_compat.c, could not get converter for \"%s\"", ucnv_getDefaultName())));
1721+
}
1722+
}
1723+
1724+
if (nbytes >= STACKBUFLEN / sizeof(UChar))
1725+
{
1726+
buflen = (nbytes + 1) * sizeof(UChar);
1727+
source = palloc(buflen);
1728+
dest = palloc(buflen);
1729+
}
1730+
else
1731+
{
1732+
buflen = STACKBUFLEN;
1733+
source = sourcebuf;
1734+
dest = destbuf;
1735+
}
1736+
// convert to UTF-16
1737+
ucnv_toUChars(conv, source, buflen, buff, nbytes, &status);
1738+
if (U_FAILURE(status))
1739+
{
1740+
ereport(ERROR,
1741+
(errcode(status),
1742+
errmsg("ICU error: Could not convert string")));
1743+
}
1744+
1745+
// run desired function
1746+
buflen = u_strToUpper(dest, buflen, source, -1, NULL, &status);
1747+
if (U_FAILURE(status))
1748+
{
1749+
ereport(ERROR,
1750+
(errcode(status),
1751+
errmsg("ICU error: Could not modify case")));
1752+
}
1753+
1754+
// and convert modified utf-16 string back to text
1755+
result_size = UCNV_GET_MAX_BYTES_FOR_STRING(buflen, ucnv_getMaxCharSize(conv));
1756+
result = palloc(result_size);
1757+
1758+
usize = ucnv_fromUChars(conv, result, result_size,
1759+
dest, buflen, &status);
1760+
1761+
if (U_FAILURE(status))
1762+
{
1763+
/* Invalid multibyte character encountered ... shouldn't happen */
1764+
ereport(ERROR,
1765+
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
1766+
errmsg("ICU: invalid multibyte character for locale")));
1767+
}
1768+
1769+
Assert(usize <= (size_t) (buflen * sizeof(UChar)));
1770+
1771+
if (nbytes >= STACKBUFLEN / sizeof(UChar))
1772+
{
1773+
pfree(source);
1774+
pfree(dest);
1775+
}
1776+
return result;
1777+
}
1778+
#else
16141779
#ifdef USE_WIDE_UPPER_LOWER
16151780
else if (pg_database_encoding_max_length() > 1)
16161781
{
@@ -1664,6 +1829,7 @@ str_toupper(const char *buff, size_t nbytes, Oid collid)
16641829
pfree(workspace);
16651830
}
16661831
#endif /* USE_WIDE_UPPER_LOWER */
1832+
#endif /* USE_ICU */
16671833
else
16681834
{
16691835
#ifdef HAVE_LOCALE_T
@@ -1732,6 +1898,82 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
17321898
{
17331899
result = asc_initcap(buff, nbytes);
17341900
}
1901+
#ifdef USE_ICU
1902+
/* use ICU only when max encoding length > one */
1903+
if (pg_database_encoding_max_length() > 1)
1904+
{
1905+
UChar sourcebuf[STACKBUFLEN], destbuf[STACKBUFLEN];
1906+
UChar *source, *dest;
1907+
int buflen;
1908+
size_t result_size, usize;
1909+
UErrorCode status = U_ZERO_ERROR;
1910+
1911+
if (conv == NULL)
1912+
{
1913+
conv = ucnv_open(NULL, &status);
1914+
if (U_FAILURE(status))
1915+
{
1916+
ereport(ERROR,
1917+
(errcode(status),
1918+
errmsg("ICU error: oracle_compat.c, could not get converter for \"%s\"", ucnv_getDefaultName())));
1919+
}
1920+
}
1921+
1922+
if (nbytes >= STACKBUFLEN / sizeof(UChar))
1923+
{
1924+
buflen = (nbytes + 1) * sizeof(UChar);
1925+
source = palloc(buflen);
1926+
dest = palloc(buflen);
1927+
}
1928+
else
1929+
{
1930+
buflen = STACKBUFLEN;
1931+
source = sourcebuf;
1932+
dest = destbuf;
1933+
}
1934+
// convert to UTF-16
1935+
ucnv_toUChars(conv, source, buflen, buff, nbytes, &status);
1936+
if (U_FAILURE(status))
1937+
{
1938+
ereport(ERROR,
1939+
(errcode(status),
1940+
errmsg("ICU error: Could not convert string")));
1941+
}
1942+
1943+
// run desired function
1944+
buflen = u_strToTitle(dest, buflen, source, -1, NULL, NULL, &status);
1945+
if (U_FAILURE(status))
1946+
{
1947+
ereport(ERROR,
1948+
(errcode(status),
1949+
errmsg("ICU error: Could not modify case")));
1950+
}
1951+
1952+
// and convert modified utf-16 string back to text
1953+
result_size = UCNV_GET_MAX_BYTES_FOR_STRING(buflen, ucnv_getMaxCharSize(conv));
1954+
result = palloc(result_size);
1955+
1956+
usize = ucnv_fromUChars(conv, result, result_size,
1957+
dest, buflen, &status);
1958+
1959+
if (U_FAILURE(status))
1960+
{
1961+
/* Invalid multibyte character encountered ... shouldn't happen */
1962+
ereport(ERROR,
1963+
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
1964+
errmsg("ICU: invalid multibyte character for locale")));
1965+
}
1966+
1967+
Assert(usize <= (size_t) (buflen * sizeof(UChar)));
1968+
1969+
if (nbytes >= STACKBUFLEN / sizeof(UChar))
1970+
{
1971+
pfree(source);
1972+
pfree(dest);
1973+
}
1974+
return result;
1975+
}
1976+
#else
17351977
#ifdef USE_WIDE_UPPER_LOWER
17361978
else if (pg_database_encoding_max_length() > 1)
17371979
{
@@ -1797,6 +2039,7 @@ str_initcap(const char *buff, size_t nbytes, Oid collid)
17972039
pfree(workspace);
17982040
}
17992041
#endif /* USE_WIDE_UPPER_LOWER */
2042+
#endif /* USE_ICU */
18002043
else
18012044
{
18022045
#ifdef HAVE_LOCALE_T

0 commit comments

Comments
 (0)