Skip to main content

veta_core/
migrations.rs

1//! Embedded database migrations for Veta.
2//!
3//! Migrations are versioned and run automatically on first database access.
4//! The schema version is tracked in the `_veta_meta` table.
5
6/// Current schema version. Increment when adding new migrations.
7pub const SCHEMA_VERSION: i64 = 2;
8
9/// A database migration with version number and SQL statements.
10pub struct Migration {
11    pub version: i64,
12    pub name: &'static str,
13    pub statements: &'static [&'static str],
14}
15
16/// All migrations in order. Each migration should be idempotent where possible.
17pub const MIGRATIONS: &[Migration] = &[
18    Migration {
19        version: 1,
20        name: "initial_schema",
21        statements: &[
22            "CREATE TABLE IF NOT EXISTS _veta_meta (
23                key TEXT PRIMARY KEY,
24                value TEXT NOT NULL
25            )",
26            "CREATE TABLE IF NOT EXISTS notes (
27                id INTEGER PRIMARY KEY AUTOINCREMENT,
28                title TEXT NOT NULL,
29                body TEXT NOT NULL,
30                created_at TEXT NOT NULL DEFAULT (datetime('now')),
31                updated_at TEXT NOT NULL DEFAULT (datetime('now'))
32            )",
33            "CREATE TABLE IF NOT EXISTS tags (
34                id INTEGER PRIMARY KEY AUTOINCREMENT,
35                name TEXT NOT NULL UNIQUE
36            )",
37            "CREATE TABLE IF NOT EXISTS note_tags (
38                note_id INTEGER NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
39                tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
40                PRIMARY KEY (note_id, tag_id)
41            )",
42            "CREATE INDEX IF NOT EXISTS idx_notes_updated_at ON notes(updated_at)",
43            "CREATE INDEX IF NOT EXISTS idx_note_tags_tag_id ON note_tags(tag_id)",
44            "CREATE INDEX IF NOT EXISTS idx_tags_name ON tags(name)",
45        ],
46    },
47    Migration {
48        version: 2,
49        name: "add_references",
50        statements: &[
51            // ALTER TABLE doesn't support IF NOT EXISTS, so we check in code
52            "ALTER TABLE notes ADD COLUMN \"references\" TEXT NOT NULL DEFAULT '[]'",
53        ],
54    },
55];
56
57/// Get migrations that need to be applied given the current version.
58pub fn get_pending_migrations(current_version: i64) -> Vec<&'static Migration> {
59    MIGRATIONS
60        .iter()
61        .filter(|m| m.version > current_version)
62        .collect()
63}