feat: add support for chrono on mssql

This commit is contained in:
Daniel Akhterov 2020-07-07 21:33:22 -07:00
parent e3b3806db5
commit 416375db32
No known key found for this signature in database
GPG Key ID: B1E37688C42BC6E8
4 changed files with 133 additions and 0 deletions

View File

@ -515,6 +515,10 @@ impl TypeInfo {
DataType::BigChar => "BIGCHAR",
DataType::NChar => "NCHAR",
DataType::DateTime2N => "DATETIME2",
DataType::DateTimeN => "DATETIME",
DataType::DateN => "DATE",
_ => unimplemented!("name: unsupported data type {:?}", self.ty),
}
}
@ -578,6 +582,18 @@ impl TypeInfo {
s.push_str("bit");
}
DataType::DateN => {
s.push_str("date");
}
DataType::DateTime2N => {
s.push_str("datetime2");
}
DataType::DateTimeN => {
s.push_str("datetime");
}
_ => unimplemented!("fmt: unsupported data type {:?}", self.ty),
}
}

View File

@ -0,0 +1,104 @@
use std::mem;
use byteorder::{ByteOrder, LittleEndian};
use chrono::{DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
use crate::decode::Decode;
use crate::encode::{Encode, IsNull};
use crate::error::BoxDynError;
use crate::mssql::protocol::type_info::{DataType, TypeInfo};
use crate::mssql::{Mssql, MssqlTypeInfo, MssqlValueRef};
use crate::types::Type;
impl Type<Mssql> for NaiveTime {
fn type_info() -> MssqlTypeInfo {
MssqlTypeInfo(TypeInfo::new(DataType::TimeN, 8))
}
}
impl Type<Mssql> for NaiveDate {
fn type_info() -> MssqlTypeInfo {
MssqlTypeInfo(TypeInfo::new(DataType::DateTimeN, 8))
}
}
impl Type<Mssql> for NaiveDateTime {
fn type_info() -> MssqlTypeInfo {
MssqlTypeInfo(TypeInfo::new(DataType::DateTimeN, 8))
}
}
impl<Tz: TimeZone> Type<Mssql> for DateTime<Tz> {
fn type_info() -> MssqlTypeInfo {
MssqlTypeInfo(TypeInfo::new(DataType::DateTimeOffsetN, 8))
}
}
impl Encode<'_, Mssql> for NaiveTime {
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
todo!()
}
}
impl<'r> Decode<'r, Mssql> for NaiveTime {
fn decode(value: MssqlValueRef<'r>) -> Result<Self, BoxDynError> {
todo!()
}
}
impl Encode<'_, Mssql> for NaiveDate {
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
todo!()
}
}
impl<'r> Decode<'r, Mssql> for NaiveDate {
fn decode(value: MssqlValueRef<'r>) -> Result<Self, BoxDynError> {
todo!()
}
}
impl Encode<'_, Mssql> for NaiveDateTime {
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
let days_duration = self.date() - NaiveDate::from_ymd(1900, 1, 1);
let ms_duration = self.time() - NaiveTime::from_hms(0, 0, 0);
let days = days_duration.num_days() as i32;
let ms = ms_duration.num_milliseconds() as u32 * 3 / 10;
buf.extend(&days.to_le_bytes());
buf.extend_from_slice(&ms.to_le_bytes());
IsNull::No
}
}
impl<'r> Decode<'r, Mssql> for NaiveDateTime {
fn decode(value: MssqlValueRef<'r>) -> Result<Self, BoxDynError> {
let days = LittleEndian::read_i32(&value.as_bytes()?[0..4]);
let third_seconds = LittleEndian::read_u32(&value.as_bytes()?[4..8]);
let ms = third_seconds / 3 * 10;
let time = NaiveTime::from_hms(0, 0, 0) + Duration::milliseconds(ms.into());
let date = NaiveDate::from_ymd(1900, 1, 1) + Duration::days(days.into());
Ok(date.and_time(time))
}
}
impl<Tz: TimeZone> Encode<'_, Mssql> for DateTime<Tz> {
fn encode_by_ref(&self, buf: &mut Vec<u8>) -> IsNull {
todo!()
}
}
impl<'r> Decode<'r, Mssql> for DateTime<Local> {
fn decode(value: MssqlValueRef<'r>) -> Result<Self, BoxDynError> {
todo!()
}
}
impl<'r> Decode<'r, Mssql> for DateTime<Utc> {
fn decode(value: MssqlValueRef<'r>) -> Result<Self, BoxDynError> {
todo!()
}
}

View File

@ -3,6 +3,7 @@ use crate::mssql::protocol::type_info::{DataType, TypeInfo};
use crate::mssql::{Mssql, MssqlTypeInfo};
mod bool;
mod chrono;
mod float;
mod int;
mod str;

View File

@ -41,3 +41,15 @@ test_type!(bool(
"CAST(1 as BIT)" == true,
"CAST(0 as BIT)" == false
));
#[cfg(feature = "chrono")]
mod chrono {
use super::*;
use sqlx::types::chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
test_type!(chrono_date<NaiveDateTime>(Mssql,
"CAST('2020-07-08 01:0:0.000' as datetime)" == NaiveDate::from_ymd(2020, 7, 8).and_hms_milli(1, 0, 0, 0),
"CAST('2020-07-08 01:41:21.900' as datetime)" == NaiveDate::from_ymd(2020, 7, 8).and_hms_milli(1, 41, 21, 900),
"CAST('2020-07-08 01:43:18.537' as datetime)" == NaiveDate::from_ymd(2020, 7, 8).and_hms_milli(1, 43, 18, 530)
));
}