Skip to content

Commit 886cf85

Browse files
committed
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 eccfef8), so back-patch to v10 where that came in. Discussion: https://postgr.es/m/15892-e5d2bea3e8a04a1b@postgresql.org
1 parent b3670f4 commit 886cf85

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

src/backend/utils/adt/selfuncs.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -5564,9 +5564,10 @@ find_join_input_rel(PlannerInfo *root, Relids relids)
55645564
/*
55655565
* Check whether char is a letter (and, hence, subject to case-folding)
55665566
*
5567-
* In multibyte character sets or with ICU, we can't use isalpha, and it does not seem
5568-
* worth trying to convert to wchar_t to use iswalpha. Instead, just assume
5569-
* any multibyte char is potentially case-varying.
5567+
* In multibyte character sets or with ICU, we can't use isalpha, and it does
5568+
* not seem worth trying to convert to wchar_t to use iswalpha or u_isalpha.
5569+
* Instead, just assume any non-ASCII char is potentially case-varying, and
5570+
* hard-wire knowledge of which ASCII chars are letters.
55705571
*/
55715572
static int
55725573
pattern_char_isalpha(char c, bool is_multibyte,
@@ -5577,7 +5578,8 @@ pattern_char_isalpha(char c, bool is_multibyte,
55775578
else if (is_multibyte && IS_HIGHBIT_SET(c))
55785579
return true;
55795580
else if (locale && locale->provider == COLLPROVIDER_ICU)
5580-
return IS_HIGHBIT_SET(c) ? true : false;
5581+
return IS_HIGHBIT_SET(c) ||
5582+
(c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
55815583
#ifdef HAVE_LOCALE_T
55825584
else if (locale && locale->provider == COLLPROVIDER_LIBC)
55835585
return isalpha_l((unsigned char) c, locale->info.lt);

src/test/regress/expected/collate.icu.utf8.out

+32
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,38 @@ SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_t
976976
collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_tests.collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX")
977977
(4 rows)
978978

979+
set enable_seqscan = off;
980+
explain (costs off)
981+
select * from collate_test1 where b ilike 'abc';
982+
QUERY PLAN
983+
-------------------------------
984+
Seq Scan on collate_test1
985+
Filter: (b ~~* 'abc'::text)
986+
(2 rows)
987+
988+
select * from collate_test1 where b ilike 'abc';
989+
a | b
990+
---+-----
991+
1 | abc
992+
4 | ABC
993+
(2 rows)
994+
995+
explain (costs off)
996+
select * from collate_test1 where b ilike 'ABC';
997+
QUERY PLAN
998+
-------------------------------
999+
Seq Scan on collate_test1
1000+
Filter: (b ~~* 'ABC'::text)
1001+
(2 rows)
1002+
1003+
select * from collate_test1 where b ilike 'ABC';
1004+
a | b
1005+
---+-----
1006+
1 | abc
1007+
4 | ABC
1008+
(2 rows)
1009+
1010+
reset enable_seqscan;
9791011
-- schema manipulation commands
9801012
CREATE ROLE regress_test_role;
9811013
CREATE SCHEMA test_schema;

src/test/regress/sql/collate.icu.utf8.sql

+9
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,15 @@ CREATE INDEX collate_test1_idx6 ON collate_test1 ((a COLLATE "C")); -- fail
333333

334334
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%' ORDER BY 1;
335335

336+
set enable_seqscan = off;
337+
explain (costs off)
338+
select * from collate_test1 where b ilike 'abc';
339+
select * from collate_test1 where b ilike 'abc';
340+
explain (costs off)
341+
select * from collate_test1 where b ilike 'ABC';
342+
select * from collate_test1 where b ilike 'ABC';
343+
reset enable_seqscan;
344+
336345

337346
-- schema manipulation commands
338347

0 commit comments

Comments
 (0)