Re: Fix for edge case in date_bin() function

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Moaaz Assali <ma5679(at)nyu(dot)edu>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Fix for edge case in date_bin() function
Date: 2024-02-27 19:13:08
Message-ID: 2142059.1709061188@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I wrote:
> Hmm, yeah. The "stride_usecs > 1" test seems like it's a partial
> attempt to account for this that is probably redundant given the
> additional condition. Also, can we avoid computing tm_diff %
> stride_usecs twice? Maybe the compiler is smart enough to remove the
> common subexpression, but it's a mighty expensive computation if not.

I think we could do it like this:

tm_diff = timestamp - origin;
tm_modulo = tm_diff % stride_usecs;
tm_delta = tm_diff - tm_modulo;
/* We want to round towards -infinity when tm_diff is negative */
if (tm_modulo < 0)
tm_delta -= stride_usecs;

Excluding tm_modulo == 0 from the correction is what fixes the
problem.

> I'm also itching a bit over whether there are integer-overflow
> hazards here. Maybe the range of timestamp is constrained enough
> that there aren't, but I didn't look hard.

Hmm, it's not. For instance this triggers the overflow check in
timestamp_mi:

regression=# select '294000-01-01'::timestamp - '4714-11-24 00:00:00 BC';
ERROR: interval out of range
regression=# \errverbose
ERROR: 22008: interval out of range
LOCATION: timestamp_mi, timestamp.c:2832

So we ought to guard the subtraction that produces tm_diff similarly.
I suspect it's also possible to overflow int64 while computing
stride_usecs.

regards, tom lane

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Nathan Bossart 2024-02-27 19:23:22 Re: Allow non-superuser to cancel superuser tasks.
Previous Message Nathan Bossart 2024-02-27 19:12:35 Re: Allow non-superuser to cancel superuser tasks.