mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-01-03 20:02:54 +00:00
refactor: support to convert time string to timestamp in convert_value() (#5242)
refactor: support to covert time string to timestamp in convert_value()
This commit is contained in:
@@ -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};
|
||||
@@ -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,
|
||||
@@ -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};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user