Skip to main content

proto_types/
diesel_impls.rs

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}