Skip to content

Commit

Permalink
refactor code.
Browse files Browse the repository at this point in the history
  • Loading branch information
QuenKar committed Sep 14, 2023
1 parent 461b593 commit 7e79753
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 40 deletions.
4 changes: 4 additions & 0 deletions src/common/time/src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ impl Date {
pub fn to_chrono_date(&self) -> Option<NaiveDate> {
NaiveDate::from_num_days_from_ce_opt(UNIX_EPOCH_FROM_CE + self.0)
}

pub fn to_secs(&self) -> i64 {
self.0 as i64 * 24 * 3600
}
}

#[cfg(test)]
Expand Down
13 changes: 13 additions & 0 deletions src/common/time/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ impl Time {
self.value
}

/// Convert a timestamp to given time unit.
/// Return `None` if conversion causes overflow.
pub fn convert_to(&self, unit: TimeUnit) -> Option<Time> {
if self.unit().factor() >= unit.factor() {
let mul = self.unit().factor() / unit.factor();
let value = self.value.checked_mul(mul as i64)?;
Some(Time::new(value, unit))
} else {
let mul = unit.factor() / self.unit().factor();
Some(Time::new(self.value.div_euclid(mul as i64), unit))
}
}

/// Split a [Time] into seconds part and nanoseconds part.
/// Notice the seconds part of split result is always rounded down to floor.
fn split(&self) -> (i64, u32) {
Expand Down
5 changes: 1 addition & 4 deletions src/datatypes/src/types/date_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ impl DataType for DateType {
fn cast(&self, from: Value) -> Option<Value> {
match from {
Value::Int32(v) => Some(Value::Date(Date::from(v))),
Value::String(v) => match Date::from_str(v.as_utf8()) {
Ok(d) => Some(Value::Date(d)),
Err(_) => None,
},
Value::String(v) => Date::from_str(v.as_utf8()).map(Value::Date).ok(),
Value::Timestamp(v) => v.to_chrono_date().map(|date| Value::Date(date.into())),
_ => None,
}
Expand Down
5 changes: 1 addition & 4 deletions src/datatypes/src/types/datetime_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ impl DataType for DateTimeType {
match from {
Value::Int64(v) => Some(Value::DateTime(DateTime::from(v))),
Value::Timestamp(v) => v.to_chrono_datetime().map(|d| Value::DateTime(d.into())),
Value::String(v) => match DateTime::from_str(v.as_utf8()) {
Ok(d) => Some(Value::DateTime(d)),
Err(_) => None,
},
Value::String(v) => DateTime::from_str(v.as_utf8()).map(Value::DateTime).ok(),
_ => None,
}
}
Expand Down
18 changes: 4 additions & 14 deletions src/datatypes/src/types/primitive_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,11 @@ macro_rules! define_non_timestamp_primitive {

fn cast(&self, from: Value) -> Option<Value> {
match from {
Value::Boolean(v) => bool_to_numeric(v).map(|val|Value::$TypeId(val)),
Value::String(v) => match v.as_utf8().parse::<$Native>(){
Ok(val) => Some(Value::from(val)),
Err(_)=> None,
}
Value::Boolean(v) => bool_to_numeric(v).map(Value::$TypeId),
Value::String(v) => v.as_utf8().parse::<$Native>().map(|val| Value::from(val)).ok(),
$(
Value::$TargetType(v) => num::cast::cast(v).map(Value::$TypeId),
)*

_ => None,
}
}
Expand Down Expand Up @@ -377,10 +373,7 @@ impl DataType for Int64Type {
Value::Int64(v) => Some(Value::Int64(v)),
Value::Float32(v) => num::cast::cast(v).map(Value::Int64),
Value::Float64(v) => num::cast::cast(v).map(Value::Int64),
Value::String(v) => match v.as_utf8().parse::<i64>() {
Ok(val) => Some(Value::Int64(val)),
Err(_) => None,
},
Value::String(v) => v.as_utf8().parse::<i64>().map(Value::Int64).ok(),
Value::DateTime(v) => Some(Value::Int64(v.val())),
Value::Timestamp(v) => Some(Value::Int64(v.value())),
Value::Time(v) => Some(Value::Int64(v.value())),
Expand Down Expand Up @@ -434,10 +427,7 @@ impl DataType for Int32Type {
Value::Int32(v) => Some(Value::Int32(v)),
Value::Float32(v) => num::cast::cast(v).map(Value::Int32),
Value::Float64(v) => num::cast::cast(v).map(Value::Int32),
Value::String(v) => match v.as_utf8().parse::<i32>() {
Ok(val) => Some(Value::Int32(val)),
Err(_) => None,
},
Value::String(v) => v.as_utf8().parse::<i32>().map(Value::Int32).ok(),
Value::Date(v) => Some(Value::Int32(v.val())),
Value::Interval(v) => match v.unit() {
IntervalUnit::YearMonth => Some(Value::Int32(v.to_i32())),
Expand Down
17 changes: 16 additions & 1 deletion src/datatypes/src/types/time_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ macro_rules! impl_data_type_for_time {
fn cast(&self, from: Value) -> Option<Value> {
match from {
Value::$TargetType(v) => Some(Value::Time(Time::new(v as i64, TimeUnit::$unit))),
Value::Time(v) => Some(Value::Time(v)),
Value::Time(v) => v.convert_to(TimeUnit::$unit).map(Value::Time),
_ => None,
}
}
Expand Down Expand Up @@ -263,5 +263,20 @@ mod tests {
let val = Value::Int32(123);
let time = ConcreteDataType::time_microsecond_datatype().cast(val);
assert_eq!(time, None);

// TimeSecond -> TimeMicroSecond
let second = Value::Time(Time::new_second(2023));
let microsecond = ConcreteDataType::time_microsecond_datatype()
.cast(second)
.unwrap();
assert_eq!(
microsecond,
Value::Time(Time::new_microsecond(2023 * 1000000))
);

// test overflow
let second = Value::Time(Time::new_second(i64::MAX));
let microsecond = ConcreteDataType::time_microsecond_datatype().cast(second);
assert_eq!(microsecond, None);
}
}
39 changes: 22 additions & 17 deletions src/datatypes/src/types/timestamp_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,11 @@ macro_rules! impl_data_type_for_timestamp {

fn cast(&self, from: Value)-> Option<Value>{
match from {
Value::Timestamp(v) => Some(Value::Timestamp(v)),
Value::String(v) => match Timestamp::from_str(v.as_utf8()){
Ok(ts) => Some(Value::Timestamp(ts)),
Err(_) => None
}
Value::Timestamp(v) => v.convert_to(TimeUnit::$unit).map(Value::Timestamp),
Value::String(v) => Timestamp::from_str(v.as_utf8()).map(Value::Timestamp).ok(),
Value::Int64(v) => Some(Value::Timestamp(Timestamp::new(v, TimeUnit::$unit))),
Value::DateTime(v) => match v.to_chrono_datetime(){
Some(dt) => Some(Value::Timestamp(Timestamp::from_chrono_datetime(dt)?)),
None => None
},
Value::Date(v) => match v.to_chrono_date(){
Some(d) => Some(Value::Timestamp(Timestamp::from_chrono_date(d)?)),
None => None
},
Value::DateTime(v) => Timestamp::new_second(v.val()).convert_to(TimeUnit::$unit).map(Value::Timestamp),
Value::Date(v) => Timestamp::new_second(v.to_secs()).convert_to(TimeUnit::$unit).map(Value::Timestamp),
_ => None
}
}
Expand Down Expand Up @@ -243,32 +234,46 @@ mod tests {
#[test]
fn test_timestamp_cast() {
std::env::set_var("TZ", "Asia/Shanghai");
// string -> timestamp
// String -> TimestampSecond
let s = Value::String("2021-01-01 01:02:03".to_string().into());
let ts = ConcreteDataType::timestamp_second_datatype()
.cast(s)
.unwrap();
assert_eq!(ts, Value::Timestamp(Timestamp::new_second(1609434123)));
// String cast failed
let s = Value::String("12345".to_string().into());
let ts = ConcreteDataType::timestamp_second_datatype().cast(s);
assert_eq!(ts, None);

let n = Value::Int64(1694589525);
// Int64 -> timestamp
// Int64 -> TimestampSecond
let ts = ConcreteDataType::timestamp_second_datatype()
.cast(n)
.unwrap();
assert_eq!(ts, Value::Timestamp(Timestamp::new_second(1694589525)));

// datetime -> timestamp
// Datetime -> TimestampSecond
let dt = Value::DateTime(DateTime::from(1234567));
let ts = ConcreteDataType::timestamp_second_datatype()
.cast(dt)
.unwrap();
assert_eq!(ts, Value::Timestamp(Timestamp::new_second(1234567)));

// date -> timestamp
// Date -> TimestampMillisecond
let d = Value::Date(Date::from_str("1970-01-01").unwrap());
let ts = ConcreteDataType::timestamp_millisecond_datatype()
.cast(d)
.unwrap();
assert_eq!(ts, Value::Timestamp(Timestamp::new_millisecond(0)));

// TimestampSecond -> TimestampMicrosecond
let second = Value::Timestamp(Timestamp::new_second(123));
let microsecond = ConcreteDataType::timestamp_microsecond_datatype()
.cast(second)
.unwrap();
assert_eq!(
microsecond,
Value::Timestamp(Timestamp::new_microsecond(123 * 1000000))
)
}
}

0 comments on commit 7e79753

Please sign in to comment.