1use bytes::Bytes;
4
5use crate::tvp::TvpData;
6
7#[derive(Debug, Clone, PartialEq)]
12#[non_exhaustive]
13pub enum SqlValue {
14 Null,
16 Bool(bool),
18 TinyInt(u8),
20 SmallInt(i16),
22 Int(i32),
24 BigInt(i64),
26 Float(f32),
28 Double(f64),
30 String(String),
32 Binary(Bytes),
34 #[cfg(feature = "decimal")]
36 Decimal(rust_decimal::Decimal),
37 #[cfg(feature = "decimal")]
45 Money(rust_decimal::Decimal),
46 #[cfg(feature = "decimal")]
48 SmallMoney(rust_decimal::Decimal),
49 #[cfg(feature = "uuid")]
51 Uuid(uuid::Uuid),
52 #[cfg(feature = "chrono")]
54 Date(chrono::NaiveDate),
55 #[cfg(feature = "chrono")]
57 Time(chrono::NaiveTime),
58 #[cfg(feature = "chrono")]
60 DateTime(chrono::NaiveDateTime),
61 #[cfg(feature = "chrono")]
68 SmallDateTime(chrono::NaiveDateTime),
69 #[cfg(feature = "chrono")]
71 DateTimeOffset(chrono::DateTime<chrono::FixedOffset>),
72 #[cfg(feature = "json")]
74 Json(serde_json::Value),
75 Xml(String),
77 Tvp(Box<TvpData>),
82}
83
84impl SqlValue {
85 #[must_use]
87 pub fn is_null(&self) -> bool {
88 matches!(self, Self::Null)
89 }
90
91 #[must_use]
93 pub fn as_bool(&self) -> Option<bool> {
94 match self {
95 Self::Bool(v) => Some(*v),
96 _ => None,
97 }
98 }
99
100 #[must_use]
102 pub fn as_i32(&self) -> Option<i32> {
103 match self {
104 Self::Int(v) => Some(*v),
105 Self::SmallInt(v) => Some(*v as i32),
106 Self::TinyInt(v) => Some(*v as i32),
107 _ => None,
108 }
109 }
110
111 #[must_use]
113 pub fn as_i64(&self) -> Option<i64> {
114 match self {
115 Self::BigInt(v) => Some(*v),
116 Self::Int(v) => Some(*v as i64),
117 Self::SmallInt(v) => Some(*v as i64),
118 Self::TinyInt(v) => Some(*v as i64),
119 _ => None,
120 }
121 }
122
123 #[must_use]
125 pub fn as_f64(&self) -> Option<f64> {
126 match self {
127 Self::Double(v) => Some(*v),
128 Self::Float(v) => Some(*v as f64),
129 _ => None,
130 }
131 }
132
133 #[must_use]
135 pub fn as_str(&self) -> Option<&str> {
136 match self {
137 Self::String(v) => Some(v),
138 Self::Xml(v) => Some(v),
139 _ => None,
140 }
141 }
142
143 #[must_use]
145 pub fn as_bytes(&self) -> Option<&[u8]> {
146 match self {
147 Self::Binary(v) => Some(v),
148 _ => None,
149 }
150 }
151
152 #[must_use]
154 pub fn type_name(&self) -> &'static str {
155 match self {
156 Self::Null => "NULL",
157 Self::Bool(_) => "BIT",
158 Self::TinyInt(_) => "TINYINT",
159 Self::SmallInt(_) => "SMALLINT",
160 Self::Int(_) => "INT",
161 Self::BigInt(_) => "BIGINT",
162 Self::Float(_) => "REAL",
163 Self::Double(_) => "FLOAT",
164 Self::String(_) => "NVARCHAR",
165 Self::Binary(_) => "VARBINARY",
166 #[cfg(feature = "decimal")]
167 Self::Decimal(_) => "DECIMAL",
168 #[cfg(feature = "decimal")]
169 Self::Money(_) => "MONEY",
170 #[cfg(feature = "decimal")]
171 Self::SmallMoney(_) => "SMALLMONEY",
172 #[cfg(feature = "uuid")]
173 Self::Uuid(_) => "UNIQUEIDENTIFIER",
174 #[cfg(feature = "chrono")]
175 Self::Date(_) => "DATE",
176 #[cfg(feature = "chrono")]
177 Self::Time(_) => "TIME",
178 #[cfg(feature = "chrono")]
179 Self::DateTime(_) => "DATETIME2",
180 #[cfg(feature = "chrono")]
181 Self::SmallDateTime(_) => "SMALLDATETIME",
182 #[cfg(feature = "chrono")]
183 Self::DateTimeOffset(_) => "DATETIMEOFFSET",
184 #[cfg(feature = "json")]
185 Self::Json(_) => "JSON",
186 Self::Xml(_) => "XML",
187 Self::Tvp(_) => "TVP",
188 }
189 }
190
191 #[must_use]
193 pub fn as_tvp(&self) -> Option<&TvpData> {
194 match self {
195 Self::Tvp(v) => Some(v),
196 _ => None,
197 }
198 }
199}
200
201impl Default for SqlValue {
202 fn default() -> Self {
203 Self::Null
204 }
205}
206
207impl From<bool> for SqlValue {
208 fn from(v: bool) -> Self {
209 Self::Bool(v)
210 }
211}
212
213impl From<i32> for SqlValue {
214 fn from(v: i32) -> Self {
215 Self::Int(v)
216 }
217}
218
219impl From<i64> for SqlValue {
220 fn from(v: i64) -> Self {
221 Self::BigInt(v)
222 }
223}
224
225impl From<f32> for SqlValue {
226 fn from(v: f32) -> Self {
227 Self::Float(v)
228 }
229}
230
231impl From<f64> for SqlValue {
232 fn from(v: f64) -> Self {
233 Self::Double(v)
234 }
235}
236
237impl From<String> for SqlValue {
238 fn from(v: String) -> Self {
239 Self::String(v)
240 }
241}
242
243impl From<&str> for SqlValue {
244 fn from(v: &str) -> Self {
245 Self::String(v.to_owned())
246 }
247}
248
249impl<T> From<Option<T>> for SqlValue
250where
251 T: Into<SqlValue>,
252{
253 fn from(v: Option<T>) -> Self {
254 match v {
255 Some(v) => v.into(),
256 None => Self::Null,
257 }
258 }
259}
260
261#[cfg(feature = "uuid")]
262impl From<uuid::Uuid> for SqlValue {
263 fn from(v: uuid::Uuid) -> Self {
264 Self::Uuid(v)
265 }
266}
267
268#[cfg(feature = "decimal")]
269impl From<rust_decimal::Decimal> for SqlValue {
270 fn from(v: rust_decimal::Decimal) -> Self {
271 Self::Decimal(v)
272 }
273}
274
275#[cfg(feature = "chrono")]
276impl From<chrono::NaiveDate> for SqlValue {
277 fn from(v: chrono::NaiveDate) -> Self {
278 Self::Date(v)
279 }
280}
281
282#[cfg(feature = "chrono")]
283impl From<chrono::NaiveDateTime> for SqlValue {
284 fn from(v: chrono::NaiveDateTime) -> Self {
285 Self::DateTime(v)
286 }
287}
288
289#[cfg(feature = "json")]
290impl From<serde_json::Value> for SqlValue {
291 fn from(v: serde_json::Value) -> Self {
292 Self::Json(v)
293 }
294}
295
296impl From<TvpData> for SqlValue {
297 fn from(v: TvpData) -> Self {
298 Self::Tvp(Box::new(v))
299 }
300}
301
302#[cfg(feature = "decimal")]
309#[derive(Debug, Clone, Copy, PartialEq, Eq)]
310pub struct Money(pub rust_decimal::Decimal);
311
312#[cfg(feature = "decimal")]
315#[derive(Debug, Clone, Copy, PartialEq, Eq)]
316pub struct SmallMoney(pub rust_decimal::Decimal);
317
318#[cfg(feature = "chrono")]
326#[derive(Debug, Clone, Copy, PartialEq, Eq)]
327pub struct SmallDateTime(pub chrono::NaiveDateTime);
328
329#[cfg(feature = "decimal")]
330impl From<Money> for SqlValue {
331 fn from(v: Money) -> Self {
332 Self::Money(v.0)
333 }
334}
335
336#[cfg(feature = "decimal")]
337impl From<SmallMoney> for SqlValue {
338 fn from(v: SmallMoney) -> Self {
339 Self::SmallMoney(v.0)
340 }
341}
342
343#[cfg(feature = "chrono")]
344impl From<SmallDateTime> for SqlValue {
345 fn from(v: SmallDateTime) -> Self {
346 Self::SmallDateTime(v.0)
347 }
348}