From: | Ashutosh Bapat <ashutosh(dot)bapat(dot)oss(at)gmail(dot)com> |
---|---|
To: | Joseph Koshakow <koshy44(at)gmail(dot)com> |
Cc: | "Gregory Stark (as CFM)" <stark(dot)cfm(at)gmail(dot)com>, jian he <jian(dot)universality(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
Subject: | Re: Infinite Interval |
Date: | 2023-03-28 13:38:40 |
Message-ID: | CAExHW5sBtOGbHZ05dWQ6XtdFRS63dvM7pKaMTFw4jkkTyi4nOw@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
On Sun, Mar 19, 2023 at 12:18 AM Joseph Koshakow <koshy44(at)gmail(dot)com> wrote:
>
> The problem is that `secs = rint(secs)` rounds the seconds too early
> and loses any fractional seconds. Do we have an overflow detecting
> multiplication function for floats?
We have float8_mul() which checks for overflow. typedef double float8;
>
> > + if (INTERVAL_NOT_FINITE(result))
> > + ereport(ERROR,
> > + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
> > + errmsg("interval out of range")));
> >
> > Probably, I added these kind of checks. But I don't remember if those are
> > defensive checks or whether it's really possible that the arithmetic above
> > these lines can yield an non-finite interval.
>
> These checks appear in `make_interval`, `justify_X`,
> `interval_um_internal`, `interval_pl`, `interval_mi`, `interval_mul`,
> `interval_div`. For all of these it's possible that the interval
> overflows/underflows the non-finite ranges, but does not
> overflow/underflow the data type. For example
> `SELECT INTERVAL '2147483646 months' + INTERVAL '1 month'` would error
> on this check.
Without this patch
postgres(at)64807=#SELECT INTERVAL '2147483646 months' + INTERVAL '1 month';
?column?
------------------------
178956970 years 7 mons
(1 row)
That result looks correct
postgres(at)64807=#select 178956970 * 12 + 7;
?column?
------------
2147483647
(1 row)
So some backward compatibility break. I don't think we can avoid the
backward compatibility break without expanding interval structure and
thus causing on-disk breakage. But we can reduce the chances of
breaking, if we change INTERVAL_NOT_FINITE to check all the three
fields, instead of just month.
>
>
> > + else
> > + {
> > + result->time = -interval->time;
> > + result->day = -interval->day;
> > + result->month = -interval->month;
> > +
> > + if (INTERVAL_NOT_FINITE(result))
> > + ereport(ERROR,
> > + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
> > + errmsg("interval out of range")));
> >
> > If this error ever gets to the user, it could be confusing. Can we elaborate by
> > adding context e.g. errcontext("while negating an interval") or some such?
>
> Done.
Thanks. Can we add relevant contexts at similar other places?
Also if we use all the three fields, we will need to add such checks
in interval_justify_hours()
>
> I replaced these checks with the following:
>
> + else if (interval->time == PG_INT64_MIN || interval->day == PG_INT32_MIN || interval->month == PG_INT32_MIN)
> + ereport(ERROR,
> + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
> + errmsg("interval out of range")));
>
> I think this covers the same overflow check but is maybe a bit more
> obvious. Unless, there's something I'm missing?
Thanks. Your current version is closer to int4um().
Some more review comments in the following email.
--
Best Wishes,
Ashutosh Bapat
From | Date | Subject | |
---|---|---|---|
Next Message | Erik Rijkers | 2023-03-28 13:40:24 | Re: SQL/JSON revisited |
Previous Message | Jeff Davis | 2023-03-28 13:30:00 | Re: Add standard collation UNICODE |