use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::{SystemTime, UNIX_EPOCH};
use switchy_database::Database;
pub type Db = Arc<Box<dyn Database>>;
#[must_use]
pub fn db_ref(db: &Db) -> &dyn Database {
db.as_ref().as_ref()
}
pub struct BackendInfo {
pub name: &'static str,
pub db: Db,
}
static TABLE_COUNTER: AtomicU64 = AtomicU64::new(0);
#[must_use]
pub fn unique_table_name(prefix: &str) -> String {
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis();
let counter = TABLE_COUNTER.fetch_add(1, Ordering::SeqCst);
format!("{prefix}_{timestamp}_{counter}")
}
#[must_use]
pub fn init_backends(rt: &tokio::runtime::Runtime) -> Vec<BackendInfo> {
let _guard = rt.enter();
rt.block_on(get_available_backends())
}
pub async fn get_available_backends() -> Vec<BackendInfo> {
let mut backends = Vec::new();
#[cfg(feature = "sqlite-rusqlite")]
if let Some(backend) = init_rusqlite().await {
backends.push(backend);
}
#[cfg(feature = "sqlite-sqlx")]
if let Some(backend) = init_sqlx_sqlite().await {
backends.push(backend);
}
#[cfg(feature = "turso")]
if let Some(backend) = init_turso().await {
backends.push(backend);
}
#[cfg(feature = "postgres-raw")]
if let Some(backend) = init_postgres_raw().await {
backends.push(backend);
}
#[cfg(feature = "postgres-sqlx")]
if let Some(backend) = init_postgres_sqlx().await {
backends.push(backend);
}
#[cfg(feature = "mysql-sqlx")]
if let Some(backend) = init_mysql_sqlx().await {
backends.push(backend);
}
backends
}
#[cfg(feature = "sqlite-rusqlite")]
async fn init_rusqlite() -> Option<BackendInfo> {
let db = switchy_database_connection::init_sqlite_rusqlite(None).ok()?;
Some(BackendInfo {
name: "sqlite-rusqlite",
db: Arc::new(db),
})
}
#[cfg(feature = "sqlite-sqlx")]
async fn init_sqlx_sqlite() -> Option<BackendInfo> {
let db = switchy_database_connection::init_sqlite_sqlx(None)
.await
.ok()?;
Some(BackendInfo {
name: "sqlite-sqlx",
db: Arc::new(db),
})
}
#[cfg(feature = "turso")]
async fn init_turso() -> Option<BackendInfo> {
let db = switchy_database_connection::init_turso_local(None)
.await
.ok()?;
Some(BackendInfo {
name: "turso",
db: Arc::new(db),
})
}
#[cfg(feature = "postgres-raw")]
async fn init_postgres_raw() -> Option<BackendInfo> {
let url = std::env::var("POSTGRES_BENCH_URL").ok()?;
let creds = switchy_database_connection::Credentials::from_url(&url).ok()?;
#[cfg(feature = "tls")]
{
if let Ok(db) = switchy_database_connection::init_postgres_raw_native_tls(creds).await {
return Some(BackendInfo {
name: "postgres-raw",
db: Arc::new(db),
});
}
}
#[cfg(not(feature = "tls"))]
{
if let Ok(db) = switchy_database_connection::init_postgres_raw_no_tls(creds).await {
return Some(BackendInfo {
name: "postgres-raw",
db: Arc::new(db),
});
}
}
None
}
#[cfg(feature = "postgres-sqlx")]
async fn init_postgres_sqlx() -> Option<BackendInfo> {
let url = std::env::var("POSTGRES_BENCH_URL").ok()?;
let creds = switchy_database_connection::Credentials::from_url(&url).ok()?;
let db = switchy_database_connection::init_postgres_sqlx(creds)
.await
.ok()?;
Some(BackendInfo {
name: "postgres-sqlx",
db: Arc::new(db),
})
}
#[cfg(feature = "mysql-sqlx")]
async fn init_mysql_sqlx() -> Option<BackendInfo> {
let url = std::env::var("MYSQL_BENCH_URL").ok()?;
let creds = switchy_database_connection::Credentials::from_url(&url).ok()?;
let db = switchy_database_connection::init_mysql_sqlx(creds)
.await
.ok()?;
Some(BackendInfo {
name: "mysql-sqlx",
db: Arc::new(db),
})
}