On Thu, Nov 16, 2023 at 12:06 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Thomas Munro <thomas.munro@gmail.com> writes:
> > Perhaps we could use snprintf_l() and strtod_l() where available.
> > They're not standard, but they are obvious extensions that NetBSD and
> > Windows have, and those are the two systems for which we are doing
> > grotty things in that code.
>
> Oooh, shiny. I do not see any man page for strtod_l, but I do see
> that it's declared on mamba's host. I wonder how long they've had it?
> The man page for snprintf_l appears to be quite ancient, so we could
> hope that strtod_l is available on all versions anyone cares about.
A decade[1]. And while I'm doing archeology, I noticed that POSIX has
agreed[2] in principle that *all* functions affected by the thread's
current locale should have a _l() variant, it's just that no one has
sent in the patch.
> > That would amount to extending
> > pg_locale.c's philosophy: either you must have uselocale(), or the
> > full set of _l() functions (that POSIX failed to standardise, dunno
> > what the history is behind that, seems weird).
>
> Yeah. I'd say the _l functions should be preferred over uselocale()
> if available, but sadly they're not there on common systems. (It
> looks like glibc has strtod_l but not snprintf_l, which is odd.)
Here is a first attempt. In this version, new functions are exported
by pgtypeslib. I realised that I had to do it in there because ECPG's
uselocale() jiggery-pokery is clearly intended to affect the
conversions happening in there too, and we probably don't want
circular dependencies between pgtypeslib and ecpglib. I think this
means that pgtypeslib is actually subtly b0rked if you use it
independently without an ECPG connection (is that a thing people do?),
because all that code copied-and-pasted from the backend when run in
frontend code with eg a French locale will produce eg "0,42"; this
patch doesn't change that.
I also had a go[3] at doing it with static inlined functions, to avoid
creating a load of new exported functions and associated function call
overheads. It worked fine, except on Windows: I needed a global
variable PGTYPESclocale that all the inlined functions can see when
called from ecpglib or pgtypeslib code, but if I put that in the
exports list then on that platform it seems to contain garbage; there
is probably some other magic needed to export non-function symbols
from the DLL or something like that, I didn't look into it. See CI
failure + crash dumps.
[1] https://github.com/NetBSD/src/commit/c99aac45e540bc210cc660619a6b5323cbb5c17f
[2] https://www.austingroupbugs.net/view.php?id=1004
[3] https://github.com/macdice/postgres/tree/strtod_l_inline