diff --git a/Cargo.lock b/Cargo.lock index 4f6a10e0..9bdedbaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1962,9 +1962,9 @@ dependencies = [ [[package]] name = "sqlite" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e66cb949f931ece6201d72bffad3f3601b94998a345793713dd13af70a77c185" +checksum = "2d7dcfcc5c3247141692d47227842b3e9c3cf7fe8dd78d91786d76eb3f27b717" dependencies = [ "libc", "sqlite3-sys", diff --git a/radicle-crypto/Cargo.toml b/radicle-crypto/Cargo.toml index 4ebb8736..359b44c5 100644 --- a/radicle-crypto/Cargo.toml +++ b/radicle-crypto/Cargo.toml @@ -16,7 +16,7 @@ ssh = ["base64", "radicle-ssh", "sha2", "ssh-key"] ed25519-compact = { version = "1.0.12", features = ["pem"] } multibase = { version = "0.9.1" } serde = { version = "1", features = ["derive"] } -sqlite = { version = "0.27.0", optional = true } +sqlite = { version = "0.28.1", optional = true } thiserror = { version = "1" } zeroize = { version = "1.5.7" } diff --git a/radicle-crypto/src/lib.rs b/radicle-crypto/src/lib.rs index aa8ce39e..c48b0a2f 100644 --- a/radicle-crypto/src/lib.rs +++ b/radicle-crypto/src/lib.rs @@ -342,10 +342,17 @@ impl sqlite::ValueInto for PublicKey { } } +#[cfg(feature = "sqlite")] +impl From for sqlite::Value { + fn from(pk: PublicKey) -> Self { + sqlite::Value::String(pk.to_human()) + } +} + #[cfg(feature = "sqlite")] impl sqlite::Bindable for &PublicKey { fn bind(self, stmt: &mut sqlite::Statement<'_>, i: usize) -> sqlite::Result<()> { - self.to_human().as_str().bind(stmt, i) + sqlite::Value::from(*self).bind(stmt, i) } } diff --git a/radicle-node/Cargo.toml b/radicle-node/Cargo.toml index 634f55ef..1a9463fe 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"] } -sqlite = { version = "0.27.0" } +sqlite = { version = "0.28.1" } sqlite3-src = { version = "0.4.0", features = ["bundled"] } # Ensures static linking scrypt = { version = "0.10.0", default-features = false } serde = { version = "1", features = ["derive"] } diff --git a/radicle-node/src/address/store.rs b/radicle-node/src/address/store.rs index 8ea2d715..97307269 100644 --- a/radicle-node/src/address/store.rs +++ b/radicle-node/src/address/store.rs @@ -57,29 +57,28 @@ impl Book { impl Store for Book { fn get(&self, node: &NodeId) -> Result, Error> { - let row = self + let mut stmt = self .db - .prepare("SELECT features, alias, timestamp FROM nodes WHERE id = ?")? - .bind(1, node)? - .into_cursor() - .next(); + .prepare("SELECT features, alias, timestamp FROM nodes WHERE id = ?")?; - if let Some(Ok(row)) = row { - let features = row.get::(0); - let alias = row.get::(1); - let timestamp = row.get::(2) as Timestamp; + stmt.bind(1, node)?; + + if let Some(Ok(row)) = stmt.into_cursor().next() { + let features = row.get::("features"); + let alias = row.get::("alias"); + let timestamp = row.get::("timestamp") as Timestamp; let mut addrs = Vec::new(); let mut stmt = self .db - .prepare("SELECT type, value, source FROM addresses WHERE node = ?")? - .bind(1, node)? - .into_cursor(); + .prepare("SELECT type, value, source FROM addresses WHERE node = ?")?; + stmt.bind(1, node)?; - while let Some(Ok(row)) = stmt.next() { - let _typ = row.get::(0); - let addr = row.get::(1); - let source = row.get::(2); + for row in stmt.into_cursor() { + let row = row?; + let _typ = row.get::("type"); + let addr = row.get::("value"); + let source = row.get::("source"); addrs.push(KnownAddress { addr, @@ -121,35 +120,34 @@ impl Store for Book { timestamp: Timestamp, addrs: impl IntoIterator, ) -> Result { - self.db - .prepare( - "INSERT INTO nodes (id, features, alias, timestamp) - VALUES (?1, ?2, ?3, ?4) - ON CONFLICT DO UPDATE - SET features = ?2, alias = ?3, timestamp = ?4 - WHERE timestamp < ?4", - )? - .bind(1, node)? - .bind(2, features)? - .bind(3, alias)? - .bind(4, timestamp as i64)? - .next()?; + let mut stmt = self.db.prepare( + "INSERT INTO nodes (id, features, alias, timestamp) + VALUES (?1, ?2, ?3, ?4) + ON CONFLICT DO UPDATE + SET features = ?2, alias = ?3, timestamp = ?4 + WHERE timestamp < ?4", + )?; + + stmt.bind(1, node)?; + stmt.bind(2, features)?; + stmt.bind(3, alias)?; + stmt.bind(4, timestamp as i64)?; + stmt.next()?; for addr in addrs { - self.db - .prepare( - "INSERT INTO addresses (node, type, value, source, timestamp) - VALUES (?1, ?2, ?3, ?4, ?5) - ON CONFLICT DO UPDATE - SET timestamp = ?5 - WHERE timestamp < ?5", - )? - .bind(1, node)? - .bind(2, AddressType::from(&addr.addr))? - .bind(3, addr.addr)? - .bind(4, addr.source)? - .bind(5, timestamp as i64)? - .next()?; + let mut stmt = self.db.prepare( + "INSERT INTO addresses (node, type, value, source, timestamp) + VALUES (?1, ?2, ?3, ?4, ?5) + ON CONFLICT DO UPDATE + SET timestamp = ?5 + WHERE timestamp < ?5", + )?; + stmt.bind(1, node)?; + stmt.bind(2, AddressType::from(&addr.addr))?; + stmt.bind(3, addr.addr)?; + stmt.bind(4, addr.source)?; + stmt.bind(5, timestamp as i64)?; + stmt.next()?; } Ok(self.db.change_count() > 0) } @@ -157,12 +155,15 @@ impl Store for Book { fn remove(&mut self, node: &NodeId) -> Result { self.db .prepare("DELETE FROM nodes WHERE id = ?")? - .bind(1, node)? - .next()?; + .into_cursor() + .bind(&[(*node).into()])? + .next(); + self.db .prepare("DELETE FROM addresses WHERE node = ?")? - .bind(1, node)? - .next()?; + .into_cursor() + .bind(&[(*node).into()])? + .next(); Ok(self.db.change_count() > 0) } @@ -175,10 +176,10 @@ impl Store for Book { let mut entries = Vec::new(); while let Some(Ok(row)) = stmt.next() { - let node = row.get(0); - let _typ = row.get::(1); - let addr = row.get::(2); - let source = row.get::(3); + let node = row.get("node"); + let _typ = row.get::("type"); + let addr = row.get::("value"); + let source = row.get::("source"); entries.push(( node, diff --git a/radicle-node/src/service/routing.rs b/radicle-node/src/service/routing.rs index 21eb98a4..cebbb917 100644 --- a/radicle-node/src/service/routing.rs +++ b/radicle-node/src/service/routing.rs @@ -73,45 +73,42 @@ impl Store for Table { fn get(&self, id: &Id) -> Result, Error> { let mut stmt = self .db - .prepare("SELECT (node) FROM routing WHERE resource = ?")? - .bind(1, id)? - .into_cursor(); - let mut nodes = HashSet::new(); + .prepare("SELECT (node) FROM routing WHERE resource = ?")?; + stmt.bind(1, id)?; - while let Some(Ok(row)) = stmt.next() { - nodes.insert(row.get::(0)); + let mut nodes = HashSet::new(); + for row in stmt.into_cursor() { + nodes.insert(row?.get::("node")); } Ok(nodes) } fn entry(&self, id: &Id, node: &NodeId) -> Result, Error> { - let row = self + let mut stmt = self .db - .prepare("SELECT (time) FROM routing WHERE resource = ? AND node = ?")? - .bind(1, id)? - .bind(2, node)? - .into_cursor() - .next(); + .prepare("SELECT (time) FROM routing WHERE resource = ? AND node = ?")?; - if let Some(Ok(row)) = row { - return Ok(Some(row.get::(0) as Timestamp)); + stmt.bind(1, id)?; + stmt.bind(2, node)?; + + if let Some(Ok(row)) = stmt.into_cursor().next() { + return Ok(Some(row.get::("time") as Timestamp)); } Ok(None) } fn insert(&mut self, id: Id, node: NodeId, time: Timestamp) -> Result { let time: i64 = time.try_into().map_err(|_| Error::TimeOverflow)?; + let mut stmt = self.db.prepare( + "INSERT INTO routing (resource, node, time) + VALUES (?, ?, ?) + ON CONFLICT DO NOTHING", + )?; - self.db - .prepare( - "INSERT INTO routing (resource, node, time) - VALUES (?, ?, ?) - ON CONFLICT DO NOTHING", - )? - .bind(1, &id)? - .bind(2, &node)? - .bind(3, time)? - .next()?; + stmt.bind(1, &id)?; + stmt.bind(2, &node)?; + stmt.bind(3, time)?; + stmt.next()?; Ok(self.db.change_count() > 0) } @@ -124,8 +121,8 @@ impl Store for Table { let mut entries = Vec::new(); while let Some(Ok(row)) = stmt.next() { - let id = row.get(0); - let node = row.get(1); + let id = row.get("resource"); + let node = row.get("node"); entries.push((id, node)); } @@ -133,22 +130,23 @@ impl Store for Table { } fn remove(&mut self, id: &Id, node: &NodeId) -> Result { - self.db - .prepare("DELETE FROM routing WHERE resource = ? AND node = ?")? - .bind(1, id)? - .bind(2, node)? - .next()?; + let mut stmt = self + .db + .prepare("DELETE FROM routing WHERE resource = ? AND node = ?")?; + + stmt.bind(1, id)?; + stmt.bind(2, node)?; + stmt.next()?; Ok(self.db.change_count() > 0) } fn prune(&mut self, oldest: Timestamp) -> Result { let oldest: i64 = oldest.try_into().map_err(|_| Error::TimeOverflow)?; + let mut stmt = self.db.prepare("DELETE FROM routing WHERE time < ?")?; - self.db - .prepare("DELETE FROM routing WHERE time < ?")? - .bind(1, oldest)? - .next()?; + stmt.bind(1, oldest)?; + stmt.next()?; Ok(self.db.change_count()) } diff --git a/radicle/Cargo.toml b/radicle/Cargo.toml index 30c91095..44e075cb 100644 --- a/radicle/Cargo.toml +++ b/radicle/Cargo.toml @@ -26,7 +26,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"] } -sqlite = { version = "0.27.0", optional = true } +sqlite = { version = "0.28.1", optional = true } nonempty = { version = "0.8.0", features = ["serialize"] } tempfile = { version = "3.3.0" } thiserror = { version = "1" }