Skip to content

Commit

Permalink
refactor: support to covert time string to timestamp in convert_value()
Browse files Browse the repository at this point in the history
  • Loading branch information
zyy17 committed Dec 27, 2024
1 parent 7471f55 commit c154090
Showing 1 changed file with 119 additions and 1 deletion.
120 changes: 119 additions & 1 deletion src/servers/src/mysql/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use std::time::Duration;

use chrono::NaiveDate;
use common_query::prelude::ScalarValue;
use common_time::Timestamp;
use datatypes::prelude::ConcreteDataType;
use datatypes::types::TimestampType;
use datatypes::value::{self, Value};
use itertools::Itertools;
use opensrv_mysql::{to_naive_datetime, ParamValue, ValueInner};
Expand Down Expand Up @@ -161,7 +163,7 @@ pub fn convert_value(param: &ParamValue, t: &ConcreteDataType) -> Result<ScalarV
String::from_utf8_lossy(b).to_string(),
))),
ConcreteDataType::Binary(_) => Ok(ScalarValue::Binary(Some(b.to_vec()))),

ConcreteDataType::Timestamp(ts_type) => covert_bytes_to_timestamp(b, ts_type),
_ => error::PreparedStmtTypeMismatchSnafu {
expected: t,
actual: param.coltype,
Expand Down Expand Up @@ -235,8 +237,41 @@ pub fn convert_expr_to_scalar_value(param: &Expr, t: &ConcreteDataType) -> Resul
}
}

fn covert_bytes_to_timestamp(bytes: &[u8], ts_type: &TimestampType) -> Result<ScalarValue> {
let ts = Timestamp::from_str_utc(&String::from_utf8_lossy(bytes))
.map_err(|e| {
error::MysqlValueConversionSnafu {
err_msg: e.to_string(),
}
.build()
})?
.convert_to(ts_type.unit())
.ok_or_else(|| {
error::MysqlValueConversionSnafu {
err_msg: "Overflow when converting timestamp to target unit".to_string(),
}
.build()
})?;
match ts_type {
TimestampType::Nanosecond(_) => {
Ok(ScalarValue::TimestampNanosecond(Some(ts.value()), None))
}
TimestampType::Microsecond(_) => {
Ok(ScalarValue::TimestampMicrosecond(Some(ts.value()), None))
}
TimestampType::Millisecond(_) => {
Ok(ScalarValue::TimestampMillisecond(Some(ts.value()), None))
}
TimestampType::Second(_) => Ok(ScalarValue::TimestampSecond(Some(ts.value()), None)),
}
}

#[cfg(test)]
mod tests {
use datatypes::types::{
TimestampMicrosecondType, TimestampMillisecondType, TimestampNanosecondType,
TimestampSecondType,
};
use sql::dialect::MySqlDialect;
use sql::parser::{ParseOptions, ParserContext};

Expand Down Expand Up @@ -340,4 +375,87 @@ mod tests {
let v = convert_expr_to_scalar_value(&expr, &t).unwrap();
assert_eq!(ScalarValue::Time64Microsecond(None), v);
}

#[test]
fn test_convert_bytes_to_timestamp() {
let test_cases = vec![
// input unix timestamp in seconds -> nanosecond.
(
"2024-12-26 12:00:00",
TimestampType::Nanosecond(TimestampNanosecondType),
ScalarValue::TimestampNanosecond(Some(1735214400000000000), None),
),
// input unix timestamp in seconds -> microsecond.
(
"2024-12-26 12:00:00",
TimestampType::Microsecond(TimestampMicrosecondType),
ScalarValue::TimestampMicrosecond(Some(1735214400000000), None),
),
// input unix timestamp in seconds -> millisecond.
(
"2024-12-26 12:00:00",
TimestampType::Millisecond(TimestampMillisecondType),
ScalarValue::TimestampMillisecond(Some(1735214400000), None),
),
// input unix timestamp in seconds -> second.
(
"2024-12-26 12:00:00",
TimestampType::Second(TimestampSecondType),
ScalarValue::TimestampSecond(Some(1735214400), None),
),
// input unix timestamp in milliseconds -> nanosecond.
(
"2024-12-26 12:00:00.123",
TimestampType::Nanosecond(TimestampNanosecondType),
ScalarValue::TimestampNanosecond(Some(1735214400123000000), None),
),
// input unix timestamp in milliseconds -> microsecond.
(
"2024-12-26 12:00:00.123",
TimestampType::Microsecond(TimestampMicrosecondType),
ScalarValue::TimestampMicrosecond(Some(1735214400123000), None),
),
// input unix timestamp in milliseconds -> millisecond.
(
"2024-12-26 12:00:00.123",
TimestampType::Millisecond(TimestampMillisecondType),
ScalarValue::TimestampMillisecond(Some(1735214400123), None),
),
// input unix timestamp in milliseconds -> second.
(
"2024-12-26 12:00:00.123",
TimestampType::Second(TimestampSecondType),
ScalarValue::TimestampSecond(Some(1735214400), None),
),
// input unix timestamp in microseconds -> nanosecond.
(
"2024-12-26 12:00:00.123456",
TimestampType::Nanosecond(TimestampNanosecondType),
ScalarValue::TimestampNanosecond(Some(1735214400123456000), None),
),
// input unix timestamp in microseconds -> microsecond.
(
"2024-12-26 12:00:00.123456",
TimestampType::Microsecond(TimestampMicrosecondType),
ScalarValue::TimestampMicrosecond(Some(1735214400123456), None),
),
// input unix timestamp in microseconds -> millisecond.
(
"2024-12-26 12:00:00.123456",
TimestampType::Millisecond(TimestampMillisecondType),
ScalarValue::TimestampMillisecond(Some(1735214400123), None),
),
// input unix timestamp in milliseconds -> second.
(
"2024-12-26 12:00:00.123456",
TimestampType::Second(TimestampSecondType),
ScalarValue::TimestampSecond(Some(1735214400), None),
),
];

for (input, ts_type, expected) in test_cases {
let result = covert_bytes_to_timestamp(input.as_bytes(), &ts_type).unwrap();
assert_eq!(result, expected);
}
}
}

0 comments on commit c154090

Please sign in to comment.