Modify Sheet struct, add OrphanFile table and db

This commit is contained in:
2024-02-07 18:40:39 +01:00
parent 7120520347
commit b102906f11
7 changed files with 176 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
use log::debug;
use sqlx::{migrate::MigrateDatabase, Sqlite, SqlitePool};
use crate::sheet::Sheet;
use crate::sheet::{OrphanFile, Sheet};
pub struct Database {
connection: SqlitePool,
@@ -36,14 +36,16 @@ impl Database {
pub async fn _insert_sheet(&self, sheet: Sheet) -> sqlx::Result<()> {
sqlx::query(
"
INSERT INTO sheets (name, path, file_size, file_hash)
VALUES ($1, $2, $3, $4)
INSERT INTO sheets (name, composer_id, path, file_size, file_hash, last_modified)
VALUES ($1, $2, $3, $4, $5, $6)
",
)
.bind(sheet.name)
.bind(sheet.path)
.bind(sheet.file_size)
.bind(sheet.composer_id)
.bind(sheet.path.to_str().unwrap().to_string())
.bind(sheet.file_size as i32)
.bind(sheet.file_hash)
.bind(sheet.last_opened.timestamp())
.execute(&self.connection)
.await
.map(|_| ())
@@ -51,7 +53,7 @@ impl Database {
pub async fn update_sheet_path(&self, sheet: &Sheet) -> sqlx::Result<()> {
sqlx::query("UPDATE sheets SET path = $1 WHERE id = $2")
.bind(sheet.path.clone())
.bind(sheet.path.to_str().unwrap().to_string())
.bind(sheet.id)
.execute(&self.connection)
.await
@@ -63,4 +65,35 @@ impl Database {
.fetch_all(&self.connection)
.await
}
pub async fn insert_orphan_file(&self, file: OrphanFile) -> sqlx::Result<()> {
sqlx::query(
"
INSERT INTO orphan_files (path, file_size, file_hash, last_modified)
VALUES ($1, $2, $3, $4)
",
)
.bind(file.path.to_str().unwrap().to_string())
.bind(file.file_size as i32)
.bind(file.file_hash)
.bind(file.last_opened.timestamp())
.execute(&self.connection)
.await
.map(|_| ())
}
pub async fn update_orphan_file_path(&self, file: &OrphanFile) -> sqlx::Result<()> {
sqlx::query("UPDATE orphan_files SET path = $1 WHERE id = $2")
.bind(file.path.to_str().unwrap().to_string())
.bind(file.id)
.execute(&self.connection)
.await
.map(|_| ())
}
pub async fn fetch_all_orphan_files(&self) -> sqlx::Result<Vec<OrphanFile>> {
sqlx::query_as::<_, OrphanFile>("SELECT * FROM orphan_files")
.fetch_all(&self.connection)
.await
}
}

View File

@@ -87,7 +87,7 @@ fn validate_sheet_files(sheets: Vec<Sheet>, dir: impl AsRef<Path>) -> FileValida
.find(|(_, sheet)| sheet.validate_path(&pdf_file).unwrap_or(false))
{
let mut sheet = invalidated_sheets.remove(i);
sheet.path = pdf_file.to_str().unwrap().to_string();
sheet.path = pdf_file;
updated_sheets.push(sheet);
} else {
unassigned_files.push(pdf_file);

View File

@@ -1,14 +1,40 @@
use std::{fs, path::Path};
use std::{
fs,
path::{Path, PathBuf},
};
#[derive(sqlx::FromRow, Debug, Clone)]
use sqlx::{prelude::*, sqlite::SqliteRow};
// use sqlx::{FromRow, sqlite::SqliteRow, sqlx::Row};
use chrono::{DateTime, NaiveDateTime, Utc};
#[derive(Debug, Clone)]
pub struct Sheet {
pub id: i32,
pub name: String,
// #[sqlx(from = "String")]
pub path: String,
// #[sqlx(from = "i64")]
pub file_size: i32,
pub composer_id: i32,
pub path: PathBuf,
pub file_size: u64,
pub file_hash: String,
pub last_opened: DateTime<Utc>,
}
impl FromRow<'_, SqliteRow> for Sheet {
fn from_row(row: &SqliteRow) -> sqlx::Result<Self> {
Ok(Self {
id: row.try_get("id")?,
name: row.try_get("name")?,
composer_id: row.try_get("composer_id")?,
path: row.try_get::<&str, _>("path")?.into(),
file_size: row.try_get::<i32, _>("file_size")? as u64,
file_hash: row.try_get("file_hash")?,
last_opened: NaiveDateTime::from_timestamp_opt(
row.try_get::<i64, _>("last_opened")?,
0,
)
.unwrap()
.and_utc(),
})
}
}
#[derive(sqlx::FromRow)]
@@ -21,7 +47,7 @@ impl Sheet {
pub fn validate_path(&self, path: impl AsRef<Path>) -> std::io::Result<bool> {
// First compare file size since it is faster than hashing
let file_size = fs::metadata(path.as_ref())?.len();
if file_size as i32 == self.file_size {
if file_size == self.file_size {
let file_content = fs::read(path.as_ref())?;
let file_hash = blake3::hash(&file_content);
if file_hash.to_string() == self.file_hash {
@@ -32,3 +58,29 @@ impl Sheet {
Ok(false)
}
}
#[derive(Debug, Clone)]
pub struct OrphanFile {
pub id: i32,
pub path: PathBuf,
pub file_size: u64,
pub file_hash: String,
pub last_opened: DateTime<Utc>,
}
impl FromRow<'_, SqliteRow> for OrphanFile {
fn from_row(row: &SqliteRow) -> sqlx::Result<Self> {
Ok(Self {
id: row.try_get("id")?,
path: row.try_get::<&str, _>("path")?.into(),
file_size: row.try_get::<i32, _>("file_size")? as u64,
file_hash: row.try_get("file_hash")?,
last_opened: NaiveDateTime::from_timestamp_opt(
row.try_get::<i64, _>("last_opened")?,
0,
)
.unwrap()
.and_utc(),
})
}
}

View File

@@ -1,4 +1,4 @@
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use gtk::prelude::*;
use relm4::prelude::*;
@@ -14,10 +14,10 @@ pub enum SheetModelType {
}
impl SheetModelType {
pub fn get_path(&self) -> &str {
pub fn get_path(&self) -> &Path {
match self {
SheetModelType::Sheet { sheet } => &sheet.path,
SheetModelType::Pdf { path } => path.to_str().unwrap(),
SheetModelType::Sheet { sheet } => &sheet.path.as_path(),
SheetModelType::Pdf { path } => path.as_path(),
}
}
}
@@ -64,9 +64,7 @@ impl FactoryComponent for SheetModel {
fn init_model(value: Self::Init, _index: &DynamicIndex, _sender: FactorySender<Self>) -> Self {
let label = match &value {
SheetModelType::Sheet { sheet } => sheet.name.to_string(),
SheetModelType::Pdf { path } => {
path.file_name().unwrap().to_str().unwrap().to_string()
}
SheetModelType::Pdf { path } => path.file_name().unwrap().to_str().unwrap().to_string(),
};
SheetModel {