Add local KV store commands
This commit is contained in:
parent
4ec50d7473
commit
1a0f1e7671
14 changed files with 395 additions and 13 deletions
|
|
@ -105,6 +105,13 @@ impl Store {
|
|||
resource_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS kv_entries (
|
||||
kv_id TEXT NOT NULL,
|
||||
key TEXT NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
updated_at_ms INTEGER NOT NULL,
|
||||
PRIMARY KEY(kv_id, key)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS db_resources (
|
||||
db_id TEXT PRIMARY KEY,
|
||||
resource_id TEXT NOT NULL,
|
||||
|
|
@ -275,6 +282,63 @@ impl Store {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn insert_kv_store(&self, kv: &StoredKvStore) -> Result<(), StoreError> {
|
||||
self.conn.execute(
|
||||
r#"INSERT OR REPLACE INTO kv_stores(kv_id, resource_id, name)
|
||||
VALUES (?1, ?2, ?3)"#,
|
||||
params![kv.kv_id, kv.resource_id, kv.name],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_kv_store_by_name(&self, name: &str) -> Result<Option<StoredKvStore>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT kv_id, resource_id, name
|
||||
FROM kv_stores WHERE name = ?1"#,
|
||||
)?;
|
||||
let mut rows = stmt.query(params![name])?;
|
||||
if let Some(row) = rows.next()? {
|
||||
Ok(Some(StoredKvStore {
|
||||
kv_id: row.get(0)?,
|
||||
resource_id: row.get(1)?,
|
||||
name: row.get(2)?,
|
||||
}))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_kv_entry(&self, entry: &StoredKvEntry) -> Result<(), StoreError> {
|
||||
self.conn.execute(
|
||||
r#"INSERT OR REPLACE INTO kv_entries(kv_id, key, value, updated_at_ms)
|
||||
VALUES (?1, ?2, ?3, ?4)"#,
|
||||
params![entry.kv_id, entry.key, entry.value, entry.updated_at_ms],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_kv_entry(
|
||||
&self,
|
||||
kv_id: &str,
|
||||
key: &str,
|
||||
) -> Result<Option<StoredKvEntry>, StoreError> {
|
||||
let mut stmt = self.conn.prepare(
|
||||
r#"SELECT kv_id, key, value, updated_at_ms
|
||||
FROM kv_entries WHERE kv_id = ?1 AND key = ?2"#,
|
||||
)?;
|
||||
let mut rows = stmt.query(params![kv_id, key])?;
|
||||
if let Some(row) = rows.next()? {
|
||||
Ok(Some(StoredKvEntry {
|
||||
kv_id: row.get(0)?,
|
||||
key: row.get(1)?,
|
||||
value: row.get(2)?,
|
||||
updated_at_ms: row.get(3)?,
|
||||
}))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_cas_object(
|
||||
&self,
|
||||
hash: &str,
|
||||
|
|
@ -622,6 +686,21 @@ pub struct StoredDbResource {
|
|||
pub path: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct StoredKvStore {
|
||||
pub kv_id: String,
|
||||
pub resource_id: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct StoredKvEntry {
|
||||
pub kv_id: String,
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
pub updated_at_ms: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CasObject {
|
||||
pub hash: String,
|
||||
|
|
@ -883,4 +962,33 @@ mod tests {
|
|||
Some("/tmp/notes.sqlite".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kv_store_and_entries_roundtrip() {
|
||||
let store = Store::open_memory().expect("open");
|
||||
let kv = StoredKvStore {
|
||||
kv_id: "kv:prefs".to_owned(),
|
||||
resource_id: "resource:kv:prefs".to_owned(),
|
||||
name: "prefs".to_owned(),
|
||||
};
|
||||
store.insert_kv_store(&kv).expect("insert kv");
|
||||
assert_eq!(
|
||||
store.get_kv_store_by_name("prefs").expect("get kv"),
|
||||
Some(kv.clone())
|
||||
);
|
||||
|
||||
let entry = StoredKvEntry {
|
||||
kv_id: kv.kv_id.clone(),
|
||||
key: "apps/foo/theme".to_owned(),
|
||||
value: "dark".to_owned(),
|
||||
updated_at_ms: 1,
|
||||
};
|
||||
store.set_kv_entry(&entry).expect("set entry");
|
||||
assert_eq!(
|
||||
store
|
||||
.get_kv_entry("kv:prefs", "apps/foo/theme")
|
||||
.expect("get entry"),
|
||||
Some(entry)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue