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)
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