From 6974a8f7682beeb515b78b34a5253d5f96552f58 Mon Sep 17 00:00:00 2001 From: Jeff Davis Date: Thu, 23 Feb 2023 11:17:41 -0800 Subject: [PATCH] Refactor to introduce pg_locale_deterministic(). Avoids the need of callers to test for NULL, and also avoids the need to access the pg_locale_t structure directly. Reviewed-by: Peter Eisentraut, Peter Geoghegan Discussion: https://postgr.es/m/a581136455c940d7bd0ff482d3a2bd51af25a94f.camel%40j-davis.com --- src/backend/access/hash/hashfunc.c | 4 ++-- src/backend/regex/regc_pg_locale.c | 2 +- src/backend/utils/adt/like.c | 4 ++-- src/backend/utils/adt/pg_locale.c | 9 +++++++++ src/backend/utils/adt/varchar.c | 8 ++++---- src/backend/utils/adt/varlena.c | 14 ++++++-------- src/include/utils/pg_locale.h | 1 + 7 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/backend/access/hash/hashfunc.c b/src/backend/access/hash/hashfunc.c index 2deba44abd..2e2fd5566e 100644 --- a/src/backend/access/hash/hashfunc.c +++ b/src/backend/access/hash/hashfunc.c @@ -282,7 +282,7 @@ hashtext(PG_FUNCTION_ARGS) if (!lc_collate_is_c(collid)) mylocale = pg_newlocale_from_collation(collid); - if (!mylocale || mylocale->deterministic) + if (pg_locale_deterministic(mylocale)) { result = hash_any((unsigned char *) VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key)); @@ -342,7 +342,7 @@ hashtextextended(PG_FUNCTION_ARGS) if (!lc_collate_is_c(collid)) mylocale = pg_newlocale_from_collation(collid); - if (!mylocale || mylocale->deterministic) + if (pg_locale_deterministic(mylocale)) { result = hash_any_extended((unsigned char *) VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key), diff --git a/src/backend/regex/regc_pg_locale.c b/src/backend/regex/regc_pg_locale.c index 323f00516d..00ce735fdd 100644 --- a/src/backend/regex/regc_pg_locale.c +++ b/src/backend/regex/regc_pg_locale.c @@ -259,7 +259,7 @@ pg_set_regex_collation(Oid collation) */ pg_regex_locale = pg_newlocale_from_collation(collation); - if (pg_regex_locale && !pg_regex_locale->deterministic) + if (!pg_locale_deterministic(pg_regex_locale)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for regular expressions"))); diff --git a/src/backend/utils/adt/like.c b/src/backend/utils/adt/like.c index fc6cb7f5b7..33a2f46aab 100644 --- a/src/backend/utils/adt/like.c +++ b/src/backend/utils/adt/like.c @@ -155,7 +155,7 @@ GenericMatchText(const char *s, int slen, const char *p, int plen, Oid collation { pg_locale_t locale = pg_newlocale_from_collation(collation); - if (locale && !locale->deterministic) + if (!pg_locale_deterministic(locale)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for LIKE"))); @@ -196,7 +196,7 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation) else locale = pg_newlocale_from_collation(collation); - if (locale && !locale->deterministic) + if (!pg_locale_deterministic(locale)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for ILIKE"))); diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index ef9efb4a7c..274b8b9ccd 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -1481,6 +1481,15 @@ report_newlocale_failure(const char *localename) } #endif /* HAVE_LOCALE_T */ +bool +pg_locale_deterministic(pg_locale_t locale) +{ + /* default locale must always be deterministic */ + if (locale == NULL) + return true; + else + return locale->deterministic; +} /* * Create a locale_t from a collation OID. Results are cached for the diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 9ff3bcbdb7..99a4ca7cd0 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -762,7 +762,7 @@ bpchareq(PG_FUNCTION_ARGS) else mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || !mylocale || mylocale->deterministic) + if (locale_is_c || pg_locale_deterministic(mylocale)) { /* * Since we only care about equality or not-equality, we can avoid all @@ -807,7 +807,7 @@ bpcharne(PG_FUNCTION_ARGS) else mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || !mylocale || mylocale->deterministic) + if (locale_is_c || pg_locale_deterministic(mylocale)) { /* * Since we only care about equality or not-equality, we can avoid all @@ -1015,7 +1015,7 @@ hashbpchar(PG_FUNCTION_ARGS) if (!lc_collate_is_c(collid)) mylocale = pg_newlocale_from_collation(collid); - if (!mylocale || mylocale->deterministic) + if (pg_locale_deterministic(mylocale)) { result = hash_any((unsigned char *) keydata, keylen); } @@ -1077,7 +1077,7 @@ hashbpcharextended(PG_FUNCTION_ARGS) if (!lc_collate_is_c(collid)) mylocale = pg_newlocale_from_collation(collid); - if (!mylocale || mylocale->deterministic) + if (pg_locale_deterministic(mylocale)) { result = hash_any_extended((unsigned char *) keydata, keylen, PG_GETARG_INT64(1)); diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 4ca823ca7b..5778e3f0ef 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -1221,7 +1221,7 @@ text_position_setup(text *t1, text *t2, Oid collid, TextPositionState *state) if (!lc_collate_is_c(collid)) mylocale = pg_newlocale_from_collation(collid); - if (mylocale && !mylocale->deterministic) + if (!pg_locale_deterministic(mylocale)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for substring searches"))); @@ -1572,8 +1572,7 @@ varstr_cmp(const char *arg1, int len1, const char *arg2, int len2, Oid collid) result = pg_strncoll(arg1, len1, arg2, len2, mylocale); /* Break tie if necessary. */ - if (result == 0 && - (!mylocale || mylocale->deterministic)) + if (result == 0 && pg_locale_deterministic(mylocale)) { result = memcmp(arg1, arg2, Min(len1, len2)); if ((result == 0) && (len1 != len2)) @@ -1628,7 +1627,7 @@ texteq(PG_FUNCTION_ARGS) else mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || !mylocale || mylocale->deterministic) + if (locale_is_c || pg_locale_deterministic(mylocale)) { Datum arg1 = PG_GETARG_DATUM(0); Datum arg2 = PG_GETARG_DATUM(1); @@ -1687,7 +1686,7 @@ textne(PG_FUNCTION_ARGS) else mylocale = pg_newlocale_from_collation(collid); - if (locale_is_c || !mylocale || mylocale->deterministic) + if (locale_is_c || pg_locale_deterministic(mylocale)) { Datum arg1 = PG_GETARG_DATUM(0); Datum arg2 = PG_GETARG_DATUM(1); @@ -1801,7 +1800,7 @@ text_starts_with(PG_FUNCTION_ARGS) if (!lc_collate_is_c(collid)) mylocale = pg_newlocale_from_collation(collid); - if (mylocale && !mylocale->deterministic) + if (!pg_locale_deterministic(mylocale)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("nondeterministic collations are not supported for substring searches"))); @@ -2217,8 +2216,7 @@ varstrfastcmp_locale(char *a1p, int len1, char *a2p, int len2, SortSupport ssup) result = pg_strcoll(sss->buf1, sss->buf2, sss->locale); /* Break tie if necessary. */ - if (result == 0 && - (!sss->locale || sss->locale->deterministic)) + if (result == 0 && pg_locale_deterministic(sss->locale)) result = strcmp(sss->buf1, sss->buf2); /* Cache result, perhaps saving an expensive strcoll() call next time */ diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h index def2b55f94..b8f22875a8 100644 --- a/src/include/utils/pg_locale.h +++ b/src/include/utils/pg_locale.h @@ -97,6 +97,7 @@ extern PGDLLIMPORT struct pg_locale_struct default_locale; extern void make_icu_collator(const char *iculocstr, struct pg_locale_struct *resultp); +extern bool pg_locale_deterministic(pg_locale_t locale); extern pg_locale_t pg_newlocale_from_collation(Oid collid); extern char *get_collation_actual_version(char collprovider, const char *collcollate);