Skip to main content

wae_database/connection/
value_impl.rs

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