quaint_forked/connector/mssql/
conversion.rs

1use crate::ast::Value;
2#[cfg(not(feature = "bigdecimal"))]
3use crate::error::*;
4#[cfg(feature = "bigdecimal")]
5use bigdecimal::BigDecimal;
6use std::{borrow::Cow, convert::TryFrom};
7#[cfg(feature = "bigdecimal")]
8use tiberius::ToSql;
9use tiberius::{ColumnData, FromSql, IntoSql};
10
11impl<'a> IntoSql<'a> for &'a Value<'a> {
12    fn into_sql(self) -> ColumnData<'a> {
13        match self {
14            Value::Int32(val) => val.into_sql(),
15            Value::Int64(val) => val.into_sql(),
16            Value::Float(val) => val.into_sql(),
17            Value::Double(val) => val.into_sql(),
18            Value::Text(val) => val.as_deref().into_sql(),
19            Value::Bytes(val) => val.as_deref().into_sql(),
20            Value::Enum(val) => val.as_deref().into_sql(),
21            Value::Boolean(val) => val.into_sql(),
22            Value::Char(val) => val.as_ref().map(|val| format!("{val}")).into_sql(),
23            Value::Xml(val) => val.as_deref().into_sql(),
24            Value::Array(_) => panic!("Arrays are not supported on SQL Server."),
25            #[cfg(feature = "bigdecimal")]
26            Value::Numeric(val) => (*val).to_sql(),
27            #[cfg(feature = "json")]
28            Value::Json(val) => val.as_ref().map(|val| serde_json::to_string(&val).unwrap()).into_sql(),
29            #[cfg(feature = "uuid")]
30            Value::Uuid(val) => val.into_sql(),
31            #[cfg(feature = "chrono")]
32            Value::DateTime(val) => val.into_sql(),
33            #[cfg(feature = "chrono")]
34            Value::Date(val) => val.into_sql(),
35            #[cfg(feature = "chrono")]
36            Value::Time(val) => val.into_sql(),
37        }
38    }
39}
40
41impl TryFrom<ColumnData<'static>> for Value<'static> {
42    type Error = crate::error::Error;
43
44    fn try_from(cd: ColumnData<'static>) -> crate::Result<Self> {
45        let res = match cd {
46            ColumnData::U8(num) => Value::Int32(num.map(i32::from)),
47            ColumnData::I16(num) => Value::Int32(num.map(i32::from)),
48            ColumnData::I32(num) => Value::Int32(num.map(i32::from)),
49            ColumnData::I64(num) => Value::Int64(num.map(i64::from)),
50            ColumnData::F32(num) => Value::Float(num),
51            ColumnData::F64(num) => Value::Double(num),
52            ColumnData::Bit(b) => Value::Boolean(b),
53            ColumnData::String(s) => Value::Text(s),
54            ColumnData::Guid(uuid) => Value::Uuid(uuid),
55            ColumnData::Binary(bytes) => Value::Bytes(bytes),
56            #[cfg(feature = "bigdecimal")]
57            numeric @ ColumnData::Numeric(_) => Value::Numeric(BigDecimal::from_sql(&numeric)?),
58            #[cfg(not(feature = "bigdecimal"))]
59            _numeric @ ColumnData::Numeric(_) => {
60                let kind = ErrorKind::conversion("Please enable `bigdecimal` feature to read numeric values");
61                return Err(Error::builder(kind).build());
62            }
63            #[cfg(feature = "chrono")]
64            dt @ ColumnData::DateTime(_) => {
65                use tiberius::time::chrono::{DateTime, NaiveDateTime, Utc};
66
67                let dt = NaiveDateTime::from_sql(&dt)?.map(|dt| DateTime::<Utc>::from_utc(dt, Utc));
68                Value::DateTime(dt)
69            }
70            #[cfg(feature = "chrono")]
71            dt @ ColumnData::SmallDateTime(_) => {
72                use tiberius::time::chrono::{DateTime, NaiveDateTime, Utc};
73
74                let dt = NaiveDateTime::from_sql(&dt)?.map(|dt| DateTime::<Utc>::from_utc(dt, Utc));
75                Value::DateTime(dt)
76            }
77            #[cfg(feature = "chrono")]
78            dt @ ColumnData::Time(_) => {
79                use tiberius::time::chrono::NaiveTime;
80
81                Value::Time(NaiveTime::from_sql(&dt)?)
82            }
83            #[cfg(feature = "chrono")]
84            dt @ ColumnData::Date(_) => {
85                use tiberius::time::chrono::NaiveDate;
86                Value::Date(NaiveDate::from_sql(&dt)?)
87            }
88            #[cfg(feature = "chrono")]
89            dt @ ColumnData::DateTime2(_) => {
90                use tiberius::time::chrono::{DateTime, NaiveDateTime, Utc};
91
92                let dt = NaiveDateTime::from_sql(&dt)?.map(|dt| DateTime::<Utc>::from_utc(dt, Utc));
93
94                Value::DateTime(dt)
95            }
96            #[cfg(feature = "chrono")]
97            dt @ ColumnData::DateTimeOffset(_) => {
98                use tiberius::time::chrono::{DateTime, Utc};
99
100                Value::DateTime(DateTime::<Utc>::from_sql(&dt)?)
101            }
102            ColumnData::Xml(cow) => Value::Xml(cow.map(|xml_data| Cow::Owned(xml_data.into_owned().into_string()))),
103        };
104
105        Ok(res)
106    }
107}