1use crate::query::select::{SelectStatement, Selectable, WildCard};
2use crate::{CheckedSql, ToSql};
3use sqlx::{Database, Error, Executor, FromRow};
4use std::future::Future;
5use std::pin::Pin;
6
7pub trait Fetch<'c, 'out, E>: ToSql + CheckedSql
8where
9 E: Executor<'c> + 'out,
10{
11 type Output: for<'r> FromRow<'r, <E::Database as Database>::Row>;
12
13 fn fetch_one(
14 &self,
15 exec: E,
16 ) -> Pin<Box<dyn Future<Output = Result<Self::Output, Error>> + Send + 'out>> {
17 let sql = self.to_sql();
18 Box::pin(async move {
19 exec.fetch_one(sql.as_ref())
20 .await
21 .and_then(|row| FromRow::from_row(&row))
22 })
23 }
24
25 fn fetch_optional(
26 &self,
27 exec: E,
28 ) -> Pin<Box<dyn Future<Output = Result<Option<Self::Output>, Error>> + Send + 'out>> {
29 let sql = self.to_sql();
30 Box::pin(async move {
31 exec.fetch_optional(sql.as_ref())
32 .await
33 .and_then(|row| row.as_ref().map(FromRow::from_row).transpose())
34 })
35 }
36}
37
38impl<'c, 'out, E, S> Fetch<'c, 'out, E> for SelectStatement<S, WildCard>
39where
40 E: Executor<'c> + 'out,
41 S: Selectable,
42 S::Table: for<'r> FromRow<'r, <E::Database as Database>::Row>,
43{
44 type Output = S::Table;
45}