1use sqlx::{any::AnyRow, Error, Row};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone)]
14pub struct AnyInfo {
15 pub column: &'static str,
17
18 pub sql_type: &'static str,
20
21 pub table: &'static str,
23}
24
25pub trait AnyImpl {
37 fn columns() -> Vec<AnyInfo>;
39
40 fn to_map(&self) -> HashMap<String, String>;
42}
43
44pub trait FromAnyRow: Sized {
50 fn from_any_row(row: &AnyRow) -> Result<Self, Error>;
51}
52
53macro_rules! impl_supported_primitive {
58 ($($t:ty),*) => {
59 $(
60 impl AnyImpl for $t {
61 fn columns() -> Vec<AnyInfo> { Vec::new() }
62 fn to_map(&self) -> HashMap<String, String> { HashMap::new() }
63 }
64
65 impl FromAnyRow for $t {
66 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
67 row.try_get(0)
68 }
69 }
70 )*
71 };
72}
73
74impl_supported_primitive!(bool, i16, i32, i64, f32, f64, String);
76
77macro_rules! impl_cast_primitive {
78 ($($t:ty),*) => {
79 $(
80 impl AnyImpl for $t {
81 fn columns() -> Vec<AnyInfo> { Vec::new() }
82 fn to_map(&self) -> HashMap<String, String> { HashMap::new() }
83 }
84
85 impl FromAnyRow for $t {
86 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
87 let val: i64 = row.try_get(0)?;
89 Ok(val as $t)
90 }
91 }
92 )*
93 };
94}
95
96impl_cast_primitive!(i8, isize, u8, u16, u32, u64, usize);
98
99impl AnyImpl for uuid::Uuid {
104 fn columns() -> Vec<AnyInfo> {
105 Vec::new()
106 }
107 fn to_map(&self) -> HashMap<String, String> {
108 HashMap::new()
109 }
110}
111
112impl FromAnyRow for uuid::Uuid {
113 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
114 let s: String = row.try_get(0)?;
115 s.parse().map_err(|e| Error::Decode(Box::new(e)))
116 }
117}
118
119impl AnyImpl for chrono::NaiveDateTime {
120 fn columns() -> Vec<AnyInfo> {
121 Vec::new()
122 }
123 fn to_map(&self) -> HashMap<String, String> {
124 HashMap::new()
125 }
126}
127
128impl FromAnyRow for chrono::NaiveDateTime {
129 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
130 let s: String = row.try_get(0)?;
131 s.parse().map_err(|e| Error::Decode(Box::new(e)))
132 }
133}
134
135impl AnyImpl for chrono::NaiveDate {
136 fn columns() -> Vec<AnyInfo> {
137 Vec::new()
138 }
139 fn to_map(&self) -> HashMap<String, String> {
140 HashMap::new()
141 }
142}
143
144impl FromAnyRow for chrono::NaiveDate {
145 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
146 let s: String = row.try_get(0)?;
147 s.parse().map_err(|e| Error::Decode(Box::new(e)))
148 }
149}
150
151impl AnyImpl for chrono::NaiveTime {
152 fn columns() -> Vec<AnyInfo> {
153 Vec::new()
154 }
155 fn to_map(&self) -> HashMap<String, String> {
156 HashMap::new()
157 }
158}
159
160impl FromAnyRow for chrono::NaiveTime {
161 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
162 let s: String = row.try_get(0)?;
163 s.parse().map_err(|e| Error::Decode(Box::new(e)))
164 }
165}
166
167impl AnyImpl for chrono::DateTime<chrono::Utc> {
168 fn columns() -> Vec<AnyInfo> {
169 Vec::new()
170 }
171 fn to_map(&self) -> HashMap<String, String> {
172 HashMap::new()
173 }
174}
175
176impl FromAnyRow for chrono::DateTime<chrono::Utc> {
177 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
178 let s: String = row.try_get(0)?;
179 s.parse().map_err(|e| Error::Decode(Box::new(e)))
180 }
181}
182
183impl<T: AnyImpl> AnyImpl for Option<T> {
188 fn columns() -> Vec<AnyInfo> {
189 T::columns()
190 }
191 fn to_map(&self) -> HashMap<String, String> {
192 match self {
193 Some(v) => v.to_map(),
194 None => HashMap::new(),
195 }
196 }
197}
198
199impl<T: FromAnyRow> FromAnyRow for Option<T> {
200 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
201 match T::from_any_row(row) {
203 Ok(v) => Ok(Some(v)),
204 Err(_) => Ok(None), }
208 }
209}
210
211macro_rules! impl_any_tuple {
221 ($($T:ident),+) => {
222 impl<$($T: AnyImpl),+> AnyImpl for ($($T,)+) {
223 fn columns() -> Vec<AnyInfo> {
224 let mut cols = Vec::new();
225 $(
226 cols.extend($T::columns());
227 )+
228 cols
229 }
230
231 fn to_map(&self) -> HashMap<String, String> {
232 let mut map = HashMap::new();
233 #[allow(non_snake_case)]
234 let ($($T,)+) = self;
235 $(
236 map.extend($T.to_map());
237 )+
238 map
239 }
240 }
241
242 impl<$($T: FromAnyRow),+> FromAnyRow for ($($T,)+) {
243 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
244 Ok((
245 $(
246 $T::from_any_row(row)?,
247 )+
248 ))
249 }
250 }
251 };
252}
253
254impl_any_tuple!(T1);
255impl_any_tuple!(T1, T2);
256impl_any_tuple!(T1, T2, T3);
257impl_any_tuple!(T1, T2, T3, T4);
258impl_any_tuple!(T1, T2, T3, T4, T5);
259impl_any_tuple!(T1, T2, T3, T4, T5, T6);
260impl_any_tuple!(T1, T2, T3, T4, T5, T6, T7);
261impl_any_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);