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 = "uuid")]
39 Uuid(uuid::Uuid),
40 #[cfg(feature = "chrono")]
42 Date(chrono::NaiveDate),
43 #[cfg(feature = "chrono")]
45 Time(chrono::NaiveTime),
46 #[cfg(feature = "chrono")]
48 DateTime(chrono::NaiveDateTime),
49 #[cfg(feature = "chrono")]
51 DateTimeOffset(chrono::DateTime<chrono::FixedOffset>),
52 #[cfg(feature = "json")]
54 Json(serde_json::Value),
55 Xml(String),
57 Tvp(Box<TvpData>),
62}
63
64impl SqlValue {
65 #[must_use]
67 pub fn is_null(&self) -> bool {
68 matches!(self, Self::Null)
69 }
70
71 #[must_use]
73 pub fn as_bool(&self) -> Option<bool> {
74 match self {
75 Self::Bool(v) => Some(*v),
76 _ => None,
77 }
78 }
79
80 #[must_use]
82 pub fn as_i32(&self) -> Option<i32> {
83 match self {
84 Self::Int(v) => Some(*v),
85 Self::SmallInt(v) => Some(*v as i32),
86 Self::TinyInt(v) => Some(*v as i32),
87 _ => None,
88 }
89 }
90
91 #[must_use]
93 pub fn as_i64(&self) -> Option<i64> {
94 match self {
95 Self::BigInt(v) => Some(*v),
96 Self::Int(v) => Some(*v as i64),
97 Self::SmallInt(v) => Some(*v as i64),
98 Self::TinyInt(v) => Some(*v as i64),
99 _ => None,
100 }
101 }
102
103 #[must_use]
105 pub fn as_f64(&self) -> Option<f64> {
106 match self {
107 Self::Double(v) => Some(*v),
108 Self::Float(v) => Some(*v as f64),
109 _ => None,
110 }
111 }
112
113 #[must_use]
115 pub fn as_str(&self) -> Option<&str> {
116 match self {
117 Self::String(v) => Some(v),
118 Self::Xml(v) => Some(v),
119 _ => None,
120 }
121 }
122
123 #[must_use]
125 pub fn as_bytes(&self) -> Option<&[u8]> {
126 match self {
127 Self::Binary(v) => Some(v),
128 _ => None,
129 }
130 }
131
132 #[must_use]
134 pub fn type_name(&self) -> &'static str {
135 match self {
136 Self::Null => "NULL",
137 Self::Bool(_) => "BIT",
138 Self::TinyInt(_) => "TINYINT",
139 Self::SmallInt(_) => "SMALLINT",
140 Self::Int(_) => "INT",
141 Self::BigInt(_) => "BIGINT",
142 Self::Float(_) => "REAL",
143 Self::Double(_) => "FLOAT",
144 Self::String(_) => "NVARCHAR",
145 Self::Binary(_) => "VARBINARY",
146 #[cfg(feature = "decimal")]
147 Self::Decimal(_) => "DECIMAL",
148 #[cfg(feature = "uuid")]
149 Self::Uuid(_) => "UNIQUEIDENTIFIER",
150 #[cfg(feature = "chrono")]
151 Self::Date(_) => "DATE",
152 #[cfg(feature = "chrono")]
153 Self::Time(_) => "TIME",
154 #[cfg(feature = "chrono")]
155 Self::DateTime(_) => "DATETIME2",
156 #[cfg(feature = "chrono")]
157 Self::DateTimeOffset(_) => "DATETIMEOFFSET",
158 #[cfg(feature = "json")]
159 Self::Json(_) => "JSON",
160 Self::Xml(_) => "XML",
161 Self::Tvp(_) => "TVP",
162 }
163 }
164
165 #[must_use]
167 pub fn as_tvp(&self) -> Option<&TvpData> {
168 match self {
169 Self::Tvp(v) => Some(v),
170 _ => None,
171 }
172 }
173}
174
175impl Default for SqlValue {
176 fn default() -> Self {
177 Self::Null
178 }
179}
180
181impl From<bool> for SqlValue {
182 fn from(v: bool) -> Self {
183 Self::Bool(v)
184 }
185}
186
187impl From<i32> for SqlValue {
188 fn from(v: i32) -> Self {
189 Self::Int(v)
190 }
191}
192
193impl From<i64> for SqlValue {
194 fn from(v: i64) -> Self {
195 Self::BigInt(v)
196 }
197}
198
199impl From<f32> for SqlValue {
200 fn from(v: f32) -> Self {
201 Self::Float(v)
202 }
203}
204
205impl From<f64> for SqlValue {
206 fn from(v: f64) -> Self {
207 Self::Double(v)
208 }
209}
210
211impl From<String> for SqlValue {
212 fn from(v: String) -> Self {
213 Self::String(v)
214 }
215}
216
217impl From<&str> for SqlValue {
218 fn from(v: &str) -> Self {
219 Self::String(v.to_owned())
220 }
221}
222
223impl<T> From<Option<T>> for SqlValue
224where
225 T: Into<SqlValue>,
226{
227 fn from(v: Option<T>) -> Self {
228 match v {
229 Some(v) => v.into(),
230 None => Self::Null,
231 }
232 }
233}
234
235#[cfg(feature = "uuid")]
236impl From<uuid::Uuid> for SqlValue {
237 fn from(v: uuid::Uuid) -> Self {
238 Self::Uuid(v)
239 }
240}
241
242#[cfg(feature = "decimal")]
243impl From<rust_decimal::Decimal> for SqlValue {
244 fn from(v: rust_decimal::Decimal) -> Self {
245 Self::Decimal(v)
246 }
247}
248
249#[cfg(feature = "chrono")]
250impl From<chrono::NaiveDate> for SqlValue {
251 fn from(v: chrono::NaiveDate) -> Self {
252 Self::Date(v)
253 }
254}
255
256#[cfg(feature = "chrono")]
257impl From<chrono::NaiveDateTime> for SqlValue {
258 fn from(v: chrono::NaiveDateTime) -> Self {
259 Self::DateTime(v)
260 }
261}
262
263#[cfg(feature = "json")]
264impl From<serde_json::Value> for SqlValue {
265 fn from(v: serde_json::Value) -> Self {
266 Self::Json(v)
267 }
268}
269
270impl From<TvpData> for SqlValue {
271 fn from(v: TvpData) -> Self {
272 Self::Tvp(Box::new(v))
273 }
274}