From af35c90c5089b5529d65c66b33b44f7b5d64ac0b Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Thu, 22 May 2025 08:17:51 -0400 Subject: [PATCH] Add schema version constant and checks --- docs/adr/DP-001_schema_v1.1.md | 1 + libmarlin/src/db/mod.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/docs/adr/DP-001_schema_v1.1.md b/docs/adr/DP-001_schema_v1.1.md index d5480b1..e8bf484 100644 --- a/docs/adr/DP-001_schema_v1.1.md +++ b/docs/adr/DP-001_schema_v1.1.md @@ -36,6 +36,7 @@ All foreign keys use `ON DELETE CASCADE` so deleting a file, tag, etc. automatic 3. **0003\_create\_links\_collections\_views.sql** – introduce `links`, `collections`, `collection_files`, and `views` tables. 4. **0004\_fix\_hierarchical\_tags\_fts.sql** – refine FTS triggers to index full hierarchical tag-paths via a recursive CTE. 3. Expose this schema through our library (`libmarlin::db::open`) so any client sees a v1.1 store. +4. Track the version in code via `SCHEMA_VERSION` and provide `current_schema_version()` to query the DB. ## 3. ER Diagram diff --git a/libmarlin/src/db/mod.rs b/libmarlin/src/db/mod.rs index f173d56..01adca0 100644 --- a/libmarlin/src/db/mod.rs +++ b/libmarlin/src/db/mod.rs @@ -18,6 +18,11 @@ use rusqlite::{ use std::result::Result as StdResult; use tracing::{debug, info, warn}; +/* ─── schema version ───────────────────────────────────────────────── */ + +/// Current library schema version. +pub const SCHEMA_VERSION: i32 = 1_1; + /* ─── embedded migrations ─────────────────────────────────────────── */ const MIGRATIONS: &[(&str, &str)] = &[ @@ -47,6 +52,18 @@ const MIGRATIONS: &[(&str, &str)] = &[ ), ]; +/* ─── schema helpers ─────────────────────────────────────────────── */ + +/// Fetch the highest version recorded in the `schema_version` table. +pub fn current_schema_version(conn: &Connection) -> Result { + let version: i32 = conn.query_row( + "SELECT IFNULL(MAX(version), 0) FROM schema_version", + [], + |r| r.get(0), + )?; + Ok(version) +} + /* ─── connection bootstrap ────────────────────────────────────────── */ pub fn open>(db_path: P) -> Result { @@ -133,6 +150,15 @@ pub(crate) fn apply_migrations(conn: &mut Connection) -> Result<()> { warn!("migrations not applied: {:?}", missing); } + let current = current_schema_version(conn)?; + if current != SCHEMA_VERSION { + anyhow::bail!( + "database schema version {} does not match library version {}", + current, + SCHEMA_VERSION + ); + } + Ok(()) }