diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index bf61fd7dbc0..2a296909492 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -4430,35 +4430,62 @@ int8_numeric(PG_FUNCTION_ARGS) PG_RETURN_NUMERIC(int64_to_numeric(val)); } +int64 +numeric_int8_opt_error(Numeric num, bool *have_error) +{ + NumericVar x; + int64 result; + + if (have_error) + *have_error = false; + + if (NUMERIC_IS_SPECIAL(num)) + { + if (have_error) + { + *have_error = true; + return 0; + } + else + { + if (NUMERIC_IS_NAN(num)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot convert NaN to %s", "bigint"))); + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot convert infinity to %s", "bigint"))); + } + } + + /* Convert to variable format, then convert to int8 */ + init_var_from_num(num, &x); + + if (!numericvar_to_int64(&x, &result)) + { + if (have_error) + { + *have_error = true; + return 0; + } + else + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("bigint out of range"))); + } + } + + return result; +} Datum numeric_int8(PG_FUNCTION_ARGS) { Numeric num = PG_GETARG_NUMERIC(0); - NumericVar x; - int64 result; - if (NUMERIC_IS_SPECIAL(num)) - { - if (NUMERIC_IS_NAN(num)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot convert NaN to %s", "bigint"))); - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot convert infinity to %s", "bigint"))); - } - - /* Convert to variable format and thence to int8 */ - init_var_from_num(num, &x); - - if (!numericvar_to_int64(&x, &result)) - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("bigint out of range"))); - - PG_RETURN_INT64(result); + PG_RETURN_INT64(numeric_int8_opt_error(num, NULL)); } diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h index 08e4f8c217d..0780b52094d 100644 --- a/src/include/utils/numeric.h +++ b/src/include/utils/numeric.h @@ -101,5 +101,6 @@ extern Numeric numeric_div_opt_error(Numeric num1, Numeric num2, extern Numeric numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error); extern int32 numeric_int4_opt_error(Numeric num, bool *have_error); +extern int64 numeric_int8_opt_error(Numeric num, bool *have_error); #endif /* _PG_NUMERIC_H_ */