use async_trait::async_trait;
use crate::{
error::*,
sql::FromQueryResult,
statements::SqlStatement,
util::{TypedConsListNil, TypesNotEqual},
};
mod connection;
mod connection_pool;
mod transaction;
pub use connection::*;
pub use connection_pool::*;
pub use transaction::*;
#[async_trait]
pub trait SqlStatementExecutor: Sized + Send + Sync {
async fn execute(&self, statement: impl SqlStatement + Send) -> Result<ExecuteResult>;
async fn load_one<O: FromQueryResult + Send, S: SqlStatement + Send>(
&self,
statement: S,
) -> Result<O>
where
(S::OutputFields, TypedConsListNil): TypesNotEqual;
async fn load_one_value<
FieldName: crate::sql::FieldNameCharsConsListItem,
FieldType: deadpool_postgres::tokio_postgres::types::FromSqlOwned + Send,
S: SqlStatement<
OutputFields = crate::sql::FieldsConsListCons<
FieldName,
FieldType,
crate::util::TypedConsListNil,
>,
> + Send,
>(
&self,
statement: S,
) -> Result<FieldType>;
async fn load_optional<O: FromQueryResult + Send, S: SqlStatement + Send>(
&self,
statement: S,
) -> Result<Option<O>>
where
(S::OutputFields, TypedConsListNil): TypesNotEqual;
async fn load_optional_value<
FieldName: crate::sql::FieldNameCharsConsListItem,
FieldType: deadpool_postgres::tokio_postgres::types::FromSqlOwned + Send,
S: SqlStatement<
OutputFields = crate::sql::FieldsConsListCons<
FieldName,
FieldType,
crate::util::TypedConsListNil,
>,
> + Send,
>(
&self,
statement: S,
) -> Result<Option<FieldType>>;
async fn load_all<O: FromQueryResult + Send, S: SqlStatement + Send>(
&self,
statement: S,
) -> Result<Vec<O>>
where
(S::OutputFields, TypedConsListNil): TypesNotEqual;
async fn load_all_values<
FieldName: crate::sql::FieldNameCharsConsListItem,
FieldType: deadpool_postgres::tokio_postgres::types::FromSqlOwned + Send,
S: SqlStatement<
OutputFields = crate::sql::FieldsConsListCons<
FieldName,
FieldType,
crate::util::TypedConsListNil,
>,
> + Send,
>(
&self,
statement: S,
) -> Result<Vec<FieldType>>;
}
pub struct ExecuteResult {
pub rows_modified: u64,
}
macro_rules! impl_sql_statement_executor {
{$impl_for: ty, $get_raw_executor: expr $(,$($generic:tt),+)?} => {
#[async_trait::async_trait]
impl $(< $($generic),+ >)? crate::execution::SqlStatementExecutor for $impl_for {
async fn execute(
&self,
statement: impl crate::statements::SqlStatement + Send,
) -> Result<ExecuteResult> {
let (query_string, parameter_binder) = statement.build();
let rows_modified = $get_raw_executor(self).await?
.execute(&query_string, parameter_binder.parameters())
.await?;
Ok(ExecuteResult { rows_modified })
}
async fn load_one<O: FromQueryResult, S: SqlStatement + Send>(
&self,
statement: S,
) -> Result<O>
where
(S::OutputFields, crate::util::TypedConsListNil): crate::util::TypesNotEqual
{
use futures::{pin_mut, TryStreamExt};
let (query_string, parameter_binder) = statement.build();
let row_stream = $get_raw_executor(self).await?
.query_raw(&query_string, parameter_binder.parameters().iter().copied())
.await?;
pin_mut!(row_stream);
let maybe_row = row_stream.try_next().await?;
match maybe_row {
Some(row) => Ok(O::from_row(row)?),
None => Err(Error::NoRecords),
}
}
async fn load_one_value<
FieldName: crate::sql::FieldNameCharsConsListItem,
FieldType: deadpool_postgres::tokio_postgres::types::FromSqlOwned + Send,
S: SqlStatement<
OutputFields = crate::sql::FieldsConsListCons<
FieldName,
FieldType,
crate::util::TypedConsListNil,
>,
> + Send,
>(
&self,
statement: S,
) -> Result<FieldType> {
use futures::{pin_mut, TryStreamExt};
let (query_string, parameter_binder) = statement.build();
let row_stream = $get_raw_executor(self).await?
.query_raw(&query_string, parameter_binder.parameters().iter().copied())
.await?;
pin_mut!(row_stream);
let maybe_row = row_stream.try_next().await?;
match maybe_row {
Some(row) => Ok(row.try_get(0)?),
None => Err(Error::NoRecords),
}
}
async fn load_optional<O: FromQueryResult, S: SqlStatement + Send>(
&self,
statement: S,
) -> Result<Option<O>>
where
(S::OutputFields, crate::util::TypedConsListNil): crate::util::TypesNotEqual
{
use futures::{pin_mut, TryStreamExt};
let (query_string, parameter_binder) = statement.build();
let row_stream = $get_raw_executor(self).await?
.query_raw(&query_string, parameter_binder.parameters().iter().copied())
.await?;
pin_mut!(row_stream);
let maybe_row = row_stream.try_next().await?;
match maybe_row {
Some(row) => Ok(Some(O::from_row(row)?)),
None => Ok(None),
}
}
async fn load_optional_value<
FieldName: crate::sql::FieldNameCharsConsListItem,
FieldType: deadpool_postgres::tokio_postgres::types::FromSqlOwned + Send,
S: SqlStatement<
OutputFields = crate::sql::FieldsConsListCons<
FieldName,
FieldType,
crate::util::TypedConsListNil,
>,
> + Send,
>(
&self,
statement: S,
) -> Result<Option<FieldType>> {
use futures::{pin_mut, TryStreamExt};
let (query_string, parameter_binder) = statement.build();
let row_stream = $get_raw_executor(self).await?
.query_raw(&query_string, parameter_binder.parameters().iter().copied())
.await?;
pin_mut!(row_stream);
let maybe_row = row_stream.try_next().await?;
match maybe_row {
Some(row) => Ok(Some(row.try_get(0)?)),
None => Ok(None),
}
}
async fn load_all<O: FromQueryResult + Send, S: SqlStatement + Send>(
&self,
statement: S,
) -> Result<Vec<O>>
where
(S::OutputFields, crate::util::TypedConsListNil): crate::util::TypesNotEqual
{
use futures::{pin_mut, TryStreamExt};
let (query_string, parameter_binder) = statement.build();
let row_stream = $get_raw_executor(self).await?
.query_raw(&query_string, parameter_binder.parameters().iter().copied())
.await?;
pin_mut!(row_stream);
let mut records = Vec::new();
while let Some(row) = row_stream.try_next().await? {
records.push(O::from_row(row)?)
}
Ok(records)
}
async fn load_all_values<
FieldName: crate::sql::FieldNameCharsConsListItem,
FieldType: deadpool_postgres::tokio_postgres::types::FromSqlOwned + Send,
S: SqlStatement<
OutputFields = crate::sql::FieldsConsListCons<
FieldName,
FieldType,
crate::util::TypedConsListNil,
>,
> + Send,
>(
&self,
statement: S,
) -> Result<Vec<FieldType>> {
use futures::{pin_mut, TryStreamExt};
let (query_string, parameter_binder) = statement.build();
let row_stream = $get_raw_executor(self).await?
.query_raw(&query_string, parameter_binder.parameters().iter().copied())
.await?;
pin_mut!(row_stream);
let mut records = Vec::new();
while let Some(row) = row_stream.try_next().await? {
records.push(row.try_get(0)?)
}
Ok(records)
}
}
};
}
pub(in crate::execution) use impl_sql_statement_executor;