use sqlx::{sqlite::SqlitePoolOptions, SqlitePool}; pub async fn init() -> Result { let url = std::env::var("DATABASE_URL") .unwrap_or_else(|_| "sqlite:/data/attendance.db".into()); let pool = SqlitePoolOptions::new() .after_connect(|conn, _| Box::pin(async move { sqlx::query("PRAGMA foreign_keys = ON") .execute(conn).await?; Ok(()) })) .connect(&url).await?; sqlx::migrate!("./migrations").run(&pool).await?; Ok(pool) } #[cfg(test)] mod tests { use super::*; // NOTE: #[sqlx::test] injects its own pool, bypassing after_connect. // We test FK enforcement behaviorally: insert a row with a bad FK and assert it fails. // The PRAGMA is manually issued at the top of this test body. #[sqlx::test(migrations = "./migrations")] async fn foreign_keys_enforced(pool: SqlitePool) { // Enable FK for this test connection (mirrors what after_connect does in production) sqlx::query("PRAGMA foreign_keys = ON").execute(&pool).await.unwrap(); let err = sqlx::query( "INSERT INTO students (course_id, name) VALUES (999, 'Ghost')" ).execute(&pool).await; assert!(err.is_err(), "FK violation should be rejected when foreign_keys = ON"); } #[sqlx::test(migrations = "./migrations")] async fn all_tables_exist(pool: SqlitePool) { for table in &["courses","tutors","tutor_courses","students","rooms", "sessions","slots","attendances","notes"] { let count: (i64,) = sqlx::query_as( "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?" ).bind(table).fetch_one(&pool).await.unwrap(); assert_eq!(count.0, 1, "table {table} missing"); } } }