diff --git a/Cargo.lock b/Cargo.lock index 74692cdbb5..c9e9888625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,7 +211,7 @@ dependencies = [ "common-error", "common-time", "datatypes", - "greptime-proto 0.1.0 (git+https://github.com/GreptimeTeam/greptime-proto.git?rev=eeae2d0dfa8ee320a7b9e987b4631a6c1c732ebd)", + "greptime-proto 0.1.0 (git+https://github.com/GreptimeTeam/greptime-proto.git?rev=940694cfd05c1e93c1dd7aab486184c9e2853098)", "prost", "snafu", "tonic 0.9.2", @@ -4126,7 +4126,7 @@ dependencies = [ [[package]] name = "greptime-proto" version = "0.1.0" -source = "git+https://github.com/GreptimeTeam/greptime-proto.git?rev=eeae2d0dfa8ee320a7b9e987b4631a6c1c732ebd#eeae2d0dfa8ee320a7b9e987b4631a6c1c732ebd" +source = "git+https://github.com/GreptimeTeam/greptime-proto.git?rev=940694cfd05c1e93c1dd7aab486184c9e2853098#940694cfd05c1e93c1dd7aab486184c9e2853098" dependencies = [ "prost", "serde", @@ -6996,7 +6996,7 @@ dependencies = [ "datafusion", "datatypes", "futures", - "greptime-proto 0.1.0 (git+https://github.com/GreptimeTeam/greptime-proto.git?rev=eeae2d0dfa8ee320a7b9e987b4631a6c1c732ebd)", + "greptime-proto 0.1.0 (git+https://github.com/GreptimeTeam/greptime-proto.git?rev=940694cfd05c1e93c1dd7aab486184c9e2853098)", "promql-parser", "prost", "query", @@ -7267,7 +7267,7 @@ dependencies = [ "format_num", "futures", "futures-util", - "greptime-proto 0.1.0 (git+https://github.com/GreptimeTeam/greptime-proto.git?rev=eeae2d0dfa8ee320a7b9e987b4631a6c1c732ebd)", + "greptime-proto 0.1.0 (git+https://github.com/GreptimeTeam/greptime-proto.git?rev=940694cfd05c1e93c1dd7aab486184c9e2853098)", "humantime", "metrics", "num", diff --git a/Cargo.toml b/Cargo.toml index b9af4a696a..00936e93df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ datafusion-substrait = { git = "https://github.com/waynexia/arrow-datafusion.git derive_builder = "0.12" futures = "0.3" futures-util = "0.3" -greptime-proto = { git = "https://github.com/GreptimeTeam/greptime-proto.git", rev = "eeae2d0dfa8ee320a7b9e987b4631a6c1c732ebd" } +greptime-proto = { git = "https://github.com/GreptimeTeam/greptime-proto.git", rev = "940694cfd05c1e93c1dd7aab486184c9e2853098" } itertools = "0.10" lazy_static = "1.4" once_cell = "1.18" diff --git a/src/api/src/helper.rs b/src/api/src/helper.rs index e36dd0d68f..673cfa93ff 100644 --- a/src/api/src/helper.rs +++ b/src/api/src/helper.rs @@ -13,15 +13,17 @@ // limitations under the License. use common_base::BitVec; +use common_time::interval::IntervalUnit; use common_time::timestamp::TimeUnit; +use common_time::Interval; use datatypes::prelude::ConcreteDataType; -use datatypes::types::{TimeType, TimestampType}; +use datatypes::types::{IntervalType, TimeType, TimestampType}; use datatypes::value::Value; use datatypes::vectors::VectorRef; use greptime_proto::v1::ddl_request::Expr; use greptime_proto::v1::greptime_request::Request; use greptime_proto::v1::query_request::Query; -use greptime_proto::v1::{DdlRequest, QueryRequest}; +use greptime_proto::v1::{DdlRequest, IntervalMonthDayNano, QueryRequest}; use snafu::prelude::*; use crate::error::{self, Result}; @@ -75,6 +77,11 @@ impl From for ConcreteDataType { ColumnDataType::TimeMillisecond => ConcreteDataType::time_millisecond_datatype(), ColumnDataType::TimeMicrosecond => ConcreteDataType::time_microsecond_datatype(), ColumnDataType::TimeNanosecond => ConcreteDataType::time_nanosecond_datatype(), + ColumnDataType::IntervalYearMonth => ConcreteDataType::interval_year_month_datatype(), + ColumnDataType::IntervalDayTime => ConcreteDataType::interval_day_time_datatype(), + ColumnDataType::IntervalMonthDayNano => { + ConcreteDataType::interval_month_day_nano_datatype() + } } } } @@ -111,8 +118,12 @@ impl TryFrom for ColumnDataTypeWrapper { TimeType::Microsecond(_) => ColumnDataType::TimeMicrosecond, TimeType::Nanosecond(_) => ColumnDataType::TimeNanosecond, }, - ConcreteDataType::Interval(_) - | ConcreteDataType::Null(_) + ConcreteDataType::Interval(i) => match i { + IntervalType::YearMonth(_) => ColumnDataType::IntervalYearMonth, + IntervalType::DayTime(_) => ColumnDataType::IntervalDayTime, + IntervalType::MonthDayNano(_) => ColumnDataType::IntervalMonthDayNano, + }, + ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => { return error::IntoColumnDataTypeSnafu { from: datatype }.fail() @@ -216,6 +227,18 @@ pub fn values_with_capacity(datatype: ColumnDataType, capacity: usize) -> Values time_nanosecond_values: Vec::with_capacity(capacity), ..Default::default() }, + ColumnDataType::IntervalDayTime => Values { + interval_day_time_values: Vec::with_capacity(capacity), + ..Default::default() + }, + ColumnDataType::IntervalYearMonth => Values { + interval_year_month_values: Vec::with_capacity(capacity), + ..Default::default() + }, + ColumnDataType::IntervalMonthDayNano => Values { + interval_month_day_nano_values: Vec::with_capacity(capacity), + ..Default::default() + }, } } @@ -256,7 +279,14 @@ pub fn push_vals(column: &mut Column, origin_count: usize, vector: VectorRef) { TimeUnit::Microsecond => values.time_microsecond_values.push(val.value()), TimeUnit::Nanosecond => values.time_nanosecond_values.push(val.value()), }, - Value::Interval(_) | Value::List(_) => unreachable!(), + Value::Interval(val) => match val.unit() { + IntervalUnit::YearMonth => values.interval_year_month_values.push(val.to_i32()), + IntervalUnit::DayTime => values.interval_day_time_values.push(val.to_i64()), + IntervalUnit::MonthDayNano => values + .interval_month_day_nano_values + .push(convert_i128_to_interval(val.to_i128())), + }, + Value::List(_) => unreachable!(), }); column.null_mask = null_mask.into_vec(); } @@ -295,14 +325,26 @@ fn ddl_request_type(request: &DdlRequest) -> &'static str { } } +/// Converts an i128 value to google protobuf type [IntervalMonthDayNano]. +pub fn convert_i128_to_interval(v: i128) -> IntervalMonthDayNano { + let interval = Interval::from_i128(v); + let (months, days, nanoseconds) = interval.to_month_day_nano(); + IntervalMonthDayNano { + months, + days, + nanoseconds, + } +} + #[cfg(test)] mod tests { use std::sync::Arc; use datatypes::vectors::{ - BooleanVector, TimeMicrosecondVector, TimeMillisecondVector, TimeNanosecondVector, - TimeSecondVector, TimestampMicrosecondVector, TimestampMillisecondVector, - TimestampNanosecondVector, TimestampSecondVector, + BooleanVector, IntervalDayTimeVector, IntervalMonthDayNanoVector, IntervalYearMonthVector, + TimeMicrosecondVector, TimeMillisecondVector, TimeNanosecondVector, TimeSecondVector, + TimestampMicrosecondVector, TimestampMillisecondVector, TimestampNanosecondVector, + TimestampSecondVector, Vector, }; use super::*; @@ -368,6 +410,14 @@ mod tests { let values = values_with_capacity(ColumnDataType::TimeMillisecond, 2); let values = values.time_millisecond_values; assert_eq!(2, values.capacity()); + + let values = values_with_capacity(ColumnDataType::IntervalDayTime, 2); + let values = values.interval_day_time_values; + assert_eq!(2, values.capacity()); + + let values = values_with_capacity(ColumnDataType::IntervalMonthDayNano, 2); + let values = values.interval_month_day_nano_values; + assert_eq!(2, values.capacity()); } #[test] @@ -440,6 +490,18 @@ mod tests { ConcreteDataType::time_datatype(TimeUnit::Millisecond), ColumnDataTypeWrapper(ColumnDataType::TimeMillisecond).into() ); + assert_eq!( + ConcreteDataType::interval_datatype(IntervalUnit::DayTime), + ColumnDataTypeWrapper(ColumnDataType::IntervalDayTime).into() + ); + assert_eq!( + ConcreteDataType::interval_datatype(IntervalUnit::YearMonth), + ColumnDataTypeWrapper(ColumnDataType::IntervalYearMonth).into() + ); + assert_eq!( + ConcreteDataType::interval_datatype(IntervalUnit::MonthDayNano), + ColumnDataTypeWrapper(ColumnDataType::IntervalMonthDayNano).into() + ); } #[test] @@ -510,6 +572,24 @@ mod tests { .try_into() .unwrap() ); + assert_eq!( + ColumnDataTypeWrapper(ColumnDataType::IntervalYearMonth), + ConcreteDataType::interval_datatype(IntervalUnit::YearMonth) + .try_into() + .unwrap() + ); + assert_eq!( + ColumnDataTypeWrapper(ColumnDataType::IntervalDayTime), + ConcreteDataType::interval_datatype(IntervalUnit::DayTime) + .try_into() + .unwrap() + ); + assert_eq!( + ColumnDataTypeWrapper(ColumnDataType::IntervalMonthDayNano), + ConcreteDataType::interval_datatype(IntervalUnit::MonthDayNano) + .try_into() + .unwrap() + ); let result: Result = ConcreteDataType::null_datatype().try_into(); assert!(result.is_err()); @@ -609,6 +689,50 @@ mod tests { ); } + #[test] + fn test_column_put_interval_values() { + let mut column = Column { + column_name: "test".to_string(), + semantic_type: 0, + values: Some(Values { + ..Default::default() + }), + null_mask: vec![], + datatype: 0, + }; + + let vector = Arc::new(IntervalYearMonthVector::from_vec(vec![1, 2, 3])); + push_vals(&mut column, 3, vector); + assert_eq!( + vec![1, 2, 3], + column.values.as_ref().unwrap().interval_year_month_values + ); + + let vector = Arc::new(IntervalDayTimeVector::from_vec(vec![4, 5, 6])); + push_vals(&mut column, 3, vector); + assert_eq!( + vec![4, 5, 6], + column.values.as_ref().unwrap().interval_day_time_values + ); + + let vector = Arc::new(IntervalMonthDayNanoVector::from_vec(vec![7, 8, 9])); + let len = vector.len(); + push_vals(&mut column, 3, vector); + (0..len).for_each(|i| { + assert_eq!( + 7 + i as i64, + column + .values + .as_ref() + .unwrap() + .interval_month_day_nano_values + .get(i) + .unwrap() + .nanoseconds + ); + }); + } + #[test] fn test_column_put_vector() { use crate::v1::SemanticType; @@ -633,4 +757,13 @@ mod tests { let null_mask = column.null_mask; assert_eq!(34, null_mask[0]); } + + #[test] + fn test_convert_i128_to_interval() { + let i128_val = 3000; + let interval = convert_i128_to_interval(i128_val); + assert_eq!(interval.months, 0); + assert_eq!(interval.days, 0); + assert_eq!(interval.nanoseconds, 3000); + } } diff --git a/src/common/grpc-expr/src/insert.rs b/src/common/grpc-expr/src/insert.rs index 77bbd33981..97531e3f8d 100644 --- a/src/common/grpc-expr/src/insert.rs +++ b/src/common/grpc-expr/src/insert.rs @@ -24,16 +24,19 @@ use api::v1::{ use common_base::BitVec; use common_time::time::Time; use common_time::timestamp::Timestamp; -use common_time::{Date, DateTime}; +use common_time::{Date, DateTime, Interval}; use datatypes::data_type::{ConcreteDataType, DataType}; use datatypes::prelude::{ValueRef, VectorRef}; use datatypes::scalars::ScalarVector; use datatypes::schema::SchemaRef; -use datatypes::types::{Int16Type, Int8Type, TimeType, TimestampType, UInt16Type, UInt8Type}; +use datatypes::types::{ + Int16Type, Int8Type, IntervalType, TimeType, TimestampType, UInt16Type, UInt8Type, +}; use datatypes::value::Value; use datatypes::vectors::{ BinaryVector, BooleanVector, DateTimeVector, DateVector, Float32Vector, Float64Vector, - Int32Vector, Int64Vector, PrimitiveVector, StringVector, TimeMicrosecondVector, + Int32Vector, Int64Vector, IntervalDayTimeVector, IntervalMonthDayNanoVector, + IntervalYearMonthVector, PrimitiveVector, StringVector, TimeMicrosecondVector, TimeMillisecondVector, TimeNanosecondVector, TimeSecondVector, TimestampMicrosecondVector, TimestampMillisecondVector, TimestampNanosecondVector, TimestampSecondVector, UInt32Vector, UInt64Vector, @@ -216,6 +219,25 @@ fn collect_column_values(column_datatype: ColumnDataType, values: &Values) -> Ve Time::new_nanosecond(*v) )) } + ColumnDataType::IntervalYearMonth => { + collect_values!(values.interval_year_month_values, |v| { + ValueRef::Interval(Interval::from_i32(*v)) + }) + } + ColumnDataType::IntervalDayTime => { + collect_values!(values.interval_day_time_values, |v| { + ValueRef::Interval(Interval::from_i64(*v)) + }) + } + ColumnDataType::IntervalMonthDayNano => { + collect_values!(values.interval_month_day_nano_values, |v| { + ValueRef::Interval(Interval::from_month_day_nano( + v.months, + v.days, + v.nanoseconds, + )) + }) + } } } @@ -424,10 +446,22 @@ fn values_to_vector(data_type: &ConcreteDataType, values: Values) -> VectorRef { )), }, - ConcreteDataType::Interval(_) - | ConcreteDataType::Null(_) - | ConcreteDataType::List(_) - | ConcreteDataType::Dictionary(_) => { + ConcreteDataType::Interval(unit) => match unit { + IntervalType::YearMonth(_) => Arc::new(IntervalYearMonthVector::from_vec( + values.interval_year_month_values, + )), + IntervalType::DayTime(_) => Arc::new(IntervalDayTimeVector::from_vec( + values.interval_day_time_values, + )), + IntervalType::MonthDayNano(_) => { + Arc::new(IntervalMonthDayNanoVector::from_iter_values( + values.interval_month_day_nano_values.iter().map(|x| { + Interval::from_month_day_nano(x.months, x.days, x.nanoseconds).to_i128() + }), + )) + } + }, + ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => { unreachable!() } } @@ -556,10 +590,28 @@ fn convert_values(data_type: &ConcreteDataType, values: Values) -> Vec { .map(|v| Value::Time(Time::new_nanosecond(v))) .collect(), - ConcreteDataType::Interval(_) - | ConcreteDataType::Null(_) - | ConcreteDataType::List(_) - | ConcreteDataType::Dictionary(_) => { + ConcreteDataType::Interval(IntervalType::YearMonth(_)) => values + .interval_year_month_values + .into_iter() + .map(|v| Value::Interval(Interval::from_i32(v))) + .collect(), + ConcreteDataType::Interval(IntervalType::DayTime(_)) => values + .interval_day_time_values + .into_iter() + .map(|v| Value::Interval(Interval::from_i64(v))) + .collect(), + ConcreteDataType::Interval(IntervalType::MonthDayNano(_)) => values + .interval_month_day_nano_values + .into_iter() + .map(|v| { + Value::Interval(Interval::from_month_day_nano( + v.months, + v.days, + v.nanoseconds, + )) + }) + .collect(), + ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => { unreachable!() } } @@ -576,15 +628,16 @@ mod tests { use api::helper::ColumnDataTypeWrapper; use api::v1::column::Values; - use api::v1::{Column, ColumnDataType, SemanticType}; + use api::v1::{Column, ColumnDataType, IntervalMonthDayNano, SemanticType}; use common_base::BitVec; use common_catalog::consts::MITO_ENGINE; + use common_time::interval::IntervalUnit; use common_time::timestamp::{TimeUnit, Timestamp}; use datatypes::data_type::ConcreteDataType; use datatypes::schema::{ColumnSchema, SchemaBuilder}; use datatypes::types::{ - TimeMillisecondType, TimeSecondType, TimeType, TimestampMillisecondType, - TimestampSecondType, TimestampType, + IntervalDayTimeType, IntervalMonthDayNanoType, IntervalYearMonthType, TimeMillisecondType, + TimeSecondType, TimeType, TimestampMillisecondType, TimestampSecondType, TimestampType, }; use datatypes::value::Value; use paste::paste; @@ -642,8 +695,8 @@ mod tests { ); let column_defs = create_expr.column_defs; - assert_eq!(column_defs[4].name, create_expr.time_index); - assert_eq!(5, column_defs.len()); + assert_eq!(column_defs[5].name, create_expr.time_index); + assert_eq!(6, column_defs.len()); assert_eq!( ConcreteDataType::string_datatype(), @@ -701,6 +754,20 @@ mod tests { ) ); + assert_eq!( + ConcreteDataType::interval_datatype(IntervalUnit::MonthDayNano), + ConcreteDataType::from( + ColumnDataTypeWrapper::try_new( + column_defs + .iter() + .find(|c| c.name == "interval") + .unwrap() + .datatype + ) + .unwrap() + ) + ); + assert_eq!( ConcreteDataType::timestamp_millisecond_datatype(), ConcreteDataType::from( @@ -734,7 +801,7 @@ mod tests { let add_columns = find_new_columns(&schema, &insert_batch.0).unwrap().unwrap(); - assert_eq!(3, add_columns.add_columns.len()); + assert_eq!(4, add_columns.add_columns.len()); let host_column = &add_columns.add_columns[0]; assert!(host_column.is_key); @@ -767,6 +834,19 @@ mod tests { .unwrap() ) ); + + let interval_column = &add_columns.add_columns[3]; + assert!(!interval_column.is_key); + + assert_eq!( + ConcreteDataType::interval_datatype(IntervalUnit::MonthDayNano), + ConcreteDataType::from( + ColumnDataTypeWrapper::try_new( + interval_column.column_def.as_ref().unwrap().datatype + ) + .unwrap() + ) + ); } #[test] @@ -1011,6 +1091,70 @@ mod tests { assert_eq!(expect, actual); } + #[test] + fn test_convert_interval_values() { + // year_month + let actual = convert_values( + &ConcreteDataType::Interval(IntervalType::YearMonth(IntervalYearMonthType)), + Values { + interval_year_month_values: vec![1_i32, 2_i32, 3_i32], + ..Default::default() + }, + ); + let expect = vec![ + Value::Interval(Interval::from_year_month(1_i32)), + Value::Interval(Interval::from_year_month(2_i32)), + Value::Interval(Interval::from_year_month(3_i32)), + ]; + assert_eq!(expect, actual); + + // day_time + let actual = convert_values( + &ConcreteDataType::Interval(IntervalType::DayTime(IntervalDayTimeType)), + Values { + interval_day_time_values: vec![1_i64, 2_i64, 3_i64], + ..Default::default() + }, + ); + let expect = vec![ + Value::Interval(Interval::from_i64(1_i64)), + Value::Interval(Interval::from_i64(2_i64)), + Value::Interval(Interval::from_i64(3_i64)), + ]; + assert_eq!(expect, actual); + + // month_day_nano + let actual = convert_values( + &ConcreteDataType::Interval(IntervalType::MonthDayNano(IntervalMonthDayNanoType)), + Values { + interval_month_day_nano_values: vec![ + IntervalMonthDayNano { + months: 1, + days: 2, + nanoseconds: 3, + }, + IntervalMonthDayNano { + months: 5, + days: 6, + nanoseconds: 7, + }, + IntervalMonthDayNano { + months: 9, + days: 10, + nanoseconds: 11, + }, + ], + ..Default::default() + }, + ); + let expect = vec![ + Value::Interval(Interval::from_month_day_nano(1, 2, 3)), + Value::Interval(Interval::from_month_day_nano(5, 6, 7)), + Value::Interval(Interval::from_month_day_nano(9, 10, 11)), + ]; + assert_eq!(expect, actual); + } + #[test] fn test_is_null() { let null_mask = BitVec::from_slice(&[0b0000_0001, 0b0000_1000]); @@ -1076,6 +1220,28 @@ mod tests { datatype: ColumnDataType::TimeMillisecond as i32, }; + let interval1 = IntervalMonthDayNano { + months: 1, + days: 2, + nanoseconds: 3, + }; + let interval2 = IntervalMonthDayNano { + months: 4, + days: 5, + nanoseconds: 6, + }; + let interval_vals = Values { + interval_month_day_nano_values: vec![interval1, interval2], + ..Default::default() + }; + let interval_column = Column { + column_name: "interval".to_string(), + semantic_type: SemanticType::Field as i32, + values: Some(interval_vals), + null_mask: vec![0], + datatype: ColumnDataType::IntervalMonthDayNano as i32, + }; + let ts_vals = Values { ts_millisecond_values: vec![100, 101], ..Default::default() @@ -1089,7 +1255,14 @@ mod tests { }; ( - vec![host_column, cpu_column, mem_column, time_column, ts_column], + vec![ + host_column, + cpu_column, + mem_column, + time_column, + interval_column, + ts_column, + ], row_count, ) } diff --git a/src/common/grpc/src/select.rs b/src/common/grpc/src/select.rs index aed198d7fa..c0caabdfa7 100644 --- a/src/common/grpc/src/select.rs +++ b/src/common/grpc/src/select.rs @@ -12,12 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use api::helper::convert_i128_to_interval; use api::v1::column::Values; use common_base::BitVec; -use datatypes::types::{TimeType, TimestampType, WrapperType}; +use datatypes::types::{IntervalType, TimeType, TimestampType, WrapperType}; use datatypes::vectors::{ BinaryVector, BooleanVector, DateTimeVector, DateVector, Float32Vector, Float64Vector, - Int16Vector, Int32Vector, Int64Vector, Int8Vector, StringVector, TimeMicrosecondVector, + Int16Vector, Int32Vector, Int64Vector, Int8Vector, IntervalDayTimeVector, + IntervalMonthDayNanoVector, IntervalYearMonthVector, StringVector, TimeMicrosecondVector, TimeMillisecondVector, TimeNanosecondVector, TimeSecondVector, TimestampMicrosecondVector, TimestampMillisecondVector, TimestampNanosecondVector, TimestampSecondVector, UInt16Vector, UInt32Vector, UInt64Vector, UInt8Vector, VectorRef, @@ -68,7 +70,7 @@ macro_rules! convert_arrow_array_to_grpc_vals { return Ok(vals); }, )+ - ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_)| ConcreteDataType::Interval(_) => unreachable!("Should not send {:?} in gRPC", $data_type), + ConcreteDataType::Null(_) | ConcreteDataType::List(_) | ConcreteDataType::Dictionary(_) => unreachable!("Should not send {:?} in gRPC", $data_type), } }}; } @@ -192,6 +194,24 @@ pub fn values(arrays: &[VectorRef]) -> Result { TimeNanosecondVector, time_nanosecond_values, |x| { x.into_native() } + ), + ( + ConcreteDataType::Interval(IntervalType::YearMonth(_)), + IntervalYearMonthVector, + interval_year_month_values, + |x| { x.into_native() } + ), + ( + ConcreteDataType::Interval(IntervalType::DayTime(_)), + IntervalDayTimeVector, + interval_day_time_values, + |x| { x.into_native() } + ), + ( + ConcreteDataType::Interval(IntervalType::MonthDayNano(_)), + IntervalMonthDayNanoVector, + interval_month_day_nano_values, + |x| { convert_i128_to_interval(x.into_native()) } ) ) } @@ -222,6 +242,43 @@ mod tests { assert_eq!(vec![1, 2, 3], values.time_second_values); } + #[test] + fn test_convert_arrow_array_interval_year_month() { + let array = IntervalYearMonthVector::from(vec![Some(1), Some(2), None, Some(3)]); + let array: VectorRef = Arc::new(array); + + let values = values(&[array]).unwrap(); + + assert_eq!(vec![1, 2, 3], values.interval_year_month_values); + } + + #[test] + fn test_convert_arrow_array_interval_day_time() { + let array = IntervalDayTimeVector::from(vec![Some(1), Some(2), None, Some(3)]); + let array: VectorRef = Arc::new(array); + + let values = values(&[array]).unwrap(); + + assert_eq!(vec![1, 2, 3], values.interval_day_time_values); + } + + #[test] + fn test_convert_arrow_array_interval_month_day_nano() { + let array = IntervalMonthDayNanoVector::from(vec![Some(1), Some(2), None, Some(3)]); + let array: VectorRef = Arc::new(array); + + let values = values(&[array]).unwrap(); + + (0..3).for_each(|i| { + assert_eq!(values.interval_month_day_nano_values[i].months, 0); + assert_eq!(values.interval_month_day_nano_values[i].days, 0); + assert_eq!( + values.interval_month_day_nano_values[i].nanoseconds, + i as i64 + 1 + ); + }) + } + #[test] fn test_convert_arrow_arrays_string() { let array = StringVector::from(vec![ diff --git a/src/common/time/src/interval.rs b/src/common/time/src/interval.rs index 7d4f6bc5f7..fadd9235b7 100644 --- a/src/common/time/src/interval.rs +++ b/src/common/time/src/interval.rs @@ -114,6 +114,11 @@ impl Interval { } } + /// Return a tuple(months, days, nanoseconds) from the interval. + pub fn to_month_day_nano(&self) -> (i32, i32, i64) { + (self.months, self.days, self.nsecs) + } + /// Converts the interval to nanoseconds. pub fn to_nanosecond(&self) -> i128 { let days = (self.days as i64) + DAYS_PER_MONTH * (self.months as i64); diff --git a/src/datatypes/src/interval.rs b/src/datatypes/src/interval.rs index 1a1e2b1dbd..3b80277fcc 100644 --- a/src/datatypes/src/interval.rs +++ b/src/datatypes/src/interval.rs @@ -135,4 +135,19 @@ mod tests { assert_eq!(interval, interval.to_owned_scalar()); assert_eq!(1000, interval.into_native()); } + + #[test] + fn test_interval_convert_to_native_type() { + let interval = IntervalMonthDayNano::new(1000); + let native_value: i128 = interval.into(); + assert_eq!(native_value, 1000); + + let interval = IntervalDayTime::new(1000); + let native_interval: i64 = interval.into(); + assert_eq!(native_interval, 1000); + + let interval = IntervalYearMonth::new(1000); + let native_interval: i32 = interval.into(); + assert_eq!(native_interval, 1000); + } }