X-Git-Url: http://git.euphorik.ch/?p=recipes.git;a=blobdiff_plain;f=backend%2Fsrc%2Fdb.rs;fp=backend%2Fsrc%2Fdb.rs;h=1d38a454f03091e1d1020f1a19001919494aef8b;hp=ac97f1b14639db17377415e1e736c773810a4788;hb=108476e3554ea3a25dca5b5ab260f38c1e734221;hpb=a080d19cb9076780db9e86325b2ab617886e2a5f diff --git a/backend/src/db.rs b/backend/src/db.rs index ac97f1b..1d38a45 100644 --- a/backend/src/db.rs +++ b/backend/src/db.rs @@ -1,27 +1,24 @@ -use std::path::Path; -use std::fs; +use crate::consts::SQL_FILENAME; -//use rusqlite::types::ToSql; -//use rusqlite::{Connection, Result, NO_PARAMS}; +use super::consts; -//extern crate r2d2; -//extern crate r2d2_sqlite; -//extern crate rusqlite; +use std::{fs::{self, File}, path::Path, io::Read}; -use r2d2_sqlite::SqliteConnectionManager; +//use rusqlite::types::ToSql; +//use rusqlite::{Connection, Result, NO_PARAMS}; use r2d2::Pool; +use r2d2_sqlite::SqliteConnectionManager; + +const CURRENT_DB_VERSION: u32 = 1; #[derive(Debug)] -pub enum DbError { +pub enum DBError { SqliteError(rusqlite::Error), R2d2Error(r2d2::Error), - UnsupportedVersion(i32), + UnsupportedVersion(u32), + Other(String), } -use super::consts; - -const CURRENT_DB_VERSION: u32 = 1; - pub struct Connection { //con: rusqlite::Connection pool: Pool @@ -32,20 +29,20 @@ pub struct Recipe { pub id: i32, } -impl std::convert::From for DbError { +impl std::convert::From for DBError { fn from(error: rusqlite::Error) -> Self { - DbError::SqliteError(error) + DBError::SqliteError(error) } } -impl std::convert::From for DbError { +impl std::convert::From for DBError { fn from(error: r2d2::Error) -> Self { - DbError::R2d2Error(error) + DBError::R2d2Error(error) } } impl Connection { - pub fn new() -> Result { + pub fn new() -> Result { let data_dir = Path::new(consts::DB_DIRECTORY); @@ -53,7 +50,7 @@ impl Connection { fs::DirBuilder::new().create(data_dir).unwrap(); } - let manager = SqliteConnectionManager::file("file.db"); + let manager = SqliteConnectionManager::file(consts::DB_FILENAME); let pool = r2d2::Pool::new(manager).unwrap(); let connection = Connection { pool }; @@ -65,7 +62,7 @@ impl Connection { * Called after the connection has been established for creating or updating the database. * The 'Version' table tracks the current state of the database. */ - fn create_or_update(self: &Self) -> Result<(), DbError> { + fn create_or_update(self: &Self) -> Result<(), DBError> { // let connection = Connection::new(); // let mut stmt = connection.sqlite_con.prepare("SELECT * FROM versions ORDER BY date").unwrap(); // let mut stmt = connection.sqlite_con.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='versions'").unwrap(); @@ -74,13 +71,14 @@ impl Connection { let mut con = self.pool.get()?; let tx = con.transaction()?; + // Version 0 corresponds to an empty database. let mut version = { match tx.query_row( "SELECT [name] FROM [sqlite_master] WHERE [type] = 'table' AND [name] = 'Version'", - rusqlite::NO_PARAMS, + [], |row| row.get::(0) ) { - Ok(_) => tx.query_row("SELECT [version] FROM [Version]", rusqlite::NO_PARAMS, |row| row.get(0)).unwrap_or_default(), + Ok(_) => tx.query_row("SELECT [version] FROM [Version]", [], |row| row.get(0)).unwrap_or_default(), Err(_) => 0 } }; @@ -94,49 +92,45 @@ impl Connection { Ok(()) } - fn update_to_next_version(version: i32, tx: &rusqlite::Transaction) -> Result { - match version { - 0 => { - println!("Update to version 1..."); - - // Initial structure. - tx.execute_batch( - " - CREATE TABLE [Version] ( - [id] INTEGER PRIMARY KEY, - [version] INTEGER NOT NULL UNIQUE, - [datetime] INTEGER DATETIME - ); - - CREATE TABLE [Recipe] ( - [id] INTEGER PRIMARY KEY, - [title] INTEGER NOT NULL, - [description] INTEGER DATETIME - ); - " - )?; - - /* - tx.execute( - " - INSERT INTO Version - ", - rusqlite::NO_PARAMS - );*/ - - Ok(true) + fn update_to_next_version(current_version: u32, tx: &rusqlite::Transaction) -> Result { + let next_version = current_version + 1; + + if next_version <= CURRENT_DB_VERSION { + println!("Update to version {}...", next_version); + } + + fn ok(updated: bool) -> Result { + if updated { + println!("Version updated"); } + Ok(updated) + } - // Current version. - 1 => - Ok(false), + match next_version { + 1 => { + tx.execute_batch(&load_sql_file(next_version)?)?; + + ok(true) + } + + // Version 1 doesn't exist yet. + 2 => + ok(false), v => - Err(DbError::UnsupportedVersion(v)), + Err(DBError::UnsupportedVersion(v)), } } pub fn get_all_recipes() { } +} + +fn load_sql_file(version: u32) -> Result { + let sql_file = SQL_FILENAME.replace("{VERSION}", &version.to_string()); + let mut file = File::open(&sql_file).map_err(|err| DBError::Other(format!("Cannot open SQL file ({}): {}", &sql_file, err.to_string())))?; + let mut sql = String::new(); + file.read_to_string(&mut sql).map_err(|err| DBError::Other(format!("Cannot read SQL file ({}) : {}", &sql_file, err.to_string())))?; + Ok(sql) } \ No newline at end of file