1use sqlx::{any::AnyRow, Error, Row};
2use std::collections::HashMap;
3use serde::{Serialize, Deserialize};
4
5#[derive(Debug, Clone)]
15pub struct AnyInfo {
16 pub column: &'static str,
18
19 pub sql_type: &'static str,
21
22 pub table: &'static str,
24}
25
26pub trait AnyImpl {
38 fn columns() -> Vec<AnyInfo>;
40
41 fn to_map(&self) -> HashMap<String, Option<String>>;
43}
44
45pub trait FromAnyRow: Sized {
47 fn from_any_row(row: &AnyRow) -> Result<Self, Error>;
49
50 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error>;
53}
54
55macro_rules! impl_supported_primitive {
60 ($($t:ty),*) => {
61 $(
62 impl AnyImpl for $t {
63 fn columns() -> Vec<AnyInfo> { Vec::new() }
64 fn to_map(&self) -> HashMap<String, Option<String>> { HashMap::new() }
65 }
66
67 impl FromAnyRow for $t {
68 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
69 row.try_get(0).map_err(|e| Error::Decode(Box::new(e)))
70 }
71
72 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
73 if *index >= row.len() {
74 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
75 }
76 let res = row.try_get(*index);
77 *index += 1;
78 res.map_err(|e| Error::Decode(Box::new(e)))
79 }
80 }
81 )*
82 };
83}
84
85impl_supported_primitive!(bool, i16, i32, i64, f32, f64, String);
87
88macro_rules! impl_cast_primitive {
89 ($($t:ty),*) => {
90 $(
91 impl AnyImpl for $t {
92 fn columns() -> Vec<AnyInfo> { Vec::new() }
93 fn to_map(&self) -> HashMap<String, Option<String>> { HashMap::new() }
94 }
95
96 impl FromAnyRow for $t {
97 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
98 let val: i64 = row.try_get(0).map_err(|e| Error::Decode(Box::new(e)))?;
100 Ok(val as $t)
101 }
102
103 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
104 if *index >= row.len() {
105 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
106 }
107 let res = row.try_get::<i64, _>(*index);
108 *index += 1;
109 let val = res.map_err(|e| Error::Decode(Box::new(e)))?;
110 Ok(val as $t)
111 }
112 }
113 )*
114 };
115}
116
117impl_cast_primitive!(i8, isize, u8, u16, u32, u64, usize);
119
120impl<T> AnyImpl for Vec<T>
125where
126 T: AnyImpl + Serialize + for<'de> Deserialize<'de>,
127{
128 fn columns() -> Vec<AnyInfo> {
129 Vec::new()
130 }
131 fn to_map(&self) -> HashMap<String, Option<String>> {
132 let mut map = HashMap::new();
133 if let Ok(json) = serde_json::to_string(self) {
134 map.insert("".to_string(), Some(json));
135 }
136 map
137 }
138}
139
140impl<T> FromAnyRow for Vec<T>
141where
142 T: Serialize + for<'de> Deserialize<'de> + Send,
143{
144 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
145 let mut index = 0;
146 Self::from_any_row_at(row, &mut index)
147 }
148
149 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
150 if *index >= row.len() {
151 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
152 }
153 let res = row.try_get::<String, _>(*index);
154 *index += 1;
155 let s = res.map_err(|e| Error::Decode(Box::new(e)))?;
156 serde_json::from_str(&s).map_err(|e| Error::Decode(Box::new(e)))
157 }
158}
159
160impl AnyImpl for serde_json::Value {
161 fn columns() -> Vec<AnyInfo> {
162 Vec::new()
163 }
164 fn to_map(&self) -> HashMap<String, Option<String>> {
165 let mut map = HashMap::new();
166 map.insert("".to_string(), Some(self.to_string()));
167 map
168 }
169}
170
171impl FromAnyRow for serde_json::Value {
172 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
173 let mut index = 0;
174 Self::from_any_row_at(row, &mut index)
175 }
176
177 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
178 if *index >= row.len() {
179 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
180 }
181 let res = row.try_get::<String, _>(*index);
182 *index += 1;
183 let s = res.map_err(|e| Error::Decode(Box::new(e)))?;
184 serde_json::from_str(&s).map_err(|e| Error::Decode(Box::new(e)))
185 }
186}
187
188impl AnyImpl for uuid::Uuid {
193 fn columns() -> Vec<AnyInfo> {
194 Vec::new()
195 }
196 fn to_map(&self) -> HashMap<String, Option<String>> {
197 HashMap::new()
198 }
199}
200
201impl FromAnyRow for uuid::Uuid {
202 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
203 let mut index = 0;
204 Self::from_any_row_at(row, &mut index)
205 }
206
207 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
208 if *index >= row.len() {
209 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
210 }
211 let res = row.try_get::<String, _>(*index);
212 *index += 1;
213 let s = res.map_err(|e| Error::Decode(Box::new(e)))?;
214 s.parse().map_err(|e| Error::Decode(Box::new(e)))
215 }
216}
217
218impl AnyImpl for chrono::NaiveDateTime {
219 fn columns() -> Vec<AnyInfo> {
220 Vec::new()
221 }
222 fn to_map(&self) -> HashMap<String, Option<String>> {
223 HashMap::new()
224 }
225}
226
227impl FromAnyRow for chrono::NaiveDateTime {
228 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
229 let mut index = 0;
230 Self::from_any_row_at(row, &mut index)
231 }
232
233 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
234 if *index >= row.len() {
235 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
236 }
237 let res = row.try_get::<String, _>(*index);
238 match res {
239 Ok(s) => {
240 *index += 1;
241 crate::temporal::parse_naive_datetime(&s).map_err(|e| Error::Decode(Box::new(e)))
242 }
243 Err(e) => {
244 if let Ok(i) = row.try_get::<i64, _>(*index) {
246 *index += 1;
247 return Ok(chrono::DateTime::from_timestamp(i, 0).map(|dt| dt.naive_utc()).unwrap_or_default());
248 }
249 if let Ok(None) = row.try_get::<Option<String>, _>(*index) {
253 *index += 1;
254 return Err(Error::Decode(Box::new(e))); }
256
257 Err(Error::Decode(Box::new(e)))
258 }
259 }
260 }
261}
262
263impl AnyImpl for chrono::NaiveDate {
264 fn columns() -> Vec<AnyInfo> {
265 Vec::new()
266 }
267 fn to_map(&self) -> HashMap<String, Option<String>> {
268 HashMap::new()
269 }
270}
271
272impl FromAnyRow for chrono::NaiveDate {
273 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
274 let mut index = 0;
275 Self::from_any_row_at(row, &mut index)
276 }
277
278 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
279 if *index >= row.len() {
280 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
281 }
282 let res = row.try_get::<String, _>(*index);
283 *index += 1;
284 let s = res.map_err(|e| Error::Decode(Box::new(e)))?;
285 crate::temporal::parse_naive_date(&s).map_err(|e| Error::Decode(Box::new(e)))
286 }
287}
288
289impl AnyImpl for chrono::NaiveTime {
290 fn columns() -> Vec<AnyInfo> {
291 Vec::new()
292 }
293 fn to_map(&self) -> HashMap<String, Option<String>> {
294 HashMap::new()
295 }
296}
297
298impl FromAnyRow for chrono::NaiveTime {
299 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
300 let mut index = 0;
301 Self::from_any_row_at(row, &mut index)
302 }
303
304 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
305 if *index >= row.len() {
306 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
307 }
308 let res = row.try_get::<String, _>(*index);
309 *index += 1;
310 let s = res.map_err(|e| Error::Decode(Box::new(e)))?;
311 crate::temporal::parse_naive_time(&s).map_err(|e| Error::Decode(Box::new(e)))
312 }
313}
314
315impl AnyImpl for chrono::DateTime<chrono::Utc> {
316 fn columns() -> Vec<AnyInfo> {
317 Vec::new()
318 }
319 fn to_map(&self) -> HashMap<String, Option<String>> {
320 HashMap::new()
321 }
322}
323
324impl FromAnyRow for chrono::DateTime<chrono::Utc> {
325 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
326 let mut index = 0;
327 Self::from_any_row_at(row, &mut index)
328 }
329
330 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
331 if *index >= row.len() {
332 return Err(Error::ColumnIndexOutOfBounds { index: *index, len: row.len() });
333 }
334 let res = row.try_get::<String, _>(*index);
335 match res {
336 Ok(s) => {
337 *index += 1;
338 crate::temporal::parse_datetime_utc(&s).map_err(|e| Error::Decode(Box::new(e)))
339 }
340 Err(e) => {
341 if let Ok(i) = row.try_get::<i64, _>(*index) {
343 *index += 1;
344 return Ok(chrono::DateTime::from_timestamp(i, 0).unwrap_or_else(|| chrono::DateTime::<chrono::Utc>::from_naive_utc_and_offset(chrono::NaiveDateTime::default(), chrono::Utc)));
345 }
346
347 if let Ok(None) = row.try_get::<Option<String>, _>(*index) {
348 *index += 1;
349 return Err(Error::Decode(Box::new(e)));
350 }
351
352 Err(Error::Decode(Box::new(e)))
353 }
354 }
355 }
356}
357
358impl<T: AnyImpl> AnyImpl for Option<T> {
363 fn columns() -> Vec<AnyInfo> {
364 T::columns()
365 }
366 fn to_map(&self) -> HashMap<String, Option<String>> {
367 match self {
368 Some(v) => v.to_map(),
369 None => HashMap::new(),
370 }
371 }
372}
373
374impl<T: FromAnyRow> FromAnyRow for Option<T> {
375 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
376 match T::from_any_row(row) {
377 Ok(v) => Ok(Some(v)),
378 Err(_) => Ok(None),
379 }
380 }
381
382 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
383 match T::from_any_row_at(row, index) {
384 Ok(v) => Ok(Some(v)),
385 Err(_) => Ok(None),
386 }
387 }
388}
389
390macro_rules! impl_any_tuple {
395 ($($T:ident),+) => {
396 impl<$($T: AnyImpl),+> AnyImpl for ($($T,)+) {
397 fn columns() -> Vec<AnyInfo> {
398 let mut cols = Vec::new();
399 $(
400 cols.extend($T::columns());
401 )+
402 cols
403 }
404
405 fn to_map(&self) -> HashMap<String, Option<String>> {
406 let mut map = HashMap::new();
407 #[allow(non_snake_case)]
408 let ($($T,)+) = self;
409 $(
410 map.extend($T.to_map());
411 )+
412 map
413 }
414 }
415
416 impl<$($T: FromAnyRow),+> FromAnyRow for ($($T,)+) {
417 fn from_any_row(row: &AnyRow) -> Result<Self, Error> {
418 let mut index = 0;
419 Ok((
420 $(
421 $T::from_any_row_at(row, &mut index)?,
422 )+
423 ))
424 }
425
426 fn from_any_row_at(row: &AnyRow, index: &mut usize) -> Result<Self, Error> {
427 Ok((
428 $(
429 $T::from_any_row_at(row, index)?,
430 )+
431 ))
432 }
433 }
434 };
435}
436
437impl_any_tuple!(T1);
438impl_any_tuple!(T1, T2);
439impl_any_tuple!(T1, T2, T3);
440impl_any_tuple!(T1, T2, T3, T4);
441impl_any_tuple!(T1, T2, T3, T4, T5);
442impl_any_tuple!(T1, T2, T3, T4, T5, T6);
443impl_any_tuple!(T1, T2, T3, T4, T5, T6, T7);
444impl_any_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);