On Wed, Sep 7, 2011 at 21:37, Tom Lane <t...@sss.pgh.pa.us> wrote: > Hmm. I agree that this is a bug, but the proposed fix seems like a bit > of a kluge. Wouldn't it be better to make get_last_relevant_decnum > honor its contract, that is not delete any relevant digits?
You're right, it was a kludge. Here's an improved version. I need to take a NUMProc* argument to do that right, because that's how it knows how many '0's to keep from the format. What do you think? Regards, Marti
From d0264d8fe8179716bfd58e12201e456387ca5469 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp <ma...@juffo.org> Date: Wed, 7 Sep 2011 20:12:58 +0300 Subject: [PATCH] Don't truncate integer part in to_char for 'FM99.' When the numeric to_char format used fillmode (FM), didn't contain 0s and had a trailing dot, the integer part of the number was truncated in error. to_char(10, 'FM99.') used to return '1', now it will return '10' --- src/backend/utils/adt/formatting.c | 29 ++++++++++++++++------------- src/test/regress/expected/numeric.out | 6 ++++++ src/test/regress/sql/numeric.sql | 2 ++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 7efd988..eada4a8 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -979,7 +979,7 @@ static char *fill_str(char *str, int c, int max); static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree); static char *int_to_roman(int number); static void NUM_prepare_locale(NUMProc *Np); -static char *get_last_relevant_decnum(char *num); +static char *get_last_relevant_decnum(NUMProc *Np); static void NUM_numpart_from_char(NUMProc *Np, int id, int plen); static void NUM_numpart_to_char(NUMProc *Np, int id); static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, @@ -3911,17 +3911,26 @@ NUM_prepare_locale(NUMProc *Np) * ---------- */ static char * -get_last_relevant_decnum(char *num) +get_last_relevant_decnum(NUMProc *Np) { char *result, - *p = strchr(num, '.'); + *p; #ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "get_last_relevant_decnum()"); #endif - if (!p) - p = num; + if (Np->Num->zero_end > Np->num_pre) + /* Keep digits according to '0's in the format */ + p = Np->number + Np->Num->zero_end - Np->num_pre; + else + { + p = strchr(Np->number, '.'); + + if (!p) + return NULL; + } + result = p; while (*(++p)) @@ -4458,14 +4467,8 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number, { Np->num_pre = plen; - if (IS_FILLMODE(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)); - } + if (IS_FILLMODE(Np->Num) && IS_DECIMAL(Np->Num)) + Np->last_relevant = get_last_relevant_decnum(Np); if (Np->sign_wrote == FALSE && Np->num_pre == 0) ++Np->num_count; diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out index d9927b7..e12ab5b 100644 --- a/src/test/regress/expected/numeric.out +++ b/src/test/regress/expected/numeric.out @@ -1154,6 +1154,12 @@ 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.'); + to_char_24 | 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 a1435ec..d552526 100644 --- a/src/test/regress/sql/numeric.sql +++ b/src/test/regress/sql/numeric.sql @@ -764,6 +764,8 @@ 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.'); + -- TO_NUMBER() -- SELECT '' AS to_number_1, to_number('-34,338,492', '99G999G999'); -- 1.7.6.1
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers