Converted to using rusqlite

This commit is contained in:
Mikayla Maki 2022-10-13 18:24:00 -07:00 committed by K Simmons
parent aa8fa4a6d5
commit dbea3cf20c
8 changed files with 91 additions and 172 deletions

View file

@ -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"] }

View file

@ -1,4 +0,0 @@
CREATE TABLE kv_store(
key TEXT PRIMARY KEY,
value TEXT NOT NULL
) STRICT;

View file

@ -1,3 +0,0 @@
{
"db": "SQLite"
}

View file

@ -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] {

View file

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

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