X-Git-Url: http://git.euphorik.ch/?p=recipes.git;a=blobdiff_plain;f=backend%2Fsrc%2Fdb.rs;h=ac97f1b14639db17377415e1e736c773810a4788;hp=a4a0d9700492903a448af54acafb013d28b6cac5;hb=a080d19cb9076780db9e86325b2ab617886e2a5f;hpb=e2e54b8f43015738af860b005825dc809f5275ab diff --git a/backend/src/db.rs b/backend/src/db.rs index a4a0d97..ac97f1b 100644 --- a/backend/src/db.rs +++ b/backend/src/db.rs @@ -11,6 +11,12 @@ use std::fs; use r2d2_sqlite::SqliteConnectionManager; use r2d2::Pool; +#[derive(Debug)] +pub enum DbError { + SqliteError(rusqlite::Error), + R2d2Error(r2d2::Error), + UnsupportedVersion(i32), +} use super::consts; @@ -26,8 +32,20 @@ pub struct Recipe { pub id: i32, } +impl std::convert::From for DbError { + fn from(error: rusqlite::Error) -> Self { + DbError::SqliteError(error) + } +} + +impl std::convert::From for DbError { + fn from(error: r2d2::Error) -> Self { + DbError::R2d2Error(error) + } +} + impl Connection { - pub fn new() -> Connection { + pub fn new() -> Result { let data_dir = Path::new(consts::DB_DIRECTORY); @@ -39,59 +57,83 @@ impl Connection { let pool = r2d2::Pool::new(manager).unwrap(); let connection = Connection { pool }; - connection.create_or_update(); - connection + connection.create_or_update()?; + Ok(connection) } - fn create_or_update(self: &Self) { + /* + * 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> { // 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(); + // let mut stmt = connection.sqlite_con.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='versions'").unwrap(); // Check the Database version. - let con = self.pool.get().unwrap(); + let mut con = self.pool.get()?; + let tx = con.transaction()?; - let version = { - match - con.query_row( + 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(_) => con.query_row("SELECT [version] FROM [Version]", rusqlite::NO_PARAMS, |row| row.get(0)).unwrap_or_default(), + 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(), Err(_) => 0 } }; + while Connection::update_to_next_version(version, &tx)? { + version += 1; + } + + tx.commit()?; + + Ok(()) + } + + fn update_to_next_version(version: i32, tx: &rusqlite::Transaction) -> Result { match version { 0 => { println!("Update to version 1..."); - con.execute( + + // Initial structure. + tx.execute_batch( " CREATE TABLE [Version] ( [id] INTEGER PRIMARY KEY, - [version] INTEGER NOT NULL, + [version] INTEGER NOT NULL UNIQUE, [datetime] INTEGER DATETIME - ) - ", - rusqlite::NO_PARAMS - ); - con.execute( - " + ); + CREATE TABLE [Recipe] ( [id] INTEGER PRIMARY KEY, [title] INTEGER NOT NULL, [description] INTEGER DATETIME - ) + ); + " + )?; + + /* + tx.execute( + " + INSERT INTO Version ", rusqlite::NO_PARAMS - ); - () + );*/ + + Ok(true) } + + // Current version. + 1 => + Ok(false), + v => - panic!("Unsupported database version: {}", v) - }; + Err(DbError::UnsupportedVersion(v)), + } } pub fn get_all_recipes() {