From 889dc4f87b05d838b25428478a8c42dac454a5cf Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Mon, 7 Nov 2022 22:29:35 +0100 Subject: finished rusqlite; added all db tests --- src/db.rs | 406 ++++++++++++++++++++++++++------------------------------------ 1 file changed, 171 insertions(+), 235 deletions(-) (limited to 'src/db.rs') diff --git a/src/db.rs b/src/db.rs index 86e697e..5d82271 100644 --- a/src/db.rs +++ b/src/db.rs @@ -2,9 +2,9 @@ use std::io::{Error, ErrorKind}; use rusqlite::Connection; -use crate::{Modloader, config::Cfg, List}; +use crate::{Modloader, config::Cfg, List, get_modloader}; -//MODS +//mods pub fn mods_insert(config: Cfg, id: String, name: String, versions: Vec) -> Result<(), Box> { println!("Inserting mod {}({}) into database", name, id); @@ -75,6 +75,43 @@ pub fn mods_remove(config: Cfg, id: String) -> Result<(), Box) -> Result, Box> { + let data = format!("{}/data.db", config.data); + let connection = Connection::open(data)?; + + if mods.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "MODS_NO_INPUT"))); } + + let mut wherestr = String::from("WHERE"); + for (i, id) in mods.iter().enumerate() { + let mut or = " OR"; + if i == mods.len() - 1 { or = "" }; + wherestr = format!("{} id = '{}'{}", wherestr, id, or); + } + + let mut versionmaps: Vec = Vec::new(); + let mut stmt = connection.prepare(dbg!(format!("SELECT id, versions FROM mods {}", wherestr).as_str()))?; + let id_iter = stmt.query_map([], |row| { + Ok(vec![row.get::(0)?, row.get::(1)?]) + })?; + + for ver in id_iter { + let version = ver?; + println!("Found versions {} for mod {}", version[1], version[0]); + versionmaps.push(DBModlistVersions { mod_id: String::from(&version[0]), versions: String::from(&version[1]) }) + }; + + match versionmaps.is_empty() { + true => Err(Box::new(Error::new(ErrorKind::NotFound, "MODS_MODS_NOT_FOUND"))), + false => Ok(versionmaps), + } +} + //userlist pub fn userlist_insert(config: Cfg, list_id: String, mod_id: String, current_version: String, applicable_versions: Vec, current_link: String) -> Result<(), Box> { println!("Inserting {} into current list({})", mod_id, list_id); @@ -119,69 +156,74 @@ pub fn userlist_remove(config: Cfg, list_id: String, mod_id: String) -> Result<( } -#[derive(Debug, Clone)] -pub struct DBModlistVersions { - pub mod_id: String, - pub versions: String, -} - -pub fn get_versions(config: Cfg, mods: Vec) -> Result, Box> { - /* +pub fn userlist_get_applicable_versions(config: Cfg, list_id: String, mod_id: String) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data).unwrap(); - let mut wherestr = String::from("WHERE"); - for (i, id) in mods.iter().enumerate() { - let mut or = " OR"; - if i == mods.len() - 1 { or = "" } - println!("Pushing {}({}) | OR: '{}'", id, i, or); - wherestr = format!("{} id = '{}'{}", wherestr, id, or); - } + let mut version: String = String::new(); + let mut stmt = connection.prepare(format!("SELECT applicable_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; + let ver_iter = stmt.query_map([mod_id], |row| { + row.get::(0) + })?; - let sql = format!("SELECT id, versions FROM mods {}", wherestr); + for ver in ver_iter { + println!("Found id {:?}", ver); + version = ver?; + }; - dbg!(&sql); + match version.is_empty() { + true => Err(Box::new(Error::new(ErrorKind::NotFound, "MOD_NOT_FOUND"))), + false => Ok(version), + } +} - let mut versionmaps: Vec = Vec::new(); - //TODO catch sql errors better - let mut cursor = connection.prepare(sql).unwrap().into_cursor(); +pub fn userlist_get_all_current_version_ids(config: Cfg, list_id: String) -> Result, Box> { + let data = format!("{}/data.db", config.data); + let connection = Connection::open(data)?; - while let Some(Ok(row)) = cursor.next() { - println!("{}: {}", row.get::(0), row.get::(1)); - versionmaps.push(DBModlistVersions { mod_id: row.get::(0), versions: row.get::(1) }) + let mut versions: Vec = Vec::new(); + let mut stmt = connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; + let id_iter = stmt.query_map([], |row| { + row.get::(0) + })?; + + for id in id_iter { + versions.push(id?); }; - if versionmaps.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; + if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; - Ok(versionmaps) - */ - Ok(vec![DBModlistVersions { mod_id: String::new(), versions: String::new() }]) + Ok(versions) } -pub fn get_list_version(config: Cfg, list: List, mod_id: String) -> Result> { - /* +pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT applicable_versions FROM {} WHERE mod_id = '{}'", list.id, mod_id); - - //TODO catch sql errors better - let mut version: String = String::new(); - connection.iterate(sql, |ver| { - if ver.is_empty() { return false; }; - for &(_column, value) in ver.iter() { - version = String::from(value.unwrap()); - } - true - }).unwrap(); - - if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; + let connection = Connection::open(data)?; - Ok(version) - */ - Ok(String::new()) + connection.execute(format!("UPDATE {} SET current_version = ?1, applicable_versions = ?2, current_download = ?3 WHERE mod_id = ?4", list_id).as_str(), [current_version, versions, link, mod_id])?; + Ok(()) } +pub fn userlist_get_all_downloads(config: Cfg, list_id: String) -> Result, Box> { + let data = format!("{}/data.db", config.data); + let connection = Connection::open(data).unwrap(); + + let mut links: Vec = Vec::new(); + let mut stmt = connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?; + let link_iter = stmt.query_map([], |row| { + row.get::(0) + })?; + + for link in link_iter { + let l = link?; + println!("Found link {}", String::from(&l)); + links.push(l) + }; + + if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; + + Ok(links) +} //lists pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Modloader) -> Result<(), Box> { @@ -196,222 +238,134 @@ pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Mod Ok(()) } -pub fn remove_list(config: Cfg, id: String) -> Result<(), Box> { - /* +pub fn lists_remove(config: Cfg, id: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql_list = format!("DELETE FROM lists WHERE id = '{}'", id); - let sql_table = format!("DROP TABLE '{}'", id); - let sql = format!("{};{};", sql_list, sql_table); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute("DELETE FROM lists WHERE id = ?", [&id])?; + connection.execute(format!("DROP TABLE {}", id).as_str(), [])?; Ok(()) } -pub fn get_lists(config: Cfg) -> Result, Box> { - /* +pub fn lists_get(config: Cfg, list_id: String) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = "SELECT id FROM lists"; - - let mut list: Vec = Vec::new(); - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - list.push(String::from(value.unwrap())); - } - true - }).unwrap(); - match list.is_empty() { - true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))), - false => Ok(list), - } - */ - Ok(vec![String::new()]) -} - -pub fn get_current_versions(config: Cfg, list: List) -> Result, Box> { - /* - let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT current_version FROM {}", list.id); + let connection = Connection::open(data).unwrap(); - dbg!(&sql); + let mut list = List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric }; + let mut stmt = connection.prepare("SELECT mc_version, modloader FROM lists WHERE id = ?")?; - let mut versions: Vec = Vec::new(); - //TODO catch sql errors better - let mut cursor = connection.prepare(sql).unwrap().into_cursor(); + let list_iter = stmt.query_map([&list_id], |row| { + Ok(vec![row.get::(0)?, row.get::(1)?]) + })?; - while let Some(Ok(row)) = cursor.next() { - versions.push(row.get::(0)); + for l in list_iter { + let li = l?; + list = List { id: String::from(&list_id), mc_version: String::from(&li[0]), modloader: get_modloader(String::from(&li[1]))? }; }; - if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; - - Ok(versions) - */ - Ok(vec![String::new()]) -} - -pub fn get_list(config: Cfg, id: String) -> Result> { - /* - let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT mc_version, modloader FROM lists WHERE id = '{}'", id); + if list.id.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "LIST_NOT_FOUND"))); } - let mut list = vec![]; - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - list.push(String::from(value.unwrap())); - } - true - }).unwrap(); - - if list.len() != 2 { return Err(Box::new(std::io::Error::new(ErrorKind::InvalidData, "LIST_MISSING_DATA"))) }; - - Ok(List { id, mc_version: String::from(&list[0]), modloader: get_modloader(String::from(&list[1]))? }) - */ - Ok(List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric }) + Ok(list) } -pub fn change_list_versions(config: Cfg, list: List, current_version: String, versions: Vec, mod_id: String) -> Result<(), Box> { - /* +pub fn lists_get_all_ids(config: Cfg) -> Result, Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data).unwrap(); + + let mut list_ids: Vec = Vec::new(); + let mut stmt = connection.prepare("SELECT id FROM lists")?; + let id_iter = stmt.query_map([], |row| { + row.get::(0) + })?; - let sql = format!("UPDATE {} SET current_version = '{}', applicable_versions = '{}' WHERE mod_id = '{}'", list.id, current_version, versions.join("|"), mod_id); + for id in id_iter { + println!("Found id {:?}", id.as_ref().unwrap()); + list_ids.push(id?) + }; - connection.execute(sql) - */ - Ok(()) + match list_ids.is_empty() { + true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))), + false => Ok(list_ids), + } } -//DOWNLOAD - -pub fn insert_dl_link(config: Cfg, list: List, mod_id: String, link: String) -> Result<(), Box> { - /* +//config +pub fn config_change_current_list(config: Cfg, id: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("UPDATE {} SET current_download = '{}' WHERE mod_id = '{}'", list.id, link, mod_id); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute("UPDATE user_config SET value = ? WHERE id = 'current_list'", [id])?; Ok(()) } -pub fn get_dl_links(config: Cfg, list: List) -> Result, Box> { - /* +pub fn config_get_current_list(config: Cfg) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("SELECT current_download FROM {}", list.id); - - dbg!(&sql); - - let mut links: Vec = Vec::new(); - //TODO catch sql errors better - let mut cursor = connection.prepare(sql).unwrap().into_cursor(); + let connection = Connection::open(data).unwrap(); + + let mut list_id = String::new(); + let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; + let list_iter = stmt.query_map([], |row| { + row.get::(0) + })?; - while let Some(Ok(row)) = cursor.next() { - links.push(row.get::(0)); + for list in list_iter { + list_id = list?; }; - if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; - - Ok(links) - */ - Ok(vec![String::new()]) + if list_id.is_empty() { return Err(Box::new(Error::new(ErrorKind::Other, "NO_CURRENT_LIST"))); } + + Ok(list_id) } -//config -pub fn change_list(config: Cfg, id: String) -> Result<(), Box> { - /* +//SETUP(UPDATES) +pub fn s_userlist_update_download(config: Cfg, list_id: String, mod_id: String, link: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'current_list'", id); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute(format!("UPDATE {} SET current_download = ?1 WHERE mod_id = ?2", list_id).as_str(), [link, mod_id])?; Ok(()) } -pub fn get_current_list_id(config: Cfg) -> Result> { - /* +pub fn s_config_create_version(config: Cfg) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data)?; - let sql = "SELECT id FROM lists"; - - let mut list: String = String::new(); - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - list = String::from(value.unwrap()); - } - true - }).unwrap(); - if list.is_empty() { - get_lists(config)?; - panic!("current list field should never be empty if there are other lists"); - }; - Ok(list) - */ - Ok(String::new()) + connection.execute("INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )", ())?; + Ok(()) } -pub fn update_dbversion(config: Cfg, ver: String) -> Result<(), Box> { - /* +pub fn s_config_update_version(config: Cfg, ver: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'db_version'", ver); + let connection = Connection::open(data)?; - connection.execute(sql) - */ + connection.execute("UPDATE user_config SET value = ? WHERE id = 'db_version'", [ver])?; Ok(()) } -pub fn create_dbversion(config: Cfg) -> Result<(), Box> { - /* +pub fn s_config_get_version(config: Cfg) -> Result> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - let sql = "INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' );"; - connection.execute(sql) - */ - Ok(()) + let connection = Connection::open(data)?; + + let mut version: String = String::new(); + let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; + let ver_iter = stmt.query_map([], |row| { + row.get::(0) + })?; + + for ver in ver_iter { + version = ver?; + }; + + if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); }; + Ok(version) } -pub fn user_dbversion(config: Cfg) -> Result> { - /* +pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: String) -> Result<(), Box> { let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); + let connection = Connection::open(data)?; - let sql = "SELECT db_version FROM user_config"; - - let mut ver: String = String::new(); - //TODO catch sql errors better - connection.iterate(sql, |ids| { - if ids.is_empty() { return false; }; - for &(_column, value) in ids.iter() { - ver = String::from(value.unwrap()); - } - true - })?; - if ver.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); }; - Ok(ver) - */ - Ok(String::from("0.2")) + connection.execute(format!("ALTER TABLE {} ADD '{}' {}", table, column, c_type).as_str(), ())?; + Ok(()) } pub fn db_setup(config: Cfg) -> Result<(), Box> { @@ -432,21 +386,3 @@ pub fn db_setup(config: Cfg) -> Result<(), Box> { Ok(()) } -pub fn insert_column(config: Cfg, table: String, column: String, c_type: String) -> Result<(), Box> { - /* - let data = format!("{}/data.db", config.data); - let connection = sqlite::open(data).unwrap(); - - let ct = match c_type { - sqlite::Type::Null => "NULL", - sqlite::Type::Float => "FLOAT", - sqlite::Type::Binary => "BINARY", - sqlite::Type::String => "TEXT", - sqlite::Type::Integer => "INT", - }; - - let sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, ct); - connection.execute(sql) - */ - Ok(()) -} -- cgit v1.2.3