//! SQLite connection helper. //! //! Migrations stay per-tool: `sqlx::migrate!` resolves its path at compile //! time relative to the calling crate, so each daemon runs its own //! `sqlx::migrate!("./migrations").run(&pool)`. This module owns only the //! connect-with-sane-defaults step, which is identical everywhere. use anyhow::Result; use sqlx::SqlitePool; use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; use std::path::Path; use std::str::FromStr; /// Open (creating if missing) a pooled SQLite connection with foreign keys on. pub async fn connect(path: &Path) -> Result { let url = format!("sqlite://{}?mode=rwc", path.display()); let opts = SqliteConnectOptions::from_str(&url)? .create_if_missing(true) .foreign_keys(true); let pool = SqlitePoolOptions::new().max_connections(4).connect_with(opts).await?; Ok(pool) } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn connect_creates_and_enables_foreign_keys() { let dir = tempfile::tempdir().unwrap(); let pool = connect(&dir.path().join("t.db")).await.unwrap(); let fk: i64 = sqlx::query_scalar("PRAGMA foreign_keys").fetch_one(&pool).await.unwrap(); assert_eq!(fk, 1); } }