From 886cf85b52cfdd84c0ff9b24193c7e0e0035b1c7 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 12 Aug 2019 13:15:48 -0400 Subject: Fix planner's test for case-foldable characters in ILIKE with ICU. As coded, the ICU-collation path in pattern_char_isalpha() failed to consider regular ASCII letters to be case-varying. This led to like_fixed_prefix treating too much of an ILIKE pattern as being a fixed prefix, so that indexscans derived from an ILIKE clause might miss entries that they should find. Per bug #15892 from James Inform. This is an oversight in the original ICU patch (commit eccfef81e), so back-patch to v10 where that came in. Discussion: https://postgr.es/m/15892-e5d2bea3e8a04a1b@postgresql.org --- src/backend/utils/adt/selfuncs.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/backend/utils/adt/selfuncs.c') diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 9f5318bd99e..eb0fed49634 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -5564,9 +5564,10 @@ find_join_input_rel(PlannerInfo *root, Relids relids) /* * Check whether char is a letter (and, hence, subject to case-folding) * - * In multibyte character sets or with ICU, we can't use isalpha, and it does not seem - * worth trying to convert to wchar_t to use iswalpha. Instead, just assume - * any multibyte char is potentially case-varying. + * In multibyte character sets or with ICU, we can't use isalpha, and it does + * not seem worth trying to convert to wchar_t to use iswalpha or u_isalpha. + * Instead, just assume any non-ASCII char is potentially case-varying, and + * hard-wire knowledge of which ASCII chars are letters. */ static int pattern_char_isalpha(char c, bool is_multibyte, @@ -5577,7 +5578,8 @@ pattern_char_isalpha(char c, bool is_multibyte, else if (is_multibyte && IS_HIGHBIT_SET(c)) return true; else if (locale && locale->provider == COLLPROVIDER_ICU) - return IS_HIGHBIT_SET(c) ? true : false; + return IS_HIGHBIT_SET(c) || + (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); #ifdef HAVE_LOCALE_T else if (locale && locale->provider == COLLPROVIDER_LIBC) return isalpha_l((unsigned char) c, locale->info.lt); -- cgit v1.2.3