mirror of
https://github.com/postgres/postgres.git
synced 2025-05-02 11:44:50 +03:00
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
This commit is contained in:
parent
ceb850d4a3
commit
c914e74d2d
@ -5815,9 +5815,10 @@ find_join_input_rel(PlannerInfo *root, Relids relids)
|
|||||||
/*
|
/*
|
||||||
* Check whether char is a letter (and, hence, subject to case-folding)
|
* 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
|
* In multibyte character sets or with ICU, we can't use isalpha, and it does
|
||||||
* worth trying to convert to wchar_t to use iswalpha. Instead, just assume
|
* not seem worth trying to convert to wchar_t to use iswalpha or u_isalpha.
|
||||||
* any multibyte char is potentially case-varying.
|
* Instead, just assume any non-ASCII char is potentially case-varying, and
|
||||||
|
* hard-wire knowledge of which ASCII chars are letters.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
pattern_char_isalpha(char c, bool is_multibyte,
|
pattern_char_isalpha(char c, bool is_multibyte,
|
||||||
@ -5828,7 +5829,8 @@ pattern_char_isalpha(char c, bool is_multibyte,
|
|||||||
else if (is_multibyte && IS_HIGHBIT_SET(c))
|
else if (is_multibyte && IS_HIGHBIT_SET(c))
|
||||||
return true;
|
return true;
|
||||||
else if (locale && locale->provider == COLLPROVIDER_ICU)
|
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
|
#ifdef HAVE_LOCALE_T
|
||||||
else if (locale && locale->provider == COLLPROVIDER_LIBC)
|
else if (locale && locale->provider == COLLPROVIDER_LIBC)
|
||||||
return isalpha_l((unsigned char) c, locale->info.lt);
|
return isalpha_l((unsigned char) c, locale->info.lt);
|
||||||
|
@ -976,6 +976,38 @@ SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_t
|
|||||||
collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_tests.collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX")
|
collate_test1_idx4 | CREATE INDEX collate_test1_idx4 ON collate_tests.collate_test1 USING btree (((b || 'foo'::text)) COLLATE "POSIX")
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
|
set enable_seqscan = off;
|
||||||
|
explain (costs off)
|
||||||
|
select * from collate_test1 where b ilike 'abc';
|
||||||
|
QUERY PLAN
|
||||||
|
-------------------------------
|
||||||
|
Seq Scan on collate_test1
|
||||||
|
Filter: (b ~~* 'abc'::text)
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
select * from collate_test1 where b ilike 'abc';
|
||||||
|
a | b
|
||||||
|
---+-----
|
||||||
|
1 | abc
|
||||||
|
4 | ABC
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
explain (costs off)
|
||||||
|
select * from collate_test1 where b ilike 'ABC';
|
||||||
|
QUERY PLAN
|
||||||
|
-------------------------------
|
||||||
|
Seq Scan on collate_test1
|
||||||
|
Filter: (b ~~* 'ABC'::text)
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
select * from collate_test1 where b ilike 'ABC';
|
||||||
|
a | b
|
||||||
|
---+-----
|
||||||
|
1 | abc
|
||||||
|
4 | ABC
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
reset enable_seqscan;
|
||||||
-- schema manipulation commands
|
-- schema manipulation commands
|
||||||
CREATE ROLE regress_test_role;
|
CREATE ROLE regress_test_role;
|
||||||
CREATE SCHEMA test_schema;
|
CREATE SCHEMA test_schema;
|
||||||
|
@ -333,6 +333,15 @@ CREATE INDEX collate_test1_idx6 ON collate_test1 ((a COLLATE "C")); -- fail
|
|||||||
|
|
||||||
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%' ORDER BY 1;
|
SELECT relname, pg_get_indexdef(oid) FROM pg_class WHERE relname LIKE 'collate_test%_idx%' ORDER BY 1;
|
||||||
|
|
||||||
|
set enable_seqscan = off;
|
||||||
|
explain (costs off)
|
||||||
|
select * from collate_test1 where b ilike 'abc';
|
||||||
|
select * from collate_test1 where b ilike 'abc';
|
||||||
|
explain (costs off)
|
||||||
|
select * from collate_test1 where b ilike 'ABC';
|
||||||
|
select * from collate_test1 where b ilike 'ABC';
|
||||||
|
reset enable_seqscan;
|
||||||
|
|
||||||
|
|
||||||
-- schema manipulation commands
|
-- schema manipulation commands
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user