use std::{
future::{Future, IntoFuture},
marker::PhantomData,
pin::Pin,
};
use crate::{DecodeRow, Dialect, Driver, Table};
#[non_exhaustive]
pub struct SelectOperation {
pub table: &'static str,
}
pub struct Select<D: Driver, T> {
driver: D,
op: SelectOperation,
phantom: PhantomData<T>,
}
impl<D: Driver, T: Table> Select<D, T> {
pub(crate) fn new(driver: D) -> Self {
Self {
driver,
op: SelectOperation { table: T::NAME },
phantom: PhantomData,
}
}
pub fn to_sql(&self) -> (String, D::Arguments<'_>) {
D::Dialect::select(&self.op)
}
}
impl<D: Driver, T: Table> IntoFuture for Select<D, T>
where
T::Model: DecodeRow<D>,
{
type Output = Result<Vec<T::Model>, D::Error>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output>>>;
fn into_future(self) -> Self::IntoFuture {
let driver = self.driver.clone();
let (sql, arguments) = D::Dialect::select(&self.op);
Box::pin(async move {
driver
.query(&sql, arguments)
.await?
.into_iter()
.map(|r| T::Model::decode(r))
.collect::<Result<Vec<_>, _>>()
.map_err(D::error_decoding_value)
})
}
}