diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 25a3986204..c5718040fc 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ @@ -1448,6 +1448,30 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir' + + + significant digits + + + display + of float numbers + + + EXTRA_FLOAT_DIGITS (integer) + + + This parameter adjusts the number of digits displayed for + floating-point values, including float4, float8, + and geometric datatypes. The parameter value is added to the + standard number of digits (FLT_DIG or DBL_DIG + as appropriate). The value can be set as high as 2, to include + partially-significant digits; this is especially useful for dumping + float data that needs to be restored exactly. Or it can be set + negative to suppress unwanted digits. + + + + KRB_SERVER_KEYFILE (string) diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index fa34e105c1..c0acc554b8 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.82 2002/10/19 02:08:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.83 2002/11/08 17:37:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -94,9 +94,6 @@ extern double rint(double x); #endif /* NeXT check */ -static void CheckFloat4Val(double val); -static void CheckFloat8Val(double val); - #ifndef M_PI /* from my RH5.2 gcc math.h file - thomas 2000-04-03 */ #define M_PI 3.14159265358979323846 @@ -113,8 +110,6 @@ static void CheckFloat8Val(double val); #define SHRT_MIN (-32768) #endif -#define FORMAT 'g' /* use "g" output format as standard - * format */ /* not sure what the following should be, but better to make it over-sufficient */ #define MAXFLOATWIDTH 64 #define MAXDOUBLEWIDTH 128 @@ -128,6 +123,14 @@ static void CheckFloat8Val(double val); #define FLOAT8_MIN DBL_MIN +/* Configurable GUC parameter */ +int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */ + + +static void CheckFloat4Val(double val); +static void CheckFloat8Val(double val); + + /* * check to see if a float4 val is outside of * the FLOAT4_MIN, FLOAT4_MAX bounds. @@ -228,6 +231,7 @@ float4out(PG_FUNCTION_ARGS) float4 num = PG_GETARG_FLOAT4(0); char *ascii = (char *) palloc(MAXFLOATWIDTH + 1); int infflag; + int ndig; if (isnan(num)) PG_RETURN_CSTRING(strcpy(ascii, "NaN")); @@ -237,7 +241,12 @@ float4out(PG_FUNCTION_ARGS) if (infflag < 0) PG_RETURN_CSTRING(strcpy(ascii, "-Infinity")); - sprintf(ascii, "%.*g", FLT_DIG, num); + ndig = FLT_DIG + extra_float_digits; + if (ndig < 1) + ndig = 1; + + sprintf(ascii, "%.*g", ndig, num); + PG_RETURN_CSTRING(ascii); } @@ -290,6 +299,7 @@ float8out(PG_FUNCTION_ARGS) float8 num = PG_GETARG_FLOAT8(0); char *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1); int infflag; + int ndig; if (isnan(num)) PG_RETURN_CSTRING(strcpy(ascii, "NaN")); @@ -299,7 +309,12 @@ float8out(PG_FUNCTION_ARGS) if (infflag < 0) PG_RETURN_CSTRING(strcpy(ascii, "-Infinity")); - sprintf(ascii, "%.*g", DBL_DIG, num); + ndig = DBL_DIG + extra_float_digits; + if (ndig < 1) + ndig = 1; + + sprintf(ascii, "%.*g", ndig, num); + PG_RETURN_CSTRING(ascii); } diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 68917a64d6..ddad122585 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.66 2002/09/05 00:43:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.67 2002/11/08 17:37:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include #include +#include "utils/builtins.h" #include "utils/geo_decls.h" #ifndef PI @@ -79,11 +80,9 @@ static Point *line_interpt_internal(LINE *l1, LINE *l2); #define LDELIM_C '<' #define RDELIM_C '>' -/* Maximum number of output digits printed */ -#define P_MAXDIG DBL_DIG -#define P_MAXLEN (2*(P_MAXDIG+7)+1) - -static int digits8 = P_MAXDIG; +/* Maximum number of characters printed by pair_encode() */ +/* ...+2+7 : 2 accounts for extra_float_digits max value */ +#define P_MAXLEN (2*(DBL_DIG+2+7)+1) /* @@ -139,7 +138,12 @@ single_decode(char *str, float8 *x, char **s) static int single_encode(float8 x, char *str) { - sprintf(str, "%.*g", digits8, x); + int ndig = DBL_DIG + extra_float_digits; + + if (ndig < 1) + ndig = 1; + + sprintf(str, "%.*g", ndig, x); return TRUE; } /* single_encode() */ @@ -190,7 +194,12 @@ pair_decode(char *str, float8 *x, float8 *y, char **s) static int pair_encode(float8 x, float8 y, char *str) { - sprintf(str, "%.*g,%.*g", digits8, x, digits8, y); + int ndig = DBL_DIG + extra_float_digits; + + if (ndig < 1) + ndig = 1; + + sprintf(str, "%.*g,%.*g", ndig, x, ndig, y); return TRUE; } @@ -976,7 +985,7 @@ line_construct_pts(LINE *line, Point *pt1, Point *pt2) #endif #ifdef GEODEBUG printf("line_construct_pts- line is neither vertical nor horizontal (diffs x=%.*g, y=%.*g\n", - digits8, (pt2->x - pt1->x), digits8, (pt2->y - pt1->y)); + DBL_DIG, (pt2->x - pt1->x), DBL_DIG, (pt2->y - pt1->y)); #endif } } @@ -1181,8 +1190,8 @@ line_interpt_internal(LINE *l1, LINE *l2) #ifdef GEODEBUG printf("line_interpt- lines are A=%.*g, B=%.*g, C=%.*g, A=%.*g, B=%.*g, C=%.*g\n", - digits8, l1->A, digits8, l1->B, digits8, l1->C, digits8, l2->A, digits8, l2->B, digits8, l2->C); - printf("line_interpt- lines intersect at (%.*g,%.*g)\n", digits8, x, digits8, y); + DBL_DIG, l1->A, DBL_DIG, l1->B, DBL_DIG, l1->C, DBL_DIG, l2->A, DBL_DIG, l2->B, DBL_DIG, l2->C); + printf("line_interpt- lines intersect at (%.*g,%.*g)\n", DBL_DIG, x, DBL_DIG, y); #endif return result; @@ -2381,14 +2390,14 @@ interpt_sl(LSEG *lseg, LINE *line) p = line_interpt_internal(&tmp, line); #ifdef GEODEBUG printf("interpt_sl- segment is (%.*g %.*g) (%.*g %.*g)\n", - digits8, lseg->p[0].x, digits8, lseg->p[0].y, digits8, lseg->p[1].x, digits8, lseg->p[1].y); + DBL_DIG, lseg->p[0].x, DBL_DIG, lseg->p[0].y, DBL_DIG, lseg->p[1].x, DBL_DIG, lseg->p[1].y); printf("interpt_sl- segment becomes line A=%.*g B=%.*g C=%.*g\n", - digits8, tmp.A, digits8, tmp.B, digits8, tmp.C); + DBL_DIG, tmp.A, DBL_DIG, tmp.B, DBL_DIG, tmp.C); #endif if (PointerIsValid(p)) { #ifdef GEODEBUG - printf("interpt_sl- intersection point is (%.*g %.*g)\n", digits8, p->x, digits8, p->y); + printf("interpt_sl- intersection point is (%.*g %.*g)\n", DBL_DIG, p->x, DBL_DIG, p->y); #endif if (on_ps_internal(p, lseg)) { @@ -3940,7 +3949,7 @@ circle_out(PG_FUNCTION_ARGS) char *result; char *cp; - result = palloc(3 * (P_MAXLEN + 1) + 3); + result = palloc(2 * P_MAXLEN + 6); cp = result; *cp++ = LDELIM_C; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 48c3cdb4bf..ac1c97fedf 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5,7 +5,7 @@ * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.99 2002/11/01 22:52:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.100 2002/11/08 17:37:52 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -680,6 +680,11 @@ static struct config_int 5, 1, 1000, NULL, NULL }, + { + {"extra_float_digits", PGC_USERSET}, &extra_float_digits, + 0, -15, 2, NULL, NULL + }, + { {NULL, 0}, NULL, 0, 0, 0, NULL, NULL } diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c597342263..ee721a358a 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -127,7 +127,7 @@ #log_duration = false #log_timestamp = false -#log_min_error_statement = error # Values in order of increasing severity: +#log_min_error_statement = error # Values in order of increasing severity: # debug5, debug4, debug3, debug2, debug1, # info, notice, warning, error #debug_print_parse = false @@ -198,6 +198,7 @@ #authentication_timeout = 60 # 1-600, in seconds #deadlock_timeout = 1000 # in milliseconds #default_transaction_isolation = 'read committed' +#extra_float_digits = 0 # min -15, max 2 #max_expr_depth = 10000 # min 10 #max_files_per_process = 1000 # min 25 #password_encryption = true diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 0b9a1e8b7a..2b111bdce5 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -22,7 +22,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.305 2002/10/22 19:15:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.306 2002/11/08 17:37:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -171,6 +171,7 @@ main(int argc, char **argv) const char *pgport = NULL; const char *username = NULL; bool oids = false; + PGresult *res; TableInfo *tblinfo; int numTables; bool force_password = false; @@ -549,22 +550,32 @@ main(int argc, char **argv) /* * Start serializable transaction to dump consistent data. */ + res = PQexec(g_conn, "BEGIN"); + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + exit_horribly(g_fout, NULL, "BEGIN command failed: %s", + PQerrorMessage(g_conn)); + PQclear(res); + + res = PQexec(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + exit_horribly(g_fout, NULL, "could not set transaction isolation level to serializable: %s", + PQerrorMessage(g_conn)); + PQclear(res); + + /* + * If supported, set extra_float_digits so that we can dump float data + * exactly (given correctly implemented float I/O code, anyway) + */ + if (g_fout->remoteVersion >= 70400) { - PGresult *res; - - res = PQexec(g_conn, "BEGIN"); + res = PQexec(g_conn, "SET extra_float_digits TO 2"); if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) - exit_horribly(g_fout, NULL, "BEGIN command failed: %s", - PQerrorMessage(g_conn)); - PQclear(res); - - res = PQexec(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); - if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) - exit_horribly(g_fout, NULL, "could not set transaction isolation level to serializable: %s", + exit_horribly(g_fout, NULL, "could not set extra_float_digits: %s", PQerrorMessage(g_conn)); PQclear(res); } + /* Find the last built-in OID, if needed */ if (g_fout->remoteVersion < 70300) { if (g_fout->remoteVersion >= 70100) diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index ce4a2b5a80..4b3e4c13a9 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.64 2002/09/04 20:31:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.65 2002/11/08 17:37:52 tgl Exp $ */ /*---------------------------------------------------------------------- @@ -261,6 +261,7 @@ psql_completion(char *text, int start, int end) "max_expr_depth", "commit_delay", "commit_siblings", + "extra_float_digits", "effective_cache_size", "random_page_cost", diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index a933520daa..f134bdb495 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.204 2002/11/02 18:41:22 tgl Exp $ + * $Id: builtins.h,v 1.205 2002/11/08 17:37:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -212,6 +212,8 @@ extern Datum btnamecmp(PG_FUNCTION_ARGS); extern Datum bttextcmp(PG_FUNCTION_ARGS); /* float.c */ +extern int extra_float_digits; + extern Datum float4in(PG_FUNCTION_ARGS); extern Datum float4out(PG_FUNCTION_ARGS); extern Datum float8in(PG_FUNCTION_ARGS);