Skip to main content

wae_database/connection/
value_impl.rs

1//! 从数据库值转换的 trait 实现
2
3use crate::connection::config::DatabaseResult;
4use wae_types::{ValidationErrorKind, WaeError};
5
6/// 从数据库值转换的 trait
7pub trait FromDatabaseValue: Sized {
8    /// 从 Turso 数据库值转换
9    #[cfg(feature = "turso")]
10    fn from_turso_value(value: turso::Value) -> DatabaseResult<Self>;
11
12    /// 从 PostgreSQL 行获取值
13    #[cfg(feature = "postgres")]
14    fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self>;
15
16    /// 从 MySQL 行获取值
17    #[cfg(feature = "mysql")]
18    fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self>;
19}
20
21#[cfg(all(feature = "turso", not(feature = "postgres"), not(feature = "mysql")))]
22mod database_value_impl {
23    use super::*;
24
25    macro_rules! impl_from_value {
26        ($type:ty, $pattern:pat => $expr:expr) => {
27            impl FromDatabaseValue for $type {
28                fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
29                    match value {
30                        $pattern => Ok($expr),
31                        _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
32                            field: stringify!($type).to_string(),
33                            expected: format!("{:?}", value),
34                        })),
35                    }
36                }
37            }
38        };
39    }
40
41    impl_from_value!(i64, turso::Value::Integer(i) => i);
42    impl_from_value!(i32, turso::Value::Integer(i) => i as i32);
43    impl_from_value!(i16, turso::Value::Integer(i) => i as i16);
44    impl_from_value!(u64, turso::Value::Integer(i) => i as u64);
45    impl_from_value!(u32, turso::Value::Integer(i) => i as u32);
46    impl_from_value!(Vec<u8>, turso::Value::Blob(b) => b);
47
48    impl FromDatabaseValue for f64 {
49        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
50            match value {
51                turso::Value::Integer(i) => Ok(i as f64),
52                turso::Value::Text(s) => s.parse().map_err(|_| {
53                    WaeError::validation(ValidationErrorKind::InvalidFormat {
54                        field: "f64".to_string(),
55                        expected: format!("Cannot parse '{}' as float", s),
56                    })
57                }),
58                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
59                    field: "f64".to_string(),
60                    expected: format!("{:?}", value),
61                })),
62            }
63        }
64    }
65
66    impl FromDatabaseValue for String {
67        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
68            match value {
69                turso::Value::Text(s) => Ok(s),
70                turso::Value::Integer(i) => Ok(i.to_string()),
71                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
72                    field: "String".to_string(),
73                    expected: format!("{:?}", value),
74                })),
75            }
76        }
77    }
78
79    impl FromDatabaseValue for bool {
80        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
81            match value {
82                turso::Value::Integer(i) => Ok(i != 0),
83                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
84                    field: "bool".to_string(),
85                    expected: format!("{:?}", value),
86                })),
87            }
88        }
89    }
90
91    impl<T: FromDatabaseValue> FromDatabaseValue for Option<T> {
92        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
93            match value {
94                turso::Value::Null => Ok(None),
95                v => T::from_turso_value(v).map(Some),
96            }
97        }
98    }
99}
100
101#[cfg(all(feature = "postgres", not(feature = "turso"), not(feature = "mysql")))]
102mod database_value_impl {
103    use super::*;
104
105    macro_rules! impl_from_value {
106        ($type:ty) => {
107            impl FromDatabaseValue for $type {
108                fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
109                    row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
110                }
111            }
112        };
113    }
114
115    impl_from_value!(i64);
116    impl_from_value!(i32);
117    impl_from_value!(i16);
118    impl_from_value!(f64);
119    impl_from_value!(String);
120    impl_from_value!(Vec<u8>);
121    impl_from_value!(bool);
122
123    impl FromDatabaseValue for u64 {
124        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
125            let i: i64 =
126                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
127            Ok(i as u64)
128        }
129    }
130
131    impl FromDatabaseValue for u32 {
132        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
133            let i: i32 =
134                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
135            Ok(i as u32)
136        }
137    }
138
139    impl FromDatabaseValue for Option<i64> {
140        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
141            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
142        }
143    }
144
145    impl FromDatabaseValue for Option<i32> {
146        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
147            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
148        }
149    }
150
151    impl FromDatabaseValue for Option<i16> {
152        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
153            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
154        }
155    }
156
157    impl FromDatabaseValue for Option<u64> {
158        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
159            let opt: Option<i64> =
160                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
161            Ok(opt.map(|i| i as u64))
162        }
163    }
164
165    impl FromDatabaseValue for Option<u32> {
166        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
167            let opt: Option<i32> =
168                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
169            Ok(opt.map(|i| i as u32))
170        }
171    }
172
173    impl FromDatabaseValue for Option<f64> {
174        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
175            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
176        }
177    }
178
179    impl FromDatabaseValue for Option<String> {
180        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
181            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
182        }
183    }
184
185    impl FromDatabaseValue for Option<Vec<u8>> {
186        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
187            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
188        }
189    }
190
191    impl FromDatabaseValue for Option<bool> {
192        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
193            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
194        }
195    }
196}
197
198#[cfg(all(feature = "mysql", not(feature = "turso"), not(feature = "postgres")))]
199mod database_value_impl {
200    use super::*;
201    use mysql_async::prelude::FromValue;
202
203    macro_rules! impl_from_value {
204        ($type:ty) => {
205            impl FromDatabaseValue for $type {
206                fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
207                    row.get_opt(index)
208                        .transpose()
209                        .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
210                        .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))
211                }
212            }
213        };
214    }
215
216    impl_from_value!(i64);
217    impl_from_value!(i32);
218    impl_from_value!(i16);
219    impl_from_value!(f64);
220    impl_from_value!(String);
221    impl_from_value!(Vec<u8>);
222    impl_from_value!(bool);
223
224    impl FromDatabaseValue for u64 {
225        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
226            let i: i64 = row
227                .get_opt(index)
228                .transpose()
229                .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
230                .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))?;
231            Ok(i as u64)
232        }
233    }
234
235    impl FromDatabaseValue for u32 {
236        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
237            let i: i32 = row
238                .get_opt(index)
239                .transpose()
240                .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
241                .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))?;
242            Ok(i as u32)
243        }
244    }
245
246    impl<T: FromDatabaseValue + FromValue> FromDatabaseValue for Option<T> {
247        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
248            match row.get_opt::<Option<T>, usize>(index) {
249                Some(Ok(val)) => Ok(val),
250                Some(Err(e)) => Err(WaeError::internal(format!("Failed to get column {}: {:?}", index, e))),
251                None => Ok(None),
252            }
253        }
254    }
255}
256
257#[cfg(any(
258    all(feature = "turso", feature = "postgres"),
259    all(feature = "turso", feature = "mysql"),
260    all(feature = "postgres", feature = "mysql"),
261    all(feature = "turso", feature = "postgres", feature = "mysql")
262))]
263mod database_value_impl {
264    use super::*;
265
266    macro_rules! impl_from_value_multi {
267        ($type:ty) => {
268            impl FromDatabaseValue for $type {
269                #[cfg(feature = "turso")]
270                fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
271                    match value {
272                        turso::Value::Integer(i) => Ok(i as $type),
273                        turso::Value::Text(s) => s.parse().map_err(|_| {
274                            WaeError::validation(ValidationErrorKind::InvalidFormat {
275                                field: stringify!($type).to_string(),
276                                expected: format!("Cannot parse as {}", stringify!($type)),
277                            })
278                        }),
279                        _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
280                            field: stringify!($type).to_string(),
281                            expected: format!("{:?}", value),
282                        })),
283                    }
284                }
285
286                #[cfg(feature = "postgres")]
287                fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
288                    row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
289                }
290
291                #[cfg(feature = "mysql")]
292                fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
293                    row.get_opt(index)
294                        .transpose()
295                        .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
296                        .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))
297                }
298            }
299        };
300    }
301
302    impl_from_value_multi!(i64);
303    impl_from_value_multi!(i32);
304    impl_from_value_multi!(i16);
305    impl_from_value_multi!(f64);
306
307    impl FromDatabaseValue for String {
308        #[cfg(feature = "turso")]
309        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
310            match value {
311                turso::Value::Text(s) => Ok(s),
312                turso::Value::Integer(i) => Ok(i.to_string()),
313                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
314                    field: "String".to_string(),
315                    expected: format!("{:?}", value),
316                })),
317            }
318        }
319
320        #[cfg(feature = "postgres")]
321        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
322            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
323        }
324
325        #[cfg(feature = "mysql")]
326        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
327            row.get_opt(index)
328                .transpose()
329                .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
330                .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))
331        }
332    }
333
334    impl FromDatabaseValue for Vec<u8> {
335        #[cfg(feature = "turso")]
336        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
337            match value {
338                turso::Value::Blob(b) => Ok(b),
339                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
340                    field: "Vec<u8>".to_string(),
341                    expected: format!("{:?}", value),
342                })),
343            }
344        }
345
346        #[cfg(feature = "postgres")]
347        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
348            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
349        }
350
351        #[cfg(feature = "mysql")]
352        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
353            row.get_opt(index)
354                .transpose()
355                .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
356                .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))
357        }
358    }
359
360    impl FromDatabaseValue for bool {
361        #[cfg(feature = "turso")]
362        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
363            match value {
364                turso::Value::Integer(i) => Ok(i != 0),
365                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
366                    field: "bool".to_string(),
367                    expected: format!("{:?}", value),
368                })),
369            }
370        }
371
372        #[cfg(feature = "postgres")]
373        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
374            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
375        }
376
377        #[cfg(feature = "mysql")]
378        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
379            row.get_opt(index)
380                .transpose()
381                .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
382                .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))
383        }
384    }
385
386    impl FromDatabaseValue for u64 {
387        #[cfg(feature = "turso")]
388        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
389            match value {
390                turso::Value::Integer(i) => Ok(i as u64),
391                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
392                    field: "u64".to_string(),
393                    expected: format!("{:?}", value),
394                })),
395            }
396        }
397
398        #[cfg(feature = "postgres")]
399        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
400            let i: i64 =
401                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
402            Ok(i as u64)
403        }
404
405        #[cfg(feature = "mysql")]
406        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
407            let i: i64 = row
408                .get_opt(index)
409                .transpose()
410                .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
411                .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))?;
412            Ok(i as u64)
413        }
414    }
415
416    impl FromDatabaseValue for u32 {
417        #[cfg(feature = "turso")]
418        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
419            match value {
420                turso::Value::Integer(i) => Ok(i as u32),
421                _ => Err(WaeError::validation(ValidationErrorKind::InvalidFormat {
422                    field: "u32".to_string(),
423                    expected: format!("{:?}", value),
424                })),
425            }
426        }
427
428        #[cfg(feature = "postgres")]
429        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
430            let i: i32 =
431                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
432            Ok(i as u32)
433        }
434
435        #[cfg(feature = "mysql")]
436        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
437            let i: i32 = row
438                .get_opt(index)
439                .transpose()
440                .map_err(|e| WaeError::internal(format!("Failed to get column {}: {:?}", index, e)))?
441                .ok_or_else(|| WaeError::internal(format!("Column {} is NULL", index)))?;
442            Ok(i as u32)
443        }
444    }
445
446    impl FromDatabaseValue for Option<i64> {
447        #[cfg(feature = "turso")]
448        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
449            match value {
450                turso::Value::Null => Ok(None),
451                v => i64::from_turso_value(v).map(Some),
452            }
453        }
454
455        #[cfg(feature = "postgres")]
456        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
457            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
458        }
459
460        #[cfg(feature = "mysql")]
461        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
462            match row.get_opt::<Option<i64>, usize>(index) {
463                Some(Ok(val)) => Ok(val),
464                Some(Err(_)) => Ok(None),
465                None => Ok(None),
466            }
467        }
468    }
469
470    impl FromDatabaseValue for Option<i32> {
471        #[cfg(feature = "turso")]
472        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
473            match value {
474                turso::Value::Null => Ok(None),
475                v => i32::from_turso_value(v).map(Some),
476            }
477        }
478
479        #[cfg(feature = "postgres")]
480        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
481            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
482        }
483
484        #[cfg(feature = "mysql")]
485        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
486            match row.get_opt::<Option<i32>, usize>(index) {
487                Some(Ok(val)) => Ok(val),
488                Some(Err(_)) => Ok(None),
489                None => Ok(None),
490            }
491        }
492    }
493
494    impl FromDatabaseValue for Option<i16> {
495        #[cfg(feature = "turso")]
496        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
497            match value {
498                turso::Value::Null => Ok(None),
499                v => i16::from_turso_value(v).map(Some),
500            }
501        }
502
503        #[cfg(feature = "postgres")]
504        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
505            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
506        }
507
508        #[cfg(feature = "mysql")]
509        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
510            match row.get_opt::<Option<i16>, usize>(index) {
511                Some(Ok(val)) => Ok(val),
512                Some(Err(_)) => Ok(None),
513                None => Ok(None),
514            }
515        }
516    }
517
518    impl FromDatabaseValue for Option<u64> {
519        #[cfg(feature = "turso")]
520        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
521            match value {
522                turso::Value::Null => Ok(None),
523                v => u64::from_turso_value(v).map(Some),
524            }
525        }
526
527        #[cfg(feature = "postgres")]
528        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
529            let opt: Option<i64> =
530                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
531            Ok(opt.map(|i| i as u64))
532        }
533
534        #[cfg(feature = "mysql")]
535        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
536            match row.get_opt::<Option<i64>, usize>(index) {
537                Some(Ok(val)) => Ok(val.map(|i| i as u64)),
538                Some(Err(_)) => Ok(None),
539                None => Ok(None),
540            }
541        }
542    }
543
544    impl FromDatabaseValue for Option<u32> {
545        #[cfg(feature = "turso")]
546        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
547            match value {
548                turso::Value::Null => Ok(None),
549                v => u32::from_turso_value(v).map(Some),
550            }
551        }
552
553        #[cfg(feature = "postgres")]
554        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
555            let opt: Option<i32> =
556                row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))?;
557            Ok(opt.map(|i| i as u32))
558        }
559
560        #[cfg(feature = "mysql")]
561        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
562            match row.get_opt::<Option<i32>, usize>(index) {
563                Some(Ok(val)) => Ok(val.map(|i| i as u32)),
564                Some(Err(_)) => Ok(None),
565                None => Ok(None),
566            }
567        }
568    }
569
570    impl FromDatabaseValue for Option<f64> {
571        #[cfg(feature = "turso")]
572        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
573            match value {
574                turso::Value::Null => Ok(None),
575                v => f64::from_turso_value(v).map(Some),
576            }
577        }
578
579        #[cfg(feature = "postgres")]
580        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
581            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
582        }
583
584        #[cfg(feature = "mysql")]
585        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
586            match row.get_opt::<Option<f64>, usize>(index) {
587                Some(Ok(val)) => Ok(val),
588                Some(Err(_)) => Ok(None),
589                None => Ok(None),
590            }
591        }
592    }
593
594    impl FromDatabaseValue for Option<String> {
595        #[cfg(feature = "turso")]
596        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
597            match value {
598                turso::Value::Null => Ok(None),
599                v => String::from_turso_value(v).map(Some),
600            }
601        }
602
603        #[cfg(feature = "postgres")]
604        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
605            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
606        }
607
608        #[cfg(feature = "mysql")]
609        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
610            match row.get_opt::<Option<String>, usize>(index) {
611                Some(Ok(val)) => Ok(val),
612                Some(Err(_)) => Ok(None),
613                None => Ok(None),
614            }
615        }
616    }
617
618    impl FromDatabaseValue for Option<Vec<u8>> {
619        #[cfg(feature = "turso")]
620        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
621            match value {
622                turso::Value::Null => Ok(None),
623                v => Vec::<u8>::from_turso_value(v).map(Some),
624            }
625        }
626
627        #[cfg(feature = "postgres")]
628        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
629            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
630        }
631
632        #[cfg(feature = "mysql")]
633        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
634            match row.get_opt::<Option<Vec<u8>>, usize>(index) {
635                Some(Ok(val)) => Ok(val),
636                Some(Err(_)) => Ok(None),
637                None => Ok(None),
638            }
639        }
640    }
641
642    impl FromDatabaseValue for Option<bool> {
643        #[cfg(feature = "turso")]
644        fn from_turso_value(value: turso::Value) -> DatabaseResult<Self> {
645            match value {
646                turso::Value::Null => Ok(None),
647                v => bool::from_turso_value(v).map(Some),
648            }
649        }
650
651        #[cfg(feature = "postgres")]
652        fn from_postgres_row(row: &tokio_postgres::Row, index: usize) -> DatabaseResult<Self> {
653            row.try_get(index).map_err(|e| WaeError::internal(format!("Failed to get column {}: {}", index, e)))
654        }
655
656        #[cfg(feature = "mysql")]
657        fn from_mysql_row(row: &mysql_async::Row, index: usize) -> DatabaseResult<Self> {
658            match row.get_opt::<Option<bool>, usize>(index) {
659                Some(Ok(val)) => Ok(val),
660                Some(Err(_)) => Ok(None),
661                None => Ok(None),
662            }
663        }
664    }
665}