Switch to a lighter sqlite dependency

Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
Alexis Sellier 2022-10-08 12:13:59 +02:00
parent e909e04c6c
commit b8c2ab5316
No known key found for this signature in database
5 changed files with 90 additions and 126 deletions

100
Cargo.lock generated
View File

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

View File

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

View File

@ -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<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
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<Self, Error> {
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<HashSet<NodeId>, 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::<NodeId, _>(0));
}
Ok(nodes)
}
fn insert(&mut self, id: Id, node: NodeId) -> Result<bool, Error> {
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<Box<dyn Iterator<Item = (Id, NodeId)>>, 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<bool, Error> {
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::<Id>(6..9);
let nodes = arbitrary::set::<NodeId>(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());
}

View File

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

View File

@ -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<Self> {
impl sql::ValueInto for Id {
fn into(value: &Value) -> Option<Self> {
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<ToSqlOutput<'_>> {
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<Self> {
impl sql::ValueInto for PublicKey {
fn into(value: &Value) -> Option<Self> {
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<ToSqlOutput<'_>> {
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)
}
}