Skip to content

Commit d2c744a

Browse files
committed
Add extra_float_digits GUC parameter to allow adjustment of displayed
precision for float4, float8, and geometric types. Set it in pg_dump so that float data can be dumped/reloaded exactly (at least on platforms where the float I/O support is properly implemented). Initial patch by Pedro Ferreira, some additional work by Tom Lane.
1 parent fef731d commit d2c744a

File tree

8 files changed

+106
-38
lines changed

8 files changed

+106
-38
lines changed

doc/src/sgml/runtime.sgml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.148 2002/11/05 23:16:56 momjian Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.149 2002/11/08 17:37:52 tgl Exp $
33
-->
44

55
<Chapter Id="runtime">
@@ -1448,6 +1448,30 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
14481448
</listitem>
14491449
</varlistentry>
14501450

1451+
<varlistentry>
1452+
<indexterm>
1453+
<primary>significant digits</primary>
1454+
</indexterm>
1455+
<indexterm>
1456+
<primary>display</primary>
1457+
<secondary>of float numbers</secondary>
1458+
</indexterm>
1459+
1460+
<term><varname>EXTRA_FLOAT_DIGITS</varname> (<type>integer</type>)</term>
1461+
<listitem>
1462+
<para>
1463+
This parameter adjusts the number of digits displayed for
1464+
floating-point values, including <type>float4</>, <type>float8</>,
1465+
and geometric datatypes. The parameter value is added to the
1466+
standard number of digits (<literal>FLT_DIG</> or <literal>DBL_DIG</>
1467+
as appropriate). The value can be set as high as 2, to include
1468+
partially-significant digits; this is especially useful for dumping
1469+
float data that needs to be restored exactly. Or it can be set
1470+
negative to suppress unwanted digits.
1471+
</para>
1472+
</listitem>
1473+
</varlistentry>
1474+
14511475
<varlistentry>
14521476
<term><varname>KRB_SERVER_KEYFILE</varname> (<type>string</type>)</term>
14531477
<listitem>

src/backend/utils/adt/float.c

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.82 2002/10/19 02:08:17 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.83 2002/11/08 17:37:52 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -94,9 +94,6 @@ extern double rint(double x);
9494
#endif /* NeXT check */
9595

9696

97-
static void CheckFloat4Val(double val);
98-
static void CheckFloat8Val(double val);
99-
10097
#ifndef M_PI
10198
/* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
10299
#define M_PI 3.14159265358979323846
@@ -113,8 +110,6 @@ static void CheckFloat8Val(double val);
113110
#define SHRT_MIN (-32768)
114111
#endif
115112

116-
#define FORMAT 'g' /* use "g" output format as standard
117-
* format */
118113
/* not sure what the following should be, but better to make it over-sufficient */
119114
#define MAXFLOATWIDTH 64
120115
#define MAXDOUBLEWIDTH 128
@@ -128,6 +123,14 @@ static void CheckFloat8Val(double val);
128123
#define FLOAT8_MIN DBL_MIN
129124

130125

126+
/* Configurable GUC parameter */
127+
int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */
128+
129+
130+
static void CheckFloat4Val(double val);
131+
static void CheckFloat8Val(double val);
132+
133+
131134
/*
132135
* check to see if a float4 val is outside of
133136
* the FLOAT4_MIN, FLOAT4_MAX bounds.
@@ -228,6 +231,7 @@ float4out(PG_FUNCTION_ARGS)
228231
float4 num = PG_GETARG_FLOAT4(0);
229232
char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
230233
int infflag;
234+
int ndig;
231235

232236
if (isnan(num))
233237
PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
@@ -237,7 +241,12 @@ float4out(PG_FUNCTION_ARGS)
237241
if (infflag < 0)
238242
PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));
239243

240-
sprintf(ascii, "%.*g", FLT_DIG, num);
244+
ndig = FLT_DIG + extra_float_digits;
245+
if (ndig < 1)
246+
ndig = 1;
247+
248+
sprintf(ascii, "%.*g", ndig, num);
249+
241250
PG_RETURN_CSTRING(ascii);
242251
}
243252

@@ -290,6 +299,7 @@ float8out(PG_FUNCTION_ARGS)
290299
float8 num = PG_GETARG_FLOAT8(0);
291300
char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);
292301
int infflag;
302+
int ndig;
293303

294304
if (isnan(num))
295305
PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
@@ -299,7 +309,12 @@ float8out(PG_FUNCTION_ARGS)
299309
if (infflag < 0)
300310
PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));
301311

302-
sprintf(ascii, "%.*g", DBL_DIG, num);
312+
ndig = DBL_DIG + extra_float_digits;
313+
if (ndig < 1)
314+
ndig = 1;
315+
316+
sprintf(ascii, "%.*g", ndig, num);
317+
303318
PG_RETURN_CSTRING(ascii);
304319
}
305320

src/backend/utils/adt/geo_ops.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.66 2002/09/05 00:43:07 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.67 2002/11/08 17:37:52 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -19,6 +19,7 @@
1919
#include <float.h>
2020
#include <ctype.h>
2121

22+
#include "utils/builtins.h"
2223
#include "utils/geo_decls.h"
2324

2425
#ifndef PI
@@ -79,11 +80,9 @@ static Point *line_interpt_internal(LINE *l1, LINE *l2);
7980
#define LDELIM_C '<'
8081
#define RDELIM_C '>'
8182

82-
/* Maximum number of output digits printed */
83-
#define P_MAXDIG DBL_DIG
84-
#define P_MAXLEN (2*(P_MAXDIG+7)+1)
85-
86-
static int digits8 = P_MAXDIG;
83+
/* Maximum number of characters printed by pair_encode() */
84+
/* ...+2+7 : 2 accounts for extra_float_digits max value */
85+
#define P_MAXLEN (2*(DBL_DIG+2+7)+1)
8786

