Skip to content

Commit fe42dd7

Browse files
authored
add min/max for time (#3178)
1 parent c0d5e23 commit fe42dd7

3 files changed

Lines changed: 64 additions & 4 deletions

File tree

datafusion/core/tests/sql/aggregates.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,25 @@ async fn aggregate_timestamps_avg() -> Result<()> {
14561456
Ok(())
14571457
}
14581458

1459+
#[tokio::test]
1460+
async fn aggregate_time_min_and_max() -> Result<()> {
1461+
let ctx = SessionContext::new();
1462+
1463+
let sql = "select min(t), max(t) from (select '00:00:00' as t union select '00:00:01' union select '00:00:02');";
1464+
let results = execute_to_batches(&ctx, sql).await;
1465+
let expected = vec![
1466+
"+----------+----------+",
1467+
"| MIN(t) | MAX(t) |",
1468+
"+----------+----------+",
1469+
"| 00:00:00 | 00:00:02 |",
1470+
"+----------+----------+",
1471+
];
1472+
1473+
assert_batches_eq!(expected, &results);
1474+
1475+
Ok(())
1476+
}
1477+
14591478
#[tokio::test]
14601479
async fn aggregate_decimal_min() -> Result<()> {
14611480
let ctx = SessionContext::new();

datafusion/expr/src/aggregate_function.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ pub static TIMESTAMPS: &[DataType] = &[
4949

5050
pub static DATES: &[DataType] = &[DataType::Date32, DataType::Date64];
5151

52+
pub static TIMES: &[DataType] = &[
53+
DataType::Time32(TimeUnit::Second),
54+
DataType::Time32(TimeUnit::Millisecond),
55+
DataType::Time64(TimeUnit::Microsecond),
56+
DataType::Time64(TimeUnit::Nanosecond),
57+
];
58+
5259
/// Enum of all built-in aggregate functions
5360
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
5461
pub enum AggregateFunction {
@@ -354,6 +361,7 @@ pub fn signature(fun: &AggregateFunction) -> Signature {
354361
.chain(NUMERICS.iter())
355362
.chain(TIMESTAMPS.iter())
356363
.chain(DATES.iter())
364+
.chain(TIMES.iter())
357365
.cloned()
358366
.collect::<Vec<_>>();
359367
Signature::uniform(1, valid, Volatility::Immutable)

datafusion/physical-expr/src/aggregate/min_max.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ use arrow::{
2828
array::{
2929
ArrayRef, BasicDecimalArray, Date32Array, Date64Array, Float32Array,
3030
Float64Array, Int16Array, Int32Array, Int64Array, Int8Array, LargeStringArray,
31-
StringArray, TimestampMicrosecondArray, TimestampMillisecondArray,
32-
TimestampNanosecondArray, TimestampSecondArray, UInt16Array, UInt32Array,
33-
UInt64Array, UInt8Array,
31+
StringArray, Time64NanosecondArray, TimestampMicrosecondArray,
32+
TimestampMillisecondArray, TimestampNanosecondArray, TimestampSecondArray,
33+
UInt16Array, UInt32Array, UInt64Array, UInt8Array,
3434
},
3535
datatypes::Field,
3636
};
@@ -257,6 +257,9 @@ macro_rules! min_max_batch {
257257
),
258258
DataType::Date32 => typed_min_max_batch!($VALUES, Date32Array, Date32, $OP),
259259
DataType::Date64 => typed_min_max_batch!($VALUES, Date64Array, Date64, $OP),
260+
DataType::Time64(TimeUnit::Nanosecond) => {
261+
typed_min_max_batch!($VALUES, Time64NanosecondArray, Time64, $OP)
262+
}
260263
other => {
261264
// This should have been handled before
262265
return Err(DataFusionError::Internal(format!(
@@ -433,12 +436,18 @@ macro_rules! min_max {
433436
) => {
434437
typed_min_max!(lhs, rhs, Date32, $OP)
435438
}
436-
(
439+
(
437440
ScalarValue::Date64(lhs),
438441
ScalarValue::Date64(rhs),
439442
) => {
440443
typed_min_max!(lhs, rhs, Date64, $OP)
441444
}
445+
(
446+
ScalarValue::Time64(lhs),
447+
ScalarValue::Time64(rhs),
448+
) => {
449+
typed_min_max!(lhs, rhs, Time64, $OP)
450+
}
442451
e => {
443452
return Err(DataFusionError::Internal(format!(
444453
"MIN/MAX is not expected to receive scalars of incompatible types {:?}",
@@ -1190,4 +1199,28 @@ mod tests {
11901199
DataType::Date64
11911200
)
11921201
}
1202+
1203+
#[test]
1204+
fn min_time64() -> Result<()> {
1205+
let a: ArrayRef = Arc::new(Time64NanosecondArray::from(vec![1, 2, 3, 4, 5]));
1206+
generic_test_op!(
1207+
a,
1208+
DataType::Time64(TimeUnit::Nanosecond),
1209+
Max,
1210+
ScalarValue::Time64(Some(5)),
1211+
DataType::Time64(TimeUnit::Nanosecond)
1212+
)
1213+
}
1214+
1215+
#[test]
1216+
fn max_time64() -> Result<()> {
1217+
let a: ArrayRef = Arc::new(Time64NanosecondArray::from(vec![1, 2, 3, 4, 5]));
1218+
generic_test_op!(
1219+
a,
1220+
DataType::Time64(TimeUnit::Nanosecond),
1221+
Max,
1222+
ScalarValue::Time64(Some(5)),
1223+
DataType::Time64(TimeUnit::Nanosecond)
1224+
)
1225+
}
11931226
}

0 commit comments

Comments
 (0)