use crate::result::Result;
use crate::TaitanOrmError;
use sqlx::query::Query;
use sqlx::{Database, Executor, IntoArguments};
use std::marker::PhantomData;
use taitan_orm_trait::SelectedEntity;
pub trait SqlGenericExecutor {
type DB: Database;
type CountType: SelectedEntity<Self::DB>;
fn get_affected_rows(query_result: &<Self::DB as Database>::QueryResult) -> u64;
async fn generic_exists<'a, EX, A>(ex: EX, stmt: &'a str, args: A) -> Result<bool>
where
EX: Executor<'a, Database = Self::DB>,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(_) = result_opt {
Ok(true)
} else {
Ok(false)
}
}
async fn generic_exists_plain<'a, EX, A>(
ex: EX,
stmt: &'a str,
_args: PhantomData<A>,
) -> Result<bool>
where
EX: Executor<'a, Database = Self::DB>,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(_) = result_opt {
Ok(true)
} else {
Ok(false)
}
}
async fn generic_count<'s, 'a, EX, A>(ex: EX, stmt: &'s str, args: A) -> Result<Self::CountType>
where
's: 'a,
EX: Executor<'a, Database = Self::DB>,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(row) = result_opt {
Ok(Self::CountType::from_row_full(row)?)
} else {
Ok(Default::default())
}
}
async fn generic_count_plain<'a, EX, A>(
ex: EX,
stmt: &'a str,
_args: PhantomData<A>,
) -> Result<Self::CountType>
where
EX: Executor<'a, Database = Self::DB>,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(row) = result_opt {
Ok(Self::CountType::from_row_full(row)?)
} else {
Ok(Default::default())
}
}
async fn generic_execute<'a, 'e, EX, A>(ex: EX, query: &'a str, args: A) -> Result<u64>
where
EX: Executor<'e, Database = Self::DB>,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(query, args);
let result: <Self::DB as Database>::QueryResult = query.execute(ex).await?;
Ok(Self::get_affected_rows(&result))
}
async fn generic_execute_plain<'a, EX, A>(
ex: EX,
query: &'a str,
_args: PhantomData<A>,
) -> Result<u64>
where
EX: Executor<'a, Database = Self::DB>,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(query, Default::default());
let result: <Self::DB as Database>::QueryResult = query.execute(ex).await?;
Ok(Self::get_affected_rows(&result))
}
async fn generic_fetch_all<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE::Selection,
args: A,
) -> Result<Vec<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Vec<<Self::DB as Database>::Row> = query.fetch_all(ex).await?;
let mut result: Vec<SE> = Vec::new();
for row in result_opt {
let selected_result = SE::from_row(selection, row);
if let Ok(selected_entity) = selected_result {
result.push(selected_entity);
} else {
return Err(TaitanOrmError::FromRowToEntityError);
}
}
Ok(result)
}
async fn generic_fetch_all_<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE,
args: A,
) -> Result<Vec<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Vec<<Self::DB as Database>::Row> = query.fetch_all(ex).await?;
let mut result: Vec<SE> = Vec::new();
for row in result_opt {
let selected_result = SE::select_from_row(selection, row);
if let Ok(selected_entity) = selected_result {
result.push(selected_entity);
} else {
return Err(TaitanOrmError::FromRowToEntityError);
}
}
Ok(result)
}
async fn generic_fetch_all_plain<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE::Selection,
_: PhantomData<A>,
) -> Result<Vec<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Vec<<Self::DB as Database>::Row> = query.fetch_all(ex).await?;
let mut result: Vec<SE> = Vec::new();
for row in result_opt {
let selected_result = SE::from_row(selection, row);
if let Ok(selected_entity) = selected_result {
result.push(selected_entity);
} else {
return Err(TaitanOrmError::FromRowToEntityError);
}
}
Ok(result)
}
async fn generic_fetch_all_plain_<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE,
_: PhantomData<A>,
) -> Result<Vec<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Vec<<Self::DB as Database>::Row> = query.fetch_all(ex).await?;
let mut result: Vec<SE> = Vec::new();
for row in result_opt {
let selected_result = SE::select_from_row(selection, row);
if let Ok(selected_entity) = selected_result {
result.push(selected_entity);
} else {
return Err(TaitanOrmError::FromRowToEntityError);
}
}
Ok(result)
}
async fn generic_fetch_one<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE::Selection,
args: A,
) -> Result<SE>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result: <Self::DB as Database>::Row = query.fetch_one(ex).await?;
Ok(SE::from_row(selection, result)?)
}
async fn generic_fetch_one_<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE,
args: A,
) -> Result<SE>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result: <Self::DB as Database>::Row = query.fetch_one(ex).await?;
Ok(SE::select_from_row(selection, result)?)
}
async fn generic_fetch_one_plain<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE::Selection,
_: PhantomData<A>,
) -> Result<SE>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result: <Self::DB as Database>::Row = query.fetch_one(ex).await?;
Ok(SE::from_row(selection, result)?)
}
async fn generic_fetch_one_plain_<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE,
_: PhantomData<A>,
) -> Result<SE>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result: <Self::DB as Database>::Row = query.fetch_one(ex).await?;
Ok(SE::select_from_row(selection, result)?)
}
async fn generic_fetch_option<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE::Selection,
args: A,
) -> Result<Option<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(Some(SE::from_row(selection, result)?))
} else {
Ok(None)
}
}
async fn generic_fetch_option_<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE,
args: A,
) -> Result<Option<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(Some(SE::select_from_row(selection, result)?))
} else {
Ok(None)
}
}
async fn generic_fetch_option_plain<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE::Selection,
_: PhantomData<A>,
) -> Result<Option<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(Some(SE::from_row(selection, result)?))
} else {
Ok(None)
}
}
async fn generic_fetch_option_plain_<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
selection: &SE,
_: PhantomData<A>,
) -> Result<Option<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(Some(SE::select_from_row(selection, result)?))
} else {
Ok(None)
}
}
async fn generic_fetch_all_full<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
args: A,
) -> Result<Vec<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_vec: Vec<<Self::DB as Database>::Row> = query.fetch_all(ex).await?;
let mut result: Vec<SE> = Vec::new();
for row in result_vec {
result.push(SE::from_row_full(row)?);
}
Ok(result)
}
async fn generic_fetch_all_full_plain<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
_: PhantomData<A>,
) -> Result<Vec<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_vec: Vec<<Self::DB as Database>::Row> = query.fetch_all(ex).await?;
let mut result: Vec<SE> = Vec::new();
for row in result_vec {
result.push(SE::from_row_full(row)?);
}
Ok(result)
}
async fn generic_fetch_one_full<'a, EX, SE, A>(ex: EX, stmt: &'a str, args: A) -> Result<SE>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(SE::from_row_full(result)?)
} else {
Err(sqlx::error::Error::RowNotFound.into())
}
}
async fn generic_fetch_one_full_plain<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
_: PhantomData<A>,
) -> Result<SE>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(SE::from_row_full(result)?)
} else {
Err(sqlx::error::Error::RowNotFound.into())
}
}
async fn generic_fetch_option_full<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
args: A,
) -> Result<Option<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, args);
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(Some(SE::from_row_full(result)?))
} else {
Ok(None)
}
}
async fn generic_fetch_option_full_plain<'a, EX, SE, A>(
ex: EX,
stmt: &'a str,
_: PhantomData<A>,
) -> Result<Option<SE>>
where
EX: Executor<'a, Database = Self::DB>,
SE: SelectedEntity<Self::DB> + Send + Unpin,
A: IntoArguments<'a, Self::DB> + 'a + Default,
{
let query: Query<'a, Self::DB, A> = sqlx::query_with(stmt, Default::default());
let result_opt: Option<<Self::DB as Database>::Row> = query.fetch_optional(ex).await?;
if let Some(result) = result_opt {
Ok(Some(SE::from_row_full(result)?))
} else {
Ok(None)
}
}
}