46 lines
1.8 KiB
Rust
46 lines
1.8 KiB
Rust
use sqlx::{sqlite::SqlitePoolOptions, SqlitePool};
|
|
|
|
pub async fn init() -> Result<SqlitePool, sqlx::Error> {
|
|
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");
|
|
}
|
|
}
|
|
}
|