Skip to main content

drizzle_mysql/values/
owned.rs

1//! [`OwnedMySQLValue`], the owned form of [`MySQLValue`](super::MySQLValue).
2
3use super::MySQLValue;
4use crate::prelude::*;
5use drizzle_core::{Dialect, MySQLDialect, SQL, SQLParam};
6
7/// A [`MySQLValue`] that owns its bytes, for storing parameters beyond the
8/// borrow (for example in a cached prepared statement).
9///
10/// Convert with [`MySQLValue::into_owned`] or `From`. `SQL::into_owned()`
11/// does not do this for you: it owns the chunk list but keeps the parameter
12/// type.
13#[derive(Debug, Clone, PartialEq, Default)]
14pub enum OwnedMySQLValue {
15    /// SQL `NULL`.
16    #[default]
17    Null,
18    /// Owned text, binary, decimal, JSON, enum, or set bytes.
19    Bytes(Vec<u8>),
20    /// Signed integer payload.
21    Int(i64),
22    /// Unsigned integer payload.
23    UInt(u64),
24    /// Single-precision floating-point payload.
25    Float(f32),
26    /// Double-precision floating-point payload.
27    Double(f64),
28    /// Owned date, datetime, or timestamp payload.
29    Date {
30        /// Four-digit year.
31        year: u16,
32        /// Month in the range 1 through 12.
33        month: u8,
34        /// Day of the month.
35        day: u8,
36        /// Hour in the range 0 through 23.
37        hour: u8,
38        /// Minute in the range 0 through 59.
39        minute: u8,
40        /// Second in the range 0 through 59.
41        second: u8,
42        /// Fractional seconds in microseconds.
43        microseconds: u32,
44    },
45    /// Owned time or duration payload.
46    Time {
47        /// Whether the duration is negative.
48        negative: bool,
49        /// Whole days in the duration.
50        days: u32,
51        /// Remaining hours after whole days.
52        hours: u8,
53        /// Remaining minutes after whole hours.
54        minutes: u8,
55        /// Remaining seconds after whole minutes.
56        seconds: u8,
57        /// Fractional seconds in microseconds.
58        microseconds: u32,
59    },
60}
61
62impl SQLParam for OwnedMySQLValue {
63    const DIALECT: Dialect = Dialect::MySQL;
64    type DialectMarker = MySQLDialect;
65
66    fn pagination_param(value: usize) -> Option<Self> {
67        u64::try_from(value).ok().map(Self::UInt)
68    }
69}
70
71impl From<OwnedMySQLValue> for SQL<'_, OwnedMySQLValue> {
72    fn from(value: OwnedMySQLValue) -> Self {
73        SQL::param(value)
74    }
75}
76
77impl From<OwnedMySQLValue> for Cow<'_, OwnedMySQLValue> {
78    fn from(value: OwnedMySQLValue) -> Self {
79        Cow::Owned(value)
80    }
81}
82
83impl<'a> From<&'a OwnedMySQLValue> for Cow<'a, OwnedMySQLValue> {
84    fn from(value: &'a OwnedMySQLValue) -> Self {
85        Cow::Borrowed(value)
86    }
87}
88
89impl<'a> From<MySQLValue<'a>> for OwnedMySQLValue {
90    fn from(value: MySQLValue<'a>) -> Self {
91        match value {
92            MySQLValue::Null => Self::Null,
93            MySQLValue::Bytes(value) => Self::Bytes(value.into_owned()),
94            MySQLValue::Int(value) => Self::Int(value),
95            MySQLValue::UInt(value) => Self::UInt(value),
96            MySQLValue::Float(value) => Self::Float(value),
97            MySQLValue::Double(value) => Self::Double(value),
98            MySQLValue::Date {
99                year,
100                month,
101                day,
102                hour,
103                minute,
104                second,
105                microseconds,
106            } => Self::Date {
107                year,
108                month,
109                day,
110                hour,
111                minute,
112                second,
113                microseconds,
114            },
115            MySQLValue::Time {
116                negative,
117                days,
118                hours,
119                minutes,
120                seconds,
121                microseconds,
122            } => Self::Time {
123                negative,
124                days,
125                hours,
126                minutes,
127                seconds,
128                microseconds,
129            },
130        }
131    }
132}
133
134impl From<OwnedMySQLValue> for MySQLValue<'_> {
135    fn from(value: OwnedMySQLValue) -> Self {
136        match value {
137            OwnedMySQLValue::Null => Self::Null,
138            OwnedMySQLValue::Bytes(value) => Self::Bytes(Cow::Owned(value)),
139            OwnedMySQLValue::Int(value) => Self::Int(value),
140            OwnedMySQLValue::UInt(value) => Self::UInt(value),
141            OwnedMySQLValue::Float(value) => Self::Float(value),
142            OwnedMySQLValue::Double(value) => Self::Double(value),
143            OwnedMySQLValue::Date {
144                year,
145                month,
146                day,
147                hour,
148                minute,
149                second,
150                microseconds,
151            } => Self::Date {
152                year,
153                month,
154                day,
155                hour,
156                minute,
157                second,
158                microseconds,
159            },
160            OwnedMySQLValue::Time {
161                negative,
162                days,
163                hours,
164                minutes,
165                seconds,
166                microseconds,
167            } => Self::Time {
168                negative,
169                days,
170                hours,
171                minutes,
172                seconds,
173                microseconds,
174            },
175        }
176    }
177}
178
179impl<'a> From<&'a OwnedMySQLValue> for MySQLValue<'a> {
180    fn from(value: &'a OwnedMySQLValue) -> Self {
181        match value {
182            OwnedMySQLValue::Null => Self::Null,
183            OwnedMySQLValue::Bytes(value) => Self::Bytes(Cow::Borrowed(value)),
184            OwnedMySQLValue::Int(value) => Self::Int(*value),
185            OwnedMySQLValue::UInt(value) => Self::UInt(*value),
186            OwnedMySQLValue::Float(value) => Self::Float(*value),
187            OwnedMySQLValue::Double(value) => Self::Double(*value),
188            OwnedMySQLValue::Date {
189                year,
190                month,
191                day,
192                hour,
193                minute,
194                second,
195                microseconds,
196            } => Self::Date {
197                year: *year,
198                month: *month,
199                day: *day,
200                hour: *hour,
201                minute: *minute,
202                second: *second,
203                microseconds: *microseconds,
204            },
205            OwnedMySQLValue::Time {
206                negative,
207                days,
208                hours,
209                minutes,
210                seconds,
211                microseconds,
212            } => Self::Time {
213                negative: *negative,
214                days: *days,
215                hours: *hours,
216                minutes: *minutes,
217                seconds: *seconds,
218                microseconds: *microseconds,
219            },
220        }
221    }
222}
223
224macro_rules! via_mysql_value {
225    (both: [$($both:ty),+ $(,)?], owned: [$($owned:ty),* $(,)?]) => {
226        $(
227            impl From<$both> for OwnedMySQLValue {
228                fn from(value: $both) -> Self {
229                    MySQLValue::from(value).into_owned()
230                }
231            }
232
233            impl From<&$both> for OwnedMySQLValue {
234                fn from(value: &$both) -> Self {
235                    MySQLValue::from(value).into_owned()
236                }
237            }
238        )+
239
240        $(
241            impl From<$owned> for OwnedMySQLValue {
242                fn from(value: $owned) -> Self {
243                    MySQLValue::from(value).into_owned()
244                }
245            }
246        )*
247    };
248}
249
250via_mysql_value!(
251    both: [
252        i8,
253        i16,
254        i32,
255        i64,
256        isize,
257        u8,
258        u16,
259        u32,
260        u64,
261        usize,
262        bool,
263        f32,
264        f64,
265        String,
266        Box<String>,
267        Rc<String>,
268        Arc<String>,
269        Box<str>,
270        Rc<str>,
271        Arc<str>,
272        Box<Vec<u8>>,
273        Rc<Vec<u8>>,
274        Arc<Vec<u8>>,
275    ],
276    owned: [Vec<u8>]
277);
278
279impl From<&str> for OwnedMySQLValue {
280    fn from(value: &str) -> Self {
281        MySQLValue::from(value).into_owned()
282    }
283}
284
285impl From<&[u8]> for OwnedMySQLValue {
286    fn from(value: &[u8]) -> Self {
287        MySQLValue::from(value).into_owned()
288    }
289}
290
291impl<const N: usize> From<[u8; N]> for OwnedMySQLValue {
292    fn from(value: [u8; N]) -> Self {
293        MySQLValue::from(value).into_owned()
294    }
295}
296
297impl<const N: usize> From<&[u8; N]> for OwnedMySQLValue {
298    fn from(value: &[u8; N]) -> Self {
299        MySQLValue::from(value).into_owned()
300    }
301}
302
303impl<const N: usize> From<[char; N]> for OwnedMySQLValue {
304    fn from(value: [char; N]) -> Self {
305        MySQLValue::from(value).into_owned()
306    }
307}
308
309impl<const N: usize> From<&[char; N]> for OwnedMySQLValue {
310    fn from(value: &[char; N]) -> Self {
311        MySQLValue::from(value).into_owned()
312    }
313}
314
315impl From<Cow<'_, str>> for OwnedMySQLValue {
316    fn from(value: Cow<'_, str>) -> Self {
317        MySQLValue::from(value).into_owned()
318    }
319}
320
321impl From<Cow<'_, [u8]>> for OwnedMySQLValue {
322    fn from(value: Cow<'_, [u8]>) -> Self {
323        MySQLValue::from(value).into_owned()
324    }
325}
326
327impl<T> From<Option<T>> for OwnedMySQLValue
328where
329    Self: From<T>,
330{
331    fn from(value: Option<T>) -> Self {
332        value.map_or(Self::Null, Self::from)
333    }
334}
335
336#[cfg(feature = "compact-str")]
337via_mysql_value!(both: [compact_str::CompactString], owned: []);
338
339#[cfg(feature = "arrayvec")]
340impl<const N: usize> From<arrayvec::ArrayString<N>> for OwnedMySQLValue {
341    fn from(value: arrayvec::ArrayString<N>) -> Self {
342        MySQLValue::from(value).into_owned()
343    }
344}
345
346#[cfg(feature = "arrayvec")]
347impl<const N: usize> From<arrayvec::ArrayVec<u8, N>> for OwnedMySQLValue {
348    fn from(value: arrayvec::ArrayVec<u8, N>) -> Self {
349        MySQLValue::from(value).into_owned()
350    }
351}
352
353#[cfg(feature = "smallvec")]
354impl<const N: usize> From<smallvec::SmallVec<[u8; N]>> for OwnedMySQLValue {
355    fn from(value: smallvec::SmallVec<[u8; N]>) -> Self {
356        MySQLValue::from(value).into_owned()
357    }
358}
359
360#[cfg(feature = "bytes")]
361via_mysql_value!(both: [bytes::Bytes, bytes::BytesMut], owned: []);
362
363#[cfg(feature = "uuid")]
364via_mysql_value!(both: [uuid::Uuid], owned: []);
365
366#[cfg(feature = "serde")]
367via_mysql_value!(both: [serde_json::Value], owned: []);
368
369#[cfg(feature = "rust-decimal")]
370via_mysql_value!(both: [rust_decimal::Decimal], owned: []);
371
372#[cfg(feature = "chrono")]
373via_mysql_value!(
374    both: [chrono::NaiveDate, chrono::NaiveTime, chrono::NaiveDateTime],
375    owned: [chrono::DateTime<chrono::Utc>, chrono::DateTime<chrono::FixedOffset>]
376);
377
378#[cfg(feature = "time")]
379via_mysql_value!(
380    both: [time::Date, time::Time, time::PrimitiveDateTime],
381    owned: [time::OffsetDateTime]
382);
383
384#[cfg(feature = "jiff")]
385via_mysql_value!(
386    both: [
387        jiff::civil::Date,
388        jiff::civil::Time,
389        jiff::civil::DateTime,
390        jiff::Timestamp,
391    ],
392    owned: []
393);