diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 7efd988362..a7000250b0 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -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) diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out index d9927b7915..71c520e5e7 100644 --- a/src/test/regress/expected/numeric.out +++ b/src/test/regress/expected/numeric.out @@ -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'); diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql index a1435ec85e..b2dc46fae2 100644 --- a/src/test/regress/sql/numeric.sql +++ b/src/test/regress/sql/numeric.sql @@ -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');