use crate::QueryError;
pub(crate) fn first_or_not_found<T>(results: Vec<T>, table: &str) -> Result<T, QueryError> {
results
.into_iter()
.next()
.ok_or_else(|| QueryError::NotFound {
table: table.to_owned(),
})
}
#[cfg(any(feature = "libsql", feature = "postgres"))]
macro_rules! impl_async_fetch {
($scalar_ty:ty) => {
impl super::super::SelectBuilder {
pub async fn fetch_all<T: toolu_orm_core::row::FromRow + Send>(
&self,
exec: &(impl $crate::executor::Executor + Send + Sync),
) -> Result<Vec<T>, $crate::QueryError> {
let (sql, params) = self.to_sql();
exec.query_map::<T>(&sql, params).await
}
pub async fn fetch_one<T: toolu_orm_core::row::FromRow + Send>(
&self,
exec: &(impl $crate::executor::Executor + Send + Sync),
) -> Result<T, $crate::QueryError> {
let results = self.fetch_all::<T>(exec).await?;
super::shared::first_or_not_found(results, &self.table)
}
pub async fn fetch_optional<T: toolu_orm_core::row::FromRow + Send>(
&self,
exec: &(impl $crate::executor::Executor + Send + Sync),
) -> Result<Option<T>, $crate::QueryError> {
let results = self.fetch_all::<T>(exec).await?;
Ok(results.into_iter().next())
}
pub async fn count(
&self,
exec: &(impl $crate::executor::Executor + Send + Sync),
) -> Result<i64, $crate::QueryError> {
let (sql, params) = self.to_count_sql();
let rows = exec.query_map::<$scalar_ty>(&sql, params).await?;
super::shared::first_or_not_found(rows, &self.table).map(|r| r.value)
}
pub async fn exists(
&self,
exec: &(impl $crate::executor::Executor + Send + Sync),
) -> Result<bool, $crate::QueryError> {
let (sql, params) = self.to_exists_sql();
let rows = exec.query_map::<$scalar_ty>(&sql, params).await?;
Ok(
rows
.into_iter()
.next()
.map(|r| r.value != 0)
.unwrap_or(false),
)
}
}
};
}
#[cfg(any(feature = "libsql", feature = "postgres"))]
pub(super) use impl_async_fetch;
#[cfg(feature = "rusqlite")]
macro_rules! impl_sync_fetch {
($scalar_ty:ty) => {
impl super::super::SelectBuilder {
pub fn fetch_all<T: toolu_orm_core::row::FromRow>(
&self,
exec: &impl $crate::executor::Executor,
) -> Result<Vec<T>, $crate::QueryError> {
let (sql, params) = self.to_sql();
exec.query_map::<T>(&sql, params)
}
pub fn fetch_one<T: toolu_orm_core::row::FromRow>(
&self,
exec: &impl $crate::executor::Executor,
) -> Result<T, $crate::QueryError> {
let results = self.fetch_all::<T>(exec)?;
super::shared::first_or_not_found(results, &self.table)
}
pub fn fetch_optional<T: toolu_orm_core::row::FromRow>(
&self,
exec: &impl $crate::executor::Executor,
) -> Result<Option<T>, $crate::QueryError> {
let results = self.fetch_all::<T>(exec)?;
Ok(results.into_iter().next())
}
pub fn count(
&self,
exec: &impl $crate::executor::Executor,
) -> Result<i64, $crate::QueryError> {
let (sql, params) = self.to_count_sql();
let rows = exec.query_map::<$scalar_ty>(&sql, params)?;
super::shared::first_or_not_found(rows, &self.table).map(|r| r.value)
}
pub fn exists(
&self,
exec: &impl $crate::executor::Executor,
) -> Result<bool, $crate::QueryError> {
let (sql, params) = self.to_exists_sql();
let rows = exec.query_map::<$scalar_ty>(&sql, params)?;
Ok(
rows
.into_iter()
.next()
.map(|r| r.value != 0)
.unwrap_or(false),
)
}
}
};
}
#[cfg(feature = "rusqlite")]
pub(super) use impl_sync_fetch;