From b8c2ab53163e184bd8e730c445b0930cb2a006c6 Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Sat, 8 Oct 2022 12:13:59 +0200 Subject: [PATCH] Switch to a lighter sqlite dependency Signed-off-by: Alexis Sellier --- Cargo.lock | 100 +++++++++------------------- radicle-node/Cargo.toml | 2 +- radicle-node/src/service/routing.rs | 67 +++++++++++-------- radicle/Cargo.toml | 4 +- radicle/src/sql.rs | 43 +++++------- 5 files changed, 90 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3d2b3cf..d965ff49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -306,18 +295,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" - [[package]] name = "fastrand" version = "1.8.0" @@ -419,18 +396,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashlink" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69fe1fcf8b4278d860ad0548329f892a3631fb63f82574df68275f34cdbe0ffa" -dependencies = [ - "hashbrown", -] [[package]] name = "hermit-abi" @@ -555,17 +520,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "libsqlite3-sys" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f0455f2c1bc9a7caa792907026e469c1d91761fb0ea37cbb16427c77280cf35" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - [[package]] name = "libssh2-sys" version = "0.2.23" @@ -837,11 +791,11 @@ dependencies = [ "quickcheck_macros", "radicle-git-ext", "radicle-ssh", - "rusqlite", "serde", "serde_json", "sha2 0.10.6", "siphasher", + "sqlite", "tempfile", "thiserror", "zeroize", @@ -881,9 +835,9 @@ dependencies = [ "quickcheck", "quickcheck_macros", "radicle", - "rusqlite", "serde", "serde_json", + "sqlite", "tempfile", "thiserror", ] @@ -948,20 +902,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rusqlite" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" -dependencies = [ - "bitflags", - "fallible-iterator", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec", -] - [[package]] name = "ryu" version = "1.0.11" @@ -1055,12 +995,6 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - [[package]] name = "socket2" version = "0.4.7" @@ -1071,6 +1005,36 @@ dependencies = [ "winapi", ] +[[package]] +name = "sqlite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2df8edd55685048550daaaf2be9024182f3523086cc86f7d50c136e55173e8c" +dependencies = [ + "libc", + "sqlite3-sys", +] + +[[package]] +name = "sqlite3-src" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1815a7a02c996eb8e5c64f61fcb6fd9b12e593ce265c512c5853b2513635691" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "sqlite3-sys" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d47c99824fc55360ba00caf28de0b8a0458369b832e016a64c13af0ad9fbb9ee" +dependencies = [ + "libc", + "sqlite3-src", +] + [[package]] name = "syn" version = "1.0.100" diff --git a/radicle-node/Cargo.toml b/radicle-node/Cargo.toml index 1b2735a1..cb85c2a3 100644 --- a/radicle-node/Cargo.toml +++ b/radicle-node/Cargo.toml @@ -19,7 +19,7 @@ log = { version = "0.4.17", features = ["std"] } nakamoto-net = { version = "0.3.0" } nakamoto-net-poll = { version = "0.3.0" } nonempty = { version = "0.8.0", features = ["serialize"] } -rusqlite = { version = "0.28.0", features = ["bundled"] } +sqlite = { version = "0.27.0" } serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } tempfile = { version = "3.3.0" } diff --git a/radicle-node/src/service/routing.rs b/radicle-node/src/service/routing.rs index 7a51fbcc..81156965 100644 --- a/radicle-node/src/service/routing.rs +++ b/radicle-node/src/service/routing.rs @@ -1,7 +1,8 @@ use std::collections::HashSet; +use std::fmt; use std::path::Path; -use rusqlite as sql; +use sqlite as sql; use thiserror::Error; use crate::prelude::{Id, NodeId}; @@ -15,11 +16,16 @@ pub enum Error { } /// Persistent file storage for a routing table. -#[derive(Debug)] pub struct Table { db: sql::Connection, } +impl fmt::Debug for Table { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Table(..)") + } +} + impl Table { const SCHEMA: &str = include_str!("routing/schema.sql"); @@ -27,15 +33,15 @@ impl Table { /// if an existing store isn't found. pub fn open>(path: P) -> Result { let db = sql::Connection::open(path)?; - db.execute(Self::SCHEMA, [])?; + db.execute(Self::SCHEMA)?; Ok(Self { db }) } /// Create a new in-memory routing table. pub fn memory() -> Result { - let db = sql::Connection::open_in_memory()?; - db.execute(Self::SCHEMA, [])?; + let db = sql::Connection::open(":memory:")?; + db.execute(Self::SCHEMA)?; Ok(Self { db }) } @@ -57,36 +63,42 @@ impl Store for Table { fn get(&self, id: &Id) -> Result, Error> { let mut stmt = self .db - .prepare("SELECT (node) FROM routing WHERE resource = ?")?; - let mut rows = stmt.query([id])?; + .prepare("SELECT (node) FROM routing WHERE resource = ?")? + .bind(1, id)? + .into_cursor(); let mut nodes = HashSet::new(); - while let Ok(Some(row)) = rows.next() { - let field = row.get(0)?; - nodes.insert(field); + while let Some(Ok(row)) = stmt.next() { + nodes.insert(row.get::(0)); } Ok(nodes) } fn insert(&mut self, id: Id, node: NodeId) -> Result { - let updated = self.db.execute( - "INSERT INTO routing (resource, node, time) VALUES (?, ?, ?) ON CONFLICT DO NOTHING", - (id, node, 0), - )?; + self.db + .prepare( + "INSERT INTO routing (resource, node, time) + VALUES (?, ?, ?) + ON CONFLICT DO NOTHING", + )? + .bind(1, &id)? + .bind(2, &node)? + .bind(3, 0)? + .next()?; - Ok(updated > 0) + Ok(self.db.change_count() > 0) } fn entries(&self) -> Result>, Error> { let mut stmt = self .db - .prepare("SELECT resource, node FROM routing ORDER BY resource")?; - let mut rows = stmt.query([])?; + .prepare("SELECT resource, node FROM routing ORDER BY resource")? + .into_cursor(); let mut entries = Vec::new(); - while let Ok(Some(row)) = rows.next() { - let id = row.get(0)?; - let node = row.get(1)?; + while let Some(Ok(row)) = stmt.next() { + let id = row.get(0); + let node = row.get(1); entries.push((id, node)); } @@ -94,12 +106,13 @@ impl Store for Table { } fn remove(&mut self, id: &Id, node: &NodeId) -> Result { - let deleted = self.db.execute( - "DELETE FROM routing WHERE resource = ? AND node = ?", - (id, node), - )?; + self.db + .prepare("DELETE FROM routing WHERE resource = ? AND node = ?")? + .bind(1, id)? + .bind(2, node)? + .next()?; - Ok(deleted > 0) + Ok(self.db.change_count() > 0) } } @@ -129,7 +142,7 @@ mod test { } #[test] - fn test_iter() { + fn test_entries() { let ids = arbitrary::set::(6..9); let nodes = arbitrary::set::(6..9); let mut db = Table::open(":memory:").unwrap(); @@ -160,13 +173,11 @@ mod test { db.insert(*id, *node).unwrap(); } } - for id in &ids { for node in &nodes { assert!(db.remove(id, node).unwrap()); } } - for id in &ids { assert!(db.get(id).unwrap().is_empty()); } diff --git a/radicle/Cargo.toml b/radicle/Cargo.toml index 2042c8b5..dcce194d 100644 --- a/radicle/Cargo.toml +++ b/radicle/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [features] default = [] test = ["quickcheck"] -sql = ["rusqlite"] +sql = ["sqlite"] [dependencies] base64 = { version= "0.13" } @@ -28,7 +28,7 @@ serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } siphasher = { version = "0.3.10" } radicle-git-ext = { version = "0", features = ["serde"] } -rusqlite = { version = "0.28.0", features = ["bundled"], optional = true } +sqlite = { version = "0.27.0", optional = true } nonempty = { version = "0.8.0", features = ["serialize"] } tempfile = { version = "3.3.0" } thiserror = { version = "1" } diff --git a/radicle/src/sql.rs b/radicle/src/sql.rs index 74da2287..47e6d4ce 100644 --- a/radicle/src/sql.rs +++ b/radicle/src/sql.rs @@ -1,48 +1,37 @@ -use std::str; use std::str::FromStr; -use rusqlite as sql; -use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput, ValueRef}; +use sqlite as sql; +use sqlite::Value; use crate::crypto::PublicKey; use crate::identity::Id; -impl FromSql for Id { - fn column_result(value: ValueRef<'_>) -> FromSqlResult { +impl sql::ValueInto for Id { + fn into(value: &Value) -> Option { match value { - ValueRef::Text(id) => { - let id = str::from_utf8(id).map_err(|e| FromSqlError::Other(Box::new(e)))?; - let id = Id::from_str(id).map_err(|e| FromSqlError::Other(Box::new(e)))?; - - Ok(id) - } - _ => Err(FromSqlError::InvalidType), + Value::String(id) => Id::from_str(id).ok(), + _ => None, } } } -impl ToSql for Id { - fn to_sql(&self) -> sql::Result> { - Ok(ToSqlOutput::from(self.to_string())) +impl sqlite::Bindable for &Id { + fn bind(self, stmt: &mut sql::Statement<'_>, i: usize) -> sql::Result<()> { + self.to_human().as_str().bind(stmt, i) } } -impl FromSql for PublicKey { - fn column_result(value: ValueRef<'_>) -> FromSqlResult { +impl sql::ValueInto for PublicKey { + fn into(value: &Value) -> Option { match value { - ValueRef::Text(pk) => { - let pk = str::from_utf8(pk).map_err(|e| FromSqlError::Other(Box::new(e)))?; - let pk = PublicKey::from_str(pk).map_err(|e| FromSqlError::Other(Box::new(e)))?; - - Ok(pk) - } - _ => Err(FromSqlError::InvalidType), + Value::String(id) => PublicKey::from_str(id).ok(), + _ => None, } } } -impl ToSql for PublicKey { - fn to_sql(&self) -> sql::Result> { - Ok(ToSqlOutput::from(self.to_string())) +impl sqlite::Bindable for &PublicKey { + fn bind(self, stmt: &mut sql::Statement<'_>, i: usize) -> sql::Result<()> { + self.to_human().as_str().bind(stmt, i) } }