use futures::future::BoxFuture;
use sqlx::Acquire;
#[derive(Debug)]
pub enum AnyStatement {
#[cfg(feature = "mysql")]
MySql(sqlx::mysql::MySqlStatement),
#[cfg(feature = "sqlite")]
Sqlite(sqlx::sqlite::SqliteStatement),
}
pub enum AnyRow {
#[cfg(feature = "mysql")]
MySql(sqlx::mysql::MySqlRow),
#[cfg(feature = "sqlite")]
Sqlite(sqlx::sqlite::SqliteRow),
}
#[derive(Debug)]
pub enum AnyQueryResult {
#[cfg(feature = "mysql")]
MySql(sqlx::mysql::MySqlQueryResult),
#[cfg(feature = "sqlite")]
Sqlite(sqlx::sqlite::SqliteQueryResult),
}
impl AnyQueryResult {
pub fn rows_affected(&self) -> u64 {
match self {
#[cfg(feature = "mysql")]
Self::MySql(res) => res.rows_affected(),
#[cfg(feature = "sqlite")]
Self::Sqlite(res) => res.rows_affected(),
}
}
}
pub enum AnyQuery<'a> {
#[cfg(feature = "mysql")]
MySql(sqlx::query::Query<'a, sqlx::MySql, sqlx::mysql::MySqlArguments>),
#[cfg(feature = "sqlite")]
Sqlite(sqlx::query::Query<'a, sqlx::Sqlite, sqlx::sqlite::SqliteArguments>),
}
impl AnyQuery<'_> {
#[allow(irrefutable_let_patterns)]
pub async fn execute(self, con: &mut AnyConnection<'_>) -> Result<AnyQueryResult, sqlx::Error> {
Ok(match self {
#[cfg(feature = "mysql")]
Self::MySql(query) => {
let AnyConnection::MySql(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of mysql type, while query was.".into(),
));
};
AnyQueryResult::MySql(query.execute(&mut **con).await?)
}
#[cfg(feature = "sqlite")]
Self::Sqlite(query) => {
let AnyConnection::Sqlite(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of sqlite type, while query was.".into(),
));
};
AnyQueryResult::Sqlite(query.execute(&mut **con).await?)
}
})
}
#[allow(irrefutable_let_patterns)]
pub async fn fetch_one(self, con: &mut AnyConnection<'_>) -> Result<AnyRow, sqlx::Error> {
Ok(match self {
#[cfg(feature = "mysql")]
Self::MySql(query) => {
let AnyConnection::MySql(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of mysql type, while query was.".into(),
));
};
AnyRow::MySql(query.fetch_one(&mut **con).await?)
}
#[cfg(feature = "sqlite")]
Self::Sqlite(query) => {
let AnyConnection::Sqlite(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of sqlite type, while query was.".into(),
));
};
AnyRow::Sqlite(query.fetch_one(&mut **con).await?)
}
})
}
#[allow(irrefutable_let_patterns)]
pub async fn fetch_all(self, con: &mut AnyConnection<'_>) -> Result<Vec<AnyRow>, sqlx::Error> {
Ok(match self {
#[cfg(feature = "mysql")]
Self::MySql(query) => {
let AnyConnection::MySql(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of mysql type, while query was.".into(),
));
};
query
.fetch_all(&mut **con)
.await?
.into_iter()
.map(AnyRow::MySql)
.collect()
}
#[cfg(feature = "sqlite")]
Self::Sqlite(query) => {
let AnyConnection::Sqlite(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of sqlite type, while query was.".into(),
));
};
query
.fetch_all(&mut **con)
.await?
.into_iter()
.map(AnyRow::Sqlite)
.collect()
}
})
}
#[allow(irrefutable_let_patterns)]
pub async fn fetch_optional(
self,
con: &mut AnyConnection<'_>,
) -> Result<Option<AnyRow>, sqlx::Error> {
Ok(match self {
#[cfg(feature = "mysql")]
Self::MySql(query) => {
let AnyConnection::MySql(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of mysql type, while query was.".into(),
));
};
query.fetch_optional(&mut **con).await?.map(AnyRow::MySql)
}
#[cfg(feature = "sqlite")]
Self::Sqlite(query) => {
let AnyConnection::Sqlite(con) = con else {
return Err(sqlx::Error::AnyDriverError(
"Connection was not of sqlite type, while query was.".into(),
));
};
query.fetch_optional(&mut **con).await?.map(AnyRow::Sqlite)
}
})
}
}
#[derive(Debug)]
pub enum AnyTransaction<'a, 'b> {
#[cfg(feature = "mysql")]
MySql(&'a mut sqlx::Transaction<'b, sqlx::MySql>),
#[cfg(feature = "sqlite")]
Sqlite(&'a mut sqlx::Transaction<'b, sqlx::Sqlite>),
}
impl AnyTransaction<'_, '_> {
pub fn con(&mut self) -> AnyConnection<'_> {
match self {
#[cfg(feature = "mysql")]
AnyTransaction::MySql(trans) => AnyConnection::MySql(trans),
#[cfg(feature = "sqlite")]
AnyTransaction::Sqlite(trans) => AnyConnection::Sqlite(trans),
}
}
}
#[derive(Debug)]
pub enum AnyConnection<'a> {
#[cfg(feature = "mysql")]
MySql(&'a mut sqlx::mysql::MySqlConnection),
#[cfg(feature = "sqlite")]
Sqlite(&'a mut sqlx::sqlite::SqliteConnection),
}
impl AnyConnection<'_> {
pub async fn transaction<'a, F, R, E>(&'a mut self, callback: F) -> Result<R, E>
where
for<'c> F: FnOnce(AnyTransaction<'c, '_>) -> BoxFuture<'c, Result<R, E>> + 'a + Send + Sync,
Self: Sized,
R: Send,
E: From<sqlx::Error> + Send,
{
use sqlx::Connection;
match self {
#[cfg(feature = "mysql")]
AnyConnection::MySql(con) => {
con.transaction(|transaction| callback(AnyTransaction::MySql(transaction)))
.await
}
#[cfg(feature = "sqlite")]
AnyConnection::Sqlite(con) => {
con.transaction(|transaction| callback(AnyTransaction::Sqlite(transaction)))
.await
}
}
}
}
#[derive(Debug)]
pub enum AnyPoolConnection {
#[cfg(feature = "mysql")]
MySql(sqlx::pool::PoolConnection<sqlx::MySql>),
#[cfg(feature = "sqlite")]
Sqlite(sqlx::pool::PoolConnection<sqlx::Sqlite>),
}
impl AnyPoolConnection {
pub async fn acquire(&mut self) -> Result<AnyConnection<'_>, sqlx::Error> {
Ok(match self {
#[cfg(feature = "mysql")]
Self::MySql(con) => AnyConnection::MySql(con.acquire().await?),
#[cfg(feature = "sqlite")]
Self::Sqlite(con) => AnyConnection::Sqlite(con.acquire().await?),
})
}
}
#[derive(Debug, Clone)]
pub enum AnyPool {
#[cfg(feature = "mysql")]
MySql(sqlx::mysql::MySqlPool),
#[cfg(feature = "sqlite")]
Sqlite(sqlx::sqlite::SqlitePool),
}
impl AnyPool {
pub async fn acquire(&self) -> Result<AnyPoolConnection, sqlx::Error> {
Ok(match self {
#[cfg(feature = "mysql")]
Self::MySql(pool) => AnyPoolConnection::MySql(pool.acquire().await?),
#[cfg(feature = "sqlite")]
Self::Sqlite(pool) => AnyPoolConnection::Sqlite(pool.acquire().await?),
})
}
}