#[cfg(feature = "any")]
use sqlx::Any;
#[cfg(feature = "any")]
use sqlx::AnyConnection;
use sqlx::{Database, Error};
#[cfg(feature = "mysql")]
use sqlx::{MySql, MySqlConnection};
#[cfg(feature = "postgres")]
use sqlx::{PgConnection, Postgres};
#[cfg(feature = "sqlite")]
use sqlx::{Sqlite, SqliteConnection};
use super::QueueDatabase;
#[cfg(feature = "any")]
use super::built_in::{MYSQL_BACKEND, POSTGRES_BACKEND, SQLITE_BACKEND};
#[doc(hidden)]
#[derive(Debug, Clone, Copy)]
pub struct InsertSql<'s> {
pub postgres: Option<&'s str>,
pub mysql: Option<&'s str>,
pub sqlite: Option<&'s str>,
}
#[cfg(feature = "any")]
impl<'s> InsertSql<'s> {
fn for_backend(&self, backend: &str) -> Option<&'s str> {
match backend {
POSTGRES_BACKEND => self.postgres,
MYSQL_BACKEND => self.mysql,
SQLITE_BACKEND => self.sqlite,
_ => None,
}
}
}
#[doc(hidden)]
pub trait OnConnection: Send {
type Database: QueueDatabase;
fn connection(&mut self) -> &mut <Self::Database as Database>::Connection;
fn insert_sql<'s>(&self, sql: &InsertSql<'s>) -> Option<&'s str>;
}
#[cfg(feature = "postgres")]
impl OnConnection for PgConnection {
type Database = Postgres;
fn connection(&mut self) -> &mut Self {
self
}
fn insert_sql<'s>(&self, sql: &InsertSql<'s>) -> Option<&'s str> {
sql.postgres
}
}
#[cfg(feature = "mysql")]
impl OnConnection for MySqlConnection {
type Database = MySql;
fn connection(&mut self) -> &mut Self {
self
}
fn insert_sql<'s>(&self, sql: &InsertSql<'s>) -> Option<&'s str> {
sql.mysql
}
}
#[cfg(feature = "sqlite")]
impl OnConnection for SqliteConnection {
type Database = Sqlite;
fn connection(&mut self) -> &mut Self {
self
}
fn insert_sql<'s>(&self, sql: &InsertSql<'s>) -> Option<&'s str> {
sql.sqlite
}
}
#[cfg(feature = "any")]
impl OnConnection for AnyConnection {
type Database = Any;
fn connection(&mut self) -> &mut Self {
self
}
fn insert_sql<'s>(&self, sql: &InsertSql<'s>) -> Option<&'s str> {
sql.for_backend(self.backend_name())
}
}
#[doc(hidden)]
#[must_use]
pub fn no_insert(row: &'static str) -> Error {
Error::Configuration(
format!("`{row}` has no generated insert for this connection's database").into(),
)
}
#[cfg(all(test, feature = "any"))]
mod tests {
use super::InsertSql;
use crate::inbox::database::built_in::{MYSQL_BACKEND, POSTGRES_BACKEND, SQLITE_BACKEND};
#[test]
fn an_any_backend_runs_the_insert_of_its_database() {
let sql = InsertSql {
postgres: Some("INSERT .. ($1)"),
mysql: Some("INSERT .. (?)"),
sqlite: None,
};
assert_eq!(sql.for_backend(POSTGRES_BACKEND), Some("INSERT .. ($1)"));
assert_eq!(sql.for_backend(MYSQL_BACKEND), Some("INSERT .. (?)"));
assert_eq!(
sql.for_backend(SQLITE_BACKEND),
None,
"the derive was built without that dialect"
);
assert_eq!(sql.for_backend("MSSQL"), None);
}
}