From 3f5d790d3cf5fdf2300cc6f6855e45b1155ff843 Mon Sep 17 00:00:00 2001 From: Martin Brodbeck Date: Sat, 30 Jan 2021 17:34:01 +0100 Subject: [PATCH 1/5] Bumbling SQL query improved. --- src/main.rs | 52 ++++++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7ac6f4b..b4f354a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,7 +60,6 @@ fn get_attribute_file_as(opf: ZipFile) -> Option { }) if name.local_name == "creator" => { for attr in attributes { if attr.name.local_name == "file-as" { - println!("File-as: {}", &attr.value); return Some(attr.value); } if is_epub3 && attr.name.local_name == "id" { @@ -120,40 +119,33 @@ fn main() { { // Get book ids from entries where we have something like "firstname lastname" in author // but no "lastname, firstname" in fistauthor - let mut stmt = tx.prepare("SELECT id FROM books_impl WHERE ext LIKE 'epub' AND author LIKE '% %' AND (firstauthor NOT LIKE '%\\,%' ESCAPE '\\' OR firstauthor LIKE '%&%')").unwrap(); - let mut rows = stmt.query(NO_PARAMS).unwrap(); - let mut book_ids: Vec = Vec::new(); - while let Some(row) = rows.next().unwrap() { - book_ids.push(row.get(0).unwrap()); - } - // Get also book ids from the special case where we have multiple authors (separated by ", " in authors) // but no ampersand ("&") in firstauthor - let mut stmt = tx.prepare("SELECT id FROM books_impl WHERE ext LIKE 'epub' AND author LIKE '%\\, %' ESCAPE '\\' AND firstauthor NOT LIKE '%&%'").unwrap(); + let mut stmt = tx.prepare(r" + SELECT files.book_id, folders.name, files.filename + FROM files INNER JOIN folders + ON files.folder_id = folders.id + WHERE files.book_id IN + ( + SELECT DISTINCT id FROM books_impl + WHERE (ext LIKE 'epub' AND author LIKE '% %' AND (firstauthor NOT LIKE '%\,%' ESCAPE '\' OR firstauthor LIKE '%&%')) + OR (ext LIKE 'epub' AND author LIKE '%\, %' ESCAPE '\' AND firstauthor NOT LIKE '%&%') + ) + AND files.storageid = 1 + ;").unwrap(); + let mut rows = stmt.query(NO_PARAMS).unwrap(); - while let Some(row) = rows.next().unwrap() { - book_ids.push(row.get(0).unwrap()); - } - - book_ids.sort(); - book_ids.dedup(); - let mut bookentries = Vec::new(); - for book_id in book_ids { - let mut stmt = tx.prepare("SELECT folders.name,files.filename FROM files,folders WHERE files.book_id = :book_id AND files.storageid = 1 AND files.folder_id = folders.id").unwrap(); - let mut rows = stmt - .query_named(named_params! { ":book_id": book_id }) - .unwrap(); - while let Some(row) = rows.next().unwrap() { - let prefix: String = row.get(0).unwrap(); - let filename: String = row.get(1).unwrap(); - let filepath = format!("{}/{}", prefix, filename); - bookentries.push(BookEntry { - id: book_id, - filepath: filepath, - }); - } + while let Some(row) = rows.next().unwrap() { + let book_id: i32 = row.get(0).unwrap(); + let prefix: String = row.get(1).unwrap(); + let filename: String = row.get(2).unwrap(); + let filepath = format!("{}/{}", prefix, filename); + bookentries.push(BookEntry { + id: book_id, + filepath, + }); } for entry in bookentries { From a9ef4d2aef2217fd4e73242f03f1ac6109502f57 Mon Sep 17 00:00:00 2001 From: Martin Brodbeck Date: Sat, 30 Jan 2021 17:59:00 +0100 Subject: [PATCH 2/5] Code reorganized. --- src/main.rs | 85 ++++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/src/main.rs b/src/main.rs index b4f354a..8273e8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ mod pocketbook; -use rusqlite::{named_params, Connection, Result, NO_PARAMS}; +use rusqlite::{named_params, Connection, Result, Transaction, NO_PARAMS}; use std::error::Error; use std::fs::File; use std::io::BufReader; @@ -111,17 +111,14 @@ struct BookEntry { filepath: String, } -fn main() { +fn fix_firstauthor(tx: &Transaction) -> i32 { let mut authors_fixed = 0; - let mut conn = Connection::open("/mnt/ext1/system/explorer-3/explorer-3.db").unwrap(); - let tx = conn.transaction().unwrap(); - { - // Get book ids from entries where we have something like "firstname lastname" in author - // but no "lastname, firstname" in fistauthor - // Get also book ids from the special case where we have multiple authors (separated by ", " in authors) - // but no ampersand ("&") in firstauthor - let mut stmt = tx.prepare(r" + // Get book ids from entries where we have something like "firstname lastname" in author + // but no "lastname, firstname" in fistauthor + // Get also book ids from the special case where we have multiple authors (separated by ", " in authors) + // but no ampersand ("&") in firstauthor + let mut stmt = tx.prepare(r" SELECT files.book_id, folders.name, files.filename FROM files INNER JOIN folders ON files.folder_id = folders.id @@ -134,44 +131,52 @@ fn main() { AND files.storageid = 1 ;").unwrap(); - let mut rows = stmt.query(NO_PARAMS).unwrap(); - let mut bookentries = Vec::new(); + let mut rows = stmt.query(NO_PARAMS).unwrap(); + let mut bookentries = Vec::new(); - while let Some(row) = rows.next().unwrap() { - let book_id: i32 = row.get(0).unwrap(); - let prefix: String = row.get(1).unwrap(); - let filename: String = row.get(2).unwrap(); - let filepath = format!("{}/{}", prefix, filename); - bookentries.push(BookEntry { - id: book_id, - filepath, - }); - } + while let Some(row) = rows.next().unwrap() { + let book_id: i32 = row.get(0).unwrap(); + let prefix: String = row.get(1).unwrap(); + let filename: String = row.get(2).unwrap(); + let filepath = format!("{}/{}", prefix, filename); + bookentries.push(BookEntry { + id: book_id, + filepath, + }); + } - for entry in bookentries { - let file = File::open(entry.filepath.as_str()); - let file = match file { - Err(_) => continue, - Ok(file) => file, - }; + for entry in bookentries { + let file = File::open(entry.filepath.as_str()); + let file = match file { + Err(_) => continue, + Ok(file) => file, + }; - let mut archive = ZipArchive::new(BufReader::new(file)).unwrap(); + let mut archive = ZipArchive::new(BufReader::new(file)).unwrap(); - let container = archive.by_name("META-INF/container.xml").unwrap(); + let container = archive.by_name("META-INF/container.xml").unwrap(); - if let Some(opf_file) = get_root_file(container).unwrap() { - let opf = archive.by_name(opf_file.as_str()).unwrap(); - if let Some(file_as) = get_attribute_file_as(opf) { - let mut stmt = tx - .prepare("UPDATE books_impl SET firstauthor = :file_as WHERE id = :book_id") - .unwrap(); - stmt.execute_named(named_params![":file_as": file_as, ":book_id": entry.id]) - .unwrap(); - authors_fixed = authors_fixed + 1; - } + if let Some(opf_file) = get_root_file(container).unwrap() { + let opf = archive.by_name(opf_file.as_str()).unwrap(); + if let Some(file_as) = get_attribute_file_as(opf) { + let mut stmt = tx + .prepare("UPDATE books_impl SET firstauthor = :file_as WHERE id = :book_id") + .unwrap(); + stmt.execute_named(named_params![":file_as": file_as, ":book_id": entry.id]) + .unwrap(); + authors_fixed = authors_fixed + 1; } } } + + authors_fixed +} + +fn main() { + let mut conn = Connection::open("/mnt/ext1/system/explorer-3/explorer-3.db").unwrap(); + + let tx = conn.transaction().unwrap(); + let authors_fixed = fix_firstauthor(&tx); tx.commit().unwrap(); if cfg!(target_arch = "arm") { From 3497c1c9b21dc5f52cbf35c4e10be97548d53e5e Mon Sep 17 00:00:00 2001 From: Martin Brodbeck Date: Sat, 30 Jan 2021 17:59:52 +0100 Subject: [PATCH 3/5] Push to v0.2.0. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2f59c6a..7fef784 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pbdbfixer" -version = "0.1.0" +version = "0.2.0" authors = ["Martin Brodbeck "] edition = "2018" From e46f6eb8875f9cb40225e58df238e745ac879c6a Mon Sep 17 00:00:00 2001 From: Martin Brodbeck Date: Sat, 30 Jan 2021 18:11:11 +0100 Subject: [PATCH 4/5] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 34c14c1..cc9d175 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ applications screen and tap on the PbDbFixer icon. To be able to build PbDbFixer, you have to have the cross compiler for ARM CPUs installed. On Arch Linux, the AUR package `arm-linux-gnueabi-gcc75-linaro-bin` does the job. Don't forget to tell `cargo` which compiler/linker it has to -invoke. In my case, I hat to edit `~/.cargo/config`: +invoke. In my case, I had to edit `~/.cargo/config`: ``` [target.arm-unknown-linux-gnueabi] linker = "arm-linux-gnueabi-gcc" From 854c5633ea9e332c77a6496dc9d4471b8dc0526e Mon Sep 17 00:00:00 2001 From: Martin Brodbeck Date: Sat, 30 Jan 2021 18:11:39 +0100 Subject: [PATCH 5/5] Push to v0.2.0. --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 7a1cb7b..fd7ac1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,7 +148,7 @@ dependencies = [ [[package]] name = "pbdbfixer" -version = "0.1.0" +version = "0.2.0" dependencies = [ "rusqlite", "xml-rs",