From 54fc4b59cea6eecf611e91a8693f4a2063ece905 Mon Sep 17 00:00:00 2001 From: Joscha Date: Fri, 17 Jun 2022 18:22:22 +0200 Subject: [PATCH] Set pragmas and migrate db --- cove-tui/src/main.rs | 6 +++++- cove-tui/src/vault.rs | 19 ++++++++++++++++++- cove-tui/src/vault/migrate.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 cove-tui/src/vault/migrate.rs diff --git a/cove-tui/src/main.rs b/cove-tui/src/main.rs index 8452781..b1b7d93 100644 --- a/cove-tui/src/main.rs +++ b/cove-tui/src/main.rs @@ -15,10 +15,14 @@ async fn main() -> anyhow::Result<()> { println!("Data dir: {}", dirs.data_dir().to_string_lossy()); let vault = vault::launch(&dirs.data_dir().join("vault.db"))?; + let mut terminal = Terminal::new()?; // terminal.set_measuring(true); - Ui::run(&mut terminal).await?; + drop(terminal); // So the vault can print again + vault.close().await; + + println!("Goodbye!"); Ok(()) } diff --git a/cove-tui/src/vault.rs b/cove-tui/src/vault.rs index f31b9e0..2fea77e 100644 --- a/cove-tui/src/vault.rs +++ b/cove-tui/src/vault.rs @@ -1,3 +1,5 @@ +mod migrate; + use std::path::Path; use std::{fs, thread}; @@ -25,6 +27,8 @@ fn run(conn: Connection, mut rx: mpsc::Receiver) -> anyhow::Result<()> while let Some(request) = rx.blocking_recv() { match request { Request::Close(tx) => { + println!("Optimizing vault"); + conn.execute_batch("PRAGMA optimize")?; // Ensure `Vault::close` exits only after the sqlite connection // has been closed properly. drop(conn); @@ -42,7 +46,20 @@ pub fn launch(path: &Path) -> rusqlite::Result { // file, which saves me from adding a separate vault error type. let _ = fs::create_dir_all(path.parent().expect("path to file")); - let conn = Connection::open(path)?; + let mut conn = Connection::open(path)?; + + // Setting locking mode before journal mode so no shared memory files + // (*-shm) need to be created by sqlite. Apparently, setting the journal + // mode is also enough to immediately acquire the exclusive lock even if the + // database was already using WAL. + // https://sqlite.org/pragma.html#pragma_locking_mode + conn.pragma_update(None, "locking_mode", "exclusive")?; + conn.pragma_update(None, "journal_mode", "wal")?; + conn.pragma_update(None, "foreign_keys", true)?; + conn.pragma_update(None, "trusted_schema", false)?; + + migrate::migrate(&mut conn)?; + let (tx, rx) = mpsc::channel(8); thread::spawn(move || run(conn, rx)); Ok(Vault { tx }) diff --git a/cove-tui/src/vault/migrate.rs b/cove-tui/src/vault/migrate.rs new file mode 100644 index 0000000..33635c4 --- /dev/null +++ b/cove-tui/src/vault/migrate.rs @@ -0,0 +1,29 @@ +use rusqlite::{Connection, Transaction}; + +pub fn migrate(conn: &mut Connection) -> rusqlite::Result<()> { + let mut tx = conn.transaction()?; + + let user_version: usize = + tx.query_row("SELECT * FROM pragma_user_version", [], |r| r.get(0))?; + + let total = MIGRATIONS.len(); + for (i, migration) in MIGRATIONS.iter().enumerate().skip(user_version) { + println!("Migrating vault from {} to {} (out of {})", i, i + 1, total); + migration(&mut tx)?; + } + + tx.pragma_update(None, "user_version", total)?; + tx.commit() +} + +const MIGRATIONS: [fn(&mut Transaction) -> rusqlite::Result<()>; 1] = [m1]; + +fn m1(tx: &mut Transaction) -> rusqlite::Result<()> { + tx.execute_batch( + " + CREATE TABLE test ( + foo TEXT + ); + ", + ) +}