Module db

Module db 

Source
Expand description

SQLite database layer for scalable storage of audio samples, analysis caches, and scan metadata. Replaces JSON file persistence for data that can grow to millions of rows.

Structs§

AudioQueryParams
Parameters for paginated audio sample queries.
AudioQueryResult
Result of a paginated query.
AudioSampleRow
A single row returned from a paginated query, with analysis data inline.
AudioStatsResult
Aggregate stats for a scan.
CacheStat
Stats for a single cache table.
Database
SQLite with WAL: multiple connections can serve read-heavy queries concurrently. write is the only handle used for schema migrations and code paths that need the writer mutex; never mix it into the read round-robin — doing so serialized every db_query_* IPC with every other read/write on that mutex (spinners across tabs when one query held the slot). read is a pool of read-only file handles; Database::read_conn round-robins only here (always at least one after Database::open).
DawQueryResult
DawRow
DawStatsResult
Aggregate DAW stats from Database::daw_stats: library totals (deduped by path) when scan_id is omitted or empty; otherwise that scan only.
FilterStatsResult
Filtered aggregate stats — count + size + per-type breakdown reflecting the active search/filter. One round-trip: COUNT + SUM + GROUP BY in SQL.
MidiQueryResult
PdfQueryResult
PdfRow
PdfStatsResult
PluginQueryResult
PluginRow
PresetQueryResult
PresetRow
PresetStatsResult
Aggregate preset stats from Database::preset_stats: library totals (deduped by path, MIDI formats excluded) when scan_id is omitted or empty; otherwise that scan only.
ScanInfo
Scan metadata (no samples).
TopFolderRow
One row for heatmap dashboard “top folders” (matches heatmap-dashboard.js folder keys).
UnifiedScanRunRow
One row persisted for the last unified home-tree scan (SQLite unified_scan_run.id is always 1).

Constants§

AUDIO_LIBRARY_IDS 🔒
Canonical inventory: one row per path (highest id wins — newest insert for that path). Materialized in audio_library (migration v14) so library queries avoid GROUP BY path on hot paths.
DAW_LIBRARY_IDS 🔒
Same semantics as MAX(id) GROUP BY path, materialized in daw_library (migration v16).
FTS_INVENTORY_MATCH_COUNT_CAP 🔒
Exact FTS match counts above this force a bounded count and skip heavy aggregates (GROUP BY / size histogram over every hit) — common substrings like “loop” can match hundreds of thousands of library rows. Shared by audio, presets, MIDI, and PDF inventory queries.
LATEST_DAW_SCAN_ID_SQL 🔒
Latest complete DAW scan that has at least one daw_projects row. Empty scans remain in history but must not shadow prior results. Uses child-row presence (not project_count) so streaming scans still resolve after finalize quirks.
MIDI_LIBRARY_IDS 🔒
PDF_LIBRARY_IDS 🔒
PLUGIN_LIBRARY_IDS 🔒
Materialized in plugin_library (migration v17) — same semantics as other *_library tables.
PLUGIN_LIBRARY_IDS_QUALIFIED 🔒
PRESET_LIBRARY_IDS 🔒
Migration v15 — same semantics as MAX(id) GROUP BY path, maintained on insert and deletes.
SCHEMA_VERSION 🔒
Current schema version — bump when adding migrations.
SQLITE_CACHE_KIB_PRIMARY 🔒
Primary SQLite handle (migrations, write_conn): large page cache + mmap.
SQLITE_MMAP_BYTES_PRIMARY 🔒
SQLITE_PROGRESS_HANDLER_OPS 🔒
Check interval for the progress handler — every N virtual-machine opcodes. 1000 is ~50µs on modern hardware; low enough for responsive cancellation, high enough to avoid measurable overhead on normal queries.
SQLITE_QUERY_TIMEOUT_SECS 🔒
Per-query timeout for read-pool connections. The SQLite progress handler fires every SQLITE_PROGRESS_HANDLER_OPS VM opcodes; if wall-clock time since the query started exceeds this limit the query is interrupted (SQLITE_INTERRUPT).
SQLITE_READ_POOL_AUTO_CAP 🔒
Cap on extra connections when [sqliteReadPoolExtra] pref is "auto". Keep modest: explicit 032 extra still opens 1 + extra readers — RSS scales with read_pool_cache_kib / read_pool_mmap_bytes (budget-split, not fixed per handle).
SQLITE_READ_POOL_EXTRA_MAX 🔒
Max explicit extra connections from preferences (0 = one reader + writer; see README).

