summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/float.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/float.c')
-rw-r--r--src/backend/utils/adt/float.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index eb111ee2dbf..37c202d21ca 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -21,6 +21,7 @@
#include "catalog/pg_type.h"
#include "common/int.h"
+#include "common/shortest_dec.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "utils/array.h"
@@ -30,8 +31,15 @@
#include "utils/timestamp.h"
-/* Configurable GUC parameter */
-int extra_float_digits = 0; /* Added to DBL_DIG or FLT_DIG */
+/*
+ * Configurable GUC parameter
+ *
+ * If >0, use shortest-decimal format for output; this is both the default and
+ * allows for compatibility with clients that explicitly set a value here to
+ * get round-trip-accurate results. If 0 or less, then use the old, slow,
+ * decimal rounding method.
+ */
+int extra_float_digits = 1;
/* Cached constants for degree-based trig functions */
static bool degree_consts_set = false;
@@ -282,6 +290,12 @@ float4out(PG_FUNCTION_ARGS)
char *ascii = (char *) palloc(32);
int ndig = FLT_DIG + extra_float_digits;
+ if (extra_float_digits > 0)
+ {
+ float_to_shortest_decimal_buf(num, ascii);
+ PG_RETURN_CSTRING(ascii);
+ }
+
(void) pg_strfromd(ascii, 32, ndig, num);
PG_RETURN_CSTRING(ascii);
}
@@ -498,6 +512,12 @@ float8out_internal(double num)
char *ascii = (char *) palloc(32);
int ndig = DBL_DIG + extra_float_digits;
+ if (extra_float_digits > 0)
+ {
+ double_to_shortest_decimal_buf(num, ascii);
+ return ascii;
+ }
+
(void) pg_strfromd(ascii, 32, ndig, num);
return ascii;
}