From b0eb5c832864e6f754d1fcdd28134025861035bd Mon Sep 17 00:00:00 2001
From: Amul Sul <amul.sul@enterprisedb.com>
Date: Fri, 22 Apr 2022 02:54:20 -0400
Subject: [PATCH v2 4/5] Add float8_to_numeric and numeric_to_float8 by code
 refactoring

---
 contrib/jsonb_plperl/jsonb_plperl.c         |   4 +-
 src/backend/access/brin/brin_minmax_multi.c |   2 +-
 src/backend/utils/adt/jsonb.c               |   7 +-
 src/backend/utils/adt/jsonpath_exec.c       |   4 +-
 src/backend/utils/adt/numeric.c             | 106 +++++++++++---------
 src/backend/utils/adt/rangetypes.c          |   4 +-
 src/include/utils/numeric.h                 |   2 +
 7 files changed, 71 insertions(+), 58 deletions(-)

diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c
index 22e90afe1b6..cd645e57b22 100644
--- a/contrib/jsonb_plperl/jsonb_plperl.c
+++ b/contrib/jsonb_plperl/jsonb_plperl.c
@@ -238,9 +238,7 @@ SV_to_JsonbValue(SV *in, JsonbParseState **jsonb_state, bool is_elem)
 							 errmsg("cannot convert NaN to jsonb")));
 
 				out.type = jbvNumeric;
-				out.val.numeric =
-					DatumGetNumeric(DirectFunctionCall1(float8_numeric,
-														Float8GetDatum(nval)));
+				out.val.numeric = float8_to_numeric(nval);
 			}
 			else if (SvPOK(in))
 			{
diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index 10d4f17bc6f..764efa381f2 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -2020,7 +2020,7 @@ brin_minmax_multi_distance_numeric(PG_FUNCTION_ARGS)
 
 	d = DirectFunctionCall2(numeric_sub, a2, a1);	/* a2 - a1 */
 
-	PG_RETURN_FLOAT8(DirectFunctionCall1(numeric_float8, d));
+	PG_RETURN_FLOAT8(numeric_to_float8(DatumGetNumeric(d)));
 }
 
 /*
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 58f45afb9e2..7b295c199d8 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -2209,17 +2209,16 @@ jsonb_float8(PG_FUNCTION_ARGS)
 {
 	Jsonb	   *in = PG_GETARG_JSONB_P(0);
 	JsonbValue	v;
-	Datum		retValue;
+	float8		retValue;
 
 	if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
 		cannotCastJsonbValue(v.type, "double precision");
 
-	retValue = DirectFunctionCall1(numeric_float8,
-								   NumericGetDatum(v.val.numeric));
+	retValue = numeric_to_float8(v.val.numeric);
 
 	PG_FREE_IF_COPY(in, 0);
 
-	PG_RETURN_DATUM(retValue);
+	PG_RETURN_FLOAT8(retValue);
 }
 
 /*
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 2544c6b1551..8320a7d8249 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -1150,8 +1150,8 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
 
 					jb = &jbv;
 					jb->type = jbvNumeric;
-					jb->val.numeric = DatumGetNumeric(DirectFunctionCall1(float8_numeric,
-																		  Float8GetDatum(val)));
+					jb->val.numeric = float8_to_numeric(val);
+
 					res = jperOk;
 				}
 
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index d4970e572aa..d83fe5a326d 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -4283,6 +4283,64 @@ numeric_to_uint64_type(Numeric num, char *typeName)
 	return result;
 }
 
+Numeric
+float8_to_numeric(float8 val)
+{
+	Numeric		res;
+	NumericVar	result;
+	char		buf[DBL_DIG + 100];
+
+	if (isnan(val))
+		return make_result(&const_nan);
+
+	if (isinf(val))
+	{
+		if (val < 0)
+			return make_result(&const_ninf);
+		else
+			return make_result(&const_pinf);
+	}
+
+	snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
+
+	init_var(&result);
+
+	/* Assume we need not worry about leading/trailing spaces */
+	(void) set_var_from_str(buf, buf, &result);
+
+	res = make_result(&result);
+
+	free_var(&result);
+
+	return res;
+}
+
+float8
+numeric_to_float8(Numeric num)
+{
+	char	   *tmp;
+	Datum		result;
+
+	if (NUMERIC_IS_SPECIAL(num))
+	{
+		if (NUMERIC_IS_PINF(num))
+			return get_float8_infinity();
+		else if (NUMERIC_IS_NINF(num))
+			return -get_float8_infinity();
+		else
+			return get_float8_nan();
+	}
+
+	tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
+											  NumericGetDatum(num)));
+
+	result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
+
+	pfree(tmp);
+
+	return DatumGetFloat8(result);
+}
+
 Datum
 int4_numeric(PG_FUNCTION_ARGS)
 {
@@ -4464,33 +4522,8 @@ Datum
 float8_numeric(PG_FUNCTION_ARGS)
 {
 	float8		val = PG_GETARG_FLOAT8(0);
-	Numeric		res;
-	NumericVar	result;
-	char		buf[DBL_DIG + 100];
-
-	if (isnan(val))
-		PG_RETURN_NUMERIC(make_result(&const_nan));
-
-	if (isinf(val))
-	{
-		if (val < 0)
-			PG_RETURN_NUMERIC(make_result(&const_ninf));
-		else
-			PG_RETURN_NUMERIC(make_result(&const_pinf));
-	}
 
-	snprintf(buf, sizeof(buf), "%.*g", DBL_DIG, val);
-
-	init_var(&result);
-
-	/* Assume we need not worry about leading/trailing spaces */
-	(void) set_var_from_str(buf, buf, &result);
-
-	res = make_result(&result);
-
-	free_var(&result);
-
-	PG_RETURN_NUMERIC(res);
+	PG_RETURN_NUMERIC(float8_to_numeric(val));
 }
 
 
@@ -4498,27 +4531,8 @@ Datum
 numeric_float8(PG_FUNCTION_ARGS)
 {
 	Numeric		num = PG_GETARG_NUMERIC(0);
-	char	   *tmp;
-	Datum		result;
 
-	if (NUMERIC_IS_SPECIAL(num))
-	{
-		if (NUMERIC_IS_PINF(num))
-			PG_RETURN_FLOAT8(get_float8_infinity());
-		else if (NUMERIC_IS_NINF(num))
-			PG_RETURN_FLOAT8(-get_float8_infinity());
-		else
-			PG_RETURN_FLOAT8(get_float8_nan());
-	}
-
-	tmp = DatumGetCString(DirectFunctionCall1(numeric_out,
-											  NumericGetDatum(num)));
-
-	result = DirectFunctionCall1(float8in, CStringGetDatum(tmp));
-
-	pfree(tmp);
-
-	PG_RETURN_DATUM(result);
+	PG_RETURN_FLOAT8(numeric_to_float8(num));
 }
 
 
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index aa4c53e0ae1..8fb67387cc5 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -41,6 +41,7 @@
 #include "utils/lsyscache.h"
 #include "utils/rangetypes.h"
 #include "utils/timestamp.h"
+#include "utils/numeric.h"
 
 
 /* fn_extra cache entry for one of the range I/O functions */
@@ -1577,8 +1578,7 @@ numrange_subdiff(PG_FUNCTION_ARGS)
 
 	numresult = DirectFunctionCall2(numeric_sub, v1, v2);
 
-	floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
-													 numresult));
+	floatresult = numeric_to_float8(DatumGetNumeric(numresult));
 
 	PG_RETURN_FLOAT8(floatresult);
 }
diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h
index 11814ad828e..16aba38034e 100644
--- a/src/include/utils/numeric.h
+++ b/src/include/utils/numeric.h
@@ -77,6 +77,8 @@ extern int64 numeric_to_int64(Numeric num);
 extern int64 numeric_to_int64_type(Numeric num, char *typeName);
 extern Numeric int64_div_fast_to_numeric(int64 val1, int log10val2);
 extern uint64 numeric_to_uint64_type(Numeric num, char *typeName);
+extern Numeric float8_to_numeric(float8 val);
+extern float8 numeric_to_float8(Numeric num);
 
 extern Numeric numeric_add_opt_error(Numeric num1, Numeric num2,
 									 bool *have_error);
-- 
2.18.0

