Skip to content

Commit 82adaac

Browse files
authored
fix(query): fix months_between overflow error (#17403)
1 parent 855ecc8 commit 82adaac

File tree

3 files changed

+23
-14
lines changed

3 files changed

+23
-14
lines changed

src/query/expression/src/utils/date_helper.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -230,25 +230,17 @@ impl EvalMonthsImpl {
230230
.checked_add(SignedDuration::from_hours(date_b as i64 * 24))
231231
.unwrap();
232232

233-
let year_diff = date_a.year() - date_b.year();
234-
let month_diff = date_a.month() as i16 - date_b.month() as i16;
233+
let year_diff = (date_a.year() - date_b.year()) as i64;
234+
let month_diff = date_a.month() as i64 - date_b.month() as i64;
235235

236236
// Calculate total months difference
237237
let total_months_diff = year_diff * 12 + month_diff;
238238

239239
// Determine if special case for fractional part applies
240240
let is_same_day_of_month = date_a.day() == date_b.day();
241-
let are_both_end_of_month = date_a
242-
.checked_add(SignedDuration::from_hours(24))
243-
.unwrap()
244-
.month()
245-
!= date_a.month()
246-
&& date_b
247-
.checked_add(SignedDuration::from_hours(24))
248-
.unwrap()
249-
.month()
250-
!= date_b.month();
251241

242+
let are_both_end_of_month =
243+
date_a.last_of_month() == date_a && date_b.last_of_month() == date_b;
252244
let day_fraction = if is_same_day_of_month || are_both_end_of_month {
253245
0.0
254246
} else {

src/query/functions/src/scalars/timestamp/src/datetime.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,9 +1227,11 @@ fn register_diff_functions(registry: &mut FunctionRegistry) {
12271227
let rm = rhs.max;
12281228
let rn = rhs.min;
12291229

1230+
let min = EvalMonthsImpl::months_between(ln, rm);
1231+
let max = EvalMonthsImpl::months_between(lm, rn);
12301232
FunctionDomain::Domain(SimpleDomain::<F64> {
1231-
min: EvalMonthsImpl::months_between(ln, rm).into(),
1232-
max: EvalMonthsImpl::months_between(lm, rn).into(),
1233+
min: min.into(),
1234+
max: max.into(),
12331235
})
12341236
},
12351237
vectorize_2_arg::<DateType, DateType, Float64Type>(|a, b, _ctx| {

tests/sqllogictests/suites/query/functions/02_0012_function_datetimes.test

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,21 @@ select to_date('2023-01-01') - 100 = to_date('2022-09-23')
257257
----
258258
1
259259

260+
statement ok
261+
create or replace table t(mine_date date, birth_date date);
262+
263+
statement ok
264+
insert into t values('2022-01-01', '2022-01-01'),('2022-01-01', '2022-02-01'),('2022-02-01', '2022-01-01');
265+
266+
query T
267+
SELECT max(MONTHS_BETWEEN(mine_date, birth_date))/12 as demo_age FROM t GROUP BY mine_date order by demo_age;
268+
----
269+
0.0
270+
0.08333333333333333
271+
272+
statement ok
273+
drop table if exists t;
274+
260275
query FF
261276
SELECT
262277
MONTHS_BETWEEN('2019-03-15'::DATE,

0 commit comments

Comments
 (0)