tiberius/
to_sql.rs

1use crate::{
2    tds::{codec::ColumnData, Numeric},
3    xml::XmlData,
4};
5use std::borrow::Cow;
6use uuid::Uuid;
7
8/// A conversion trait to a TDS type.
9///
10/// A `ToSql` implementation for a Rust type is needed for using it as a
11/// parameter in the [`Client#query`] or [`Client#execute`] methods. The
12/// following Rust types are already implemented to match the given server
13/// types:
14///
15/// |Rust type|Server type|
16/// |--------|--------|
17/// |`u8`|`tinyint`|
18/// |`i16`|`smallint`|
19/// |`i32`|`int`|
20/// |`i64`|`bigint`|
21/// |`f32`|`float(24)`|
22/// |`f64`|`float(53)`|
23/// |`bool`|`bit`|
24/// |`String`/`&str` (< 4000 characters)|`nvarchar(4000)`|
25/// |`String`/`&str`|`nvarchar(max)`|
26/// |`Vec<u8>`/`&[u8]` (< 8000 bytes)|`varbinary(8000)`|
27/// |`Vec<u8>`/`&[u8]`|`varbinary(max)`|
28/// |[`Uuid`]|`uniqueidentifier`|
29/// |[`Numeric`]|`numeric`/`decimal`|
30/// |[`Decimal`] (with feature flag `rust_decimal`)|`numeric`/`decimal`|
31/// |[`BigDecimal`] (with feature flag `bigdecimal`)|`numeric`/`decimal`|
32/// |[`XmlData`]|`xml`|
33/// |[`NaiveDate`] (with `chrono` feature, TDS 7.3 >)|`date`|
34/// |[`NaiveTime`] (with `chrono` feature, TDS 7.3 >)|`time`|
35/// |[`DateTime`] (with `chrono` feature, TDS 7.3 >)|`datetimeoffset`|
36/// |[`NaiveDateTime`] (with `chrono` feature, TDS 7.3 >)|`datetime2`|
37/// |[`NaiveDateTime`] (with `chrono` feature, TDS 7.2)|`datetime`|
38///
39/// It is possible to use some of the types to write into columns that are not
40/// of the same type. For example on systems following the TDS 7.3 standard (SQL
41/// Server 2008 and later), the chrono type `NaiveDateTime` can also be used to
42/// write to `datetime`, `datetime2` and `smalldatetime` columns. All string
43/// types can also be used with `ntext`, `text`, `varchar`, `nchar` and `char`
44/// columns. All binary types can also be used with `binary` and `image`
45/// columns.
46///
47/// See the [`time`] module for more information about the date and time structs.
48///
49/// [`Client#query`]: struct.Client.html#method.query
50/// [`Client#execute`]: struct.Client.html#method.execute
51/// [`time`]: time/index.html
52/// [`Uuid`]: struct.Uuid.html
53/// [`Numeric`]: numeric/struct.Numeric.html
54/// [`Decimal`]: numeric/struct.Decimal.html
55/// [`BigDecimal`]: numeric/struct.BigDecimal.html
56/// [`XmlData`]: xml/struct.XmlData.html
57/// [`NaiveDateTime`]: time/chrono/struct.NaiveDateTime.html
58/// [`NaiveDate`]: time/chrono/struct.NaiveDate.html
59/// [`NaiveTime`]: time/chrono/struct.NaiveTime.html
60/// [`DateTime`]: time/chrono/struct.DateTime.html
61pub trait ToSql: Send + Sync {
62    /// Convert to a value understood by the SQL Server. Conversion
63    /// by-reference.
64    fn to_sql(&self) -> ColumnData<'_>;
65}
66
67/// A by-value conversion trait to a TDS type.
68pub trait IntoSql<'a>: Send + Sync {
69    /// Convert to a value understood by the SQL Server. Conversion by-value.
70    fn into_sql(self) -> ColumnData<'a>;
71}
72
73impl<'a> IntoSql<'a> for &'a str {
74    fn into_sql(self) -> ColumnData<'a> {
75        ColumnData::String(Some(Cow::Borrowed(self)))
76    }
77}
78
79impl<'a> IntoSql<'a> for Option<&'a str> {
80    fn into_sql(self) -> ColumnData<'a> {
81        ColumnData::String(self.map(Cow::Borrowed))
82    }
83}
84
85impl<'a> IntoSql<'a> for &'a String {
86    fn into_sql(self) -> ColumnData<'a> {
87        ColumnData::String(Some(Cow::Borrowed(self)))
88    }
89}
90
91impl<'a> IntoSql<'a> for Option<&'a String> {
92    fn into_sql(self) -> ColumnData<'a> {
93        ColumnData::String(self.map(Cow::from))
94    }
95}
96
97impl<'a> IntoSql<'a> for &'a [u8] {
98    fn into_sql(self) -> ColumnData<'a> {
99        ColumnData::Binary(Some(Cow::Borrowed(self)))
100    }
101}
102
103impl<'a> IntoSql<'a> for Option<&'a [u8]> {
104    fn into_sql(self) -> ColumnData<'a> {
105        ColumnData::Binary(self.map(Cow::Borrowed))
106    }
107}
108
109impl<'a> IntoSql<'a> for &'a Vec<u8> {
110    fn into_sql(self) -> ColumnData<'a> {
111        ColumnData::Binary(Some(Cow::from(self)))
112    }
113}
114
115impl<'a> IntoSql<'a> for Option<&'a Vec<u8>> {
116    fn into_sql(self) -> ColumnData<'a> {
117        ColumnData::Binary(self.map(Cow::from))
118    }
119}
120
121impl<'a> IntoSql<'a> for Cow<'a, str> {
122    fn into_sql(self) -> ColumnData<'a> {
123        ColumnData::String(Some(self))
124    }
125}
126
127impl<'a> IntoSql<'a> for Option<Cow<'a, str>> {
128    fn into_sql(self) -> ColumnData<'a> {
129        ColumnData::String(self)
130    }
131}
132
133impl<'a> IntoSql<'a> for Cow<'a, [u8]> {
134    fn into_sql(self) -> ColumnData<'a> {
135        ColumnData::Binary(Some(self))
136    }
137}
138
139impl<'a> IntoSql<'a> for Option<Cow<'a, [u8]>> {
140    fn into_sql(self) -> ColumnData<'a> {
141        ColumnData::Binary(self)
142    }
143}
144
145impl<'a> IntoSql<'a> for &'a XmlData {
146    fn into_sql(self) -> ColumnData<'a> {
147        ColumnData::Xml(Some(Cow::Borrowed(self)))
148    }
149}
150
151impl<'a> IntoSql<'a> for Option<&'a XmlData> {
152    fn into_sql(self) -> ColumnData<'a> {
153        ColumnData::Xml(self.map(Cow::Borrowed))
154    }
155}
156
157impl<'a> IntoSql<'a> for &'a Uuid {
158    fn into_sql(self) -> ColumnData<'a> {
159        ColumnData::Guid(Some(*self))
160    }
161}
162
163impl<'a> IntoSql<'a> for Option<&'a Uuid> {
164    fn into_sql(self) -> ColumnData<'a> {
165        ColumnData::Guid(self.copied())
166    }
167}
168
169into_sql!(self_,
170          String: (ColumnData::String, Cow::from(self_));
171          Vec<u8>: (ColumnData::Binary, Cow::from(self_));
172          Numeric: (ColumnData::Numeric, self_);
173          XmlData: (ColumnData::Xml, Cow::Owned(self_));
174          Uuid: (ColumnData::Guid, self_);
175          bool: (ColumnData::Bit, self_);
176          u8: (ColumnData::U8, self_);
177          i16: (ColumnData::I16, self_);
178          i32: (ColumnData::I32, self_);
179          i64: (ColumnData::I64, self_);
180          f32: (ColumnData::F32, self_);
181          f64: (ColumnData::F64, self_);
182);
183
184to_sql!(self_,
185        bool: (ColumnData::Bit, *self_);
186        u8: (ColumnData::U8, *self_);
187        i16: (ColumnData::I16, *self_);
188        i32: (ColumnData::I32, *self_);
189        i64: (ColumnData::I64, *self_);
190        f32: (ColumnData::F32, *self_);
191        f64: (ColumnData::F64, *self_);
192        &str: (ColumnData::String, Cow::from(*self_));
193        String: (ColumnData::String, Cow::from(self_));
194        Cow<'_, str>: (ColumnData::String, self_.clone());
195        &[u8]: (ColumnData::Binary, Cow::from(*self_));
196        Cow<'_, [u8]>: (ColumnData::Binary, self_.clone());
197        Vec<u8>: (ColumnData::Binary, Cow::from(self_));
198        Numeric: (ColumnData::Numeric, *self_);
199        XmlData: (ColumnData::Xml, Cow::Borrowed(self_));
200        Uuid: (ColumnData::Guid, *self_);
201);