locale / encoding / meson cleanup

From: Andrew Dunstan <andrew(at)dunslane(dot)net>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: locale / encoding / meson cleanup
Date: 2026-08-23 13:00:46
Message-ID: a40b19da-9a02-47b4-8afd-2bbbde8db1e8@dunslane.net
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

(Astute observers will notice that Claude loves the sound of its own
voice - or my voice which it's trying to emulate - a lot more than I do.
I have trimmed the text quite a bit.)

Tom observed in [1] that nothing in the buildfarm builds a cluster
with locale C and encoding UTF8, that this is where the recent
to_date() crash went undetected, and that the animal configuration had
no way to ask for one. I've taught the buildfarm client to accept an
encoding alongside the locale. However, it's not yet released, because
running an animal that way turned up two things, and the second
explains in part why the first went unnoticed for as long as it did.

1. test_regex_utf8 depends on the ctype, not just the encoding

The file decides whether to run by looking at the encoding alone:

    SELECT getdatabaseencoding() <> 'UTF8' AS skip_test \gset

but two of its cases also depend on the database ctype, so it fails in a
database with encoding UTF8 and locale C:

    @@ -152,7 +152,7 @@
        test_regex
     -----------------
      {0,REG_ULOCALE}
    - {xᔀሷ}
    + {x}
     (2 rows)

     select * from test_regex('[[:lower:]]+',  E'xᔀሷ', 'L');
    @@ -166,7 +166,7 @@
        test_regex
     -----------------
      {0,REG_ULOCALE}
    - {xᔀሷ}
    + {x}
     (2 rows)

The new output is the correct one: under ctype C, isgraph() and
isprint() are
false for anything outside ASCII, so only the x matches. The cases are
[[:graph:]] and [[:print:]] over E'xᔀሷ'. It isn't really about the regex
code;
the same difference shows up in plain SQL in two clusters differing only in
locale.

Those two are the only ctype-dependent assertions in the file —
everything else
uses explicit code point ranges such as [\u1000-\u2000], or an input with a
separator (x*, x_*) that ends the match inside ASCII, which is presumably
deliberate.

Patches 0001 (for 15 and 16) and 0002 (for 17+) attached.

0002 gives the two cases an explicit collation:

    select * from test_regex('[[:graph:]]+',  E'xᔀሷ' COLLATE pg_c_utf8,
'L');
    select * from test_regex('[[:print:]]+',  E'xᔀሷ' COLLATE pg_c_utf8,
'L');

test_regex.c already threads PG_GET_COLLATION() into the compile, and
pg_c_utf8 exists in every UTF8 database, which is the only place this file
runs. That returns {xᔀሷ} in a C+UTF8 database and in en_US.utf8, so the
result
lines in the expected file don't change at all — only the echoed query text
does. It seems to me strictly better than what's there now, since the cases
stop depending on how the animal happened to be initdb'd.

On 15 and 16 there's no collation to point at — ucs_basic has
collctype C, the builtin provider is 17+, and ICU depends on the build
— so 0001 just adds a second expected file with the C-ctype answers,
the way json_encoding.sql does for its two encodings.

I did consider just neutralising the two inputs, by putting a space or a
tab in
front of the non-ASCII characters the way x* and x_* already do elsewhere in
that block. It works and it backpatches everywhere. I'd be sorry to do it,
though: those two cases are the only ones in the file that exercise Unicode
ctype at all, and after such a change they would pass even if the ctype
lookup
for non-ASCII were completely broken.

2. collate.linux.utf8 has never run on a meson build

While checking whether anything else fails in a C+UTF8 database, I found
that
collate.linux.utf8 wasn't running on my build at all. Its guard includes

    version() !~ 'linux-gnu'

and meson builds don't produce that string:

    meson     PostgreSQL 20devel on aarch64-linux, compiled by
gcc-13.3.0, 64-bit
    autoconf  PostgreSQL 20devel on aarch64-unknown-linux-gnu, compiled
by gcc ...

meson.build composes the platform part from host_machine.cpu_family() and
host_system, which gives <cpu>-linux on any platform and never carries
the ABI
suffix, where configure substitutes the GNU host triplet. On master
that file quits at its guard after 11 lines on an unpatched meson build, and
runs to 1196 lines with the patch below applied. That's been the case since
meson support went in, in 16.

infinite_recurse is the other test that matches on the platform string,
and it
gets it the other way round: it means to skip itself on ppc64 Linux
because of
a kernel bug, and on a meson build the match will never fire, so it will be
running the case it's meant to stay away from. I don't have a ppc64
machine to
confirm that end of it, so that part is a reading of the code rather than
something I've observed.

I think this wants fixing at both ends.

0003 relaxes the two guards so they match either spelling: "-linux[-,]" for
collate.linux.utf8 and "powerpc64[^,]*-linux" for infinite_recurse.
Keeping the
punctuation on either side confines the match to the platform field. Neither
pattern excludes musl, but collate.linux.utf8's other conditions already
require a set of glibc locales to be present, so a musl box still skips.
That's
test-only, so I'd backpatch it to 16 and get the coverage back
everywhere it's
been missing.

0004 makes the meson build report the GNU host triplet, by asking the
compiler
for it with -dumpmachine where it supports that and falling back to the
present
behaviour otherwise. That seems to me worth doing on its own account --
version()
ought to say the same thing whichever way you built, and things other
than these
two tests may look at it -- but it changes a user-visible string, so
master and
19 only. If people don't want to change the way this is done on meson,
that's
fine - patch 0003 will fix the test issue alone. But I thought it would
be good
to make meson behave the same as autoconf.

Waking this test on the meson animals may turn some of them red if they
don't have
the required locales, but that hasn't been a problem with autoconf
animals, so I
don't think we need any extra guards at this stage.

cheers

andrew

[1] https://postgr.es/m/3665293.1786715742%40sss.pgh.pa.us

--
Andrew Dunstan
EDB: https://www.enterprisedb.com

Attachment Content-Type Size
0001-Provide-a-C-ctype-variant-expected-file-for-test_reg.patch text/x-patch 7.1 KB
0002-Pin-two-ctype-dependent-test_regex_utf8-cases-to-a-f.patch text/x-patch 3.6 KB
0003-Make-the-platform-guards-in-two-regression-tests-mat.patch text/x-patch 5.0 KB
0004-meson-report-the-GNU-host-triplet-in-PG_VERSION_STR.patch text/x-patch 2.4 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message Pavel Stehule 2026-08-23 13:22:51 Re: missing possibility to use alternative translated month names in to_char function
Previous Message 达劳里亚斯 2026-08-23 11:54:06 Re: pg_upgrade --copy-file-range fails with EINVAL on Linux 4.19