Add an error management in db module
This commit is contained in:
parent
e2e54b8f43
commit
a080d19cb9
6 changed files with 387 additions and 280 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -5,3 +5,4 @@ backend/data/recipes.sqlite-journal
|
||||||
/deploy-to-pi.ps1
|
/deploy-to-pi.ps1
|
||||||
style.css.map
|
style.css.map
|
||||||
backend/static/style.css
|
backend/static/style.css
|
||||||
|
backend/file.db
|
||||||
|
|
|
||||||
555
Cargo.lock
generated
555
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
2
TODO.md
2
TODO.md
|
|
@ -3,6 +3,6 @@
|
||||||
* Implement the model as relational with SQLite.
|
* Implement the model as relational with SQLite.
|
||||||
* Create and update functions.
|
* Create and update functions.
|
||||||
* Define the UI (mockups).
|
* Define the UI (mockups).
|
||||||
* Use Bulma to implement the UI in HTML5+CSS3.
|
* Two CSS: one for desktop and one for mobile
|
||||||
* Define the logic behind each page and action.
|
* Define the logic behind each page and action.
|
||||||
* Try using WASM for all the client logic
|
* Try using WASM for all the client logic
|
||||||
|
|
@ -10,10 +10,10 @@ actix-rt = "1"
|
||||||
actix-files = "0.2"
|
actix-files = "0.2"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
listenfd = "0.3" # To watch file modifications and automatically launch a build process (only used in dev/debug).
|
listenfd = "0.3" # To watch file modifications and automatically launch a build process (only used in dev/debug).
|
||||||
ron = "0.5" # Rust object notation, to load configuration files.
|
ron = "0.6" # Rust object notation, to load configuration files.
|
||||||
itertools = "0.9"
|
itertools = "0.9"
|
||||||
|
|
||||||
r2d2_sqlite = "0.15" # Connection pool with rusqlite (SQLite access).
|
r2d2_sqlite = "0.16" # Connection pool with rusqlite (SQLite access).
|
||||||
r2d2 = "0.8"
|
r2d2 = "0.8"
|
||||||
|
|
||||||
futures = "0.3" # Needed by askam with the feature 'with-actix-web'.
|
futures = "0.3" # Needed by askam with the feature 'with-actix-web'.
|
||||||
|
|
@ -21,11 +21,10 @@ futures = "0.3" # Needed by askam with the feature 'with-actix-web'.
|
||||||
common = { path = "../common" }
|
common = { path = "../common" }
|
||||||
|
|
||||||
[dependencies.rusqlite]
|
[dependencies.rusqlite]
|
||||||
version = "0.22"
|
version = "0.23"
|
||||||
features = ["bundled"]
|
features = ["bundled"]
|
||||||
|
|
||||||
# Template system.
|
# Template system.
|
||||||
[dependencies.askama]
|
[dependencies.askama]
|
||||||
version = "0.9"
|
version = "0.9"
|
||||||
features = ["with-actix-web"]
|
features = ["with-actix-web"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,12 @@ use std::fs;
|
||||||
use r2d2_sqlite::SqliteConnectionManager;
|
use r2d2_sqlite::SqliteConnectionManager;
|
||||||
use r2d2::Pool;
|
use r2d2::Pool;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DbError {
|
||||||
|
SqliteError(rusqlite::Error),
|
||||||
|
R2d2Error(r2d2::Error),
|
||||||
|
UnsupportedVersion(i32),
|
||||||
|
}
|
||||||
|
|
||||||
use super::consts;
|
use super::consts;
|
||||||
|
|
||||||
|
|
@ -26,8 +32,20 @@ pub struct Recipe {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::convert::From<rusqlite::Error> for DbError {
|
||||||
|
fn from(error: rusqlite::Error) -> Self {
|
||||||
|
DbError::SqliteError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::convert::From<r2d2::Error> for DbError {
|
||||||
|
fn from(error: r2d2::Error) -> Self {
|
||||||
|
DbError::R2d2Error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Connection {
|
impl Connection {
|
||||||
pub fn new() -> Connection {
|
pub fn new() -> Result<Connection, DbError> {
|
||||||
|
|
||||||
let data_dir = Path::new(consts::DB_DIRECTORY);
|
let data_dir = Path::new(consts::DB_DIRECTORY);
|
||||||
|
|
||||||
|
|
@ -39,59 +57,83 @@ impl Connection {
|
||||||
let pool = r2d2::Pool::new(manager).unwrap();
|
let pool = r2d2::Pool::new(manager).unwrap();
|
||||||
|
|
||||||
let connection = Connection { pool };
|
let connection = Connection { pool };
|
||||||
connection.create_or_update();
|
connection.create_or_update()?;
|
||||||
connection
|
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 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 * 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.
|
// Check the Database version.
|
||||||
let con = self.pool.get().unwrap();
|
let mut con = self.pool.get()?;
|
||||||
|
let tx = con.transaction()?;
|
||||||
|
|
||||||
let version = {
|
let mut version = {
|
||||||
match
|
match tx.query_row(
|
||||||
con.query_row(
|
|
||||||
"SELECT [name] FROM [sqlite_master] WHERE [type] = 'table' AND [name] = 'Version'",
|
"SELECT [name] FROM [sqlite_master] WHERE [type] = 'table' AND [name] = 'Version'",
|
||||||
rusqlite::NO_PARAMS,
|
rusqlite::NO_PARAMS,
|
||||||
|row| row.get::<usize, String>(0)
|
|row| row.get::<usize, String>(0)
|
||||||
) {
|
) {
|
||||||
|
Ok(_) => tx.query_row("SELECT [version] FROM [Version]", rusqlite::NO_PARAMS, |row| row.get(0)).unwrap_or_default(),
|
||||||
Ok(_) => con.query_row("SELECT [version] FROM [Version]", rusqlite::NO_PARAMS, |row| row.get(0)).unwrap_or_default(),
|
|
||||||
Err(_) => 0
|
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<bool, DbError> {
|
||||||
match version {
|
match version {
|
||||||
0 => {
|
0 => {
|
||||||
println!("Update to version 1...");
|
println!("Update to version 1...");
|
||||||
con.execute(
|
|
||||||
|
// Initial structure.
|
||||||
|
tx.execute_batch(
|
||||||
"
|
"
|
||||||
CREATE TABLE [Version] (
|
CREATE TABLE [Version] (
|
||||||
[id] INTEGER PRIMARY KEY,
|
[id] INTEGER PRIMARY KEY,
|
||||||
[version] INTEGER NOT NULL,
|
[version] INTEGER NOT NULL UNIQUE,
|
||||||
[datetime] INTEGER DATETIME
|
[datetime] INTEGER DATETIME
|
||||||
)
|
);
|
||||||
",
|
|
||||||
rusqlite::NO_PARAMS
|
|
||||||
);
|
|
||||||
con.execute(
|
|
||||||
"
|
|
||||||
CREATE TABLE [Recipe] (
|
CREATE TABLE [Recipe] (
|
||||||
[id] INTEGER PRIMARY KEY,
|
[id] INTEGER PRIMARY KEY,
|
||||||
[title] INTEGER NOT NULL,
|
[title] INTEGER NOT NULL,
|
||||||
[description] INTEGER DATETIME
|
[description] INTEGER DATETIME
|
||||||
)
|
);
|
||||||
|
"
|
||||||
|
)?;
|
||||||
|
|
||||||
|
/*
|
||||||
|
tx.execute(
|
||||||
|
"
|
||||||
|
INSERT INTO Version
|
||||||
",
|
",
|
||||||
rusqlite::NO_PARAMS
|
rusqlite::NO_PARAMS
|
||||||
);
|
);*/
|
||||||
()
|
|
||||||
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Current version.
|
||||||
|
1 =>
|
||||||
|
Ok(false),
|
||||||
|
|
||||||
v =>
|
v =>
|
||||||
panic!("Unsupported database version: {}", v)
|
Err(DbError::UnsupportedVersion(v)),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_recipes() {
|
pub fn get_all_recipes() {
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ async fn home_page(req: HttpRequest) -> impl Responder {
|
||||||
|
|
||||||
#[get("/recipe/view/{id}")]
|
#[get("/recipe/view/{id}")]
|
||||||
async fn view_page(req: HttpRequest, path: web::Path<(i32,)>) -> impl Responder {
|
async fn view_page(req: HttpRequest, path: web::Path<(i32,)>) -> impl Responder {
|
||||||
panic!("ERROR");
|
|
||||||
ViewRecipeTemplate { recipes: vec![ db::Recipe { title: String::from("Saumon en croûte feuilletée"), id: 1 }, db::Recipe { title: String::from("Croissant au jambon"), id: 2 } ], current_recipe: db::Recipe { title: String::from("Saumon en croûte feuilletée"), id: 1 } }
|
ViewRecipeTemplate { recipes: vec![ db::Recipe { title: String::from("Saumon en croûte feuilletée"), id: 1 }, db::Recipe { title: String::from("Croissant au jambon"), id: 2 } ], current_recipe: db::Recipe { title: String::from("Saumon en croûte feuilletée"), id: 1 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,7 +107,10 @@ fn process_args() -> bool {
|
||||||
print_usage();
|
print_usage();
|
||||||
return true
|
return true
|
||||||
} else if args.iter().any(|arg| arg == "--test") {
|
} else if args.iter().any(|arg| arg == "--test") {
|
||||||
let db_connection = db::Connection::new();
|
match db::Connection::new() {
|
||||||
|
Ok(_) => (),
|
||||||
|
Err(error) => println!("Error: {:?}", error)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue