1use chrono::{NaiveDate, NaiveDateTime, NaiveTime, TimeDelta};
2use diesel::{
3 deserialize::{FromSql, Result as DeserializeResult},
4 serialize::{IsNull, Output, Result as SerializeResult, ToSql},
5 sql_types::{BigInt, Date as SqlDate, Interval, Time, Timestamp as SqlTimestamp},
6};
7
8#[cfg(feature = "date")]
9use crate::Date;
10
11#[cfg(feature = "datetime")]
12use crate::DateTime;
13
14#[cfg(feature = "timeofday")]
15use crate::TimeOfDay;
16
17use crate::{Duration, Timestamp};
18
19#[cfg(feature = "diesel-mysql")]
20mod diesel_mysql {
21
22 use diesel::{
23 mysql::{Mysql, MysqlValue},
24 sql_types::Datetime as MysqlDateTime,
25 };
26
27 use super::*;
28
29 #[cfg(feature = "timeofday")]
30 impl FromSql<Time, Mysql> for TimeOfDay {
31 fn from_sql(bytes: MysqlValue<'_>) -> DeserializeResult<Self> {
32 let chrono_time: NaiveTime = FromSql::<Time, Mysql>::from_sql(bytes)?;
33 Ok(chrono_time.into())
34 }
35 }
36
37 impl FromSql<SqlTimestamp, Mysql> for Timestamp {
38 fn from_sql(bytes: MysqlValue<'_>) -> DeserializeResult<Self> {
39 let chrono_datetime: NaiveDateTime = FromSql::<SqlTimestamp, Mysql>::from_sql(bytes)?;
40 Ok(chrono_datetime.into())
41 }
42 }
43
44 impl FromSql<BigInt, Mysql> for Timestamp {
45 fn from_sql(bytes: MysqlValue<'_>) -> DeserializeResult<Self> {
46 let millis: i64 = FromSql::<BigInt, Mysql>::from_sql(bytes)?;
47
48 Ok(Self::from_unix_millis(millis))
49 }
50 }
51
52 impl FromSql<MysqlDateTime, Mysql> for Timestamp {
53 fn from_sql(bytes: MysqlValue<'_>) -> DeserializeResult<Self> {
54 let chrono_datetime: NaiveDateTime = FromSql::<MysqlDateTime, Mysql>::from_sql(bytes)?;
55 Ok(chrono_datetime.into())
56 }
57 }
58
59 #[cfg(feature = "datetime")]
60 impl FromSql<SqlTimestamp, Mysql> for DateTime {
61 fn from_sql(bytes: MysqlValue<'_>) -> DeserializeResult<Self> {
62 let chrono_datetime: NaiveDateTime = FromSql::<SqlTimestamp, Mysql>::from_sql(bytes)?;
63 Ok(chrono_datetime.into())
64 }
65 }
66
67 #[cfg(feature = "datetime")]
68 impl FromSql<MysqlDateTime, Mysql> for DateTime {
69 fn from_sql(bytes: MysqlValue<'_>) -> DeserializeResult<Self> {
70 let chrono_datetime: NaiveDateTime = FromSql::<MysqlDateTime, Mysql>::from_sql(bytes)?;
71 Ok(chrono_datetime.into())
72 }
73 }
74
75 #[cfg(feature = "date")]
76 impl FromSql<SqlDate, Mysql> for Date {
77 fn from_sql(bytes: MysqlValue<'_>) -> DeserializeResult<Self> {
78 let chrono_date: NaiveDate = FromSql::<SqlDate, Mysql>::from_sql(bytes)?;
79 Ok(chrono_date.into())
80 }
81 }
82
83 #[cfg(feature = "timeofday")]
84 impl ToSql<Time, Mysql> for TimeOfDay {
85 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> SerializeResult {
86 let chrono_time: NaiveTime = (*self).try_into()?;
87
88 ToSql::<Time, Mysql>::to_sql(&chrono_time, &mut out.reborrow())
89 }
90 }
91
92 impl ToSql<SqlTimestamp, Mysql> for Timestamp {
93 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> SerializeResult {
94 let chrono_datetime: NaiveDateTime = (*self).try_into()?;
95
96 ToSql::<SqlTimestamp, Mysql>::to_sql(&chrono_datetime, &mut out.reborrow())
97 }
98 }
99
100 impl ToSql<BigInt, Mysql> for Timestamp {
101 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> SerializeResult {
102 let millis = self
103 .checked_total_i64_millis()
104 .ok_or("Failed to convert proto timestamp to UNIX milliseconds")?;
105
106 ToSql::<BigInt, Mysql>::to_sql(&millis, &mut out.reborrow())
107 }
108 }
109
110 impl ToSql<MysqlDateTime, Mysql> for Timestamp {
111 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> SerializeResult {
112 ToSql::<SqlTimestamp, Mysql>::to_sql(self, out)
113 }
114 }
115
116 #[cfg(feature = "datetime")]
117 impl ToSql<SqlTimestamp, Mysql> for DateTime {
118 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> SerializeResult {
119 let chrono_datetime: NaiveDateTime = self.clone().try_into()?;
120
121 ToSql::<SqlTimestamp, Mysql>::to_sql(&chrono_datetime, &mut out.reborrow())
122 }
123 }
124
125 #[cfg(feature = "datetime")]
126 impl ToSql<MysqlDateTime, Mysql> for DateTime {
127 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> SerializeResult {
128 ToSql::<SqlTimestamp, Mysql>::to_sql(self, out)
129 }
130 }
131
132 #[cfg(feature = "date")]
133 impl ToSql<SqlDate, Mysql> for Date {
134 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> SerializeResult {
135 let chrono_date: NaiveDate = (*self).try_into()?;
136
137 ToSql::<SqlDate, Mysql>::to_sql(&chrono_date, &mut out.reborrow())
138 }
139 }
140}
141
142#[cfg(feature = "diesel-postgres")]
143mod diesel_postgres {
144 use diesel::{
145 pg::{Pg, PgValue},
146 sql_types::Timestamptz,
147 };
148
149 use super::*;
150
151 impl FromSql<Interval, Pg> for Duration {
152 fn from_sql(bytes: PgValue<'_>) -> DeserializeResult<Self> {
153 let chrono_duration: TimeDelta = FromSql::<Interval, Pg>::from_sql(bytes)?;
154 Ok(chrono_duration.into())
155 }
156 }
157
158 #[cfg(feature = "timeofday")]
159 impl FromSql<Time, Pg> for TimeOfDay {
160 fn from_sql(bytes: PgValue<'_>) -> DeserializeResult<Self> {
161 let chrono_time: NaiveTime = FromSql::<Time, Pg>::from_sql(bytes)?;
162 Ok(chrono_time.into())
163 }
164 }
165
166 impl FromSql<SqlTimestamp, Pg> for Timestamp {
167 fn from_sql(bytes: PgValue<'_>) -> DeserializeResult<Self> {
168 let chrono_datetime: NaiveDateTime = FromSql::<SqlTimestamp, Pg>::from_sql(bytes)?;
169 Ok(chrono_datetime.into())
170 }
171 }
172
173 impl FromSql<BigInt, Pg> for Timestamp {
174 fn from_sql(value: PgValue<'_>) -> DeserializeResult<Self> {
175 let millis: i64 = FromSql::<BigInt, Pg>::from_sql(value)?;
176
177 Ok(Self::from_unix_millis(millis))
178 }
179 }
180
181 impl FromSql<Timestamptz, Pg> for Timestamp {
182 fn from_sql(bytes: PgValue<'_>) -> DeserializeResult<Self> {
183 let chrono_datetime: NaiveDateTime = FromSql::<Timestamptz, Pg>::from_sql(bytes)?;
184 Ok(chrono_datetime.into())
185 }
186 }
187
188 #[cfg(feature = "datetime")]
189 impl FromSql<SqlTimestamp, Pg> for DateTime {
190 fn from_sql(bytes: PgValue<'_>) -> DeserializeResult<Self> {
191 let chrono_datetime: NaiveDateTime = FromSql::<SqlTimestamp, Pg>::from_sql(bytes)?;
192 Ok(chrono_datetime.into())
193 }
194 }
195
196 #[cfg(feature = "datetime")]
197 impl FromSql<Timestamptz, Pg> for DateTime {
198 fn from_sql(bytes: PgValue<'_>) -> DeserializeResult<Self> {
199 let chrono_datetime: NaiveDateTime = FromSql::<Timestamptz, Pg>::from_sql(bytes)?;
200 Ok(chrono_datetime.into())
201 }
202 }
203
204 #[cfg(feature = "date")]
205 impl FromSql<SqlDate, Pg> for Date {
206 fn from_sql(bytes: PgValue<'_>) -> DeserializeResult<Self> {
207 let chrono_date: NaiveDate = FromSql::<SqlDate, Pg>::from_sql(bytes)?;
208 Ok(chrono_date.into())
209 }
210 }
211
212 impl ToSql<Interval, Pg> for Duration {
213 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
214 let chrono_duration: TimeDelta = (*self).try_into()?;
215
216 ToSql::<Interval, Pg>::to_sql(&chrono_duration, &mut out.reborrow())
217 }
218 }
219
220 #[cfg(feature = "timeofday")]
221 impl ToSql<Time, Pg> for TimeOfDay {
222 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
223 let chrono_time: NaiveTime = (*self).try_into()?;
224
225 ToSql::<Time, Pg>::to_sql(&chrono_time, &mut out.reborrow())
226 }
227 }
228
229 impl ToSql<BigInt, Pg> for Timestamp {
230 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
231 let millis = self
232 .checked_total_i64_millis()
233 .ok_or("Failed to convert proto timestamp to UNIX milliseconds")?;
234
235 ToSql::<BigInt, Pg>::to_sql(&millis, &mut out.reborrow())
236 }
237 }
238
239 impl ToSql<SqlTimestamp, Pg> for Timestamp {
240 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
241 let chrono_datetime: NaiveDateTime = (*self).try_into()?;
242
243 ToSql::<SqlTimestamp, Pg>::to_sql(&chrono_datetime, &mut out.reborrow())
244 }
245 }
246
247 impl ToSql<Timestamptz, Pg> for Timestamp {
248 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
249 ToSql::<SqlTimestamp, Pg>::to_sql(self, out)
250 }
251 }
252
253 #[cfg(feature = "datetime")]
254 impl ToSql<SqlTimestamp, Pg> for DateTime {
255 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
256 let chrono_datetime: NaiveDateTime = self.clone().try_into()?;
257
258 ToSql::<SqlTimestamp, Pg>::to_sql(&chrono_datetime, &mut out.reborrow())
259 }
260 }
261
262 #[cfg(feature = "datetime")]
263 impl ToSql<Timestamptz, Pg> for DateTime {
264 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
265 ToSql::<SqlTimestamp, Pg>::to_sql(self, out)
266 }
267 }
268
269 #[cfg(feature = "date")]
270 impl ToSql<SqlDate, Pg> for Date {
271 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> SerializeResult {
272 let chrono_date: NaiveDate = (*self).try_into()?;
273
274 ToSql::<SqlDate, Pg>::to_sql(&chrono_date, &mut out.reborrow())
275 }
276 }
277}
278
279#[cfg(feature = "diesel-sqlite")]
280mod diesel_sqlite {
281 use crate::{String, ToString};
282 use diesel::{backend::Backend, sql_types::TimestamptzSqlite, sqlite::Sqlite};
283
284 use super::*;
285
286 const ENCODE_NAIVE_DATETIME_FORMAT: &str = "%F %T%.f";
287 const DATE_FORMAT: &str = "%F";
288 const ENCODE_TIME_FORMAT: &str = "%T%.f";
289
290 fn format_naive_datetime(value: NaiveDateTime) -> String {
291 value
292 .format(ENCODE_NAIVE_DATETIME_FORMAT)
293 .to_string()
294 }
295
296 #[cfg(feature = "timeofday")]
297 impl FromSql<Time, Sqlite> for TimeOfDay {
298 fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> DeserializeResult<Self> {
299 let chrono_time: NaiveTime = FromSql::<Time, Sqlite>::from_sql(value)?;
300 Ok(chrono_time.into())
301 }
302 }
303
304 impl FromSql<SqlTimestamp, Sqlite> for Timestamp {
305 fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> DeserializeResult<Self> {
306 let chrono_datetime: NaiveDateTime = FromSql::<SqlTimestamp, Sqlite>::from_sql(value)?;
307 Ok(chrono_datetime.into())
308 }
309 }
310
311 impl FromSql<TimestamptzSqlite, Sqlite> for Timestamp {
312 fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> DeserializeResult<Self> {
313 let chrono_datetime: NaiveDateTime =
314 FromSql::<TimestamptzSqlite, Sqlite>::from_sql(value)?;
315 Ok(chrono_datetime.into())
316 }
317 }
318
319 impl FromSql<BigInt, Sqlite> for Timestamp {
320 fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> DeserializeResult<Self> {
321 let millis: i64 = FromSql::<BigInt, Sqlite>::from_sql(value)?;
322
323 Ok(Self::from_unix_millis(millis))
324 }
325 }
326
327 #[cfg(feature = "datetime")]
328 impl FromSql<SqlTimestamp, Sqlite> for DateTime {
329 fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> DeserializeResult<Self> {
330 let chrono_datetime: NaiveDateTime = FromSql::<SqlTimestamp, Sqlite>::from_sql(value)?;
331 Ok(chrono_datetime.into())
332 }
333 }
334
335 #[cfg(feature = "datetime")]
336 impl FromSql<TimestamptzSqlite, Sqlite> for DateTime {
337 fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> DeserializeResult<Self> {
338 let chrono_datetime: NaiveDateTime =
339 FromSql::<TimestamptzSqlite, Sqlite>::from_sql(value)?;
340 Ok(chrono_datetime.into())
341 }
342 }
343
344 #[cfg(feature = "date")]
345 impl FromSql<SqlDate, Sqlite> for Date {
346 fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> DeserializeResult<Self> {
347 let chrono_date: NaiveDate = FromSql::<SqlDate, Sqlite>::from_sql(value)?;
348 Ok(chrono_date.into())
349 }
350 }
351
352 #[cfg(feature = "timeofday")]
353 impl ToSql<Time, Sqlite> for TimeOfDay {
354 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> SerializeResult {
355 let chrono_time: NaiveTime = (*self).try_into()?;
356
357 out.set_value(chrono_time.format(ENCODE_TIME_FORMAT).to_string());
358 Ok(IsNull::No)
359 }
360 }
361
362 impl ToSql<BigInt, Sqlite> for Timestamp {
363 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> SerializeResult {
364 let millis = self
365 .checked_total_i64_millis()
366 .ok_or("Failed to convert proto timestamp to UNIX milliseconds")?;
367
368 out.set_value(millis);
369 Ok(IsNull::No)
370 }
371 }
372
373 impl ToSql<TimestamptzSqlite, Sqlite> for Timestamp {
374 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> SerializeResult {
375 let chrono_datetime: NaiveDateTime = (*self).try_into()?;
376
377 out.set_value(format_naive_datetime(chrono_datetime));
378 Ok(IsNull::No)
379 }
380 }
381
382 impl ToSql<SqlTimestamp, Sqlite> for Timestamp {
383 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> SerializeResult {
384 let chrono_datetime: NaiveDateTime = (*self).try_into()?;
385
386 out.set_value(format_naive_datetime(chrono_datetime));
387 Ok(IsNull::No)
388 }
389 }
390
391 #[cfg(feature = "datetime")]
392 impl ToSql<TimestamptzSqlite, Sqlite> for DateTime {
393 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> SerializeResult {
394 let chrono_datetime: NaiveDateTime = self.clone().try_into()?;
395
396 out.set_value(format_naive_datetime(chrono_datetime));
397 Ok(IsNull::No)
398 }
399 }
400
401 #[cfg(feature = "datetime")]
402 impl ToSql<SqlTimestamp, Sqlite> for DateTime {
403 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> SerializeResult {
404 let chrono_datetime: NaiveDateTime = self.clone().try_into()?;
405
406 out.set_value(format_naive_datetime(chrono_datetime));
407 Ok(IsNull::No)
408 }
409 }
410
411 #[cfg(feature = "date")]
412 impl ToSql<SqlDate, Sqlite> for Date {
413 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> SerializeResult {
414 let chrono_date: NaiveDate = (*self).try_into()?;
415
416 out.set_value(chrono_date.format(DATE_FORMAT).to_string());
417 Ok(IsNull::No)
418 }
419 }
420}