1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-19 23:22:23 +03:00

Refactor to add pg_strcoll(), pg_strxfrm(), and variants.

Offers a generally better separation of responsibilities for collation
code. Also, a step towards multi-lib ICU, which should be based on a
clean separation of the routines required for collation providers.

Callers with NUL-terminated strings should call pg_strcoll() or
pg_strxfrm(); callers with strings and their length should call the
variants pg_strncoll() or pg_strnxfrm().

Reviewed-by: Peter Eisentraut, Peter Geoghegan
Discussion: https://postgr.es/m/a581136455c940d7bd0ff482d3a2bd51af25a94f.camel%40j-davis.com
This commit is contained in:
Jeff Davis
2023-02-23 10:55:20 -08:00
parent e9960732a9
commit d87d548cd0
5 changed files with 870 additions and 390 deletions

View File

@@ -292,21 +292,24 @@ hashtext(PG_FUNCTION_ARGS)
#ifdef USE_ICU
if (mylocale->provider == COLLPROVIDER_ICU)
{
int32_t ulen = -1;
UChar *uchar = NULL;
Size bsize;
uint8_t *buf;
Size bsize, rsize;
char *buf;
const char *keydata = VARDATA_ANY(key);
size_t keylen = VARSIZE_ANY_EXHDR(key);
ulen = icu_to_uchar(&uchar, VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
bsize = pg_strnxfrm(NULL, 0, keydata, keylen, mylocale);
buf = palloc(bsize + 1);
bsize = ucol_getSortKey(mylocale->info.icu.ucol,
uchar, ulen, NULL, 0);
buf = palloc(bsize);
ucol_getSortKey(mylocale->info.icu.ucol,
uchar, ulen, buf, bsize);
pfree(uchar);
rsize = pg_strnxfrm(buf, bsize + 1, keydata, keylen, mylocale);
if (rsize != bsize)
elog(ERROR, "pg_strnxfrm() returned unexpected result");
result = hash_any(buf, bsize);
/*
* In principle, there's no reason to include the terminating NUL
* character in the hash, but it was done before and the behavior
* must be preserved.
*/
result = hash_any((uint8_t *) buf, bsize + 1);
pfree(buf);
}
@@ -350,21 +353,25 @@ hashtextextended(PG_FUNCTION_ARGS)
#ifdef USE_ICU
if (mylocale->provider == COLLPROVIDER_ICU)
{
int32_t ulen = -1;
UChar *uchar = NULL;
Size bsize;
uint8_t *buf;
Size bsize, rsize;
char *buf;
const char *keydata = VARDATA_ANY(key);
size_t keylen = VARSIZE_ANY_EXHDR(key);
ulen = icu_to_uchar(&uchar, VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
bsize = pg_strnxfrm(NULL, 0, keydata, keylen, mylocale);
buf = palloc(bsize + 1);
bsize = ucol_getSortKey(mylocale->info.icu.ucol,
uchar, ulen, NULL, 0);
buf = palloc(bsize);
ucol_getSortKey(mylocale->info.icu.ucol,
uchar, ulen, buf, bsize);
pfree(uchar);
rsize = pg_strnxfrm(buf, bsize + 1, keydata, keylen, mylocale);
if (rsize != bsize)
elog(ERROR, "pg_strnxfrm() returned unexpected result");
result = hash_any_extended(buf, bsize, PG_GETARG_INT64(1));
/*
* In principle, there's no reason to include the terminating NUL
* character in the hash, but it was done before and the behavior
* must be preserved.
*/
result = hash_any_extended((uint8_t *) buf, bsize + 1,
PG_GETARG_INT64(1));
pfree(buf);
}