8887

8988
/*
@@ -139,7 +138,12 @@ single_decode(char *str, float8 *x, char **s)
139138
static int
140139
single_encode(float8 x, char *str)
141140
{
142-
sprintf(str, "%.*g", digits8, x);
141+
int ndig = DBL_DIG + extra_float_digits;
142+
143+
if (ndig < 1)
144+
ndig = 1;
145+
146+
sprintf(str, "%.*g", ndig, x);
143147
return TRUE;
144148
} /* single_encode() */
145149

@@ -190,7 +194,12 @@ pair_decode(char *str, float8 *x, float8 *y, char **s)
190194
static int
191195
pair_encode(float8 x, float8 y, char *str)
192196
{
193-
sprintf(str, "%.*g,%.*g", digits8, x, digits8, y);
197+
int ndig = DBL_DIG + extra_float_digits;
198+
199+
if (ndig < 1)
200+
ndig = 1;
201+
202+
sprintf(str, "%.*g,%.*g", ndig, x, ndig, y);
194203
return TRUE;
195204
}
196205

@@ -976,7 +985,7 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2)
976985
#endif
977986
#ifdef GEODEBUG
978987
printf("line_construct_pts- line is neither vertical nor horizontal (diffs x=%.*g, y=%.*g\n",
979-
digits8, (pt2->x - pt1->x), digits8, (pt2->y - pt1->y));
988+
DBL_DIG, (pt2->x - pt1->x), DBL_DIG, (pt2->y - pt1->y));
980989
#endif
981990
}
982991
}
@@ -1181,8 +1190,8 @@ line_interpt_internal(LINE *l1, LINE *l2)
11811190

11821191
#ifdef GEODEBUG
11831192
printf("line_interpt- lines are A=%.*g, B=%.*g, C=%.*g, A=%.*g, B=%.*g, C=%.*g\n",
1184-
digits8, l1->A, digits8, l1->B, digits8, l1->C, digits8, l2->A, digits8, l2->B, digits8, l2->C);
1185-
printf("line_interpt- lines intersect at (%.*g,%.*g)\n", digits8, x, digits8, y);
1193+
DBL_DIG, l1->A, DBL_DIG, l1->B, DBL_DIG, l1->C, DBL_DIG, l2->A, DBL_DIG, l2->B, DBL_DIG, l2->C);
1194+
printf("line_interpt- lines intersect at (%.*g,%.*g)\n", DBL_DIG, x, DBL_DIG, y);
11861195
#endif
11871196

