Set pragmas and migrate db

This commit is contained in:
Joscha 2022-06-17 18:22:22 +02:00
parent 74a80f6ec4
commit 54fc4b59ce
3 changed files with 52 additions and 2 deletions

View file

@ -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(())
}

View file

@ -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<Request>) -> 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<Vault> {
// 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 })

View file

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