Hi,

Currently, numeric_pg_lsn is the only one that accepts the Numeric
value and converts to uint64 and that is the reason all the type
conversion code is embedded into it.

I think it would be helpful if that numeric-to-uint64 conversion code
is extracted as a separate function so that any other SQL function
like numeric_pg_lsn which wants to accept values up to the uint64
range can use that function.

Thoughts? Comments?

--
Regards,
Amul Sul
EDB: http://www.enterprisedb.com
From 98feb2bb92d2534cccaea57cd9b9777193bacae4 Mon Sep 17 00:00:00 2001
From: Amul Sul <amul.sul@enterprisedb.com>
Date: Tue, 15 Feb 2022 23:57:26 -0500
Subject: [PATCH v1] Refactor numeric_pg_lsn

---
 src/backend/utils/adt/numeric.c | 54 +++++++++++++++++++++------------
 src/include/utils/numeric.h     |  1 +
 2 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 3208789f75e..7bb6c1d7f7c 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -4209,6 +4209,39 @@ int64_div_fast_to_numeric(int64 val1, int log10val2)
 	return res;
 }
 
+/*
+ * typeName is the user-visible type name of uint64 used for the error
+ * reporting.
+ */
+uint64
+numeric_to_uint64_type(Numeric num, char *typeName)
+{
+	NumericVar	x;
+	uint64		result;
+
+	if (NUMERIC_IS_SPECIAL(num))
+	{
+		if (NUMERIC_IS_NAN(num))
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("cannot convert NaN to %s", typeName)));
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("cannot convert infinity to %s", typeName)));
+	}
+
+	/* Convert to variable format and thence to pg_lsn */
+	init_var_from_num(num, &x);
+
+	if (!numericvar_to_uint64(&x, &result))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("%s out of range", typeName)));
+
+	return result;
+}
+
 Datum
 int4_numeric(PG_FUNCTION_ARGS)
 {
@@ -4545,28 +4578,9 @@ Datum
 numeric_pg_lsn(PG_FUNCTION_ARGS)
 {
 	Numeric		num = PG_GETARG_NUMERIC(0);
-	NumericVar	x;
 	XLogRecPtr	result;
 
-	if (NUMERIC_IS_SPECIAL(num))
-	{
-		if (NUMERIC_IS_NAN(num))
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("cannot convert NaN to %s", "pg_lsn")));
-		else
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("cannot convert infinity to %s", "pg_lsn")));
-	}
-
-	/* Convert to variable format and thence to pg_lsn */
-	init_var_from_num(num, &x);
-
-	if (!numericvar_to_uint64(&x, (uint64 *) &result))
-		ereport(ERROR,
-				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("pg_lsn out of range")));
+	result = (XLogRecPtr) numeric_to_uint64_type(num, "pg_lsn");
 
 	PG_RETURN_LSN(result);
 }
diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h
index 21cd5a5cbf5..1b9ad3b5b58 100644
--- a/src/include/utils/numeric.h
+++ b/src/include/utils/numeric.h
@@ -74,6 +74,7 @@ extern char *numeric_normalize(Numeric num);
 
 extern Numeric int64_to_numeric(int64 val);
 extern Numeric int64_div_fast_to_numeric(int64 val1, int log10val2);
+extern uint64 numeric_to_uint64_type(Numeric num, char *typeName);
 
 extern Numeric numeric_add_opt_error(Numeric num1, Numeric num2,
 									 bool *have_error);
-- 
2.18.0

Reply via email to