From f03445ac4b6a8e72dcd8068e47ff2921374fb51c Mon Sep 17 00:00:00 2001 From: ProtoByter Date: Wed, 7 Sep 2022 17:15:38 +0100 Subject: [PATCH] Db: Finish sqlite backend and remove the redis backend --- Cargo.toml | 6 ++--- src/db/mod.rs | 25 +++++++++---------- src/db/redis/mod.rs | 59 -------------------------------------------- src/db/sqlite/mod.rs | 47 +++++++++++++++++++++++------------ src/main.rs | 1 + 5 files changed, 45 insertions(+), 93 deletions(-) delete mode 100644 src/db/redis/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 616f557..c0c772f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -redis = { version = "0.21.6", optional = true } -sqlite = { version = "0.27.0", optional = true } +rusqlite = { version = "0.28.0", optional = true } [features] -redis_db = ["dep:redis"] -sqlite_db = ["dep:sqlite"] \ No newline at end of file +sqlite_db = ["dep:rusqlite"] \ No newline at end of file diff --git a/src/db/mod.rs b/src/db/mod.rs index 04aa3ff..5a18711 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,23 +1,22 @@ use std::iter::Map; mod sqlite; -mod redis; + +pub enum DbColumn { + Id = 0, + IpEncrypted = 1, + Timeout = 2 +} pub trait DbBackend { /// Connects to the DB fn connect(&mut self) -> Result<(), String>; - /// Get the map object at a key - fn get(&self, key: &str) -> Result, String>; + /// Get the value inside a map object at a key + fn get(&mut self, key: i64, inner_key: DbColumn) -> Result; - /// Get the value inside a map object at a key (likely faster than get) - fn get_inner(&self, key: &str, inner_key: &str) -> Result; - - /// Set the map object at a key, returns the value you game it - fn set(&mut self, key: &str, value: Map) -> Result, String>; - - /// Set the value inside a map object at a key, returns the value you game it - fn set_inner(&mut self, key: &str, inner_key: &str, value: &str) -> Result<&str, String>; + /// Set the value inside a map object at a key, returns the value you gave it + fn set(&mut self, key: &str, inner_key: DbColumn, value: &str) -> Result; /// Disconnects from the DB fn disconnect(&mut self) -> Result<(), String>; @@ -33,13 +32,11 @@ pub fn get_backend_names() -> Vec<&'static str> { } pub fn get_backend(db_type: &str) -> Box { - #[cfg(not(any(feature = "sqlite_db", feature = "redis_db")))] + #[cfg(not(any(feature = "sqlite_db")))] compile_error!("No database backend selected"); return match db_type { #[cfg(feature = "sqlite_db")] "sqlite" => Box::new(sqlite::SqliteBackend::new()), - #[cfg(feature = "redis_db")] - "redis" => Box::new(redis::RedisBackend::new()), _ => panic!("Unknown database type"), }; } diff --git a/src/db/redis/mod.rs b/src/db/redis/mod.rs deleted file mode 100644 index 936fa97..0000000 --- a/src/db/redis/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -use std::iter::Map; -use crate::db::DbBackend; -use crate::log::{log, LogArea, LogType}; - -pub struct RedisBackend { - conn: Option -} - -impl RedisBackend { - pub fn new() -> Self { - Self { - conn: None - } - } -} - -impl DbBackend for RedisBackend { - fn connect(&mut self) -> Result<(), String> { - // TODO: Make this URL configurable - self.conn = match redis::Client::open("redis://127.0.0.1/").unwrap().get_connection() { - Ok(conn) => Some(conn), - Err(e) => { - log(LogType::Error, LogArea::Db, &format!("Failed to connect to database: {}", e)); - None - }, - }; - - if self.conn.is_some() { - log(LogType::Info, LogArea::Db, "Connected to database"); - } - else { - return Err("Failed to connect to database".to_string()); - } - - Ok(()) - } - - fn get(&self, key: &str) -> Result, String> { - todo!() - } - - fn get_inner(&self, key: &str, inner_key: &str) -> Result { - todo!() - } - - fn set(&mut self, key: &str, value: Map) -> Result, String> { - todo!() - } - - fn set_inner(&mut self, key: &str, inner_key: &str, value: &str) -> Result<&str, String> { - todo!() - } - - fn disconnect(&mut self) -> Result<(), String> { - log(LogType::Info, LogArea::Db, "Disconnecting from database"); - self.conn.take(); - return Ok(()) - } -} \ No newline at end of file diff --git a/src/db/sqlite/mod.rs b/src/db/sqlite/mod.rs index c56dd33..8d74313 100644 --- a/src/db/sqlite/mod.rs +++ b/src/db/sqlite/mod.rs @@ -1,9 +1,10 @@ use std::iter::Map; -use crate::db::DbBackend; +use rusqlite::{Connection, named_params, params}; +use crate::db::{DbBackend, DbColumn}; use crate::log::{log, LogArea, LogType}; pub struct SqliteBackend { - conn: Option, + conn: Option, } impl SqliteBackend { @@ -12,11 +13,21 @@ impl SqliteBackend { conn: None } } + + fn check_conn(&self) -> bool { + match self.conn.is_none() { + true => { + log(LogType::Error, LogArea::Db, "Not connected to database"); + false + }, + false => true + } + } } impl DbBackend for SqliteBackend { fn connect(&mut self) -> Result<(), String> { - self.conn = match sqlite::open("db.sqlite3") { + self.conn = match Connection::open("db.sqlite3") { Ok(conn) => Some(conn), Err(e) => { log(LogType::Error, LogArea::Db, &format!("Failed to connect to database: {}", e)); @@ -31,7 +42,7 @@ impl DbBackend for SqliteBackend { return Err("Failed to connect to database".to_string()); } - if let Err(e) = self.conn.as_ref().unwrap().execute("CREATE TABLE IF NOT EXISTS nodes (id INTEGER PRIMARY KEY, ip_encrypted TEXT NOT NULL, timeout TEXT NOT NULL)") { + if let Err(e) = self.conn.as_ref().unwrap().execute("CREATE TABLE IF NOT EXISTS nodes (id INTEGER PRIMARY KEY, ip_encrypted TEXT NOT NULL, timeout TEXT NOT NULL)", ()) { log(LogType::Error, LogArea::Db, &format!("Failed to create nodes table: {}", e)); return Err("Failed to create nodes table".to_string()); } @@ -39,20 +50,24 @@ impl DbBackend for SqliteBackend { Ok(()) } - fn get(&self, key: &str) -> Result, String> { - todo!() + fn get(&mut self, key: i64, inner_key: DbColumn) -> Result { + if !self.check_conn() { return Err("Not connected to database".to_string()) } else { + + let mut statement = self.conn.as_ref().unwrap().prepare("SELECT * FROM 'nodes' WHERE id = ?;").unwrap(); + return match statement.query_row(params![key], |row| { + row.get::(inner_key as usize) + }) { + Ok(value) => Ok(value), + Err(e) => { + log(LogType::Error, LogArea::Db, &format!("Failed to get value from database: {}", e)); + Err("Failed to get value from database".to_string()) + } + } + } } - fn get_inner(&self, key: &str, inner_key: &str) -> Result { - todo!() - } - - fn set(&mut self, key: &str, value: Map) -> Result, String> { - todo!() - } - - fn set_inner(&mut self, key: &str, inner_key: &str, value: &str) -> Result<&str, String> { - todo!() + fn set(&mut self, key: &str, inner_key: DbColumn, value: &str) -> Result { + if !self.check_conn() { return Err("Not connected to database".to_string()) } else { Ok("".to_string()) } } fn disconnect(&mut self) -> Result<(), String> { diff --git a/src/main.rs b/src/main.rs index 59bfd92..d24f8f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,5 +4,6 @@ mod log; fn main() { let mut db = db::get_backend("sqlite"); db.as_mut().connect().unwrap(); + println!("{}", db.as_mut().get(1234, db::DbColumn::Timeout).unwrap()); db.as_mut().disconnect().unwrap(); }