From c8a73786a7bb021cacd54a19979dd7399cb39286 Mon Sep 17 00:00:00 2001 From: Satarupa Biswas Date: Sun, 16 Apr 2023 07:32:29 +0000 Subject: [PATCH] Loss of decimal digits when converting from REAL to DECIMAL 123456.25 requires 37 bits ( > 4 bytes) to get stored without any dataloss. REAL datatype can store upto 4B of floating point data; anything larger than that gets truncated while casting by underlying PG functions. REAL datatype in sql server relaxes this storage restriction and hence can cast the entire data without any further dataloss. Task: BABEL-3066 Signed-off-by: Satarupa Biswas [satarupb@amazon.com] --- src/backend/utils/adt/numeric.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 246ad6b8058..d9e92696dd1 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -43,6 +43,7 @@ #include "utils/numeric.h" #include "utils/pg_lsn.h" #include "utils/sortsupport.h" +#include "common/shortest_dec.h" /* ---------- * Uncomment the following to enable compilation of dump_numeric() @@ -4535,7 +4536,15 @@ float4_numeric(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(make_result(&const_pinf)); } - snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val); + /* + * REAL datatype can store upto 4B of floating point data; + * anything larger than that gets truncated unless + * buf has extra places to store those extra_float_digits + */ + if (sql_dialect == SQL_DIALECT_TSQL && extra_float_digits > 0) + float_to_shortest_decimal_buf(val, buf); + else + snprintf(buf, sizeof(buf), "%.*g", FLT_DIG, val); init_var(&result);