| From: | Greg Burd <greg(at)burd(dot)me> |
|---|---|
| To: | Jeff Davis <pgsql(at)j-davis(dot)com> |
| Cc: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: ILIKE '%' never matches a non-ASCII byte in single-byte C-ctype databases |
| Date: | 2026-10-20 15:57:37 |
| Message-ID: | uLX94vtMSSY1nDrc66QUswHzmyfoplXldeb1IgUufT8c0yA3F7uLGE7frrkZ6gdbeK3KlPHZVjQoeWEKxUKMsMnlZ-yx98dGyaqQrScE2MI=@burd.me |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On Tuesday, October 20th, 2026 at 9:29 AM, Jeff Davis <pgsql(at)j-davis(dot)com> wrote:
> On Sun, 2026-10-18 at 15:30 +0000, Greg Burd wrote:
> > Hi Hackers, Jeff,
> >
> > In v19, ILIKE in a database with a single-byte encoding and a C ctype
> > never matches when '%' is followed by a byte >= 0x80:
>
> Thank you for the report!
Thank you for the fast review! :)
> I attached a patch with a different approach though, which is to cast
> the result of pg_ascii_tolower() so that GETCHAR() consistently returns
> a 'char'. That addresses the real problem of commit 1e493158d3d, which
> is that it unintentionally changed GETCHAR() from returning 'char' to
> returning 'unsigned char' for MATCH_LOWER.
Agreed, v2j is the better fix. Casting at the macro restores exactly what
1e493158d3d changed, and keeps both operands the same type in every
MATCH_LOWER comparison, not just the firstpat one. My v1 only widened the
one variable; yours fixes the cause. +1.
> It passes the same test that you submitted, but I don't plan to commit
> the tests with the change. We are missing coverage for non-UTF8
> encodings, but if we're going to add tests for those, it should
> probably be a whole suite rather than a one-off.
Fair. A one-off LATIN1/C test next to the others would be odd, and a
non-UTF8 suite is the right home. I'd like to help build that. I have a
differential harness that runs the pattern operators against a sequential
scan in LATIN1, WIN1252 and KOI8R, which is what turned this up; it would
drop in as the generator for such a suite. I'll start a separate thread
rather than hold up your commit.
> I plan to commit it very soon and backport to 19.
Awesome, thanks!
One scope note for the commit message, from Manu's reply upthread: the
trigger is a C collation on the expression, not a C-ctype database as such.
The same wrong answer appears in a non-C-locale single-byte database via
SELECT 'xÆy' COLLATE "C" ILIKE '%Æ%';
and reaches name columns and convert_from() output (both collate "C"). v2j
fixes all of them since they share the path; it may be worth a word so the
fix isn't read as database-locale-specific.
> Regards,
> Jeff Davis
Separately, while checking the archive I found shihao zhong's thread
"[PG19] ILIKE index scan misses rows with a libc UTF-8 collation on macOS"
[1]. It's a sibling of this one, same symptom class (v19 ILIKE case
folding), different cause and path: there the wide-char classifier
wc_iscased_libc_utf8() uses iswupper()/iswlower() while ILIKE folds with
towlower(), so a code point like U+2160 that towlower changes but the
classifier doesn't flag stays in the index prefix. That's multi-byte libc
UTF-8; this one is the single-byte byte-compare path in like_match.c. The
two don't overlap in code and v2j doesn't touch his case (nor his patch
this one), but together they're two instances of the same v19 regression
family, so the non-UTF8 test suite above would ideally cover both if/when
we have one.
Thanks Jeff for picking this up and for the quick turnaround.
-greg
[1] https://postgr.es/m/CAGRkXqS6pr-hG-g=K6RTdRw53SnMZWz3iXvh_wi8rqLSf972sA@mail.gmail.com
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Sami Imseih | 2026-10-20 16:07:21 | Re: pgstat: don't assert on dropped entries when writing stats file |
| Previous Message | Harrison Booth | 2026-10-20 15:37:00 | [PATCH] Fix Windows pgwin32_fopen update-mode access |