diff --git a/datafusion/physical-expr/src/aggregate/min_max.rs b/datafusion/physical-expr/src/aggregate/min_max.rs index 95ae3207462e5..50bd24c487bfe 100644 --- a/datafusion/physical-expr/src/aggregate/min_max.rs +++ b/datafusion/physical-expr/src/aggregate/min_max.rs @@ -1103,509 +1103,3 @@ impl Accumulator for SlidingMinAccumulator { std::mem::size_of_val(self) - std::mem::size_of_val(&self.min) + self.min.size() } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::expressions::col; - use crate::expressions::tests::{aggregate, aggregate_new}; - use crate::{generic_test_op, generic_test_op_new}; - use arrow::datatypes::*; - use arrow::record_batch::RecordBatch; - use datafusion_common::ScalarValue::Decimal128; - - #[test] - fn min_decimal() -> Result<()> { - // min - let left = ScalarValue::Decimal128(Some(123), 10, 2); - let right = ScalarValue::Decimal128(Some(124), 10, 2); - let result = min(&left, &right)?; - assert_eq!(result, left); - - // min batch - let array: ArrayRef = Arc::new( - (1..6) - .map(Some) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - - let result = min_batch(&array)?; - assert_eq!(result, ScalarValue::Decimal128(Some(1), 10, 0)); - - // min batch without values - let array: ArrayRef = Arc::new( - std::iter::repeat::>(None) - .take(0) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - let result = min_batch(&array)?; - assert_eq!(ScalarValue::Decimal128(None, 10, 0), result); - - // min batch with agg - let array: ArrayRef = Arc::new( - (1..6) - .map(Some) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - generic_test_op!( - array, - DataType::Decimal128(10, 0), - Min, - ScalarValue::Decimal128(Some(1), 10, 0) - ) - } - - #[test] - fn min_decimal_all_nulls() -> Result<()> { - // min batch all nulls - let array: ArrayRef = Arc::new( - std::iter::repeat::>(None) - .take(6) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - generic_test_op!( - array, - DataType::Decimal128(10, 0), - Min, - ScalarValue::Decimal128(None, 10, 0) - ) - } - - #[test] - fn min_decimal_with_nulls() -> Result<()> { - // min batch with nulls - let array: ArrayRef = Arc::new( - (1..6) - .map(|i| if i == 2 { None } else { Some(i) }) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - - generic_test_op!( - array, - DataType::Decimal128(10, 0), - Min, - ScalarValue::Decimal128(Some(1), 10, 0) - ) - } - - #[test] - fn max_decimal() -> Result<()> { - // max - let left = ScalarValue::Decimal128(Some(123), 10, 2); - let right = ScalarValue::Decimal128(Some(124), 10, 2); - let result = max(&left, &right)?; - assert_eq!(result, right); - - let right = ScalarValue::Decimal128(Some(124), 10, 3); - let result = max(&left, &right); - let err_msg = format!( - "MIN/MAX is not expected to receive scalars of incompatible types {:?}", - (Decimal128(Some(123), 10, 2), Decimal128(Some(124), 10, 3)) - ); - let expect = DataFusionError::Internal(err_msg); - assert!(expect - .strip_backtrace() - .starts_with(&result.unwrap_err().strip_backtrace())); - - // max batch - let array: ArrayRef = Arc::new( - (1..6) - .map(Some) - .collect::() - .with_precision_and_scale(10, 5)?, - ); - let result = max_batch(&array)?; - assert_eq!(result, ScalarValue::Decimal128(Some(5), 10, 5)); - - // max batch without values - let array: ArrayRef = Arc::new( - std::iter::repeat::>(None) - .take(0) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - let result = max_batch(&array)?; - assert_eq!(ScalarValue::Decimal128(None, 10, 0), result); - - // max batch with agg - let array: ArrayRef = Arc::new( - (1..6) - .map(Some) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - generic_test_op!( - array, - DataType::Decimal128(10, 0), - Max, - ScalarValue::Decimal128(Some(5), 10, 0) - ) - } - - #[test] - fn max_decimal_with_nulls() -> Result<()> { - let array: ArrayRef = Arc::new( - (1..6) - .map(|i| if i == 2 { None } else { Some(i) }) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - generic_test_op!( - array, - DataType::Decimal128(10, 0), - Max, - ScalarValue::Decimal128(Some(5), 10, 0) - ) - } - - #[test] - fn max_decimal_all_nulls() -> Result<()> { - let array: ArrayRef = Arc::new( - std::iter::repeat::>(None) - .take(6) - .collect::() - .with_precision_and_scale(10, 0)?, - ); - generic_test_op!( - array, - DataType::Decimal128(10, 0), - Min, - ScalarValue::Decimal128(None, 10, 0) - ) - } - - #[test] - fn max_i32() -> Result<()> { - let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5])); - generic_test_op!(a, DataType::Int32, Max, ScalarValue::from(5i32)) - } - - #[test] - fn min_i32() -> Result<()> { - let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5])); - generic_test_op!(a, DataType::Int32, Min, ScalarValue::from(1i32)) - } - - #[test] - fn max_utf8() -> Result<()> { - let a: ArrayRef = Arc::new(StringArray::from(vec!["d", "a", "c", "b"])); - generic_test_op!(a, DataType::Utf8, Max, ScalarValue::from("d")) - } - - #[test] - fn max_large_utf8() -> Result<()> { - let a: ArrayRef = Arc::new(LargeStringArray::from(vec!["d", "a", "c", "b"])); - generic_test_op!( - a, - DataType::LargeUtf8, - Max, - ScalarValue::LargeUtf8(Some("d".to_string())) - ) - } - - #[test] - fn min_utf8() -> Result<()> { - let a: ArrayRef = Arc::new(StringArray::from(vec!["d", "a", "c", "b"])); - generic_test_op!(a, DataType::Utf8, Min, ScalarValue::from("a")) - } - - #[test] - fn min_large_utf8() -> Result<()> { - let a: ArrayRef = Arc::new(LargeStringArray::from(vec!["d", "a", "c", "b"])); - generic_test_op!( - a, - DataType::LargeUtf8, - Min, - ScalarValue::LargeUtf8(Some("a".to_string())) - ) - } - - #[test] - fn max_i32_with_nulls() -> Result<()> { - let a: ArrayRef = Arc::new(Int32Array::from(vec![ - Some(1), - None, - Some(3), - Some(4), - Some(5), - ])); - generic_test_op!(a, DataType::Int32, Max, ScalarValue::from(5i32)) - } - - #[test] - fn min_i32_with_nulls() -> Result<()> { - let a: ArrayRef = Arc::new(Int32Array::from(vec![ - Some(1), - None, - Some(3), - Some(4), - Some(5), - ])); - generic_test_op!(a, DataType::Int32, Min, ScalarValue::from(1i32)) - } - - #[test] - fn max_i32_all_nulls() -> Result<()> { - let a: ArrayRef = Arc::new(Int32Array::from(vec![None, None])); - generic_test_op!(a, DataType::Int32, Max, ScalarValue::Int32(None)) - } - - #[test] - fn min_i32_all_nulls() -> Result<()> { - let a: ArrayRef = Arc::new(Int32Array::from(vec![None, None])); - generic_test_op!(a, DataType::Int32, Min, ScalarValue::Int32(None)) - } - - #[test] - fn max_u32() -> Result<()> { - let a: ArrayRef = - Arc::new(UInt32Array::from(vec![1_u32, 2_u32, 3_u32, 4_u32, 5_u32])); - generic_test_op!(a, DataType::UInt32, Max, ScalarValue::from(5_u32)) - } - - #[test] - fn min_u32() -> Result<()> { - let a: ArrayRef = - Arc::new(UInt32Array::from(vec![1_u32, 2_u32, 3_u32, 4_u32, 5_u32])); - generic_test_op!(a, DataType::UInt32, Min, ScalarValue::from(1u32)) - } - - #[test] - fn max_f32() -> Result<()> { - let a: ArrayRef = - Arc::new(Float32Array::from(vec![1_f32, 2_f32, 3_f32, 4_f32, 5_f32])); - generic_test_op!(a, DataType::Float32, Max, ScalarValue::from(5_f32)) - } - - #[test] - fn min_f32() -> Result<()> { - let a: ArrayRef = - Arc::new(Float32Array::from(vec![1_f32, 2_f32, 3_f32, 4_f32, 5_f32])); - generic_test_op!(a, DataType::Float32, Min, ScalarValue::from(1_f32)) - } - - #[test] - fn max_f64() -> Result<()> { - let a: ArrayRef = - Arc::new(Float64Array::from(vec![1_f64, 2_f64, 3_f64, 4_f64, 5_f64])); - generic_test_op!(a, DataType::Float64, Max, ScalarValue::from(5_f64)) - } - - #[test] - fn min_f64() -> Result<()> { - let a: ArrayRef = - Arc::new(Float64Array::from(vec![1_f64, 2_f64, 3_f64, 4_f64, 5_f64])); - generic_test_op!(a, DataType::Float64, Min, ScalarValue::from(1_f64)) - } - - #[test] - fn min_date32() -> Result<()> { - let a: ArrayRef = Arc::new(Date32Array::from(vec![1, 2, 3, 4, 5])); - generic_test_op!(a, DataType::Date32, Min, ScalarValue::Date32(Some(1))) - } - - #[test] - fn min_date64() -> Result<()> { - let a: ArrayRef = Arc::new(Date64Array::from(vec![1, 2, 3, 4, 5])); - generic_test_op!(a, DataType::Date64, Min, ScalarValue::Date64(Some(1))) - } - - #[test] - fn max_date32() -> Result<()> { - let a: ArrayRef = Arc::new(Date32Array::from(vec![1, 2, 3, 4, 5])); - generic_test_op!(a, DataType::Date32, Max, ScalarValue::Date32(Some(5))) - } - - #[test] - fn max_date64() -> Result<()> { - let a: ArrayRef = Arc::new(Date64Array::from(vec![1, 2, 3, 4, 5])); - generic_test_op!(a, DataType::Date64, Max, ScalarValue::Date64(Some(5))) - } - - #[test] - fn min_time32second() -> Result<()> { - let a: ArrayRef = Arc::new(Time32SecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time32(TimeUnit::Second), - Min, - ScalarValue::Time32Second(Some(1)) - ) - } - - #[test] - fn max_time32second() -> Result<()> { - let a: ArrayRef = Arc::new(Time32SecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time32(TimeUnit::Second), - Max, - ScalarValue::Time32Second(Some(5)) - ) - } - - #[test] - fn min_time32millisecond() -> Result<()> { - let a: ArrayRef = Arc::new(Time32MillisecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time32(TimeUnit::Millisecond), - Min, - ScalarValue::Time32Millisecond(Some(1)) - ) - } - - #[test] - fn max_time32millisecond() -> Result<()> { - let a: ArrayRef = Arc::new(Time32MillisecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time32(TimeUnit::Millisecond), - Max, - ScalarValue::Time32Millisecond(Some(5)) - ) - } - - #[test] - fn min_time64microsecond() -> Result<()> { - let a: ArrayRef = Arc::new(Time64MicrosecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time64(TimeUnit::Microsecond), - Min, - ScalarValue::Time64Microsecond(Some(1)) - ) - } - - #[test] - fn max_time64microsecond() -> Result<()> { - let a: ArrayRef = Arc::new(Time64MicrosecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time64(TimeUnit::Microsecond), - Max, - ScalarValue::Time64Microsecond(Some(5)) - ) - } - - #[test] - fn min_time64nanosecond() -> Result<()> { - let a: ArrayRef = Arc::new(Time64NanosecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time64(TimeUnit::Nanosecond), - Min, - ScalarValue::Time64Nanosecond(Some(1)) - ) - } - - #[test] - fn max_time64nanosecond() -> Result<()> { - let a: ArrayRef = Arc::new(Time64NanosecondArray::from(vec![1, 2, 3, 4, 5])); - generic_test_op!( - a, - DataType::Time64(TimeUnit::Nanosecond), - Max, - ScalarValue::Time64Nanosecond(Some(5)) - ) - } - - #[test] - fn max_new_timestamp_micro() -> Result<()> { - let dt = DataType::Timestamp(TimeUnit::Microsecond, None); - let actual = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]) - .with_data_type(dt.clone()); - let expected: ArrayRef = - Arc::new(TimestampMicrosecondArray::from(vec![5]).with_data_type(dt.clone())); - generic_test_op_new!(Arc::new(actual), dt.clone(), Max, &expected) - } - - #[test] - fn max_new_timestamp_micro_with_tz() -> Result<()> { - let dt = DataType::Timestamp(TimeUnit::Microsecond, Some("UTC".into())); - let actual = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]) - .with_data_type(dt.clone()); - let expected: ArrayRef = - Arc::new(TimestampMicrosecondArray::from(vec![5]).with_data_type(dt.clone())); - generic_test_op_new!(Arc::new(actual), dt.clone(), Max, &expected) - } - - #[test] - fn max_bool() -> Result<()> { - let a: ArrayRef = Arc::new(BooleanArray::from(vec![false, false])); - generic_test_op!(a, DataType::Boolean, Max, ScalarValue::from(false))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![true, true])); - generic_test_op!(a, DataType::Boolean, Max, ScalarValue::from(true))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![false, true, false])); - generic_test_op!(a, DataType::Boolean, Max, ScalarValue::from(true))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![true, false, true])); - generic_test_op!(a, DataType::Boolean, Max, ScalarValue::from(true))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(Vec::::new())); - generic_test_op!( - a, - DataType::Boolean, - Max, - ScalarValue::from(None as Option) - )?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![None as Option])); - generic_test_op!( - a, - DataType::Boolean, - Max, - ScalarValue::from(None as Option) - )?; - - let a: ArrayRef = - Arc::new(BooleanArray::from(vec![None, Some(true), Some(false)])); - generic_test_op!(a, DataType::Boolean, Max, ScalarValue::from(true))?; - - Ok(()) - } - - #[test] - fn min_bool() -> Result<()> { - let a: ArrayRef = Arc::new(BooleanArray::from(vec![false, false])); - generic_test_op!(a, DataType::Boolean, Min, ScalarValue::from(false))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![true, true])); - generic_test_op!(a, DataType::Boolean, Min, ScalarValue::from(true))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![false, true, false])); - generic_test_op!(a, DataType::Boolean, Min, ScalarValue::from(false))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![true, false, true])); - generic_test_op!(a, DataType::Boolean, Min, ScalarValue::from(false))?; - - let a: ArrayRef = Arc::new(BooleanArray::from(Vec::::new())); - generic_test_op!( - a, - DataType::Boolean, - Min, - ScalarValue::from(None as Option) - )?; - - let a: ArrayRef = Arc::new(BooleanArray::from(vec![None as Option])); - generic_test_op!( - a, - DataType::Boolean, - Min, - ScalarValue::from(None as Option) - )?; - - let a: ArrayRef = - Arc::new(BooleanArray::from(vec![None, Some(true), Some(false)])); - generic_test_op!(a, DataType::Boolean, Min, ScalarValue::from(false))?; - - Ok(()) - } -} diff --git a/datafusion/physical-expr/src/expressions/mod.rs b/datafusion/physical-expr/src/expressions/mod.rs index c16b609e2375c..980297b8b433b 100644 --- a/datafusion/physical-expr/src/expressions/mod.rs +++ b/datafusion/physical-expr/src/expressions/mod.rs @@ -100,9 +100,7 @@ pub(crate) mod tests { use crate::AggregateExpr; use arrow::record_batch::RecordBatch; - use arrow_array::ArrayRef; use datafusion_common::{Result, ScalarValue}; - use datafusion_expr::EmitTo; /// macro to perform an aggregation using [`datafusion_expr::Accumulator`] and verify the /// result. @@ -250,22 +248,4 @@ pub(crate) mod tests { accum.update_batch(&values)?; accum.evaluate() } - - pub fn aggregate_new( - batch: &RecordBatch, - agg: Arc, - ) -> Result { - let mut accum = agg.create_groups_accumulator()?; - let expr = agg.expressions(); - let values = expr - .iter() - .map(|e| { - e.evaluate(batch) - .and_then(|v| v.into_array(batch.num_rows())) - }) - .collect::>>()?; - let indices = vec![0; batch.num_rows()]; - accum.update_batch(&values, &indices, None, 1)?; - accum.evaluate(EmitTo::All) - } } diff --git a/datafusion/sqllogictest/test_files/aggregate.slt b/datafusion/sqllogictest/test_files/aggregate.slt index 78421d0b64314..983f8a085ba98 100644 --- a/datafusion/sqllogictest/test_files/aggregate.slt +++ b/datafusion/sqllogictest/test_files/aggregate.slt @@ -2547,6 +2547,417 @@ Select bit_xor(DISTINCT c), arrow_typeof(bit_xor(DISTINCT c)) from t; statement ok drop table t; +################# +# Min_Max Begin # +################# +# min_decimal, max_decimal +statement ok +CREATE TABLE decimals (value DECIMAL(10, 2)); + +statement ok +INSERT INTO decimals VALUES (123.0001), (124.00); + +query RR +SELECT MIN(value), MAX(value) FROM decimals; +---- +123 124 + +statement ok +DROP TABLE decimals; + +statement ok +CREATE TABLE decimals_batch (value DECIMAL(10, 0)); + +statement ok +INSERT INTO decimals_batch VALUES (1), (2), (3), (4), (5); + +query RR +SELECT MIN(value), MAX(value) FROM decimals_batch; +---- +1 5 + +statement ok +DROP TABLE decimals_batch; + +statement ok +CREATE TABLE decimals_empty (value DECIMAL(10, 0)); + +query RR +SELECT MIN(value), MAX(value) FROM decimals_empty; +---- +NULL NULL + +statement ok +DROP TABLE decimals_empty; + +# min_decimal_all_nulls, max_decimal_all_nulls +statement ok +CREATE TABLE decimals_all_nulls (value DECIMAL(10, 0)); + +statement ok +INSERT INTO decimals_all_nulls VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL); + +query RR +SELECT MIN(value), MAX(value) FROM decimals_all_nulls; +---- +NULL NULL + +statement ok +DROP TABLE decimals_all_nulls; + +# min_decimal_with_nulls, max_decimal_with_nulls +statement ok +CREATE TABLE decimals_with_nulls (value DECIMAL(10, 0)); + +statement ok +INSERT INTO decimals_with_nulls VALUES (1), (NULL), (3), (4), (5); + +query RR +SELECT MIN(value), MAX(value) FROM decimals_with_nulls; +---- +1 5 + +statement ok +DROP TABLE decimals_with_nulls; + +statement ok +CREATE TABLE decimals_error (value DECIMAL(10, 2)); + +statement ok +INSERT INTO decimals_error VALUES (123.00), (arrow_cast(124.001, 'Decimal128(10, 3)')); + +query RR +SELECT MIN(value), MAX(value) FROM decimals_error; +---- +123 124 + +statement ok +DROP TABLE decimals_error; + +statement ok +CREATE TABLE decimals_agg (value DECIMAL(10, 0)); + +statement ok +INSERT INTO decimals_agg VALUES (1), (2), (3), (4), (5); + +query RR +SELECT MIN(value), MAX(value) FROM decimals_agg; +---- +1 5 + +statement ok +DROP TABLE decimals_agg; + +# min_i32, max_i32 +statement ok +CREATE TABLE integers (value INT); + +statement ok +INSERT INTO integers VALUES (1), (2), (3), (4), (5); + +query II +SELECT MIN(value), MAX(value) FROM integers +---- +1 5 + +statement ok +DROP TABLE integers; + +# min_utf8, max_utf8 +statement ok +CREATE TABLE strings (value TEXT); + +statement ok +INSERT INTO strings VALUES ('d'), ('a'), ('c'), ('b'); + +query TT +SELECT MIN(value), MAX(value) FROM strings +---- +a d + +statement ok +DROP TABLE strings; + +# min_i32_with_nulls, max_i32_with_nulls +statement ok +CREATE TABLE integers_with_nulls (value INT); + +statement ok +INSERT INTO integers_with_nulls VALUES (1), (NULL), (3), (4), (5); + +query II +SELECT MIN(value), MAX(value) FROM integers_with_nulls +---- +1 5 + +statement ok +DROP TABLE integers_with_nulls; + +# min_i32_all_nulls, max_i32_all_nulls +statement ok +CREATE TABLE integers_all_nulls (value INT); + +query II +SELECT MIN(value), MAX(value) FROM integers_all_nulls +---- +NULL NULL + +statement ok +DROP TABLE integers_all_nulls; + +# min_u32, max_u32 +statement ok +CREATE TABLE uintegers (value INT UNSIGNED); + +statement ok +INSERT INTO uintegers VALUES (1), (2), (3), (4), (5); + +query II +SELECT MIN(value), MAX(value) FROM uintegers +---- +1 5 + +statement ok +DROP TABLE uintegers; + +# min_f32, max_f32 +statement ok +CREATE TABLE floats (value FLOAT); + +statement ok +INSERT INTO floats VALUES (1.0), (2.0), (3.0), (4.0), (5.0); + +query RR +SELECT MIN(value), MAX(value) FROM floats +---- +1 5 + +statement ok +DROP TABLE floats; + +# min_f64, max_f64 +statement ok +CREATE TABLE doubles (value DOUBLE); + +statement ok +INSERT INTO doubles VALUES (1.0), (2.0), (3.0), (4.0), (5.0); + +query RR +SELECT MIN(value), MAX(value) FROM doubles +---- +1 5 + +statement ok +DROP TABLE doubles; + +# min_date, max_date +statement ok +CREATE TABLE dates (value DATE); + +statement ok +INSERT INTO dates VALUES ('1970-01-02'), ('1970-01-03'), ('1970-01-04'), ('1970-01-05'), ('1970-01-06'); + +query DD +SELECT MIN(value), MAX(value) FROM dates +---- +1970-01-02 1970-01-06 + +statement ok +DROP TABLE dates; + +# min_seconds, max_seconds +statement ok +CREATE TABLE times (value TIME); + +statement ok +INSERT INTO times VALUES ('00:00:01'), ('00:00:02'), ('00:00:03'), ('00:00:04'), ('00:00:05'); + +query DD +SELECT MIN(value), MAX(value) FROM times +---- +00:00:01 00:00:05 + +statement ok +DROP TABLE times; + +# min_milliseconds, max_milliseconds +statement ok +CREATE TABLE time32millisecond (value TIME); + +statement ok +INSERT INTO time32millisecond VALUES ('00:00:00.001'), ('00:00:00.002'), ('00:00:00.003'), ('00:00:00.004'), ('00:00:00.005'); + +query DD +SELECT MIN(value), MAX(value) FROM time32millisecond +---- +00:00:00.001 00:00:00.005 + +statement ok +DROP TABLE time32millisecond; + +# min_microseconds, max_microseconds +statement ok +CREATE TABLE time64microsecond (value TIME); + +statement ok +INSERT INTO time64microsecond VALUES ('00:00:00.000001'), ('00:00:00.000002'), ('00:00:00.000003'), ('00:00:00.000004'), ('00:00:00.000005'); + +query DD +SELECT MIN(value), MAX(value) FROM time64microsecond +---- +00:00:00.000001 00:00:00.000005 + +statement ok +DROP TABLE time64microsecond; + +# min_nanoseconds, max_nanoseconds +statement ok +CREATE TABLE time64nanosecond (value TIME); + +statement ok +INSERT INTO time64nanosecond VALUES ('00:00:00.000000001'), ('00:00:00.000000002'), ('00:00:00.000000003'), ('00:00:00.000000004'), ('00:00:00.000000005'); + +query DD +SELECT MIN(value), MAX(value) FROM time64nanosecond +---- +00:00:00.000000001 00:00:00.000000005 + +statement ok +DROP TABLE time64nanosecond; + +# min_timestamp, max_timestamp +statement ok +CREATE TABLE timestampmicrosecond (value TIMESTAMP); + +statement ok +INSERT INTO timestampmicrosecond VALUES ('1970-01-01 00:00:00.000001'), ('1970-01-01 00:00:00.000002'), ('1970-01-01 00:00:00.000003'), ('1970-01-01 00:00:00.000004'), ('1970-01-01 00:00:00.000005'); + +query PP +SELECT MIN(value), MAX(value) FROM timestampmicrosecond +---- +1970-01-01T00:00:00.000001 1970-01-01T00:00:00.000005 + +statement ok +DROP TABLE timestampmicrosecond; + +# max_bool +statement ok +CREATE TABLE max_bool (value BOOLEAN); + +statement ok +INSERT INTO max_bool VALUES (false), (false); + +query B +SELECT MAX(value) FROM max_bool +---- +false + +statement ok +DROP TABLE max_bool; + +statement ok +CREATE TABLE max_bool (value BOOLEAN); + +statement ok +INSERT INTO max_bool VALUES (true), (true); + +query B +SELECT MAX(value) FROM max_bool +---- +true + +statement ok +DROP TABLE max_bool; + +statement ok +CREATE TABLE max_bool (value BOOLEAN); + +statement ok +INSERT INTO max_bool VALUES (false), (true), (false); + +query B +SELECT MAX(value) FROM max_bool +---- +true + +statement ok +DROP TABLE max_bool; + +statement ok +CREATE TABLE max_bool (value BOOLEAN); + +statement ok +INSERT INTO max_bool VALUES (true), (false), (true); + +query B +SELECT MAX(value) FROM max_bool +---- +true + +statement ok +DROP TABLE max_bool; + +# min_bool +statement ok +CREATE TABLE min_bool (value BOOLEAN); + +statement ok +INSERT INTO min_bool VALUES (false), (false); + +query B +SELECT MIN(value) FROM min_bool +---- +false + +statement ok +DROP TABLE min_bool; + +statement ok +CREATE TABLE min_bool (value BOOLEAN); + +statement ok +INSERT INTO min_bool VALUES (true), (true); + +query B +SELECT MIN(value) FROM min_bool +---- +true + +statement ok +DROP TABLE min_bool; + +statement ok +CREATE TABLE min_bool (value BOOLEAN); + +statement ok +INSERT INTO min_bool VALUES (false), (true), (false); + +query B +SELECT MIN(value) FROM min_bool +---- +false + +statement ok +DROP TABLE min_bool; + +statement ok +CREATE TABLE min_bool (value BOOLEAN); + +statement ok +INSERT INTO min_bool VALUES (true), (false), (true); + +query B +SELECT MIN(value) FROM min_bool +---- +false + +statement ok +DROP TABLE min_bool; + +################# +# Min_Max End # +################# + statement ok create table bool_aggregate_functions ( c1 boolean not null,