1use super::ArrayType;
4
5#[derive(Clone, Debug, PartialEq)]
69pub enum Value {
70 Bool(Option<bool>),
75 TinyInt(Option<i8>),
77 SmallInt(Option<i16>),
79 Int(Option<i32>),
81 BigInt(Option<i64>),
83 TinyUnsigned(Option<u8>),
85 SmallUnsigned(Option<u16>),
87 Unsigned(Option<u32>),
89 BigUnsigned(Option<u64>),
91 Float(Option<f32>),
93 Double(Option<f64>),
95 Char(Option<char>),
97
98 String(Option<Box<String>>),
103 Bytes(Option<Box<Vec<u8>>>),
105
106 #[cfg(feature = "with-chrono")]
111 ChronoDate(Option<Box<chrono::NaiveDate>>),
112 #[cfg(feature = "with-chrono")]
114 ChronoTime(Option<Box<chrono::NaiveTime>>),
115 #[cfg(feature = "with-chrono")]
117 ChronoDateTime(Option<Box<chrono::NaiveDateTime>>),
118 #[cfg(feature = "with-chrono")]
120 ChronoDateTimeUtc(Option<Box<chrono::DateTime<chrono::Utc>>>),
121 #[cfg(feature = "with-chrono")]
123 ChronoDateTimeLocal(Option<Box<chrono::DateTime<chrono::Local>>>),
124 #[cfg(feature = "with-chrono")]
126 ChronoDateTimeWithTimeZone(Option<Box<chrono::DateTime<chrono::FixedOffset>>>),
127
128 #[cfg(feature = "with-uuid")]
133 Uuid(Option<Box<uuid::Uuid>>),
134
135 #[cfg(feature = "with-json")]
140 Json(Option<Box<serde_json::Value>>),
141
142 #[cfg(feature = "with-rust_decimal")]
147 Decimal(Option<Box<rust_decimal::Decimal>>),
148
149 #[cfg(feature = "with-bigdecimal")]
151 BigDecimal(Option<Box<bigdecimal::BigDecimal>>),
152
153 Array(ArrayType, Option<Box<Vec<Value>>>),
158}
159
160impl Value {
161 #[must_use]
172 pub fn is_null(&self) -> bool {
173 match self {
174 Self::Bool(v) => v.is_none(),
175 Self::TinyInt(v) => v.is_none(),
176 Self::SmallInt(v) => v.is_none(),
177 Self::Int(v) => v.is_none(),
178 Self::BigInt(v) => v.is_none(),
179 Self::TinyUnsigned(v) => v.is_none(),
180 Self::SmallUnsigned(v) => v.is_none(),
181 Self::Unsigned(v) => v.is_none(),
182 Self::BigUnsigned(v) => v.is_none(),
183 Self::Float(v) => v.is_none(),
184 Self::Double(v) => v.is_none(),
185 Self::Char(v) => v.is_none(),
186 Self::String(v) => v.is_none(),
187 Self::Bytes(v) => v.is_none(),
188 #[cfg(feature = "with-chrono")]
189 Self::ChronoDate(v) => v.is_none(),
190 #[cfg(feature = "with-chrono")]
191 Self::ChronoTime(v) => v.is_none(),
192 #[cfg(feature = "with-chrono")]
193 Self::ChronoDateTime(v) => v.is_none(),
194 #[cfg(feature = "with-chrono")]
195 Self::ChronoDateTimeUtc(v) => v.is_none(),
196 #[cfg(feature = "with-chrono")]
197 Self::ChronoDateTimeLocal(v) => v.is_none(),
198 #[cfg(feature = "with-chrono")]
199 Self::ChronoDateTimeWithTimeZone(v) => v.is_none(),
200 #[cfg(feature = "with-uuid")]
201 Self::Uuid(v) => v.is_none(),
202 #[cfg(feature = "with-json")]
203 Self::Json(v) => v.is_none(),
204 #[cfg(feature = "with-rust_decimal")]
205 Self::Decimal(v) => v.is_none(),
206 #[cfg(feature = "with-bigdecimal")]
207 Self::BigDecimal(v) => v.is_none(),
208 Self::Array(_, v) => v.is_none(),
209 }
210 }
211}
212
213impl Value {
214 #[must_use]
237 pub fn to_sql_literal(&self) -> String {
238 match self {
239 Self::Bool(Some(v)) => {
240 if *v {
241 "TRUE".to_string()
242 } else {
243 "FALSE".to_string()
244 }
245 }
246 Self::Bool(None) => "NULL".to_string(),
247 Self::TinyInt(Some(v)) => v.to_string(),
248 Self::TinyInt(None) => "NULL".to_string(),
249 Self::SmallInt(Some(v)) => v.to_string(),
250 Self::SmallInt(None) => "NULL".to_string(),
251 Self::Int(Some(v)) => v.to_string(),
252 Self::Int(None) => "NULL".to_string(),
253 Self::BigInt(Some(v)) => v.to_string(),
254 Self::BigInt(None) => "NULL".to_string(),
255 Self::TinyUnsigned(Some(v)) => v.to_string(),
256 Self::TinyUnsigned(None) => "NULL".to_string(),
257 Self::SmallUnsigned(Some(v)) => v.to_string(),
258 Self::SmallUnsigned(None) => "NULL".to_string(),
259 Self::Unsigned(Some(v)) => v.to_string(),
260 Self::Unsigned(None) => "NULL".to_string(),
261 Self::BigUnsigned(Some(v)) => v.to_string(),
262 Self::BigUnsigned(None) => "NULL".to_string(),
263 Self::Float(Some(v)) => v.to_string(),
264 Self::Float(None) => "NULL".to_string(),
265 Self::Double(Some(v)) => v.to_string(),
266 Self::Double(None) => "NULL".to_string(),
267 Self::Char(Some(v)) => {
268 if *v == '\'' {
270 "''''".to_string()
271 } else {
272 format!("'{}'", v)
273 }
274 }
275 Self::Char(None) => "NULL".to_string(),
276 Self::String(Some(v)) => {
277 format!("'{}'", v.replace('\'', "''"))
279 }
280 Self::String(None) => "NULL".to_string(),
281 Self::Bytes(Some(v)) => {
282 let hex: String = v.iter().map(|b| format!("{:02X}", b)).collect();
284 format!("X'{}'", hex)
285 }
286 Self::Bytes(None) => "NULL".to_string(),
287 #[cfg(feature = "with-chrono")]
288 Self::ChronoDate(Some(v)) => format!("'{}'", v),
289 #[cfg(feature = "with-chrono")]
290 Self::ChronoDate(None) => "NULL".to_string(),
291 #[cfg(feature = "with-chrono")]
292 Self::ChronoTime(Some(v)) => format!("'{}'", v),
293 #[cfg(feature = "with-chrono")]
294 Self::ChronoTime(None) => "NULL".to_string(),
295 #[cfg(feature = "with-chrono")]
296 Self::ChronoDateTime(Some(v)) => format!("'{}'", v),
297 #[cfg(feature = "with-chrono")]
298 Self::ChronoDateTime(None) => "NULL".to_string(),
299 #[cfg(feature = "with-chrono")]
300 Self::ChronoDateTimeUtc(Some(v)) => format!("'{}'", v.to_rfc3339()),
301 #[cfg(feature = "with-chrono")]
302 Self::ChronoDateTimeUtc(None) => "NULL".to_string(),
303 #[cfg(feature = "with-chrono")]
304 Self::ChronoDateTimeLocal(Some(v)) => format!("'{}'", v.to_rfc3339()),
305 #[cfg(feature = "with-chrono")]
306 Self::ChronoDateTimeLocal(None) => "NULL".to_string(),
307 #[cfg(feature = "with-chrono")]
308 Self::ChronoDateTimeWithTimeZone(Some(v)) => format!("'{}'", v.to_rfc3339()),
309 #[cfg(feature = "with-chrono")]
310 Self::ChronoDateTimeWithTimeZone(None) => "NULL".to_string(),
311 #[cfg(feature = "with-uuid")]
312 Self::Uuid(Some(v)) => format!("'{}'", v),
313 #[cfg(feature = "with-uuid")]
314 Self::Uuid(None) => "NULL".to_string(),
315 #[cfg(feature = "with-json")]
316 Self::Json(Some(v)) => {
317 let json_str = serde_json::to_string(v.as_ref()).unwrap_or_default();
318 format!("'{}'", json_str.replace('\'', "''"))
319 }
320 #[cfg(feature = "with-json")]
321 Self::Json(None) => "NULL".to_string(),
322 #[cfg(feature = "with-rust_decimal")]
323 Self::Decimal(Some(v)) => v.to_string(),
324 #[cfg(feature = "with-rust_decimal")]
325 Self::Decimal(None) => "NULL".to_string(),
326 #[cfg(feature = "with-bigdecimal")]
327 Self::BigDecimal(Some(v)) => v.to_string(),
328 #[cfg(feature = "with-bigdecimal")]
329 Self::BigDecimal(None) => "NULL".to_string(),
330 Self::Array(_, Some(values)) => {
331 let items: Vec<String> = values.iter().map(|v| v.to_sql_literal()).collect();
332 format!("ARRAY[{}]", items.join(","))
333 }
334 Self::Array(_, None) => "NULL".to_string(),
335 }
336 }
337}
338
339impl Default for Value {
340 fn default() -> Self {
342 Self::String(None)
343 }
344}