Files
tutortool/backend/src/db.rs
T

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");
}
}
}