Re: [PG19] ILIKE index scan misses rows with a libc UTF-8 collation on macOS

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: shihao zhong <zhong950419(at)gmail(dot)com>
Cc: pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Jeff Davis <pgsql(at)j-davis(dot)com>, Noah Misch <noah(at)leadboat(dot)com>
Subject: Re: [PG19] ILIKE index scan misses rows with a libc UTF-8 collation on macOS
Date: 2026-10-19 02:04:32
Message-ID: 66318549-4413-4633-AFFC-B6257DB0224F@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Oct 18, 2026, at 11:52, shihao zhong <zhong950419(at)gmail(dot)com> wrote:
>
> Hi,
>
> This is the first low item from my list in [1]. It has the same cause as
> the EUC_* report in [2], and 43a948b7b25 did not fix it.
>
> wc_iscased_libc_utf8() asks iswupper() and iswlower(), but ILIKE
> compares with towlower(). The macOS C library case-maps 117 code points
> that are neither upper nor lower, like U+2160 (Roman numeral one). So
> U+2160 stays in the index prefix:
>
> create table t (x text collate "en_US.UTF-8");
> insert into t values (U&'\2160q'), (U&'\2170q');
> insert into t select 'filler' || g from generate_series(1, 2000) g;
> create index on t (x text_pattern_ops);
> analyze t;
> select count(*) from t where x ilike U&'\2160q%';
>
> On the master and REL_19_STABLE heads the index scan returns 1. A seq
> scan returns 2. glibc on Linux classifies all of them, so it is fine.
>
> The attached patch also counts a character as cased when towupper() or
> towlower() changes it.
>
>
> [1] https://postgr.es/m/CAGRkXqSFdjqZP_kwRz7dv6LHX-CSrkDnynNXgntRsCEnQTKxmg@mail.gmail.com
> [2] https://postgr.es/m/20260826221526.89.noahmisch@microsoft.com
>
> Thanks,
> Shihao
> <v1-0001-Fix-pg_iswcased-for-libc-UTF8-case-mappings.patch>

I can reproduce the issue on my MacBook too.

Given that this issue has only been confirmed on macOS so far, does it make sense to add the extra checks only for macOS, like this:
```
return iswupper_l((wint_t) wc, locale->lt) ||
iswlower_l((wint_t) wc, locale->lt)
#if defined(__darwin__)
|| towupper_l((wint_t) wc, locale->lt) != (wint_t) wc
|| towlower_l((wint_t) wc, locale->lt) != (wint_t) wc
#endif
;
```

I see that #if defined(__darwin__) is already used in many places.

Then, I would suggest adding a regression test so that CI can help check whether the problem exists on other platforms.

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Richard Guo 2026-10-19 02:13:04 Re: Assert failure in create_lateral_join_info
Previous Message Scott Ray 2026-10-19 02:02:18 Re: pg_xmin_horizon: a system view of everything pinning the xmin horizon