1#[cfg(feature = "mysql")]
4use crate::db::impl_mysql::MySqlValueRef;
5#[cfg(feature = "postgres")]
6use crate::db::impl_postgres::PostgresValueRef;
7#[cfg(feature = "sqlite")]
8use crate::db::impl_sqlite::SqliteValueRef;
9use crate::db::{
10 Auto, ColumnType, DatabaseError, DatabaseField, DbFieldValue, DbValue, ForeignKey, FromDbValue,
11 LimitedString, Model, PrimaryKey, Result, SqlxValueRef, ToDbFieldValue, ToDbValue,
12};
13
14mod chrono_wrapper;
15
16macro_rules! impl_from_sqlite_default {
17 () => {
18 #[cfg(feature = "sqlite")]
19 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self> {
20 value.get::<Self>()
21 }
22 };
23 ($wrapper_ty:ty) => {
24 #[cfg(feature = "sqlite")]
25 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self> {
26 <$wrapper_ty as FromDbValue>::from_sqlite(value).map(|val| val.into())
27 }
28 };
29 ($wrapper_ty:ty, option) => {
30 #[cfg(feature = "sqlite")]
31 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self> {
32 <$wrapper_ty as FromDbValue>::from_sqlite(value).map(|val| val.map(|val| val.into()))
33 }
34 };
35}
36
37macro_rules! impl_from_postgres_default {
38 () => {
39 #[cfg(feature = "postgres")]
40 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
41 value.get::<Self>()
42 }
43 };
44 ($wrapper_ty:ty) => {
45 #[cfg(feature = "postgres")]
46 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
47 <$wrapper_ty as FromDbValue>::from_postgres(value).map(|val| val.into())
48 }
49 };
50 ($wrapper_ty:ty, option) => {
51 #[cfg(feature = "postgres")]
52 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
53 <$wrapper_ty as FromDbValue>::from_postgres(value).map(|val| val.map(|val| val.into()))
54 }
55 };
56}
57
58macro_rules! impl_from_mysql_default {
59 () => {
60 #[cfg(feature = "mysql")]
61 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
62 value.get::<Self>()
63 }
64 };
65 ($wrapper_ty:ty) => {
66 #[cfg(feature = "mysql")]
67 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
68 <$wrapper_ty as FromDbValue>::from_mysql(value).map(|val| val.into())
69 }
70 };
71 ($wrapper_ty:ty, option) => {
72 #[cfg(feature = "mysql")]
73 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
74 <$wrapper_ty as FromDbValue>::from_mysql(value).map(|val| val.map(|val| val.into()))
75 }
76 };
77}
78
79macro_rules! impl_to_db_value_default {
80 ($ty:ty) => {
81 impl ToDbValue for $ty {
82 fn to_db_value(&self) -> DbValue {
83 self.clone().into()
84 }
85 }
86
87 impl ToDbValue for Option<$ty> {
88 fn to_db_value(&self) -> DbValue {
89 self.clone().into()
90 }
91 }
92 };
93
94 ($ty:ty, $wrapper_ty:ty) => {
95 impl ToDbValue for $ty {
96 fn to_db_value(&self) -> DbValue {
97 Into::<$wrapper_ty>::into(self.clone()).to_db_value()
98 }
99 }
100
101 impl ToDbValue for Option<$ty> {
102 fn to_db_value(&self) -> DbValue {
103 self.clone()
104 .map(|val| Into::<$wrapper_ty>::into(val))
105 .to_db_value()
106 }
107 }
108 };
109}
110
111macro_rules! impl_db_field {
112 ($ty:ty, $column_type:ident) => {
113 impl DatabaseField for $ty {
114 const TYPE: ColumnType = ColumnType::$column_type;
115 }
116
117 impl FromDbValue for $ty {
118 impl_from_sqlite_default!();
119
120 impl_from_postgres_default!();
121
122 impl_from_mysql_default!();
123 }
124
125 impl FromDbValue for Option<$ty> {
126 impl_from_sqlite_default!();
127
128 impl_from_postgres_default!();
129
130 impl_from_mysql_default!();
131 }
132
133 impl_to_db_value_default!($ty);
134 };
135 ($ty:ty, $column_type:ident, with $wrapper_ty:ty) => {
136 impl DatabaseField for $ty {
137 const TYPE: ColumnType = ColumnType::$column_type;
138 }
139
140 impl FromDbValue for $ty {
141 impl_from_sqlite_default!($wrapper_ty);
142
143 impl_from_postgres_default!($wrapper_ty);
144
145 impl_from_mysql_default!($wrapper_ty);
146 }
147
148 impl FromDbValue for Option<$ty> {
149 impl_from_sqlite_default!(Option<$wrapper_ty>, option);
150
151 impl_from_postgres_default!(Option<$wrapper_ty>, option);
152
153 impl_from_mysql_default!(Option<$wrapper_ty>, option);
154 }
155
156 impl_to_db_value_default!($ty, $wrapper_ty);
157 };
158}
159
160macro_rules! impl_db_field_with_postgres_int_cast {
161 ($dest_ty:ty, $src_ty:ty, $column_type:ident) => {
162 impl DatabaseField for $dest_ty {
163 const TYPE: ColumnType = ColumnType::$column_type;
164 }
165
166 impl FromDbValue for $dest_ty {
167 impl_from_sqlite_default!();
168
169 impl_from_mysql_default!();
170
171 #[cfg(feature = "postgres")]
172 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
173 #[allow(
174 clippy::allow_attributes,
175 clippy::cast_possible_truncation,
176 clippy::cast_sign_loss,
177 reason = "needed for casting from larger to smaller integer types"
178 )]
179 value.get::<$src_ty>().map(|v| v as $dest_ty)
180 }
181 }
182
183 impl FromDbValue for Option<$dest_ty> {
184 impl_from_sqlite_default!();
185
186 impl_from_mysql_default!();
187
188 #[cfg(feature = "postgres")]
189 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
190 #[allow(
191 clippy::allow_attributes,
192 clippy::cast_possible_truncation,
193 clippy::cast_sign_loss,
194 reason = "needed for casting from larger to smaller integer types"
195 )]
196 value
197 .get::<Option<$src_ty>>()
198 .map(|v| v.map(|v| v as $dest_ty))
199 }
200 }
201
202 impl_to_db_value_default!($dest_ty);
203 };
204}
205
206impl_db_field!(bool, Boolean);
207impl_db_field!(i16, SmallInteger);
208impl_db_field!(i32, Integer);
209impl_db_field!(i64, BigInteger);
210impl_db_field_with_postgres_int_cast!(i8, i16, TinyInteger);
211impl_db_field_with_postgres_int_cast!(u8, i16, TinyUnsignedInteger);
212impl_db_field_with_postgres_int_cast!(u16, i16, SmallUnsignedInteger);
213impl_db_field_with_postgres_int_cast!(u32, i32, UnsignedInteger);
214impl_db_field_with_postgres_int_cast!(u64, i64, BigUnsignedInteger);
215impl_db_field!(f32, Float);
216impl_db_field!(f64, Double);
217impl_db_field!(chrono::NaiveDate, Date);
218impl_db_field!(chrono::NaiveTime, Time);
219impl_db_field!(chrono::NaiveDateTime, DateTime);
220impl_db_field!(
221 chrono::WeekdaySet,
222 TinyUnsignedInteger,
223 with chrono_wrapper::WeekdaySet
224);
225impl_db_field!(String, Text);
226impl_db_field!(Vec<u8>, Blob);
227
228impl ToDbValue for &str {
229 fn to_db_value(&self) -> DbValue {
230 (*self).to_string().into()
231 }
232}
233
234impl DatabaseField for chrono::DateTime<chrono::FixedOffset> {
235 const TYPE: ColumnType = ColumnType::DateTimeWithTimeZone;
236}
237
238impl FromDbValue for chrono::DateTime<chrono::FixedOffset> {
239 impl_from_sqlite_default!();
240
241 impl_from_postgres_default!();
242
243 #[cfg(feature = "mysql")]
244 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
245 Ok(value.get::<chrono::DateTime<chrono::Utc>>()?.fixed_offset())
246 }
247}
248impl FromDbValue for Option<chrono::DateTime<chrono::FixedOffset>> {
249 impl_from_sqlite_default!();
250
251 impl_from_postgres_default!();
252
253 #[cfg(feature = "mysql")]
254 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
255 Ok(value
256 .get::<Option<chrono::DateTime<chrono::Utc>>>()?
257 .map(|dt| dt.fixed_offset()))
258 }
259}
260
261impl_to_db_value_default!(chrono::DateTime<chrono::FixedOffset>);
262
263impl ToDbValue for Option<&str> {
264 fn to_db_value(&self) -> DbValue {
265 self.map(ToString::to_string).into()
266 }
267}
268
269impl<T: DatabaseField> DatabaseField for Option<T>
270where
271 Option<T>: ToDbFieldValue + FromDbValue,
272{
273 const NULLABLE: bool = true;
274 const TYPE: ColumnType = T::TYPE;
275}
276
277impl<const LIMIT: u32> DatabaseField for LimitedString<LIMIT> {
278 const TYPE: ColumnType = ColumnType::String(LIMIT);
279}
280
281impl<const LIMIT: u32> FromDbValue for LimitedString<LIMIT> {
282 #[cfg(feature = "sqlite")]
283 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self> {
284 let str = value.get::<String>()?;
285 Self::new(str).map_err(DatabaseError::value_decode)
286 }
287
288 #[cfg(feature = "postgres")]
289 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
290 let str = value.get::<String>()?;
291 Self::new(str).map_err(DatabaseError::value_decode)
292 }
293
294 #[cfg(feature = "mysql")]
295 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
296 let str = value.get::<String>()?;
297 Self::new(str).map_err(DatabaseError::value_decode)
298 }
299}
300
301impl<const LIMIT: u32> ToDbValue for LimitedString<LIMIT> {
302 fn to_db_value(&self) -> DbValue {
303 self.0.clone().into()
304 }
305}
306
307impl<const LIMIT: u32> ToDbValue for Option<LimitedString<LIMIT>> {
308 fn to_db_value(&self) -> DbValue {
309 self.clone().map(|s| s.0).into()
310 }
311}
312
313impl<T: Model + Send + Sync> DatabaseField for ForeignKey<T> {
314 const NULLABLE: bool = T::PrimaryKey::NULLABLE;
315 const TYPE: ColumnType = T::PrimaryKey::TYPE;
316}
317
318impl<T: Model + Send + Sync> FromDbValue for ForeignKey<T> {
319 #[cfg(feature = "sqlite")]
320 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self> {
321 T::PrimaryKey::from_sqlite(value).map(ForeignKey::PrimaryKey)
322 }
323
324 #[cfg(feature = "postgres")]
325 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
326 T::PrimaryKey::from_postgres(value).map(ForeignKey::PrimaryKey)
327 }
328
329 #[cfg(feature = "mysql")]
330 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
331 T::PrimaryKey::from_mysql(value).map(ForeignKey::PrimaryKey)
332 }
333}
334
335impl<T: Model + Send + Sync> ToDbFieldValue for ForeignKey<T> {
336 fn to_db_field_value(&self) -> DbFieldValue {
337 self.primary_key().to_db_field_value()
338 }
339}
340
341impl<T: Model + Send + Sync> FromDbValue for Option<ForeignKey<T>>
342where
343 Option<T::PrimaryKey>: FromDbValue,
344{
345 #[cfg(feature = "sqlite")]
346 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self> {
347 Ok(<Option<T::PrimaryKey>>::from_sqlite(value)?.map(ForeignKey::PrimaryKey))
348 }
349
350 #[cfg(feature = "postgres")]
351 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self> {
352 Ok(<Option<T::PrimaryKey>>::from_postgres(value)?.map(ForeignKey::PrimaryKey))
353 }
354
355 #[cfg(feature = "mysql")]
356 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self> {
357 Ok(<Option<T::PrimaryKey>>::from_mysql(value)?.map(ForeignKey::PrimaryKey))
358 }
359}
360
361impl<T: Model + Send + Sync> ToDbFieldValue for Option<ForeignKey<T>>
362where
363 Option<T::PrimaryKey>: ToDbFieldValue,
364{
365 fn to_db_field_value(&self) -> DbFieldValue {
366 match self {
367 Some(foreign_key) => foreign_key.to_db_field_value(),
368 None => <Option<T::PrimaryKey>>::None.to_db_field_value(),
369 }
370 }
371}
372
373impl<T: DatabaseField> DatabaseField for Auto<T> {
374 const NULLABLE: bool = T::NULLABLE;
375 const TYPE: ColumnType = T::TYPE;
376}
377
378impl<T: DatabaseField> FromDbValue for Auto<T> {
379 #[cfg(feature = "sqlite")]
380 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self>
381 where
382 Self: Sized,
383 {
384 Ok(Self::fixed(T::from_sqlite(value)?))
385 }
386
387 #[cfg(feature = "postgres")]
388 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self>
389 where
390 Self: Sized,
391 {
392 Ok(Self::fixed(T::from_postgres(value)?))
393 }
394
395 #[cfg(feature = "mysql")]
396 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self>
397 where
398 Self: Sized,
399 {
400 Ok(Self::fixed(T::from_mysql(value)?))
401 }
402}
403
404impl<T: DatabaseField> ToDbFieldValue for Auto<T> {
405 fn to_db_field_value(&self) -> DbFieldValue {
406 match self {
407 Self::Fixed(value) => value.to_db_field_value(),
408 Self::Auto => DbFieldValue::Auto,
409 }
410 }
411}
412
413impl<T: DatabaseField> FromDbValue for Option<Auto<T>>
414where
415 Option<T>: FromDbValue,
416{
417 #[cfg(feature = "sqlite")]
418 fn from_sqlite(value: SqliteValueRef<'_>) -> Result<Self>
419 where
420 Self: Sized,
421 {
422 <Option<T>>::from_sqlite(value).map(|value| value.map(Auto::fixed))
423 }
424
425 #[cfg(feature = "postgres")]
426 fn from_postgres(value: PostgresValueRef<'_>) -> Result<Self>
427 where
428 Self: Sized,
429 {
430 <Option<T>>::from_postgres(value).map(|value| value.map(Auto::fixed))
431 }
432
433 #[cfg(feature = "mysql")]
434 fn from_mysql(value: MySqlValueRef<'_>) -> Result<Self>
435 where
436 Self: Sized,
437 {
438 <Option<T>>::from_mysql(value).map(|value| value.map(Auto::fixed))
439 }
440}
441
442impl<T: DatabaseField> ToDbFieldValue for Option<Auto<T>>
443where
444 Option<T>: ToDbFieldValue,
445{
446 fn to_db_field_value(&self) -> DbFieldValue {
447 match self {
448 Some(auto) => auto.to_db_field_value(),
449 None => <Option<T>>::None.to_db_field_value(),
450 }
451 }
452}
453
454impl<T: PrimaryKey> PrimaryKey for Auto<T> {}
455
456impl PrimaryKey for i32 {}
457
458impl PrimaryKey for i64 {}
459
460impl PrimaryKey for u32 {}
461
462impl PrimaryKey for u64 {}
463
464impl PrimaryKey for String {}