Statics§

GLOBAL_DB 🔒
INIT_GLOBAL_MUTEX 🔒
Serializes Database::open + migrations on the on-disk file. Without this, many threads can pass the GLOBAL_DB empty check at once and run migrate() in parallel against the same path, which triggers SQLite database is locked (seen on multi-core CI runners).
REGEXP_FUNC_CACHE 🔒

Functions§

backfill_contentless_fts 🔒
Backfill FTS5 contentless shadow tables from primary tables for rows missing from FTS. Migration v9 created empty FTS tables; existing audio_samples (etc.) rows were never indexed, so MATCH returned no hits while the base tables still showed full library counts.
classify_fts_name_path_search 🔒
FTS-backed tabs (name + path): returns (fts_match, like_pat, regex_pat) — at most one of the three is Some. Mirrors AudioQueryParams::search_regex semantics.
classify_plugins_search 🔒
Plugins tab (name, manufacturer, path): (regex_pat, like_pat) — when regex_pat is Some, use REGEXP on all three columns; otherwise like_pat is fuzzy interleaved or invalid-regex fallback (same binding shape).
dbstat_bytes_for_scan_group 🔒
Approximate on-disk bytes for btree objects (table + indexes) for scan_table + item_table. Uses SQLite dbstat when available. Returns None if dbstat is not compiled in (caller splits DB file size by row count).
default_limit 🔒
default_sort_key 🔒
default_true 🔒
fts_phrase 🔒
Convert a user search string into an FTS5 phrase query for the trigram tokenizer. Returns None for empty/whitespace input. The result is wrapped in double quotes (phrase match) with internal quotes doubled per FTS5 syntax. Trigram tokenizer indexes substrings, so "foo" matches any row containing “foo” as a substring in any indexed column. Returns an FTS5 phrase for trigram MATCH, or None if the search is empty or too short (trigram needs ≥3 chars). Callers must fall back to LIKE for 1–2 char searches.
global
Get the global database reference.
global_initialized
Returns true after a successful init_global (including concurrent test runners).
init_global
Initialize the global database. Call once at startup.
init_sqlite_connection_pragmas 🔒
install_regexp_function 🔒
now_epoch_ms 🔒
Milliseconds since std::time::UNIX_EPOCH (monotonic enough for timeout purposes).
open_db_connection_with_pragmas 🔒
open_read_connection 🔒
Open a read-pool connection with a progress-handler query timeout. The returned Arc<AtomicU64> must be stored alongside the connection and reset (via reset_query_deadline) each time the connection is acquired from the pool.
parse_plugin_status_filter 🔒
Comma-separated update, current, unknown — matches kvr_cache + frontend pluginStatusCategory.
parse_sqlite_read_pool_extra_pref 🔒
Resolves [performance.sqliteReadPoolExtra]: "auto"sqlite_read_pool_auto, else 0..=32.
read_pool_cache_kib 🔒
~512 MiB total page-cache budget split across all read-pool connections (e.g. extra = 32 → 33 readers × ~15.5 MiB each). Caps each reader at 32 MiB when the pool is small.
read_pool_mmap_bytes 🔒
~512 MiB total mmap cap split across read-pool connections; each reader at most 64 MiB.
regexp_pattern_cache 🔒
regexp_user_matches 🔒
SQLite regexp(pattern, haystack) — matches JS new RegExp(pattern, 'i') (case-insensitive).
reset_query_deadline 🔒
Reset the query-start timestamp so the progress handler measures from now.
short_like 🔒
Build a LIKE pattern for short searches (1–2 chars) where FTS5 trigram can’t help. Returns None for empty input.
sqlite_read_pool_auto 🔒

Type Aliases§

AnalysisBatchRow
One row for Database::batch_update_analysis: path, BPM, musical key, LUFS.