11881197
return result;
@@ -2381,14 +2390,14 @@ interpt_sl(LSEG *lseg, LINE *line)
23812390
p = line_interpt_internal(&tmp, line);
23822391
#ifdef GEODEBUG
23832392
printf("interpt_sl- segment is (%.*g %.*g) (%.*g %.*g)\n",
2384-
digits8, lseg->p[0].x, digits8, lseg->p[0].y, digits8, lseg->p[1].x, digits8, lseg->p[1].y);
2393+
DBL_DIG, lseg->p[0].x, DBL_DIG, lseg->p[0].y, DBL_DIG, lseg->p[1].x, DBL_DIG, lseg->p[1].y);
23852394
printf("interpt_sl- segment becomes line A=%.*g B=%.*g C=%.*g\n",
2386-
digits8, tmp.A, digits8, tmp.B, digits8, tmp.C);
2395+
DBL_DIG, tmp.A, DBL_DIG, tmp.B, DBL_DIG, tmp.C);
23872396
#endif
23882397
if (PointerIsValid(p))
23892398
{
23902399
#ifdef GEODEBUG
2391-
printf("interpt_sl- intersection point is (%.*g %.*g)\n", digits8, p->x, digits8, p->y);
2400+
printf("interpt_sl- intersection point is (%.*g %.*g)\n", DBL_DIG, p->x, DBL_DIG, p->y);
23922401
#endif
23932402
if (on_ps_internal(p, lseg))
23942403
{
@@ -3940,7 +3949,7 @@ circle_out(PG_FUNCTION_ARGS)
39403949
char *result;
39413950
char *cp;
39423951

3943-
result = palloc(3 * (P_MAXLEN + 1) + 3);
3952+
result = palloc(2 * P_MAXLEN + 6);
39443953

39453954
cp = result;
39463955
*cp++ = LDELIM_C;

src/backend/utils/misc/guc.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* command, configuration file, and command line options.
66
* See src/backend/utils/misc/README for more information.
77
*
8-
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.99 2002/11/01 22:52:33 tgl Exp $
8+
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.100 2002/11/08 17:37:52 tgl Exp $
99
*
1010
* Copyright 2000 by PostgreSQL Global Development Group
1111
* Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -680,6 +680,11 @@ static struct config_int
680680
5, 1, 1000, NULL, NULL
681681
},
682682

683+
{
684+
{"extra_float_digits", PGC_USERSET}, &extra_float_digits,
685+
0, -15, 2, NULL, NULL
686+
},
687+
683688
{
684689
{NULL, 0}, NULL, 0, 0, 0, NULL, NULL
685690
}

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127
#log_duration = false
128128
#log_timestamp = false
129129

130-
#log_min_error_statement = error # Values in order of increasing severity:
130+
#log_min_error_statement = error # Values in order of increasing severity:
131131
# debug5, debug4, debug3, debug2, debug1,
132132
# info, notice, warning, error
133133
#debug_print_parse = false
@@ -198,6 +198,7 @@
198198
#authentication_timeout = 60 # 1-600, in seconds
199199
#deadlock_timeout = 1000 # in milliseconds
200200
#default_transaction_isolation = 'read committed'
201+
#extra_float_digits = 0 # min -15, max 2
201202
#max_expr_depth = 10000 # min 10
202203
#max_files_per_process = 1000 # min 25
203204
#password_encryption = true

src/bin/pg_dump/pg_dump.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
*
2323
*
2424
* IDENTIFICATION
25-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.305 2002/10/22 19:15:23 momjian Exp $
25+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.306 2002/11/08 17:37:52 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -171,6 +171,7 @@ main(int argc, char **argv)
171171
const char *pgport = NULL;
172172
const char *username = NULL;
173173
bool oids = false;
174+
PGresult *res;
174175
TableInfo *tblinfo;
175176
int numTables;
176177
bool force_password = false;
@@ -549,22 +550,32 @@ main(int argc, char **argv)
549550
/*
550551
* Start serializable transaction to dump consistent data.
551552
*/
552-
{
553-
PGresult *res;
553+
res = PQexec(g_conn, "BEGIN");
554+
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
555+
exit_horribly(g_fout, NULL, "BEGIN command failed: %s",
556+
PQerrorMessage(g_conn));
557+
PQclear(res);
554558

555-
res = PQexec(g_conn, "BEGIN");
556-
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
557-
exit_horribly(g_fout, NULL, "BEGIN command failed: %s",
558-
PQerrorMessage(g_conn));
559-
PQclear(res);
559+
res = PQexec(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
560+
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
561+
exit_horribly(g_fout, NULL, "could not set transaction isolation level to serializable: %s",
562+
PQerrorMessage(g_conn));
563+
PQclear(res);
560564

561-
res = PQexec(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
565+
/*
566+
* If supported, set extra_float_digits so that we can dump float data
567+
* exactly (given correctly implemented float I/O code, anyway)
568+
*/
569+
if (g_fout->remoteVersion >= 70400)
570+
{
571+
res = PQexec(g_conn, "SET extra_float_digits TO 2");
562572
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
563-
exit_horribly(g_fout, NULL, "could not set transaction isolation level to serializable: %s",
573+
exit_horribly(g_fout, NULL, "could not set extra_float_digits: %s",
564574
PQerrorMessage(g_conn));
565575
PQclear(res);
566576
}
567577

578+
/* Find the last built-in OID, if needed */
568579
if (g_fout->remoteVersion < 70300)
569580
{
570581
if (g_fout->remoteVersion >= 70100)

src/bin/psql/tab-complete.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright 2000-2002 by PostgreSQL Global Development Group
55
*
6-
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.64 2002/09/04 20:31:36 momjian Exp $
6+
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.65 2002/11/08 17:37:52 tgl Exp $
77
*/
88

99
/*----------------------------------------------------------------------
@@ -261,6 +261,7 @@ psql_completion(char *text, int start, int end)
261261
"max_expr_depth",
262262
"commit_delay",
263263
"commit_siblings",
264+
"extra_float_digits",
264265

265266
"effective_cache_size",
266267
"random_page_cost",

src/include/utils/builtins.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: builtins.h,v 1.204 2002/11/02 18:41:22 tgl Exp $
10+
* $Id: builtins.h,v 1.205 2002/11/08 17:37:52 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -212,6 +212,8 @@ extern Datum btnamecmp(PG_FUNCTION_ARGS);
212212
extern Datum bttextcmp(PG_FUNCTION_ARGS);
213213

214214
/* float.c */
215+
extern int extra_float_digits;
216+
215217
extern Datum float4in(PG_FUNCTION_ARGS);
216218
extern Datum float4out(PG_FUNCTION_ARGS);
217219
extern Datum float8in(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)