Translatable strings with formatting of 64bit values

Started by Ildus Kurbangalievover 8 years ago2 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t38609
psql -h localhost -U postgres

Built from patchset v1 (message #1), July 27, 2026 at 08:33 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t38609_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t38609_1 && git checkout t38609_1

Patchset v1 (message #1) is on t38609_1

Jump to latest
#1Ildus Kurbangaliev
i.kurbangaliev@postgrespro.ru

Hi,

apparently gettext can't properly identify strings when 64bit values
formatted with macros like INT64_FORMAT and UINT64_FORMAT. I did
some research and found out that gettext can work with PRId64 and
PRIu64. My suggestion is to use these macro for such strings.

The problem is here that PRIu64 is not accessible on all platforms but
this is easy solvable if it will be specified using INT64_MODIFIER in
c.h.

I attached a sample patch that adds PRIu64, PRId64 and makes few strings
translatable.

Using PRId64 will simplify the code like this:

char bufv[100],
bufm[100],
bufx[100];

snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("setval: value %s is out of
bounds for sequence \"%s\" (%s..%s)", bufv,
RelationGetRelationName(seqrel), bufm, bufx)));

To:

if ((next < minv) || (next > maxv))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("setval: value %s is out of
bounds for sequence \"%" PRId64 "\" (%" PRId64 "..%" PRId64
")", next, RelationGetRelationName(seqrel), minv, maxv)));

In result:

#: commands/sequence.c:944
#, fuzzy, c-format
#| msgid "setval: value %s is out of bounds for sequence
\"%s\" (%s..%s)"
msgid "setval: value %s is out of bounds for sequence
\"%<PRId64>\" (%<PRId64>..%<PRId64>)"
msgstr "setval передано значение %s вне пределов последовательности
\"%s\" (%s..%s)"

And still this string will be translatable. I found a bunch of places
when PRIx64 macros can simplify the code.

--
---
Ildus Kurbangaliev
Postgres Professional: http://www.postgrespro.com
Russian Postgres Company

Attachments:

t38609_1
prix64.patchtext/x-patchDownload+7-7
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Ildus Kurbangaliev (#1)
Re: Translatable strings with formatting of 64bit values

librelpIldus Kurbangaliev <i.kurbangaliev@postgrespro.ru> writes:

apparently gettext can't properly identify strings when 64bit values
formatted with macros like INT64_FORMAT and UINT64_FORMAT. I did
some research and found out that gettext can work with PRId64 and
PRIu64. My suggestion is to use these macro for such strings.

I do not believe what you're suggesting can actually work reliably.
In particular it'd fail if we're using our own version of snprintf
and that has different length modifiers than whatever gettext thinks
is the platform standard. Also, how do you think it can possibly work
on platforms lacking the PRId64 macro? gettext would have no better
idea than we do about what to assume that is.

Even if we could trust it to work, it doesn't seem to me that this:

ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("setval: value %s is out of
bounds for sequence \"%" PRId64 "\" (%" PRId64 "..%" PRId64
")", next, RelationGetRelationName(seqrel), minv, maxv)));

is really any cleaner or easier to read than what we're doing now.

An idea that might be worth considering is to provide a helper function
that converts an int64 to a palloc'd string, so that you could write

errmsg("setval: value %s is out of bounds ...",
int64tostr(next), ...)

If you were executing in a long-lived memory context, this might risk
a memory leak, but we've not had a lot of problems with using other
functions that allocate some memory within ereport calls. In any case
the existing method with a local buffer would work as a fallback
if that were a concern.

regards, tom lane