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) ||

Reply via email to