diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c --- a/src/backend/access/brin/brin_minmax_multi.c +++ b/src/backend/access/brin/brin_minmax_multi.c @@ -69,6 +69,7 @@ #include "catalog/pg_am.h" #include "catalog/pg_amop.h" #include "catalog/pg_type.h" +#include "nodes/miscnodes.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/date.h" @@ -77,6 +78,7 @@ #include "utils/inet.h" #include "utils/lsyscache.h" #include "utils/memutils.h" +#include "utils/numeric.h" #include "utils/pg_lsn.h" #include "utils/rel.h" #include "utils/syscache.h" @@ -2018,19 +2020,38 @@ brin_minmax_multi_distance_tid(PG_FUNCTION_ARGS) Datum brin_minmax_multi_distance_numeric(PG_FUNCTION_ARGS) { - Datum d; - Datum a1 = PG_GETARG_DATUM(0); - Datum a2 = PG_GETARG_DATUM(1); + Numeric a1 = PG_GETARG_NUMERIC(0); + Numeric a2 = PG_GETARG_NUMERIC(1); + Numeric d; + float8 distance; + ErrorSaveContext escontext = {T_ErrorSaveContext}; /* * We know the values are range boundaries, but the range may be collapsed * (i.e. single points), with equal values. */ - Assert(DatumGetBool(DirectFunctionCall2(numeric_le, a1, a2))); + Assert(DatumGetBool(DirectFunctionCall2(numeric_le, + NumericGetDatum(a1), NumericGetDatum(a2)))); + + /* + * Distances only guide range merging, so approximations are sufficient. + * Even with finite endpoints, their difference can overflow numeric. As + * the endpoints are ordered, such a difference is positive. + */ + d = numeric_sub_safe(a2, a1, (Node *) &escontext); + if (SOFT_ERROR_OCCURRED(&escontext)) + distance = get_float8_infinity(); + else + { + distance = DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow, + NumericGetDatum(d))); + pfree(d); + } - d = DirectFunctionCall2(numeric_sub, a2, a1); /* a2 - a1 */ + PG_FREE_IF_COPY(a1, 0); + PG_FREE_IF_COPY(a2, 1); - PG_RETURN_DATUM(DirectFunctionCall1(numeric_float8, d)); + PG_RETURN_FLOAT8(distance); } /*