#![forbid(unsafe_code)]
#[cfg(feature = "mysql")]
mod mysql;
#[cfg(feature = "postgres")]
mod postgres;
mod rows;
#[cfg(feature = "sqlite")]
mod sqlite;
#[cfg(feature = "mysql")]
pub use mysql::MysqlDb;
#[cfg(feature = "postgres")]
pub use postgres::PostgresDb;
#[cfg(feature = "sqlite")]
pub use sqlite::SqliteDb;
use runlight::store::{DbError, PREFIX, SqlStore, check_prefix};
#[cfg(any(feature = "sqlite", feature = "postgres", feature = "mysql"))]
use std::sync::Arc;
#[cfg(feature = "sqlite")]
pub fn sqlite(pool: sqlx::SqlitePool) -> SqlStore {
SqlStore::new(Arc::new(SqliteDb::new(pool)))
}
#[cfg(feature = "sqlite")]
pub fn sqlite_with_prefix(pool: sqlx::SqlitePool, prefix: &str) -> Result<SqlStore, DbError> {
SqlStore::with_prefix(Arc::new(SqliteDb::new(pool)), prefix)
}
#[cfg(feature = "postgres")]
pub fn postgres(pool: sqlx::PgPool) -> SqlStore {
SqlStore::new(Arc::new(PostgresDb::new(pool)))
}
#[cfg(feature = "postgres")]
pub fn postgres_with_prefix(pool: sqlx::PgPool, prefix: &str) -> Result<SqlStore, DbError> {
SqlStore::with_prefix(Arc::new(PostgresDb::new(pool)), prefix)
}
#[cfg(feature = "mysql")]
pub fn mysql(pool: sqlx::MySqlPool) -> SqlStore {
SqlStore::new(Arc::new(MysqlDb::new(pool)))
}
#[cfg(feature = "mysql")]
pub fn mysql_with_prefix(pool: sqlx::MySqlPool, prefix: &str) -> Result<SqlStore, DbError> {
SqlStore::with_prefix(Arc::new(MysqlDb::new(pool)), prefix)
}
pub async fn connect(url: &str) -> Result<SqlStore, DbError> {
connect_with_prefix(url, PREFIX).await
}
pub async fn connect_with_prefix(url: &str, prefix: &str) -> Result<SqlStore, DbError> {
check_prefix(prefix)?;
let fail = |e: &dyn std::fmt::Display| DbError(e.to_string());
let lower = url.to_ascii_lowercase();
if lower.starts_with("postgres://") || lower.starts_with("postgresql://") {
#[cfg(feature = "postgres")]
{
let pool = sqlx::postgres::PgPoolOptions::new()
.max_connections(10)
.acquire_timeout(std::time::Duration::from_secs(10))
.connect(url)
.await
.map_err(|e| fail(&e))?;
return postgres_with_prefix(pool, prefix);
}
#[cfg(not(feature = "postgres"))]
return Err(fail(&"Runlight: built without the postgres feature"));
}
if lower.starts_with("mysql://") || lower.starts_with("mariadb://") {
#[cfg(feature = "mysql")]
{
let url = format!("mysql://{}", &url[url.find("://").map_or(0, |i| i + 3)..]);
let pool = sqlx::mysql::MySqlPoolOptions::new()
.max_connections(10)
.acquire_timeout(std::time::Duration::from_secs(10))
.connect(&url)
.await
.map_err(|e| fail(&e))?;
return mysql_with_prefix(pool, prefix);
}
#[cfg(not(feature = "mysql"))]
return Err(fail(&"Runlight: built without the mysql feature"));
}
#[cfg(feature = "sqlite")]
{
use std::str::FromStr;
let path = url.strip_prefix("sqlite://").or_else(|| url.strip_prefix("sqlite:")).unwrap_or(url);
let options = if path == ":memory:" {
sqlx::sqlite::SqliteConnectOptions::from_str("sqlite::memory:").map_err(|e| fail(&e))?
} else {
if !path.starts_with("file:") {
sqlite::own_file(std::path::Path::new(path));
}
sqlx::sqlite::SqliteConnectOptions::new().filename(path).create_if_missing(true)
};
let pool = sqlx::sqlite::SqlitePoolOptions::new()
.max_connections(1)
.connect_with(options)
.await
.map_err(|e| fail(&e))?;
sqlite_with_prefix(pool, prefix)
}
#[cfg(not(feature = "sqlite"))]
Err(fail(&"Runlight: built without the sqlite feature"))
}