Db: Finish sqlite backend and remove the redis backend

This commit is contained in:
ProtoByter 2022-09-07 17:15:38 +01:00
parent 6b7373243c
commit f03445ac4b
5 changed files with 45 additions and 93 deletions

View File

@ -6,9 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
redis = { version = "0.21.6", optional = true } rusqlite = { version = "0.28.0", optional = true }
sqlite = { version = "0.27.0", optional = true }
[features] [features]
redis_db = ["dep:redis"] sqlite_db = ["dep:rusqlite"]
sqlite_db = ["dep:sqlite"]

View File

@ -1,23 +1,22 @@
use std::iter::Map; use std::iter::Map;
mod sqlite; mod sqlite;
mod redis;
pub enum DbColumn {
Id = 0,
IpEncrypted = 1,
Timeout = 2
}
pub trait DbBackend { pub trait DbBackend {
/// Connects to the DB /// Connects to the DB
fn connect(&mut self) -> Result<(), String>; fn connect(&mut self) -> Result<(), String>;
/// Get the map object at a key /// Get the value inside a map object at a key
fn get(&self, key: &str) -> Result<Map<String, String>, String>; fn get(&mut self, key: i64, inner_key: DbColumn) -> Result<String, String>;
/// Get the value inside a map object at a key (likely faster than get) /// Set the value inside a map object at a key, returns the value you gave it
fn get_inner(&self, key: &str, inner_key: &str) -> Result<String, String>; fn set(&mut self, key: &str, inner_key: DbColumn, value: &str) -> Result<String, String>;
/// Set the map object at a key, returns the value you game it
fn set(&mut self, key: &str, value: Map<String, String>) -> Result<Map<String, String>, 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>;
/// Disconnects from the DB /// Disconnects from the DB
fn disconnect(&mut self) -> Result<(), String>; 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<dyn DbBackend> { pub fn get_backend(db_type: &str) -> Box<dyn DbBackend> {
#[cfg(not(any(feature = "sqlite_db", feature = "redis_db")))] #[cfg(not(any(feature = "sqlite_db")))]
compile_error!("No database backend selected"); compile_error!("No database backend selected");
return match db_type { return match db_type {
#[cfg(feature = "sqlite_db")] #[cfg(feature = "sqlite_db")]
"sqlite" => Box::new(sqlite::SqliteBackend::new()), "sqlite" => Box::new(sqlite::SqliteBackend::new()),
#[cfg(feature = "redis_db")]
"redis" => Box::new(redis::RedisBackend::new()),
_ => panic!("Unknown database type"), _ => panic!("Unknown database type"),
}; };
} }

View File

@ -1,59 +0,0 @@
use std::iter::Map;
use crate::db::DbBackend;
use crate::log::{log, LogArea, LogType};
pub struct RedisBackend {
conn: Option<redis::Connection>
}
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<Map<String, String>, String> {
todo!()
}
fn get_inner(&self, key: &str, inner_key: &str) -> Result<String, String> {
todo!()
}
fn set(&mut self, key: &str, value: Map<String, String>) -> Result<Map<String, String>, 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(())
}
}

View File

@ -1,9 +1,10 @@
use std::iter::Map; 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}; use crate::log::{log, LogArea, LogType};
pub struct SqliteBackend { pub struct SqliteBackend {
conn: Option<sqlite::Connection>, conn: Option<rusqlite::Connection>,
} }
impl SqliteBackend { impl SqliteBackend {
@ -12,11 +13,21 @@ impl SqliteBackend {
conn: None 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 { impl DbBackend for SqliteBackend {
fn connect(&mut self) -> Result<(), String> { fn connect(&mut self) -> Result<(), String> {
self.conn = match sqlite::open("db.sqlite3") { self.conn = match Connection::open("db.sqlite3") {
Ok(conn) => Some(conn), Ok(conn) => Some(conn),
Err(e) => { Err(e) => {
log(LogType::Error, LogArea::Db, &format!("Failed to connect to database: {}", 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()); 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)); log(LogType::Error, LogArea::Db, &format!("Failed to create nodes table: {}", e));
return Err("Failed to create nodes table".to_string()); return Err("Failed to create nodes table".to_string());
} }
@ -39,20 +50,24 @@ impl DbBackend for SqliteBackend {
Ok(()) Ok(())
} }
fn get(&self, key: &str) -> Result<Map<String, String>, String> { fn get(&mut self, key: i64, inner_key: DbColumn) -> Result<String, String> {
todo!() 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::<usize, String>(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<String, String> { fn set(&mut self, key: &str, inner_key: DbColumn, value: &str) -> Result<String, String> {
todo!() if !self.check_conn() { return Err("Not connected to database".to_string()) } else { Ok("".to_string()) }
}
fn set(&mut self, key: &str, value: Map<String, String>) -> Result<Map<String, String>, String> {
todo!()
}
fn set_inner(&mut self, key: &str, inner_key: &str, value: &str) -> Result<&str, String> {
todo!()
} }
fn disconnect(&mut self) -> Result<(), String> { fn disconnect(&mut self) -> Result<(), String> {

View File

@ -4,5 +4,6 @@ mod log;
fn main() { fn main() {
let mut db = db::get_backend("sqlite"); let mut db = db::get_backend("sqlite");
db.as_mut().connect().unwrap(); db.as_mut().connect().unwrap();
println!("{}", db.as_mut().get(1234, db::DbColumn::Timeout).unwrap());
db.as_mut().disconnect().unwrap(); db.as_mut().disconnect().unwrap();
} }