Skip to content

Commit cc0d90b

Browse files
committed
to_char(float4/8): zero pad to specified length
Previously, zero padding was limited to the internal length, rather than the specified length. This allows it to match to_char(int/numeric), which always padded to the specified length. Regression tests added. BACKWARD INCOMPATIBILITY
1 parent 1933a5b commit cc0d90b

File tree

4 files changed

+163
-40
lines changed

4 files changed

+163
-40
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 75 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,6 @@
113113
#define DCH_MAX_ITEM_SIZ 12 /* max localized day name */
114114
#define NUM_MAX_ITEM_SIZ 8 /* roman number (RN has 15 chars) */
115115

116-
/* ----------
117-
* More is in float.c
118-
* ----------
119-
*/
120-
#define MAXFLOATWIDTH 60
121-
#define MAXDOUBLEWIDTH 500
122-
123116

124117
/* ----------
125118
* Format parser structs
@@ -5214,8 +5207,7 @@ int4_to_char(PG_FUNCTION_ARGS)
52145207
/* we can do it easily because float8 won't lose any precision */
52155208
float8 val = (float8) value;
52165209

5217-
orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5218-
snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, val);
5210+
orgnum = psprintf("%+.*e", Num.post, val);
52195211

52205212
/*
52215213
* Swap a leading positive sign for a space.
@@ -5414,7 +5406,6 @@ float4_to_char(PG_FUNCTION_ARGS)
54145406
numstr = orgnum = int_to_roman((int) rint(value));
54155407
else if (IS_EEEE(&Num))
54165408
{
5417-
numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
54185409
if (isnan(value) || is_infinite(value))
54195410
{
54205411
/*
@@ -5428,15 +5419,29 @@ float4_to_char(PG_FUNCTION_ARGS)
54285419
}
54295420
else
54305421
{
5431-
snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5422+
numstr = psprintf("%+.*e", Num.post, value);
5423+
5424+
/* prevent the display of imprecise/junk digits */
5425+
if (Num.pre + Num.post > FLT_DIG)
5426+
{
5427+
int digits = 0;
5428+
char *numstr_p;
5429+
5430+
for (numstr_p = numstr; *numstr_p && *numstr_p != 'e'; numstr_p++)
5431+
{
5432+
if (isdigit(*numstr_p))
5433+
{
5434+
if (++digits > FLT_DIG)
5435+
*numstr_p = '0';
5436+
}
5437+
}
5438+
}
54325439

54335440
/*
54345441
* Swap a leading positive sign for a space.
54355442
*/
5436-
if (*orgnum == '+')
5437-
*orgnum = ' ';
5438-
5439-
numstr = orgnum;
5443+
if (*numstr == '+')
5444+
*numstr = ' ';
54405445
}
54415446
}
54425447
else
@@ -5452,16 +5457,24 @@ float4_to_char(PG_FUNCTION_ARGS)
54525457
Num.pre += Num.multi;
54535458
}
54545459

5455-
orgnum = (char *) palloc(MAXFLOATWIDTH + 1);
5456-
snprintf(orgnum, MAXFLOATWIDTH + 1, "%.0f", fabs(val));
5457-
numstr_pre_len = strlen(orgnum);
5460+
/* let psprintf() do the rounding */
5461+
orgnum = psprintf("%.*f", Num.post, val);
54585462

5459-
/* adjust post digits to fit max float digits */
5460-
if (numstr_pre_len >= FLT_DIG)
5461-
Num.post = 0;
5462-
else if (numstr_pre_len + Num.post > FLT_DIG)
5463-
Num.post = FLT_DIG - numstr_pre_len;
5464-
snprintf(orgnum, MAXFLOATWIDTH + 1, "%.*f", Num.post, val);
5463+
/* prevent the display of imprecise/junk digits */
5464+
if (Num.pre + Num.post > FLT_DIG)
5465+
{
5466+
int digits = 0;
5467+
char *orgnum_p;
5468+
5469+
for (orgnum_p = orgnum; *orgnum_p; orgnum_p++)
5470+
{
5471+
if (isdigit(*orgnum_p))
5472+
{
5473+
if (++digits > FLT_DIG)
5474+
*orgnum_p = '0';
5475+
}
5476+
}
5477+
}
54655478

54665479
if (*orgnum == '-')
54675480
{ /* < 0 */
@@ -5520,7 +5533,6 @@ float8_to_char(PG_FUNCTION_ARGS)
55205533
numstr = orgnum = int_to_roman((int) rint(value));
55215534
else if (IS_EEEE(&Num))
55225535
{
5523-
numstr = orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
55245536
if (isnan(value) || is_infinite(value))
55255537
{
55265538
/*
@@ -5534,15 +5546,29 @@ float8_to_char(PG_FUNCTION_ARGS)
55345546
}
55355547
else
55365548
{
5537-
snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%+.*e", Num.post, value);
5549+
numstr = psprintf("%+.*e", Num.post, value);
5550+
5551+
/* prevent the display of imprecise/junk digits */
5552+
if (Num.pre + Num.post > DBL_DIG)
5553+
{
5554+
int digits = 0;
5555+
char *numstr_p;
5556+
5557+
for (numstr_p = numstr; *numstr_p && *numstr_p != 'e'; numstr_p++)
5558+
{
5559+
if (isdigit(*numstr_p))
5560+
{
5561+
if (++digits > DBL_DIG)
5562+
*numstr_p = '0';
5563+
}
5564+
}
5565+
}
55385566

55395567
/*
55405568
* Swap a leading positive sign for a space.
55415569
*/
5542-
if (*orgnum == '+')
5543-
*orgnum = ' ';
5544-
5545-
numstr = orgnum;
5570+
if (*numstr == '+')
5571+
*numstr = ' ';
55465572
}
55475573
}
55485574
else
@@ -5557,15 +5583,25 @@ float8_to_char(PG_FUNCTION_ARGS)
55575583
val = value * multi;
55585584
Num.pre += Num.multi;
55595585
}
5560-
orgnum = (char *) palloc(MAXDOUBLEWIDTH + 1);
5561-
numstr_pre_len = snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.0f", fabs(val));
5562-
5563-
/* adjust post digits to fit max double digits */
5564-
if (numstr_pre_len >= DBL_DIG)
5565-
Num.post = 0;
5566-
else if (numstr_pre_len + Num.post > DBL_DIG)
5567-
Num.post = DBL_DIG - numstr_pre_len;
5568-
snprintf(orgnum, MAXDOUBLEWIDTH + 1, "%.*f", Num.post, val);
5586+
5587+
/* let psprintf() do the rounding */
5588+
orgnum = psprintf("%.*f", Num.post, val);
5589+
5590+
/* prevent the display of imprecise/junk digits */
5591+
if (Num.pre + Num.post > DBL_DIG)
5592+
{
5593+
int digits = 0;
5594+
char *orgnum_p;
5595+
5596+
for (orgnum_p = orgnum; *orgnum_p; orgnum_p++)
5597+
{
5598+
if (isdigit(*orgnum_p))
5599+
{
5600+
if (++digits > DBL_DIG)
5601+
*orgnum_p = '0';
5602+
}
5603+
}
5604+
}
55695605

55705606
if (*orgnum == '-')
55715607
{ /* < 0 */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy