Commit 6325527d authored by Tom Lane's avatar Tom Lane

Further fix for psql's code for locale-aware formatting of numeric output.

On closer inspection, those seemingly redundant atoi() calls were not so
much inefficient as just plain wrong: the author of this code either had
not read, or had not understood, the POSIX specification for localeconv().
The grouping field is *not* a textual digit string but separate integers
encoded as chars.

We'll follow the existing code as well as the backend's cash.c in only
honoring the first group width, but let's at least honor it correctly.

This doesn't actually result in any behavioral change in any of the
locales I have installed on my Linux box, which may explain why nobody's
complained; grouping width 3 is close enough to universal that it's barely
worth considering other cases.  Still, wrong is wrong, so back-patch.
parent 4778a0bd
...@@ -3227,16 +3227,24 @@ setDecimalLocale(void) ...@@ -3227,16 +3227,24 @@ setDecimalLocale(void)
extlconv = localeconv(); extlconv = localeconv();
/* Don't accept an empty decimal_point string */
if (*extlconv->decimal_point) if (*extlconv->decimal_point)
decimal_point = pg_strdup(extlconv->decimal_point); decimal_point = pg_strdup(extlconv->decimal_point);
else else
decimal_point = "."; /* SQL output standard */ decimal_point = "."; /* SQL output standard */
if (*extlconv->grouping && atoi(extlconv->grouping) > 0) /*
groupdigits = atoi(extlconv->grouping); * Although the Open Group standard allows locales to supply more than one
else * group width, we consider only the first one, and we ignore any attempt
* to suppress grouping by specifying CHAR_MAX. As in the backend's
* cash.c, we must apply a range check to avoid being fooled by variant
* CHAR_MAX values.
*/
groupdigits = *extlconv->grouping;
if (groupdigits <= 0 || groupdigits > 6)
groupdigits = 3; /* most common */ groupdigits = 3; /* most common */
/* Don't accept an empty thousands_sep string, either */
/* similar code exists in formatting.c */ /* similar code exists in formatting.c */
if (*extlconv->thousands_sep) if (*extlconv->thousands_sep)
thousands_sep = pg_strdup(extlconv->thousands_sep); thousands_sep = pg_strdup(extlconv->thousands_sep);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment