use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions};
use std::str::FromStr;
const DEFAULT_MAX_CONNECTIONS: u32 = 8;
pub async fn sqlite_pool(url: &str) -> Result<SqlitePool, sqlx::Error> {
sqlite_pool_with_size(url, DEFAULT_MAX_CONNECTIONS).await
}
async fn sqlite_pool_with_size(url: &str, max_connections: u32) -> Result<SqlitePool, sqlx::Error> {
let opts = SqliteConnectOptions::from_str(url)?
.pragma("journal_mode", "WAL")
.pragma("busy_timeout", "5000")
.pragma("synchronous", "NORMAL")
.pragma("foreign_keys", "ON")
.create_if_missing(true);
SqlitePoolOptions::new()
.max_connections(max_connections)
.connect_with(opts)
.await
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn every_pragma_is_in_force_on_a_pooled_connection() {
let path = std::env::temp_dir().join(format!("a2a-pragmas-{}.db", std::process::id()));
let cleanup = |p: &std::path::Path| {
for suffix in ["", "-wal", "-shm"] {
let _ = std::fs::remove_file(format!("{}{suffix}", p.display()));
}
};
cleanup(&path);
let pool = sqlite_pool(&format!("sqlite://{}", path.display()))
.await
.expect("pool");
let journal: String = sqlx::query_scalar("PRAGMA journal_mode")
.fetch_one(&pool)
.await
.expect("journal_mode");
assert_eq!(
journal.to_lowercase(),
"wal",
"WAL is what makes a pool worth having"
);
let busy: i64 = sqlx::query_scalar("PRAGMA busy_timeout")
.fetch_one(&pool)
.await
.expect("busy_timeout");
assert_eq!(
busy, 5000,
"without this a contended write is a spurious internal error"
);
let sync: i64 = sqlx::query_scalar("PRAGMA synchronous")
.fetch_one(&pool)
.await
.expect("synchronous");
assert_eq!(sync, 1);
let fk: i64 = sqlx::query_scalar("PRAGMA foreign_keys")
.fetch_one(&pool)
.await
.expect("foreign_keys");
assert_eq!(fk, 1);
pool.close().await;
cleanup(&path);
}
}