Converted to using rusqlite
This commit is contained in:
parent
aa8fa4a6d5
commit
dbea3cf20c
8 changed files with 91 additions and 172 deletions
|
@ -15,7 +15,9 @@ collections = { path = "../collections" }
|
|||
anyhow = "1.0.57"
|
||||
async-trait = "0.1"
|
||||
parking_lot = "0.11.1"
|
||||
sqlx = { version = "0.6.2", features = ["sqlite", "macros", "offline", "json", "runtime-async-std-rustls"] }
|
||||
rusqlite = { version = "0.28.0", features = ["bundled", "serde_json"] }
|
||||
rusqlite_migration = "1.0.0"
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
gpui = { path = "../gpui", features = ["test-support"] }
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
CREATE TABLE kv_store(
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
) STRICT;
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"db": "SQLite"
|
||||
}
|
|
@ -1,16 +1,17 @@
|
|||
mod kvp;
|
||||
mod migrations;
|
||||
|
||||
use anyhow::Result;
|
||||
use sqlx::sqlite::SqliteConnectOptions;
|
||||
use sqlx::{Pool, Sqlite};
|
||||
use migrations::MIGRATIONS;
|
||||
use parking_lot::Mutex;
|
||||
use rusqlite::Connection;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use kvp::*;
|
||||
|
||||
pub struct Db {
|
||||
pool: Pool<Sqlite>,
|
||||
connecion: Connection,
|
||||
in_memory: bool,
|
||||
}
|
||||
|
||||
|
@ -21,35 +22,26 @@ pub struct Db {
|
|||
impl Db {
|
||||
/// Open or create a database at the given file path. Falls back to in memory database if the
|
||||
/// database at the given path is corrupted
|
||||
pub async fn open(path: &Path) -> Arc<Self> {
|
||||
let options = SqliteConnectOptions::from_str(&format!(
|
||||
"sqlite://{}",
|
||||
path.to_string_lossy().to_string()
|
||||
))
|
||||
.expect("database path should always be well formed")
|
||||
.create_if_missing(true);
|
||||
pub fn open(path: &Path) -> Result<Arc<Mutex<Self>>> {
|
||||
let conn = Connection::open(path)?;
|
||||
|
||||
Self::initialize(options, false)
|
||||
.await
|
||||
.unwrap_or(Self::open_in_memory().await)
|
||||
Self::initialize(conn, false).or_else(|_| Self::open_in_memory())
|
||||
}
|
||||
|
||||
/// Open a in memory database for testing and as a fallback.
|
||||
pub async fn open_in_memory() -> Arc<Self> {
|
||||
let options = SqliteConnectOptions::from_str(":memory:")
|
||||
.expect("Should always be able to create in memory database options");
|
||||
pub fn open_in_memory() -> Result<Arc<Mutex<Self>>> {
|
||||
let conn = Connection::open_in_memory()?;
|
||||
|
||||
Self::initialize(options, true)
|
||||
.await
|
||||
.expect("Should always be able to create an in memory database")
|
||||
Self::initialize(conn, true)
|
||||
}
|
||||
|
||||
async fn initialize(options: SqliteConnectOptions, in_memory: bool) -> Result<Arc<Self>> {
|
||||
let pool = Pool::<Sqlite>::connect_with(options).await?;
|
||||
fn initialize(mut conn: Connection, in_memory: bool) -> Result<Arc<Mutex<Self>>> {
|
||||
MIGRATIONS.to_latest(&mut conn)?;
|
||||
|
||||
sqlx::migrate!().run(&pool).await?;
|
||||
|
||||
Ok(Arc::new(Self { pool, in_memory }))
|
||||
Ok(Arc::new(Mutex::new(Self {
|
||||
connecion: conn,
|
||||
in_memory,
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +53,7 @@ mod tests {
|
|||
#[gpui::test]
|
||||
fn test_db() {
|
||||
let dir = TempDir::new("db-test").unwrap();
|
||||
let fake_db = Db::open_fake();
|
||||
let fake_db = Db::open_in_memory().unwrap();
|
||||
let real_db = Db::open(&dir.path().join("test.db")).unwrap();
|
||||
|
||||
for db in [&real_db, &fake_db] {
|
||||
|
|
|
@ -3,31 +3,30 @@ use anyhow::Result;
|
|||
use super::Db;
|
||||
|
||||
impl Db {
|
||||
pub async fn read_kvp(&self, key: &str) -> Result<String> {
|
||||
let value = sqlx::query!("SELECT value FROM kv_store WHERE key = ?", key)
|
||||
.fetch_one(&self.pool)
|
||||
.await
|
||||
.map(|res| res.value)?;
|
||||
pub fn read_kvp(&self, key: &str) -> Result<String> {
|
||||
let mut stmt = self
|
||||
.connecion
|
||||
.prepare_cached("SELECT value FROM kv_store WHERE key = (?)")?;
|
||||
|
||||
Ok(value)
|
||||
Ok(stmt.query_row([key], |row| row.get(0))?)
|
||||
}
|
||||
|
||||
pub async fn delete_kvp(&self, key: &str) -> Result<()> {
|
||||
sqlx::query!("DELETE FROM kv_store WHERE key = ?", key)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
pub fn delete_kvp(&self, key: &str) -> Result<()> {
|
||||
let mut stmt = self
|
||||
.connecion
|
||||
.prepare_cached("SELECT value FROM kv_store WHERE key = (?)")?;
|
||||
|
||||
stmt.execute([key])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn write_kvp(&self, key: &str, value: &str) -> Result<()> {
|
||||
sqlx::query!(
|
||||
"INSERT OR REPLACE INTO kv_store(key, value) VALUES (?, ?)",
|
||||
key,
|
||||
value
|
||||
)
|
||||
.execute(&self.pool)
|
||||
.await?;
|
||||
pub fn write_kvp(&self, key: &str, value: &str) -> Result<()> {
|
||||
let mut stmt = self
|
||||
.connecion
|
||||
.prepare_cached("INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))")?;
|
||||
|
||||
stmt.execute([key, value])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
10
crates/db/src/migrations.rs
Normal file
10
crates/db/src/migrations.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use rusqlite_migration::{Migrations, M};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref MIGRATIONS: Migrations<'static> = Migrations::new(vec![M::up(
|
||||
"CREATE TABLE kv_store(
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
) STRICT;",
|
||||
)]);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue