Skip to content

Commit 2b10e0e

Browse files
committed
Fix BRIN minmax-multi distance for interval type
The distance calculation for interval type was treating months as having 31 days, which is inconsistent with the interval comparator (using 30 days). Due to this it was possible to get negative distance (b-a) when (a<b), trigerring an assert. Fixed by adopting the same logic as interval_cmp_value. Reported-by: Jaime Casanova Discussion: https://postgr.es/m/CAJKUy5jKH0Xhneau2mNftNPtTy-BVgQfXc8zQkEvRvBHfeUThQ%40mail.gmail.com
1 parent 55873a0 commit 2b10e0e

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

src/backend/access/brin/brin_minmax_multi.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,6 +2127,9 @@ brin_minmax_multi_distance_interval(PG_FUNCTION_ARGS)
21272127
Interval *ib = PG_GETARG_INTERVAL_P(1);
21282128
Interval *result;
21292129

2130+
int64 dayfraction;
2131+
int64 days;
2132+
21302133
result = (Interval *) palloc(sizeof(Interval));
21312134

21322135
result->month = ib->month - ia->month;
@@ -2152,16 +2155,18 @@ brin_minmax_multi_distance_interval(PG_FUNCTION_ARGS)
21522155
errmsg("interval out of range")));
21532156

21542157
/*
2155-
* We assume months have 31 days - we don't need to be precise, in the
2156-
* worst case we'll build somewhat less efficient ranges.
2158+
* Delta is (fractional) number of days between the intervals. Assume
2159+
* months have 30 days for consistency with interval_cmp_internal.
2160+
* We don't need to be exact, in the worst case we'll build a bit less
2161+
* efficient ranges. But we should not contradict interval_cmp.
21572162
*/
2158-
delta = (float8) (result->month * 31 + result->day);
2159-
2160-
/* convert to microseconds (just like the time part) */
2161-
delta = 24L * 3600L * delta;
2163+
dayfraction = result->time % USECS_PER_DAY;
2164+
days = result->time / USECS_PER_DAY;
2165+
days += result->month * INT64CONST(30);
2166+
days += result->day;
21622167

2163-
/* and add the time part */
2164-
delta += result->time / (float8) 1000000.0;
2168+
/* convert to double precision */
2169+
delta = (double) days + dayfraction / (double) USECS_PER_DAY;
21652170

21662171
Assert(delta >= 0);
21672172

0 commit comments

Comments
 (0)