I hurried too much on the previous patch. It introduced other problems. Attached is a better patch and also fixes problem below #select 'infinity'::interval * 0; ?column? ---------- infinity (1 row)
with the patch we see #select 'infinity'::interval * 0; 2023-03-31 18:00:43.131 IST [240892] ERROR: interval out of range 2023-03-31 18:00:43.131 IST [240892] STATEMENT: select 'infinity'::interval * 0; ERROR: interval out of range which looks more appropriate given 0 * inf = Nan for float. There's some way to avoid separate checks for infinite-ness of interval and factor and use a single block using some integer arithmetic. But I think this is more readable. So I avoided doing that. Let me know if this works for you. Also added some test cases. -- Best Wishes, Ashutosh Bapat On Fri, Mar 31, 2023 at 3:46 PM Ashutosh Bapat <ashutosh.bapat....@gmail.com> wrote: > > On Tue, Mar 28, 2023 at 7:17 PM Ashutosh Bapat > <ashutosh.bapat....@gmail.com> wrote: > > make sure that every > > operator that interval as one of its operands or the result has been > > covered in the code. > > time_mi_time - do we want to add an Assert to make sure that this > function does not produce an Interval structure which looks like > non-finite interval? > > multiplying an interval by infinity throws an error > #select '5 days'::interval * 'infinity'::float8; > 2023-03-29 19:40:15.797 IST [136240] ERROR: interval out of range > 2023-03-29 19:40:15.797 IST [136240] STATEMENT: select '5 > days'::interval * 'infinity'::float8; > ERROR: interval out of range > > I think this should produce an infinite interval now. Attached patch > to fix this, to be applied on top of your patch. With the patch > #select '5 days'::interval * 'infinity'::float8; > ?column? > ---------- > infinity > (1 row) > > Going through the tests now. > > -- > Best Wishes, > Ashutosh Bapat
commit 29d8501bb0e1b727abc81e862185770fd8e3a6c9 Author: Ashutosh Bapat <ashutosh.ba...@enterprisedb.com> Date: Fri Mar 31 18:02:25 2023 +0530 fixup! Add infinite interval values diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index c006e27dc0..cd05c61de3 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -3566,6 +3566,7 @@ interval_mul(PG_FUNCTION_ARGS) int32 orig_month = span->month, orig_day = span->day; Interval *result; + int is_factor_inf = isinf(factor); result = (Interval *) palloc(sizeof(Interval)); @@ -3580,12 +3581,35 @@ interval_mul(PG_FUNCTION_ARGS) */ if (INTERVAL_NOT_FINITE(span)) { - if (factor < 0.0) + if (factor == 0.0) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("interval out of range"))); + else if (factor < 0.0) interval_um_internal(span, result); else memcpy(result, span, sizeof(Interval)); PG_RETURN_INTERVAL_P(result); } + else if (is_factor_inf) + { + Interval zero; + int result_is_inf; + + memset(&zero, 0, sizeof(zero)); + result_is_inf = interval_cmp_internal(span, &zero) * is_factor_inf; + + if (result_is_inf == 0) + ereport(ERROR, + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), + errmsg("interval out of range"))); + else if (result_is_inf < 0) + INTERVAL_NOBEGIN(result); + else + INTERVAL_NOEND(result); + + PG_RETURN_INTERVAL_P(result); + } result_double = span->month * factor; if (isnan(result_double) ||