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