diff --git a/datafusion/common/src/scalar.rs b/datafusion/common/src/scalar.rs index c3f91dd9b1d14..cc22cc5995fe7 100644 --- a/datafusion/common/src/scalar.rs +++ b/datafusion/common/src/scalar.rs @@ -86,8 +86,14 @@ pub enum ScalarValue { Date32(Option), /// Date stored as a signed 64bit int milliseconds since UNIX epoch 1970-01-01 Date64(Option), + /// Time stored as a signed 32bit int as seconds since midnight + Time32Second(Option), + /// Time stored as a signed 32bit int as milliseconds since midnight + Time32Millisecond(Option), + /// Time stored as a signed 64bit int as microseconds since midnight + Time64Microsecond(Option), /// Time stored as a signed 64bit int as nanoseconds since midnight - Time64(Option), + Time64Nanosecond(Option), /// Timestamp Second TimestampSecond(Option, Option), /// Timestamp Milliseconds @@ -168,8 +174,14 @@ impl PartialEq for ScalarValue { (Date32(_), _) => false, (Date64(v1), Date64(v2)) => v1.eq(v2), (Date64(_), _) => false, - (Time64(v1), Time64(v2)) => v1.eq(v2), - (Time64(_), _) => false, + (Time32Second(v1), Time32Second(v2)) => v1.eq(v2), + (Time32Second(_), _) => false, + (Time32Millisecond(v1), Time32Millisecond(v2)) => v1.eq(v2), + (Time32Millisecond(_), _) => false, + (Time64Microsecond(v1), Time64Microsecond(v2)) => v1.eq(v2), + (Time64Microsecond(_), _) => false, + (Time64Nanosecond(v1), Time64Nanosecond(v2)) => v1.eq(v2), + (Time64Nanosecond(_), _) => false, (TimestampSecond(v1, _), TimestampSecond(v2, _)) => v1.eq(v2), (TimestampSecond(_, _), _) => false, (TimestampMillisecond(v1, _), TimestampMillisecond(v2, _)) => v1.eq(v2), @@ -262,8 +274,14 @@ impl PartialOrd for ScalarValue { (Date32(_), _) => None, (Date64(v1), Date64(v2)) => v1.partial_cmp(v2), (Date64(_), _) => None, - (Time64(v1), Time64(v2)) => v1.partial_cmp(v2), - (Time64(_), _) => None, + (Time32Second(v1), Time32Second(v2)) => v1.partial_cmp(v2), + (Time32Second(_), _) => None, + (Time32Millisecond(v1), Time32Millisecond(v2)) => v1.partial_cmp(v2), + (Time32Millisecond(_), _) => None, + (Time64Microsecond(v1), Time64Microsecond(v2)) => v1.partial_cmp(v2), + (Time64Microsecond(_), _) => None, + (Time64Nanosecond(v1), Time64Nanosecond(v2)) => v1.partial_cmp(v2), + (Time64Nanosecond(_), _) => None, (TimestampSecond(v1, _), TimestampSecond(v2, _)) => v1.partial_cmp(v2), (TimestampSecond(_, _), _) => None, (TimestampMillisecond(v1, _), TimestampMillisecond(v2, _)) => { @@ -544,7 +562,10 @@ impl std::hash::Hash for ScalarValue { } Date32(v) => v.hash(state), Date64(v) => v.hash(state), - Time64(v) => v.hash(state), + Time32Second(v) => v.hash(state), + Time32Millisecond(v) => v.hash(state), + Time64Microsecond(v) => v.hash(state), + Time64Nanosecond(v) => v.hash(state), TimestampSecond(v, _) => v.hash(state), TimestampMillisecond(v, _) => v.hash(state), TimestampMicrosecond(v, _) => v.hash(state), @@ -909,7 +930,10 @@ impl ScalarValue { ))), ScalarValue::Date32(_) => DataType::Date32, ScalarValue::Date64(_) => DataType::Date64, - ScalarValue::Time64(_) => DataType::Time64(TimeUnit::Nanosecond), + ScalarValue::Time32Second(_) => DataType::Time32(TimeUnit::Second), + ScalarValue::Time32Millisecond(_) => DataType::Time32(TimeUnit::Millisecond), + ScalarValue::Time64Microsecond(_) => DataType::Time64(TimeUnit::Microsecond), + ScalarValue::Time64Nanosecond(_) => DataType::Time64(TimeUnit::Nanosecond), ScalarValue::IntervalYearMonth(_) => { DataType::Interval(IntervalUnit::YearMonth) } @@ -992,7 +1016,10 @@ impl ScalarValue { ScalarValue::List(v, _) => v.is_none(), ScalarValue::Date32(v) => v.is_none(), ScalarValue::Date64(v) => v.is_none(), - ScalarValue::Time64(v) => v.is_none(), + ScalarValue::Time32Second(v) => v.is_none(), + ScalarValue::Time32Millisecond(v) => v.is_none(), + ScalarValue::Time64Microsecond(v) => v.is_none(), + ScalarValue::Time64Nanosecond(v) => v.is_none(), ScalarValue::TimestampSecond(v, _) => v.is_none(), ScalarValue::TimestampMillisecond(v, _) => v.is_none(), ScalarValue::TimestampMicrosecond(v, _) => v.is_none(), @@ -1215,8 +1242,17 @@ impl ScalarValue { DataType::LargeBinary => build_array_string!(LargeBinaryArray, LargeBinary), DataType::Date32 => build_array_primitive!(Date32Array, Date32), DataType::Date64 => build_array_primitive!(Date64Array, Date64), + DataType::Time32(TimeUnit::Second) => { + build_array_primitive!(Time32SecondArray, Time32Second) + } + DataType::Time32(TimeUnit::Millisecond) => { + build_array_primitive!(Time32MillisecondArray, Time32Millisecond) + } + DataType::Time64(TimeUnit::Microsecond) => { + build_array_primitive!(Time64MicrosecondArray, Time64Microsecond) + } DataType::Time64(TimeUnit::Nanosecond) => { - build_array_primitive!(Time64NanosecondArray, Time64) + build_array_primitive!(Time64NanosecondArray, Time64Nanosecond) } DataType::Timestamp(TimeUnit::Second, _) => { build_array_primitive_tz!(TimestampSecondArray, TimestampSecond) @@ -1360,8 +1396,10 @@ impl ScalarValue { // explicitly enumerate unsupported types so newly added // types must be aknowledged DataType::Float16 - | DataType::Time32(_) - | DataType::Time64(_) + | DataType::Time32(TimeUnit::Microsecond) + | DataType::Time32(TimeUnit::Nanosecond) + | DataType::Time64(TimeUnit::Second) + | DataType::Time64(TimeUnit::Millisecond) | DataType::Duration(_) | DataType::FixedSizeBinary(_) | DataType::FixedSizeList(_, _) @@ -1613,7 +1651,34 @@ impl ScalarValue { ScalarValue::Date64(e) => { build_array_from_option!(Date64, Date64Array, e, size) } - ScalarValue::Time64(e) => { + ScalarValue::Time32Second(e) => { + build_array_from_option!( + Time32, + TimeUnit::Second, + Time32SecondArray, + e, + size + ) + } + ScalarValue::Time32Millisecond(e) => { + build_array_from_option!( + Time32, + TimeUnit::Millisecond, + Time32MillisecondArray, + e, + size + ) + } + ScalarValue::Time64Microsecond(e) => { + build_array_from_option!( + Time64, + TimeUnit::Microsecond, + Time64MicrosecondArray, + e, + size + ) + } + ScalarValue::Time64Nanosecond(e) => { build_array_from_option!( Time64, TimeUnit::Nanosecond, @@ -1756,8 +1821,17 @@ impl ScalarValue { DataType::Date64 => { typed_cast!(array, index, Date64Array, Date64) } + DataType::Time32(TimeUnit::Second) => { + typed_cast!(array, index, Time32SecondArray, Time32Second) + } + DataType::Time32(TimeUnit::Millisecond) => { + typed_cast!(array, index, Time32MillisecondArray, Time32Millisecond) + } + DataType::Time64(TimeUnit::Microsecond) => { + typed_cast!(array, index, Time64MicrosecondArray, Time64Microsecond) + } DataType::Time64(TimeUnit::Nanosecond) => { - typed_cast!(array, index, Time64NanosecondArray, Time64) + typed_cast!(array, index, Time64NanosecondArray, Time64Nanosecond) } DataType::Timestamp(TimeUnit::Second, tz_opt) => { typed_cast_tz!( @@ -1951,7 +2025,16 @@ impl ScalarValue { ScalarValue::Date64(val) => { eq_array_primitive!(array, index, Date64Array, val) } - ScalarValue::Time64(val) => { + ScalarValue::Time32Second(val) => { + eq_array_primitive!(array, index, Time32SecondArray, val) + } + ScalarValue::Time32Millisecond(val) => { + eq_array_primitive!(array, index, Time32MillisecondArray, val) + } + ScalarValue::Time64Microsecond(val) => { + eq_array_primitive!(array, index, Time64MicrosecondArray, val) + } + ScalarValue::Time64Nanosecond(val) => { eq_array_primitive!(array, index, Time64NanosecondArray, val) } ScalarValue::TimestampSecond(val, _) => { @@ -2090,7 +2173,9 @@ impl TryFrom for i32 { fn try_from(value: ScalarValue) -> Result { match value { ScalarValue::Int32(Some(inner_value)) - | ScalarValue::Date32(Some(inner_value)) => Ok(inner_value), + | ScalarValue::Date32(Some(inner_value)) + | ScalarValue::Time32Second(Some(inner_value)) + | ScalarValue::Time32Millisecond(Some(inner_value)) => Ok(inner_value), _ => Err(DataFusionError::Internal(format!( "Cannot convert {:?} to {}", value, @@ -2108,7 +2193,8 @@ impl TryFrom for i64 { match value { ScalarValue::Int64(Some(inner_value)) | ScalarValue::Date64(Some(inner_value)) - | ScalarValue::Time64(Some(inner_value)) + | ScalarValue::Time64Microsecond(Some(inner_value)) + | ScalarValue::Time64Nanosecond(Some(inner_value)) | ScalarValue::TimestampNanosecond(Some(inner_value), _) | ScalarValue::TimestampMicrosecond(Some(inner_value), _) | ScalarValue::TimestampMillisecond(Some(inner_value), _) @@ -2170,7 +2256,14 @@ impl TryFrom<&DataType> for ScalarValue { DataType::LargeUtf8 => ScalarValue::LargeUtf8(None), DataType::Date32 => ScalarValue::Date32(None), DataType::Date64 => ScalarValue::Date64(None), - DataType::Time64(TimeUnit::Nanosecond) => ScalarValue::Time64(None), + DataType::Time32(TimeUnit::Second) => ScalarValue::Time32Second(None), + DataType::Time32(TimeUnit::Millisecond) => { + ScalarValue::Time32Millisecond(None) + } + DataType::Time64(TimeUnit::Microsecond) => { + ScalarValue::Time64Microsecond(None) + } + DataType::Time64(TimeUnit::Nanosecond) => ScalarValue::Time64Nanosecond(None), DataType::Timestamp(TimeUnit::Second, tz_opt) => { ScalarValue::TimestampSecond(None, tz_opt.clone()) } @@ -2309,7 +2402,10 @@ impl fmt::Display for ScalarValue { }, ScalarValue::Date32(e) => format_option!(f, e)?, ScalarValue::Date64(e) => format_option!(f, e)?, - ScalarValue::Time64(e) => format_option!(f, e)?, + ScalarValue::Time32Second(e) => format_option!(f, e)?, + ScalarValue::Time32Millisecond(e) => format_option!(f, e)?, + ScalarValue::Time64Microsecond(e) => format_option!(f, e)?, + ScalarValue::Time64Nanosecond(e) => format_option!(f, e)?, ScalarValue::IntervalDayTime(e) => format_option!(f, e)?, ScalarValue::IntervalYearMonth(e) => format_option!(f, e)?, ScalarValue::IntervalMonthDayNano(e) => format_option!(f, e)?, @@ -2370,7 +2466,16 @@ impl fmt::Debug for ScalarValue { ScalarValue::List(_, _) => write!(f, "List([{}])", self), ScalarValue::Date32(_) => write!(f, "Date32(\"{}\")", self), ScalarValue::Date64(_) => write!(f, "Date64(\"{}\")", self), - ScalarValue::Time64(_) => write!(f, "Time64(\"{}\")", self), + ScalarValue::Time32Second(_) => write!(f, "Time32Second(\"{}\")", self), + ScalarValue::Time32Millisecond(_) => { + write!(f, "Time32Millisecond(\"{}\")", self) + } + ScalarValue::Time64Microsecond(_) => { + write!(f, "Time64Microsecond(\"{}\")", self) + } + ScalarValue::Time64Nanosecond(_) => { + write!(f, "Time64Nanosecond(\"{}\")", self) + } ScalarValue::IntervalDayTime(_) => { write!(f, "IntervalDayTime(\"{}\")", self) } @@ -2999,7 +3104,10 @@ mod tests { make_binary_test_case!(str_vals, LargeBinaryArray, LargeBinary), make_test_case!(i32_vals, Date32Array, Date32), make_test_case!(i64_vals, Date64Array, Date64), - make_test_case!(i64_vals, Time64NanosecondArray, Time64), + make_test_case!(i32_vals, Time32SecondArray, Time32Second), + make_test_case!(i32_vals, Time32MillisecondArray, Time32Millisecond), + make_test_case!(i64_vals, Time64MicrosecondArray, Time64Microsecond), + make_test_case!(i64_vals, Time64NanosecondArray, Time64Nanosecond), make_test_case!(i64_vals, TimestampSecondArray, TimestampSecond, None), make_test_case!( i64_vals, @@ -3810,4 +3918,4 @@ mod tests { ] ); } -} +} \ No newline at end of file diff --git a/datafusion/expr/src/type_coercion/binary.rs b/datafusion/expr/src/type_coercion/binary.rs index 2a125d56b39f8..2fd53811fcab1 100644 --- a/datafusion/expr/src/type_coercion/binary.rs +++ b/datafusion/expr/src/type_coercion/binary.rs @@ -20,7 +20,9 @@ use crate::type_coercion::is_numeric; use crate::Operator; use arrow::compute::can_cast_types; -use arrow::datatypes::{DataType, DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE}; +use arrow::datatypes::{ + DataType, TimeUnit, DECIMAL128_MAX_PRECISION, DECIMAL128_MAX_SCALE, +}; use datafusion_common::DataFusionError; use datafusion_common::Result; @@ -515,7 +517,6 @@ fn like_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option { /// casted to for the purpose of a date computation fn temporal_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option { use arrow::datatypes::DataType::*; - use arrow::datatypes::TimeUnit; match (lhs_type, rhs_type) { (Date64, Date32) => Some(Date64), (Date32, Date64) => Some(Date64), @@ -523,6 +524,22 @@ fn temporal_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option Some(Date32), (Utf8, Date64) => Some(Date64), (Date64, Utf8) => Some(Date64), + (Utf8, Time32(unit)) => match check_time_unit(Time32(unit.clone())) { + None => None, + Some(unit) => Some(Time32(unit)), + }, + (Time32(unit), Utf8) => match check_time_unit(Time32(unit.clone())) { + None => None, + Some(unit) => Some(Time32(unit)), + }, + (Utf8, Time64(unit)) => match check_time_unit(Time64(unit.clone())) { + None => None, + Some(unit) => Some(Time64(unit)), + }, + (Time64(unit), Utf8) => match check_time_unit(Time64(unit.clone())) { + None => None, + Some(unit) => Some(Time64(unit)), + }, (Timestamp(lhs_unit, lhs_tz), Timestamp(rhs_unit, rhs_tz)) => { let tz = match (lhs_tz, rhs_tz) { // can't cast across timezones @@ -623,6 +640,17 @@ fn null_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option { } } +fn check_time_unit(datatype: DataType) -> Option { + use arrow::datatypes::DataType::*; + match datatype { + Time32(TimeUnit::Second) => Some(TimeUnit::Second), + Time32(TimeUnit::Millisecond) => Some(TimeUnit::Millisecond), + Time64(TimeUnit::Microsecond) => Some(TimeUnit::Microsecond), + Time64(TimeUnit::Nanosecond) => Some(TimeUnit::Nanosecond), + _ => None, + } +} + #[cfg(test)] mod tests { use super::*; @@ -824,6 +852,30 @@ mod tests { Operator::Lt, DataType::Date64 ); + test_coercion_binary_rule!( + DataType::Utf8, + DataType::Time32(TimeUnit::Second), + Operator::Eq, + DataType::Time32(TimeUnit::Second) + ); + test_coercion_binary_rule!( + DataType::Utf8, + DataType::Time32(TimeUnit::Millisecond), + Operator::Eq, + DataType::Time32(TimeUnit::Millisecond) + ); + test_coercion_binary_rule!( + DataType::Utf8, + DataType::Time64(TimeUnit::Microsecond), + Operator::Eq, + DataType::Time64(TimeUnit::Microsecond) + ); + test_coercion_binary_rule!( + DataType::Utf8, + DataType::Time64(TimeUnit::Nanosecond), + Operator::Eq, + DataType::Time64(TimeUnit::Nanosecond) + ); test_coercion_binary_rule!( DataType::Utf8, DataType::Utf8, diff --git a/datafusion/physical-expr/src/aggregate/min_max.rs b/datafusion/physical-expr/src/aggregate/min_max.rs index 36d58c78008e7..ee5668194f3c5 100644 --- a/datafusion/physical-expr/src/aggregate/min_max.rs +++ b/datafusion/physical-expr/src/aggregate/min_max.rs @@ -28,6 +28,7 @@ use arrow::{ array::{ ArrayRef, Date32Array, Date64Array, Float32Array, Float64Array, Int16Array, Int32Array, Int64Array, Int8Array, LargeStringArray, StringArray, + Time32MillisecondArray, Time32SecondArray, Time64MicrosecondArray, Time64NanosecondArray, TimestampMicrosecondArray, TimestampMillisecondArray, TimestampNanosecondArray, TimestampSecondArray, UInt16Array, UInt32Array, UInt64Array, UInt8Array, @@ -251,8 +252,32 @@ macro_rules! min_max_batch { ), DataType::Date32 => typed_min_max_batch!($VALUES, Date32Array, Date32, $OP), DataType::Date64 => typed_min_max_batch!($VALUES, Date64Array, Date64, $OP), + DataType::Time32(TimeUnit::Second) => { + typed_min_max_batch!($VALUES, Time32SecondArray, Time32Second, $OP) + } + DataType::Time32(TimeUnit::Millisecond) => { + typed_min_max_batch!( + $VALUES, + Time32MillisecondArray, + Time32Millisecond, + $OP + ) + } + DataType::Time64(TimeUnit::Microsecond) => { + typed_min_max_batch!( + $VALUES, + Time64MicrosecondArray, + Time64Microsecond, + $OP + ) + } DataType::Time64(TimeUnit::Nanosecond) => { - typed_min_max_batch!($VALUES, Time64NanosecondArray, Time64, $OP) + typed_min_max_batch!( + $VALUES, + Time64NanosecondArray, + Time64Nanosecond, + $OP + ) } other => { // This should have been handled before @@ -417,10 +442,28 @@ macro_rules! min_max { typed_min_max!(lhs, rhs, Date64, $OP) } ( - ScalarValue::Time64(lhs), - ScalarValue::Time64(rhs), + ScalarValue::Time32Second(lhs), + ScalarValue::Time32Second(rhs), + ) => { + typed_min_max!(lhs, rhs, Time32Second, $OP) + } + ( + ScalarValue::Time32Millisecond(lhs), + ScalarValue::Time32Millisecond(rhs), ) => { - typed_min_max!(lhs, rhs, Time64, $OP) + typed_min_max!(lhs, rhs, Time32Millisecond, $OP) + } + ( + ScalarValue::Time64Microsecond(lhs), + ScalarValue::Time64Microsecond(rhs), + ) => { + typed_min_max!(lhs, rhs, Time64Microsecond, $OP) + } + ( + ScalarValue::Time64Nanosecond(lhs), + ScalarValue::Time64Nanosecond(rhs), + ) => { + typed_min_max!(lhs, rhs, Time64Nanosecond, $OP) } e => { return Err(DataFusionError::Internal(format!( @@ -1073,24 +1116,90 @@ mod tests { } #[test] - fn min_time64() -> Result<()> { + 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), + Max, + ScalarValue::Time32Second(Some(5)) + ) + } + + #[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), + Max, + ScalarValue::Time32Millisecond(Some(5)) + ) + } + + #[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::Nanosecond), + Max, + ScalarValue::Time64Nanosecond(Some(5)) + ) + } + + #[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), Max, - ScalarValue::Time64(Some(5)) + ScalarValue::Time64Nanosecond(Some(5)) ) } #[test] - fn max_time64() -> Result<()> { + 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::Time64(Some(5)) + ScalarValue::Time64Nanosecond(Some(5)) ) } -} +} \ No newline at end of file diff --git a/datafusion/physical-expr/src/expressions/binary.rs b/datafusion/physical-expr/src/expressions/binary.rs index 665ef2d6828e1..adf8cba5b80a8 100644 --- a/datafusion/physical-expr/src/expressions/binary.rs +++ b/datafusion/physical-expr/src/expressions/binary.rs @@ -458,6 +458,18 @@ macro_rules! binary_array_op { DataType::Date64 => { compute_op!($LEFT, $RIGHT, $OP, Date64Array) } + DataType::Time32(TimeUnit::Second) => { + compute_op!($LEFT, $RIGHT, $OP, Time32SecondArray) + } + DataType::Time32(TimeUnit::Millisecond) => { + compute_op!($LEFT, $RIGHT, $OP, Time32MillisecondArray) + } + DataType::Time64(TimeUnit::Microsecond) => { + compute_op!($LEFT, $RIGHT, $OP, Time64MicrosecondArray) + } + DataType::Time64(TimeUnit::Nanosecond) => { + compute_op!($LEFT, $RIGHT, $OP, Time64NanosecondArray) + } DataType::Boolean => compute_bool_op!($LEFT, $RIGHT, $OP, BooleanArray), other => Err(DataFusionError::Internal(format!( "Data type {:?} not supported for binary operation '{}' on dyn arrays", @@ -678,6 +690,10 @@ macro_rules! binary_array_op_dyn_scalar { ScalarValue::Float64(v) => compute_op_dyn_scalar!($LEFT, v, $OP, $OP_TYPE), ScalarValue::Date32(_) => compute_op_scalar!($LEFT, right, $OP, Date32Array), ScalarValue::Date64(_) => compute_op_scalar!($LEFT, right, $OP, Date64Array), + ScalarValue::Time32Second(_) => compute_op_scalar!($LEFT, right, $OP, Time32SecondArray), + ScalarValue::Time32Millisecond(_) => compute_op_scalar!($LEFT, right, $OP, Time32MillisecondArray), + ScalarValue::Time64Microsecond(_) => compute_op_scalar!($LEFT, right, $OP, Time64MicrosecondArray), + ScalarValue::Time64Nanosecond(_) => compute_op_scalar!($LEFT, right, $OP, Time64NanosecondArray), ScalarValue::TimestampSecond(..) => compute_op_scalar!($LEFT, right, $OP, TimestampSecondArray), ScalarValue::TimestampMillisecond(..) => compute_op_scalar!($LEFT, right, $OP, TimestampMillisecondArray), ScalarValue::TimestampMicrosecond(..) => compute_op_scalar!($LEFT, right, $OP, TimestampMicrosecondArray), @@ -2607,4 +2623,4 @@ mod tests { Ok(()) } -} +} \ No newline at end of file diff --git a/datafusion/proto/src/from_proto.rs b/datafusion/proto/src/from_proto.rs index 3eeb30edf6490..751ac18324be7 100644 --- a/datafusion/proto/src/from_proto.rs +++ b/datafusion/proto/src/from_proto.rs @@ -656,7 +656,7 @@ impl TryFrom<&protobuf::PrimitiveScalarType> for ScalarValue { PrimitiveScalarType::Binary => Self::Binary(None), PrimitiveScalarType::LargeBinary => Self::LargeBinary(None), PrimitiveScalarType::Date32 => Self::Date32(None), - PrimitiveScalarType::Time64 => Self::Time64(None), + PrimitiveScalarType::Time64 => Self::Time64Nanosecond(None), PrimitiveScalarType::TimestampMicrosecond => { Self::TimestampMicrosecond(None, None) } @@ -765,7 +765,7 @@ impl TryFrom<&protobuf::ScalarValue> for ScalarValue { ) } Value::Date64Value(v) => Self::Date64(Some(*v)), - Value::Time64Value(v) => Self::Time64(Some(*v)), + Value::Time64Value(v) => Self::Time64Nanosecond(Some(*v)), Value::IntervalYearmonthValue(v) => Self::IntervalYearMonth(Some(*v)), Value::IntervalDaytimeValue(v) => Self::IntervalDayTime(Some(*v)), Value::TimestampValue(v) => { @@ -1513,7 +1513,7 @@ fn typechecked_scalar_value_conversion( PrimitiveScalarType::Utf8 => ScalarValue::Utf8(None), PrimitiveScalarType::LargeUtf8 => ScalarValue::LargeUtf8(None), PrimitiveScalarType::Date32 => ScalarValue::Date32(None), - PrimitiveScalarType::Time64 => ScalarValue::Time64(None), + PrimitiveScalarType::Time64 => ScalarValue::Time64Nanosecond(None), PrimitiveScalarType::TimestampMicrosecond => { ScalarValue::TimestampMicrosecond(None, None) } @@ -1661,4 +1661,4 @@ fn parse_required_expr_inner( fn proto_error>(message: S) -> Error { Error::General(message.into()) -} +} \ No newline at end of file diff --git a/datafusion/proto/src/lib.rs b/datafusion/proto/src/lib.rs index e3b6c848a2b14..5d970c70c496f 100644 --- a/datafusion/proto/src/lib.rs +++ b/datafusion/proto/src/lib.rs @@ -438,9 +438,21 @@ mod roundtrip_tests { ScalarValue::Date32(Some(0)), ScalarValue::Date32(Some(i32::MAX)), ScalarValue::Date32(None), - ScalarValue::Time64(Some(0)), - ScalarValue::Time64(Some(i64::MAX)), - ScalarValue::Time64(None), + ScalarValue::Date64(Some(0)), + ScalarValue::Date64(Some(i64::MAX)), + ScalarValue::Date64(None), + ScalarValue::Time32Second(Some(0)), + ScalarValue::Time32Second(Some(i32::MAX)), + ScalarValue::Time32Second(None), + ScalarValue::Time32Millisecond(Some(0)), + ScalarValue::Time32Millisecond(Some(i32::MAX)), + ScalarValue::Time32Millisecond(None), + ScalarValue::Time64Microsecond(Some(0)), + ScalarValue::Time64Microsecond(Some(i64::MAX)), + ScalarValue::Time64Microsecond(None), + ScalarValue::Time64Nanosecond(Some(0)), + ScalarValue::Time64Nanosecond(Some(i64::MAX)), + ScalarValue::Time64Nanosecond(None), ScalarValue::TimestampNanosecond(Some(0), None), ScalarValue::TimestampNanosecond(Some(i64::MAX), None), ScalarValue::TimestampNanosecond(Some(0), Some("UTC".to_string())), @@ -1259,4 +1271,4 @@ mod roundtrip_tests { let ctx = SessionContext::new(); roundtrip_expr_test(test_expr, ctx); } -} +} \ No newline at end of file diff --git a/datafusion/proto/src/to_proto.rs b/datafusion/proto/src/to_proto.rs index 47b779fffc74d..436996471b62a 100644 --- a/datafusion/proto/src/to_proto.rs +++ b/datafusion/proto/src/to_proto.rs @@ -1188,7 +1188,25 @@ impl TryFrom<&ScalarValue> for protobuf::ScalarValue { }) } - datafusion::scalar::ScalarValue::Time64(v) => { + datafusion::scalar::ScalarValue::Time32Second(v) => { + create_proto_scalar(v, PrimitiveScalarType::Time64, |v| { + Value::Time64Value(*v as i64 * 1_000_000_000) + }) + } + + datafusion::scalar::ScalarValue::Time32Millisecond(v) => { + create_proto_scalar(v, PrimitiveScalarType::Time64, |v| { + Value::Time64Value(*v as i64 * 1_000_000) + }) + } + + datafusion::scalar::ScalarValue::Time64Microsecond(v) => { + create_proto_scalar(v, PrimitiveScalarType::Time64, |v| { + Value::Time64Value(*v * 1_000) + }) + } + + datafusion::scalar::ScalarValue::Time64Nanosecond(v) => { create_proto_scalar(v, PrimitiveScalarType::Time64, |v| { Value::Time64Value(*v) }) @@ -1514,4 +1532,4 @@ fn is_valid_scalar_type_no_list_check(datatype: &DataType) -> bool { DataType::List(_) => true, _ => false, } -} +} \ No newline at end of file