pub struct Db {
pool: SqlitePool,
}Fields§
§pool: SqlitePoolImplementations§
Source§impl Db
impl Db
pub fn new(database: &Database) -> Self
pub fn register_library(&self, path: &str, name: &str) -> Result<i64, Error>
pub fn get_library_by_path(&self, path: &str) -> Result<Option<i64>, Error>
fn parse_zoom_mode(json: Option<&String>) -> Option<ZoomMode>
fn parse_scroll_mode(json: Option<&String>) -> Option<ScrollMode>
fn parse_text_align(json: Option<&String>) -> Option<TextAlign>
fn parse_cropping_margins(json: Option<&String>) -> Option<CroppingMargins>
fn parse_page_names(json: Option<&String>) -> BTreeMap<usize, String>
fn parse_bookmarks(json: Option<&String>) -> BTreeSet<usize>
fn parse_annotations(json: Option<&String>) -> Vec<Annotation>
fn parse_page_offset(x: Option<i64>, y: Option<i64>) -> Option<Point>
fn extract_categories(categories: Option<String>) -> BTreeSet<String>
async fn fetch_toc_entries_for_book( pool: &SqlitePool, library_id: i64, fingerprint: &str, ) -> Result<Vec<TocEntryRow>, Error>
fn stored_book_row_to_info( row: StoredBookRow, toc: Option<Vec<SimpleTocEntry>>, ) -> Result<Info, Error>
async fn insert_toc_entries( conn: &mut SqliteConnection, book_fingerprint: &str, entries: &[SimpleTocEntry], parent_id: Option<Uuid7>, ) -> Result<(), Error>
async fn fetch_all_toc_entries( pool: &SqlitePool, library_id: i64, ) -> Result<HashMap<String, Vec<TocEntryRow>>, Error>
pub fn get_all_books(&self, library_id: i64) -> Result<Vec<Info>, Error>
pub fn get_book_by_path( &self, library_id: i64, path: &Path, ) -> Result<Option<Info>, Error>
pub fn get_book_by_fingerprint( &self, library_id: i64, fp: Fp, ) -> Result<Option<Info>, Error>
Sourcepub fn batch_get_books_by_fingerprints(
&self,
library_id: i64,
fps: &[Fp],
) -> Result<FxHashMap<Fp, Info>, Error>
pub fn batch_get_books_by_fingerprints( &self, library_id: i64, fps: &[Fp], ) -> Result<FxHashMap<Fp, Info>, Error>
Fetches complete Info for multiple fingerprints in a single library using one
pooled connection. Missing fingerprints are silently skipped.
Used by import() to retrieve book metadata (title, authors, reading state, etc.)
for all fingerprint relocations in one batch, before re-inserting under new FPs.
pub fn count_books(&self, library_id: i64) -> Result<usize, Error>
pub fn list_books_under_prefix( &self, library_id: i64, prefix: &Path, ) -> Result<Vec<Info>, Error>
pub fn most_recently_opened_reading_book( &self, library_id: i64, ) -> Result<Option<Info>, Error>
Sourcepub fn compute_sort_keys(&self, library_id: i64) -> Result<(), Error>
pub fn compute_sort_keys(&self, library_id: i64) -> Result<(), Error>
Recomputes sort ranks for all books in a library and writes them to the
five pre-computed sort columns (sort_title, sort_author,
sort_filepath, sort_filename, sort_series).
§Sparse rank scheme
Ranks are stored as multiples of 1000 rather than consecutive
integers (1 → 1 000, 2 → 2 000, …). The gaps allow a single newly
added book to be inserted cheaply via Self::insert_sort_rank:
instead of shifting every book above the insertion point, the new book
is assigned the midpoint between its two neighbours — a single UPDATE.
A full recompute is only needed after bulk changes (i.e. after
import()). It also restores uniform gaps whenever they have been
partially exhausted by many consecutive single-book insertions.
Sourcepub fn insert_sort_rank(
&self,
library_id: i64,
fp: Fp,
info: &Info,
) -> Result<(), Error>
pub fn insert_sort_rank( &self, library_id: i64, fp: Fp, info: &Info, ) -> Result<(), Error>
Inserts sort ranks for a single newly-added book without recomputing ranks for the entire library.
§How it works
Because Self::compute_sort_keys stores ranks as multiples of
SORT_RANK_STRIDE (1 000), there is always a gap between adjacent
books. For each sort column this method:
- Fetches only the two lightweight fields needed to compare the new
book’s sort key — e.g.
(book_fingerprint, title, sort_title)for the title column — ordered by the existing rank. No fullInfoload is required. - Binary-searches the sorted list to find the insertion position using
the same comparator as
sorter(method). - Assigns the midpoint between the two neighbouring ranks to the new book (e.g. between rank 3 000 and 4 000 → 3 500).
If any column has exhausted its gaps (two neighbours whose ranks differ
by at most 1), it falls back to a full Self::compute_sort_keys
recompute to restore uniform gaps for that library.
Sourcefn try_insert_sort_rank(
&self,
library_id: i64,
fp_str: &str,
info: &Info,
) -> Result<bool, Error>
fn try_insert_sort_rank( &self, library_id: i64, fp_str: &str, info: &Info, ) -> Result<bool, Error>
Attempts to insert sort ranks for a single book by midpoint assignment.
Returns true if any column has gaps too small to split (i.e. a full
recompute is needed), false if all ranks were assigned successfully.
fn resolve_title_rank( &self, library_id: i64, fp_str: &str, info: &Info, ) -> Result<Option<i64>, Error>
fn resolve_filepath_rank( &self, library_id: i64, fp_str: &str, info: &Info, ) -> Result<Option<i64>, Error>
fn resolve_filename_rank( &self, library_id: i64, fp_str: &str, info: &Info, ) -> Result<Option<i64>, Error>
fn resolve_series_rank( &self, library_id: i64, fp_str: &str, info: &Info, ) -> Result<Option<i64>, Error>
fn fetch_title_sort_rows( &self, library_id: i64, fp_str: &str, ) -> Result<Vec<TitleSortRow>, Error>
fn fetch_filepath_sort_rows( &self, library_id: i64, fp_str: &str, ) -> Result<Vec<FilePathSortRow>, Error>
fn fetch_filename_sort_rows( &self, library_id: i64, fp_str: &str, ) -> Result<Vec<FileNameSortRow>, Error>
fn fetch_series_sort_rows( &self, library_id: i64, fp_str: &str, ) -> Result<Vec<SeriesSortRow>, Error>
Sourcepub fn page_books(
&self,
library_id: i64,
prefix: &Path,
sort_method: SortMethod,
reverse: bool,
limit: i64,
offset: i64,
) -> Result<(Vec<Info>, i64), Error>
pub fn page_books( &self, library_id: i64, prefix: &Path, sort_method: SortMethod, reverse: bool, limit: i64, offset: i64, ) -> Result<(Vec<Info>, i64), Error>
Returns a page of books under prefix, sorted by sort_method, along
with the total number of matching books.
Uses untyped sqlx::query_as so the ORDER BY column can be selected
dynamically.
pub fn list_directories_under_prefix( &self, library_id: i64, prefix: &Path, ) -> Result<BTreeSet<PathBuf>, Error>
pub fn insert_book( &self, library_id: i64, fp: Fp, info: &Info, ) -> Result<(), Error>
Sourcepub fn update_book(
&self,
library_id: i64,
fp: Fp,
info: &Info,
) -> Result<(), Error>
pub fn update_book( &self, library_id: i64, fp: Fp, info: &Info, ) -> Result<(), Error>
Rewrites the stored metadata for one book and its library-specific path fields.
pub fn delete_reading_state(&self, fp: Fp) -> Result<(), Error>
pub fn delete_book(&self, library_id: i64, fp: Fp) -> Result<(), Error>
pub fn get_thumbnail(&self, fp: Fp) -> Result<Option<Vec<u8>>, Error>
pub fn get_thumbnail_by_path( &self, library_id: i64, path: &Path, ) -> Result<Option<Vec<u8>>, Error>
pub fn save_thumbnail(&self, fp: Fp, data: &[u8]) -> Result<(), Error>
pub fn delete_thumbnail(&self, fp: Fp) -> Result<(), Error>
pub fn batch_delete_thumbnails(&self, fps: &[Fp]) -> Result<(), Error>
pub fn move_thumbnail(&self, from_fp: Fp, to_fp: Fp) -> Result<(), Error>
pub fn batch_move_thumbnails(&self, moves: &[(Fp, Fp)]) -> Result<(), Error>
pub fn save_reading_state( &self, fp: Fp, reader_info: &ReaderInfo, ) -> Result<(), Error>
pub fn save_toc(&self, fp: Fp, toc: &[SimpleTocEntry]) -> Result<(), Error>
pub fn batch_insert_books( &self, library_id: i64, books: &[(Fp, &Info)], ) -> Result<(), Error>
pub fn batch_update_books( &self, library_id: i64, books: &[(Fp, &Info)], ) -> Result<(), Error>
Sourcepub fn list_book_handles(
&self,
library_id: i64,
) -> Result<Vec<(Fp, PathBuf)>, Error>
pub fn list_book_handles( &self, library_id: i64, ) -> Result<Vec<(Fp, PathBuf)>, Error>
Returns (fingerprint, path) pairs for every book currently linked to a library.
Sourcepub fn update_book_path(
&self,
library_id: i64,
fp: Fp,
rel_path: &Path,
abs_path: &Path,
) -> Result<(), Error>
pub fn update_book_path( &self, library_id: i64, fp: Fp, rel_path: &Path, abs_path: &Path, ) -> Result<(), Error>
Updates both the relative and absolute path of a book in a single transaction. No-op if the book is not found in the library.
Sourcepub fn batch_update_book_paths(
&self,
library_id: i64,
updates: &[(Fp, PathBuf, PathBuf)],
) -> Result<(), Error>
pub fn batch_update_book_paths( &self, library_id: i64, updates: &[(Fp, PathBuf, PathBuf)], ) -> Result<(), Error>
Updates relative and absolute paths for multiple books in a single transaction,
with one combined UPDATE per entry. Used by import() after directory scanning
to record the final locations of books that were moved or renamed on disk.
pub fn batch_delete_books( &self, library_id: i64, fps: &[Fp], ) -> Result<(), Error>
Sourcepub fn delete_books_with_disallowed_kinds(
&self,
library_id: i64,
allowed_kinds: &FxHashSet<FileExtension>,
) -> Result<Vec<Fp>, Error>
pub fn delete_books_with_disallowed_kinds( &self, library_id: i64, allowed_kinds: &FxHashSet<FileExtension>, ) -> Result<Vec<Fp>, Error>
Deletes all library_books rows for this library whose file_kind is not in
allowed_kinds, cleans up orphaned books rows, and returns the fingerprints
of removed entries so callers can purge thumbnails.
Called at the start of every import so that books whose kind was later removed
from allowed_kinds do not persist in the database.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Db
impl !RefUnwindSafe for Db
impl Send for Db
impl Sync for Db
impl Unpin for Db
impl UnsafeUnpin for Db
impl !UnwindSafe for Db
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more