1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Tabs is a bit special - it's a trivial SQL schema and is only used as a persistent
// cache, and the semantics of the "tabs" collection means there's no need for
// syncChangeCounter/syncStatus nor a mirror etc.
use rusqlite::{Connection, Transaction};
use sql_support::open_database::{
ConnectionInitializer as MigrationLogic, Error as MigrationError, Result as MigrationResult,
};
// The payload is json and this module doesn't need to deserialize, so we just
// store each "payload" as a row.
// On each Sync we delete all local rows re-populate them with every record on
// the server. When we read the DB, we also read every single record.
// So we have no primary keys, no foreign keys, and really completely waste the
// fact we are using sql.
const CREATE_SCHEMA_SQL: &str = "
CREATE TABLE IF NOT EXISTS tabs (
payload TEXT NOT NULL
);
";
pub struct TabsMigrationLogin;
impl MigrationLogic for TabsMigrationLogin {
const NAME: &'static str = "tabs storage db";
const END_VERSION: u32 = 1;
fn prepare(&self, conn: &Connection, _db_empty: bool) -> MigrationResult<()> {
let initial_pragmas = "
-- We don't care about temp tables being persisted to disk.
PRAGMA temp_store = 2;
-- we unconditionally want write-ahead-logging mode.
PRAGMA journal_mode=WAL;
-- foreign keys seem worth enforcing (and again, we don't care in practice)
PRAGMA foreign_keys = ON;
";
conn.execute_batch(initial_pragmas)?;
// This is where we'd define our sql functions if we had any!
conn.set_prepared_statement_cache_capacity(128);
Ok(())
}
fn init(&self, db: &Transaction<'_>) -> MigrationResult<()> {
log::debug!("Creating schema");
db.execute_batch(CREATE_SCHEMA_SQL)?;
Ok(())
}
fn upgrade_from(&self, _db: &Transaction<'_>, version: u32) -> MigrationResult<()> {
Err(MigrationError::IncompatibleVersion(version))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::storage::TabsStorage;
#[test]
fn test_create_schema_twice() {
let mut db = TabsStorage::new_with_mem_path("test");
let conn = db.open_or_create().unwrap();
conn.execute_batch(CREATE_SCHEMA_SQL)
.expect("should allow running twice");
}
}
|