search database has to be a file, as in-memory dbs are per connection
Some checks failed
Build Multiarch Container Image / call-reusable-workflow (push) Has been cancelled

This commit is contained in:
Sebastian Hugentobler 2024-06-26 16:14:58 +02:00
parent 97cf9db9ff
commit b8ed5b1cdf
Signed by: shu
GPG key ID: BB32CF3CA052C2F0
7 changed files with 72 additions and 7 deletions

View file

@ -12,5 +12,6 @@ r2d2 = "0.8.10"
r2d2_sqlite = "0.24.0"
rusqlite = { version = "0.31.0", features = ["bundled", "time"] }
serde = { workspace = true }
tempfile = "3.10.1"
thiserror = { workspace = true }
time = { workspace = true }

View file

@ -1,5 +1,8 @@
//! Error handling for calibre database access.
use std::io;
use tempfile::PersistError;
use thiserror::Error;
use time::error::Parse;
@ -16,9 +19,15 @@ pub enum DataStoreError {
/// Error connecting to the database.
#[error("connection error")]
ConnectionError(#[from] r2d2::Error),
/// Error wparsing a datetime from the database.
/// Error parsing a datetime from the database.
#[error("failed to parse datetime")]
DateTimeError(#[from] Parse),
/// Error creating the search database.
#[error("failed to create search database")]
SearchDbError(#[from] io::Error),
/// Error marking the search database as persistent.
#[error("failed to persist search database")]
PersistSearchDbError(#[from] PersistError),
}
/// Convert an SQLite error into a proper NoResults one if the query

View file

@ -1,13 +1,14 @@
//! Provide search funcitonality for calibre.
//!
//! Because the calibre database can not be disturbed (it is treated as read-only)
//! it attaches an in-memory database and inserts the relevant data into a
//! it attaches a temporary database and inserts the relevant data into a
//! virtual table leveraging fts5 (https://www.sqlite.org/fts5.html). Full-text search is run on
//! that virtual table.
use r2d2::{Pool, PooledConnection};
use r2d2_sqlite::SqliteConnectionManager;
use rusqlite::named_params;
use tempfile::NamedTempFile;
use crate::data::{book::Book, error::DataStoreError};
@ -31,11 +32,16 @@ const SEARCH_INIT_QUERY: &str = "INSERT INTO search.fts(book_id, data)
LEFT JOIN main.series AS s ON b2s.series = s.id
GROUP BY b.id";
/// Attach the fts in-memory database to the read-only calibre database.
/// Attach the fts temporary database to the read-only calibre database.
pub(crate) fn attach(pool: &Pool<SqliteConnectionManager>) -> Result<(), DataStoreError> {
let conn = pool.get()?;
let tmpfile = NamedTempFile::new()?;
let (_, path) = tmpfile.keep()?;
conn.execute("ATTACH DATABASE ':memory:' AS search", [])?;
conn.execute(
&format!("ATTACH DATABASE '{}' AS search", path.to_string_lossy()),
[],
)?;
init(&conn)?;
Ok(())