Skip to content

Commit 41ba6b6

Browse files
authored
feat(query): interval support agg func sum (#17379)
* feat(query): interval support agg func sum * impl Add/AddAssign for months_days_micros
1 parent 19c0c73 commit 41ba6b6

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

src/common/column/src/types/native.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use std::cmp::Ordering;
1717
use std::convert::TryFrom;
1818
use std::hash::Hash;
1919
use std::hash::Hasher;
20+
use std::ops::Add;
21+
use std::ops::AddAssign;
2022
use std::ops::Neg;
2123
use std::panic::RefUnwindSafe;
2224

@@ -268,6 +270,26 @@ impl NativeType for days_ms {
268270
#[repr(C)]
269271
pub struct months_days_micros(pub i128);
270272

273+
impl Add for months_days_micros {
274+
type Output = Self;
275+
276+
fn add(self, rhs: Self) -> Self::Output {
277+
let add_months = self.months() + rhs.months();
278+
let add_days = self.days() + rhs.days();
279+
let add_micros = self.microseconds() + rhs.microseconds();
280+
Self::new(add_months, add_days, add_micros)
281+
}
282+
}
283+
284+
impl AddAssign for months_days_micros {
285+
fn add_assign(&mut self, rhs: Self) {
286+
let add_months = self.months() + rhs.months();
287+
let add_days = self.days() + rhs.days();
288+
let add_micros = self.microseconds() + rhs.microseconds();
289+
self.0 = months_days_micros::new(add_months, add_days, add_micros).0
290+
}
291+
}
292+
271293
impl Hash for months_days_micros {
272294
fn hash<H: Hasher>(&self, state: &mut H) {
273295
self.total_micros().hash(state)

src/query/functions/src/aggregates/aggregate_sum.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use boolean::TrueIdxIter;
1616
use borsh::BorshDeserialize;
1717
use borsh::BorshSerialize;
18+
use databend_common_column::types::months_days_micros;
1819
use databend_common_exception::ErrorCode;
1920
use databend_common_exception::Result;
2021
use databend_common_expression::types::decimal::*;
@@ -271,6 +272,63 @@ where
271272
}
272273
}
273274

275+
#[derive(BorshSerialize, BorshDeserialize, Default)]
276+
pub struct IntervalSumState {
277+
pub value: months_days_micros,
278+
}
279+
280+
impl UnaryState<IntervalType, IntervalType> for IntervalSumState {
281+
fn add(
282+
&mut self,
283+
other: months_days_micros,
284+
_function_data: Option<&dyn FunctionData>,
285+
) -> Result<()> {
286+
self.value += other;
287+
Ok(())
288+
}
289+
290+
fn add_batch(
291+
&mut self,
292+
other: Buffer<months_days_micros>,
293+
validity: Option<&Bitmap>,
294+
_function_data: Option<&dyn FunctionData>,
295+
) -> Result<()> {
296+
let col = IntervalType::upcast_column(other);
297+
let buffer = IntervalType::try_downcast_column(&col).unwrap();
298+
match validity {
299+
Some(validity) if validity.null_count() > 0 => {
300+
buffer.iter().zip(validity.iter()).for_each(|(t, b)| {
301+
if b {
302+
self.value += *t;
303+
}
304+
});
305+
}
306+
_ => {
307+
buffer.iter().for_each(|t| {
308+
self.value += *t;
309+
});
310+
}
311+
}
312+
313+
Ok(())
314+
}
315+
316+
fn merge(&mut self, rhs: &Self) -> Result<()> {
317+
let res = self.value.total_micros() + rhs.value.total_micros();
318+
self.value = months_days_micros(res as i128);
319+
Ok(())
320+
}
321+
322+
fn merge_result(
323+
&mut self,
324+
builder: &mut Vec<months_days_micros>,
325+
_function_data: Option<&dyn FunctionData>,
326+
) -> Result<()> {
327+
IntervalType::push_item(builder, IntervalType::to_scalar_ref(&self.value));
328+
Ok(())
329+
}
330+
}
331+
274332
pub fn try_create_aggregate_sum_function(
275333
display_name: &str,
276334
params: Vec<Scalar>,
@@ -323,6 +381,15 @@ pub fn try_create_aggregate_sum_function(
323381
)
324382
}
325383
}
384+
DataType::Interval => {
385+
let return_type = DataType::Interval;
386+
AggregateUnaryFunction::<IntervalSumState, IntervalType, IntervalType>::try_create_unary(
387+
display_name,
388+
return_type,
389+
params,
390+
arguments[0].clone(),
391+
)
392+
}
326393
DataType::Decimal(DecimalDataType::Decimal256(s)) => {
327394
let p = MAX_DECIMAL256_PRECISION;
328395
let decimal_size = DecimalSize {

tests/sqllogictests/suites/base/11_data_type/11_0007_data_type_interval.test

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,36 @@ with t as ( select to_weeks(weeks) + to_hours(hours) as i, weeks*168+hours as h
88

99
statement ok
1010
drop table test_r;
11+
12+
statement ok
13+
create or replace table t (c interval);
14+
15+
statement ok
16+
insert into t values('1 year'),('1 months'),('1 day'),('1 hour'),('1 minute'),('1 second'),('1 microsecond');
17+
18+
onlyif http
19+
query T
20+
select * from t order by c;
21+
----
22+
0:00:00.000001
23+
0:00:01
24+
0:01:00
25+
1:00:00
26+
1 day
27+
1 month
28+
1 year
29+
30+
onlyif http
31+
query T
32+
select sum(c) from t;
33+
----
34+
9385:01:01.000001
35+
36+
onlyif http
37+
query T
38+
select sum(c) from t where c <= interval '1 day';
39+
----
40+
25:01:01.000001
41+
42+
statement ok
43+
drop table t;

0 commit comments

Comments
 (0)