0001-Don-t-truncate-integer-part-in-to_char-for-FM99.patch
text/x-patch
Filename: 0001-Don-t-truncate-integer-part-in-to_char-for-FM99.patch
Type: text/x-patch
Part: 0
From d0264d8fe8179716bfd58e12201e456387ca5469 Mon Sep 17 00:00:00 2001
From: Marti Raudsepp <marti@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