From 8aa854d60bad345a567d7458f53693f3fe653fdd Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Thu, 8 Oct 2026 14:21:47 -0400 Subject: [PATCH] The store's migrations are a table of steps, applied in order schema::migrate was thirteen hand-copied blocks of "if version < N, apply, stamp N". The versions are now a STEPS list (SQL, or code for v8). migrate walks the list, applies each step a store hasn't had and stamps it. A new version is a new entry at the end; there is no block to copy. DRY pass #2, batch 2, F7 (#5372). Co-Authored-By: Claude Opus 5.5 --- core/src/local/schema.rs | 87 ++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/core/src/local/schema.rs b/core/src/local/schema.rs index f0cfe0e..176eacd 100644 --- a/core/src/local/schema.rs +++ b/core/src/local/schema.rs @@ -4,7 +4,8 @@ //! `#tags` are NOT stored as such (derived at query time into labels), matching //! docs/sync.md. //! -//! Migrations are gated on `PRAGMA user_version`; bump it and add a block per change. +//! Migrations are gated on `PRAGMA user_version`; a change is a new entry at the end of +//! [`STEPS`]. use rusqlite::{params, Connection, OptionalExtension}; @@ -331,60 +332,42 @@ const SCHEMA_V13: &str = r#" DROP TABLE saved_filters; "#; +/// One schema version's change: SQL, or code for a change SQL alone can't make. +enum Step { + Sql(&'static str), + Code(fn(&Connection) -> rusqlite::Result<()>), +} + +/// Every version in order: entry N brings a store to version N + 1. A change is a +/// new entry at the end; [`migrate`] applies each one a store hasn't had yet. +const STEPS: &[Step] = &[ + Step::Sql(SCHEMA_V1), + Step::Sql(SCHEMA_V2), + Step::Sql(SCHEMA_V3), + Step::Sql(SCHEMA_V4), + Step::Sql(SCHEMA_V5), + Step::Sql(SCHEMA_V6), + Step::Sql(SCHEMA_V7), + Step::Code(migrate_v8), + Step::Sql(SCHEMA_V9), + Step::Sql(SCHEMA_V10), + Step::Sql(SCHEMA_V11), + Step::Sql(SCHEMA_V12), + Step::Sql(SCHEMA_V13), +]; + pub fn migrate(conn: &Connection) -> rusqlite::Result<()> { conn.execute_batch("PRAGMA foreign_keys = ON;")?; let version: i64 = conn.query_row("PRAGMA user_version", [], |r| r.get(0))?; - if version < 1 { - conn.execute_batch(SCHEMA_V1)?; - conn.execute_batch("PRAGMA user_version = 1;")?; - } - if version < 2 { - conn.execute_batch(SCHEMA_V2)?; - conn.execute_batch("PRAGMA user_version = 2;")?; - } - if version < 3 { - conn.execute_batch(SCHEMA_V3)?; - conn.execute_batch("PRAGMA user_version = 3;")?; - } - if version < 4 { - conn.execute_batch(SCHEMA_V4)?; - conn.execute_batch("PRAGMA user_version = 4;")?; - } - if version < 5 { - conn.execute_batch(SCHEMA_V5)?; - conn.execute_batch("PRAGMA user_version = 5;")?; - } - if version < 6 { - conn.execute_batch(SCHEMA_V6)?; - conn.execute_batch("PRAGMA user_version = 6;")?; - } - if version < 7 { - conn.execute_batch(SCHEMA_V7)?; - conn.execute_batch("PRAGMA user_version = 7;")?; - } - if version < 8 { - migrate_v8(conn)?; - conn.execute_batch("PRAGMA user_version = 8;")?; - } - if version < 9 { - conn.execute_batch(SCHEMA_V9)?; - conn.execute_batch("PRAGMA user_version = 9;")?; - } - if version < 10 { - conn.execute_batch(SCHEMA_V10)?; - conn.execute_batch("PRAGMA user_version = 10;")?; - } - if version < 11 { - conn.execute_batch(SCHEMA_V11)?; - conn.execute_batch("PRAGMA user_version = 11;")?; - } - if version < 12 { - conn.execute_batch(SCHEMA_V12)?; - conn.execute_batch("PRAGMA user_version = 12;")?; - } - if version < 13 { - conn.execute_batch(SCHEMA_V13)?; - conn.execute_batch("PRAGMA user_version = 13;")?; + for (to, step) in (1..).zip(STEPS) { + if version >= to { + continue; + } + match step { + Step::Sql(sql) => conn.execute_batch(sql)?, + Step::Code(apply) => apply(conn)?, + } + conn.execute_batch(&format!("PRAGMA user_version = {to};"))?; } Ok(()) }