Compare commits

...

5 commits

Author SHA1 Message Date
854c5633ea Push to v0.2.0. 2021-01-30 18:11:39 +01:00
e46f6eb887 typo 2021-01-30 18:11:11 +01:00
3497c1c9b2 Push to v0.2.0. 2021-01-30 17:59:52 +01:00
a9ef4d2aef Code reorganized. 2021-01-30 17:59:00 +01:00
3f5d790d3c Bumbling SQL query improved. 2021-01-30 17:34:01 +01:00
4 changed files with 59 additions and 62 deletions

2
Cargo.lock generated
View file

@ -148,7 +148,7 @@ dependencies = [
[[package]] [[package]]
name = "pbdbfixer" name = "pbdbfixer"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"rusqlite", "rusqlite",
"xml-rs", "xml-rs",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "pbdbfixer" name = "pbdbfixer"
version = "0.1.0" version = "0.2.0"
authors = ["Martin Brodbeck <martin@brodbeck-online.de>"] authors = ["Martin Brodbeck <martin@brodbeck-online.de>"]
edition = "2018" edition = "2018"

View file

@ -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 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` 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 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] [target.arm-unknown-linux-gnueabi]
linker = "arm-linux-gnueabi-gcc" linker = "arm-linux-gnueabi-gcc"

View file

@ -1,6 +1,6 @@
mod pocketbook; 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::error::Error;
use std::fs::File; use std::fs::File;
use std::io::BufReader; use std::io::BufReader;
@ -60,7 +60,6 @@ fn get_attribute_file_as(opf: ZipFile) -> Option<String> {
}) if name.local_name == "creator" => { }) if name.local_name == "creator" => {
for attr in attributes { for attr in attributes {
if attr.name.local_name == "file-as" { if attr.name.local_name == "file-as" {
println!("File-as: {}", &attr.value);
return Some(attr.value); return Some(attr.value);
} }
if is_epub3 && attr.name.local_name == "id" { if is_epub3 && attr.name.local_name == "id" {
@ -112,74 +111,72 @@ struct BookEntry {
filepath: String, filepath: String,
} }
fn main() { fn fix_firstauthor(tx: &Transaction) -> i32 {
let mut authors_fixed = 0; let mut authors_fixed = 0;
let mut conn = Connection::open("/mnt/ext1/system/explorer-3/explorer-3.db").unwrap(); // Get book ids from entries where we have something like "firstname lastname" in author
let tx = conn.transaction().unwrap(); // but no "lastname, firstname" in fistauthor
{ // Get also book ids from the special case where we have multiple authors (separated by ", " in authors)
// Get book ids from entries where we have something like "firstname lastname" in author // but no ampersand ("&") in firstauthor
// but no "lastname, firstname" in fistauthor let mut stmt = tx.prepare(r"
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 '%&amp;%')").unwrap(); SELECT files.book_id, folders.name, files.filename
let mut rows = stmt.query(NO_PARAMS).unwrap(); FROM files INNER JOIN folders
let mut book_ids: Vec<i32> = Vec::new(); ON files.folder_id = folders.id
while let Some(row) = rows.next().unwrap() { WHERE files.book_id IN
book_ids.push(row.get(0).unwrap()); (
} SELECT DISTINCT id FROM books_impl
WHERE (ext LIKE 'epub' AND author LIKE '% %' AND (firstauthor NOT LIKE '%\,%' ESCAPE '\' OR firstauthor LIKE '%&amp;%'))
OR (ext LIKE 'epub' AND author LIKE '%\, %' ESCAPE '\' AND firstauthor NOT LIKE '%&%')
)
AND files.storageid = 1
;").unwrap();
// Get also book ids from the special case where we have multiple authors (separated by ", " in authors) let mut rows = stmt.query(NO_PARAMS).unwrap();
// but no ampersand ("&") in firstauthor let mut bookentries = Vec::new();
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 rows = stmt.query(NO_PARAMS).unwrap();
while let Some(row) = rows.next().unwrap() {
book_ids.push(row.get(0).unwrap());
}
book_ids.sort(); while let Some(row) = rows.next().unwrap() {
book_ids.dedup(); 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,
});
}
let mut bookentries = Vec::new(); for entry in bookentries {
let file = File::open(entry.filepath.as_str());
let file = match file {
Err(_) => continue,
Ok(file) => file,
};
for book_id in book_ids { let mut archive = ZipArchive::new(BufReader::new(file)).unwrap();
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,
});
}
}
for entry in bookentries { let container = archive.by_name("META-INF/container.xml").unwrap();
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(); if let Some(opf_file) = get_root_file(container).unwrap() {
let opf = archive.by_name(opf_file.as_str()).unwrap();
let container = archive.by_name("META-INF/container.xml").unwrap(); if let Some(file_as) = get_attribute_file_as(opf) {
let mut stmt = tx
if let Some(opf_file) = get_root_file(container).unwrap() { .prepare("UPDATE books_impl SET firstauthor = :file_as WHERE id = :book_id")
let opf = archive.by_name(opf_file.as_str()).unwrap(); .unwrap();
if let Some(file_as) = get_attribute_file_as(opf) { stmt.execute_named(named_params![":file_as": file_as, ":book_id": entry.id])
let mut stmt = tx .unwrap();
.prepare("UPDATE books_impl SET firstauthor = :file_as WHERE id = :book_id") authors_fixed = authors_fixed + 1;
.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(); tx.commit().unwrap();
if cfg!(target_arch = "arm") { if cfg!(target_arch = "arm") {