Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Library Database

Cadmus stores library roots, scanned files, book metadata, reading progress, thumbnails, and table-of-contents data in SQLite. This page explains where each category of library data belongs and how scans move data from disk into the database.

Core Shape

The library database separates four concerns:

erDiagram
    libraries ||--o{ library_books : contains
    books ||--o{ library_books : appears_in
    books ||--o{ book_authors : has
    authors ||--o{ book_authors : names
    books ||--o{ book_categories : tagged_with
    categories ||--o{ book_categories : names
    books ||--o| reading_states : tracks
    books ||--o| thumbnails : caches
    books ||--o{ toc_entries : contains
    toc_entries ||--o{ toc_entries : parent

Libraries

libraries represents scan roots. A row answers: “which directory did Cadmus index as a library?”

Keep library-level data here only when it describes the library itself, such as its path, display name, or creation metadata.

Library Membership

library_books connects a library to the book files found under it. It is the place for data that depends on a specific file within a specific library scan, including relative paths, absolute paths, timestamps, sizes, and other scan-cache metadata.

This table is deliberately separate from books because one canonical book can appear in more than one library or at more than one path over time. File-system state belongs to the membership row, not to the canonical book row.

Canonical Books

books is the canonical per-book record, keyed by fingerprint. It holds data that should be the same regardless of which library found the file, such as title and file kind.

Per-book tables reference books and are removed with the book when cascading deletes apply. New per-book data should usually live in a dedicated table rather than being mixed into library membership.

Derived Per-Book Data

Authors, categories, reading state, thumbnails, and table-of-contents entries are derived from either metadata extraction, reader state, or generated assets. They are tied to the canonical book fingerprint, not to a specific library path.

Use join tables for many-to-many relationships such as authors and categories. Use child tables for optional or repeatable data such as reading state, thumbnails, and TOC entries.

Scan Flow

Library scans move from the filesystem toward canonical book data:

flowchart TD
    root[Library root] --> files[Discover supported book files]
    files --> membership[Update library membership and scan cache]
    membership --> fingerprint[Fingerprint changed or new files]
    fingerprint --> book[Upsert canonical book metadata]
    book --> derived[Refresh derived per-book data]

The membership row is checked before expensive work. If the scan-cache data says the file has not changed, Cadmus can skip re-fingerprinting and metadata extraction. If the file is new or changed, Cadmus updates the canonical book row and any derived data collected during import.

What Goes Where

Use these rules when adding or reviewing library database changes:

Data kindBelongs in
Library root path or display namelibraries
File path inside one scanned librarylibrary_books
File modification or size cachelibrary_books
Stable book identity or extracted titlebooks
Data shared by all copies of a bookbooks or a per-book child table
Many-to-many metadataNamed entity table plus join table
Reading progressreading_states
Generated cover imagethumbnails
Nested table of contentstoc_entries, using parent references and positions
Migration bookkeepingMigration tables managed by the migration runner

If data describes a file’s current location, put it in library membership. If it describes the book identified by its fingerprint, put it in canonical book data or a per-book child table.

Schema Details

For exact schema details, read the migrations in crates/core/migrations/ in order. They define the tables, views, indexes, constraints, and data migrations that exist at each database version.

Data Access

The cadmus_core::library::db::Db type is the entry point for library database operations. It wraps the shared SQLite pool and presents a synchronous API to the rest of the app.

Keep database access behind this layer so callers work with domain types instead of raw SQL rows. For SQLx conventions, type overrides, and migration review rules, see the related pages below.