mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 10:21:51 +02:00
Fix corner case bug in numeric to_char().
Trailing-zero stripping applied by the FM specifier could strip zeroes to the left of the decimal point, for a format with no digit positions after the decimal point (such as "FM999."). Reported and diagnosed by Marti Raudsepp, though I didn't use his patch.
This commit is contained in:
parent
7b8e10f2be
commit
f0bedf3e45
@ -3908,6 +3908,9 @@ NUM_prepare_locale(NUMProc *Np)
|
||||
/* ----------
|
||||
* Return pointer of last relevant number after decimal point
|
||||
* 12.0500 --> last relevant is '5'
|
||||
* 12.0000 --> last relevant is '.'
|
||||
* If there is no decimal point, return NULL (which will result in same
|
||||
* behavior as if FM hadn't been specified).
|
||||
* ----------
|
||||
*/
|
||||
static char *
|
||||
@ -3921,7 +3924,8 @@ get_last_relevant_decnum(char *num)
|
||||
#endif
|
||||
|
||||
if (!p)
|
||||
p = num;
|
||||
return NULL;
|
||||
|
||||
result = p;
|
||||
|
||||
while (*(++p))
|
||||
@ -4458,13 +4462,22 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
|
||||
{
|
||||
Np->num_pre = plen;
|
||||
|
||||
if (IS_FILLMODE(Np->Num))
|
||||
if (IS_FILLMODE(Np->Num) && IS_DECIMAL(Np->Num))
|
||||
{
|
||||
if (IS_DECIMAL(Np->Num))
|
||||
Np->last_relevant = get_last_relevant_decnum(
|
||||
Np->number +
|
||||
((Np->Num->zero_end - Np->num_pre > 0) ?
|
||||
Np->Num->zero_end - Np->num_pre : 0));
|
||||
Np->last_relevant = get_last_relevant_decnum(Np->number);
|
||||
|
||||
/*
|
||||
* If any '0' specifiers are present, make sure we don't strip
|
||||
* those digits.
|
||||
*/
|
||||
if (Np->last_relevant && Np->Num->zero_end > Np->num_pre)
|
||||
{
|
||||
char *last_zero;
|
||||
|
||||
last_zero = Np->number + (Np->Num->zero_end - Np->num_pre);
|
||||
if (Np->last_relevant < last_zero)
|
||||
Np->last_relevant = last_zero;
|
||||
}
|
||||
}
|
||||
|
||||
if (Np->sign_wrote == FALSE && Np->num_pre == 0)
|
||||
|
@ -1154,6 +1154,24 @@ SELECT '' AS to_char_23, to_char(val, '9.999EEEE') FROM num_data;
|
||||
| -2.493e+07
|
||||
(10 rows)
|
||||
|
||||
SELECT '' AS to_char_24, to_char('100'::numeric, 'FM999.9');
|
||||
to_char_24 | to_char
|
||||
------------+---------
|
||||
| 100.
|
||||
(1 row)
|
||||
|
||||
SELECT '' AS to_char_25, to_char('100'::numeric, 'FM999.');
|
||||
to_char_25 | to_char
|
||||
------------+---------
|
||||
| 100
|
||||
(1 row)
|
||||
|
||||
SELECT '' AS to_char_26, to_char('100'::numeric, 'FM999');
|
||||
to_char_26 | to_char
|
||||
------------+---------
|
||||
| 100
|
||||
(1 row)
|
||||
|
||||
-- TO_NUMBER()
|
||||
--
|
||||
SELECT '' AS to_number_1, to_number('-34,338,492', '99G999G999');
|
||||
|
@ -764,6 +764,10 @@ SELECT '' AS to_char_21, to_char(val, '999999SG9999999999') FROM num_data;
|
||||
SELECT '' AS to_char_22, to_char(val, 'FM9999999999999999.999999999999999') FROM num_data;
|
||||
SELECT '' AS to_char_23, to_char(val, '9.999EEEE') FROM num_data;
|
||||
|
||||
SELECT '' AS to_char_24, to_char('100'::numeric, 'FM999.9');
|
||||
SELECT '' AS to_char_25, to_char('100'::numeric, 'FM999.');
|
||||
SELECT '' AS to_char_26, to_char('100'::numeric, 'FM999');
|
||||
|
||||
-- TO_NUMBER()
|
||||
--
|
||||
SELECT '' AS to_number_1, to_number('-34,338,492', '99G999G999');
|
||||
|
Loading…
Reference in New Issue
Block a user