mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-26 03:11:12 +01:00
150 lines
4.9 KiB
Rust
150 lines
4.9 KiB
Rust
use crate::db_context::DbContext;
|
|
use crate::error::Result;
|
|
use crate::models::{KeyValue, KeyValueIden, UpsertModelInfo};
|
|
use crate::util::UpdateSource;
|
|
use log::error;
|
|
use sea_query::{Asterisk, Cond, Expr, Query, SqliteQueryBuilder};
|
|
use sea_query_rusqlite::RusqliteBinder;
|
|
|
|
impl<'a> DbContext<'a> {
|
|
pub fn list_key_values(&self) -> Result<Vec<KeyValue>> {
|
|
let (sql, params) = Query::select()
|
|
.from(KeyValueIden::Table)
|
|
.column(Asterisk)
|
|
// Temporary clause to prevent bug when reverting to the previous version, before the
|
|
// ID column was added. A previous version will not know about ID and will create
|
|
// key/value entries that don't have one. This clause ensures they are not queried
|
|
// TODO: Add migration to delete key/values with NULL IDs later on, then remove this
|
|
.cond_where(Expr::col(KeyValueIden::Id).is_not_null())
|
|
.build_rusqlite(SqliteQueryBuilder);
|
|
let mut stmt = self.conn.prepare(sql.as_str())?;
|
|
let items = stmt.query_map(&*params.as_params(), KeyValue::from_row)?;
|
|
Ok(items.map(|v| v.unwrap()).collect())
|
|
}
|
|
|
|
pub fn get_key_value_string(&self, namespace: &str, key: &str, default: &str) -> String {
|
|
match self.get_key_value_raw(namespace, key) {
|
|
None => default.to_string(),
|
|
Some(v) => {
|
|
let result = serde_json::from_str(&v.value);
|
|
match result {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
error!("Failed to parse string key value: {}", e);
|
|
default.to_string()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn get_key_value_int(&self, namespace: &str, key: &str, default: i32) -> i32 {
|
|
match self.get_key_value_raw(namespace, key) {
|
|
None => default.clone(),
|
|
Some(v) => {
|
|
let result = serde_json::from_str(&v.value);
|
|
match result {
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
error!("Failed to parse int key value: {}", e);
|
|
default.clone()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn get_key_value_raw(&self, namespace: &str, key: &str) -> Option<KeyValue> {
|
|
let (sql, params) = Query::select()
|
|
.from(KeyValueIden::Table)
|
|
.column(Asterisk)
|
|
.cond_where(
|
|
Cond::all()
|
|
.add(Expr::col(KeyValueIden::Namespace).eq(namespace))
|
|
.add(Expr::col(KeyValueIden::Key).eq(key)),
|
|
)
|
|
.build_rusqlite(SqliteQueryBuilder);
|
|
self.conn.resolve().query_row(sql.as_str(), &*params.as_params(), KeyValue::from_row).ok()
|
|
}
|
|
|
|
pub fn set_key_value_string(
|
|
&self,
|
|
namespace: &str,
|
|
key: &str,
|
|
value: &str,
|
|
source: &UpdateSource,
|
|
) -> (KeyValue, bool) {
|
|
let encoded = serde_json::to_string(&value).unwrap();
|
|
self.set_key_value_raw(namespace, key, &encoded, source)
|
|
}
|
|
|
|
pub fn set_key_value_int(
|
|
&self,
|
|
namespace: &str,
|
|
key: &str,
|
|
value: i32,
|
|
source: &UpdateSource,
|
|
) -> (KeyValue, bool) {
|
|
let encoded = serde_json::to_string(&value).unwrap();
|
|
self.set_key_value_raw(namespace, key, &encoded, source)
|
|
}
|
|
|
|
pub fn set_key_value_raw(
|
|
&self,
|
|
namespace: &str,
|
|
key: &str,
|
|
value: &str,
|
|
source: &UpdateSource,
|
|
) -> (KeyValue, bool) {
|
|
match self.get_key_value_raw(namespace, key) {
|
|
None => (
|
|
self.upsert_key_value(
|
|
&KeyValue {
|
|
namespace: namespace.to_string(),
|
|
key: key.to_string(),
|
|
value: value.to_string(),
|
|
..Default::default()
|
|
},
|
|
source,
|
|
)
|
|
.expect("Failed to create key value"),
|
|
true,
|
|
),
|
|
Some(kv) => (
|
|
self.upsert_key_value(
|
|
&KeyValue {
|
|
value: value.to_string(),
|
|
..kv
|
|
},
|
|
source,
|
|
)
|
|
.expect("Failed to update key value"),
|
|
false,
|
|
),
|
|
}
|
|
}
|
|
|
|
pub fn upsert_key_value(
|
|
&self,
|
|
key_value: &KeyValue,
|
|
source: &UpdateSource,
|
|
) -> Result<KeyValue> {
|
|
self.upsert(key_value, source)
|
|
}
|
|
|
|
pub fn delete_key_value(
|
|
&self,
|
|
namespace: &str,
|
|
key: &str,
|
|
source: &UpdateSource,
|
|
) -> Result<()> {
|
|
let kv = match self.get_key_value_raw(namespace, key) {
|
|
None => return Ok(()),
|
|
Some(m) => m,
|
|
};
|
|
|
|
self.delete(&kv, source)?;
|
|
Ok(())
|
|
}
|
|
}
|