Database

Struct Database 

Source
pub struct Database {
    write: Mutex<Connection>,
    read: Vec<Mutex<Connection>>,
    read_deadlines: Vec<Arc<AtomicU64>>,
    read_idx: AtomicUsize,
    midi_library_total_cache: Mutex<Option<u64>>,
    pdf_library_total_cache: Mutex<Option<u64>>,
    audio_library_total_cache: Mutex<Option<u64>>,
    preset_inventory_total_cache: Mutex<Option<u64>>,
    daw_library_total_cache: Mutex<Option<u64>>,
    plugin_library_total_cache: Mutex<Option<u64>>,
}
Expand description

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).

Fields§

§write: Mutex<Connection>§read: Vec<Mutex<Connection>>§read_deadlines: Vec<Arc<AtomicU64>>

Per-slot query-start timestamp (epoch ms) for the progress-handler timeout.

§read_idx: AtomicUsize§midi_library_total_cache: Mutex<Option<u64>>

SELECT COUNT(*) FROM midi_library is O(rows); cache and invalidate on MIDI library writes.

§pdf_library_total_cache: Mutex<Option<u64>>

Same pattern as Self::midi_library_total_rows for pdf_library.

§audio_library_total_cache: Mutex<Option<u64>>

SELECT COUNT(*) FROM audio_library — invalidated on audio library writes.

§preset_inventory_total_cache: Mutex<Option<u64>>

Preset tab header: non-MIDI rows in library (query_presets / preset_filter_stats).

§daw_library_total_cache: Mutex<Option<u64>>

SELECT COUNT(*) FROM daw_library — invalidated on DAW library writes.

§plugin_library_total_cache: Mutex<Option<u64>>

SELECT COUNT(*) FROM plugin_library — invalidated on plugin library writes.

Implementations§

Source§

impl Database

Source

const SYNC_AUDIO_LIBRARY_PATHS_SQL: &'static str = r#"DELETE FROM audio_library WHERE path IN (SELECT path FROM _al_refresh_paths) AND path NOT IN (SELECT DISTINCT path FROM audio_samples); INSERT OR REPLACE INTO audio_library (path, sample_id) SELECT path, MAX(id) FROM audio_samples WHERE path IN (SELECT path FROM _al_refresh_paths) GROUP BY path; DROP TABLE _al_refresh_paths;"#

SQL bodies for [sync_*_after_paths_refresh] (standalone: wrapped in BEGIN IMMEDIATE by [exec_sync_paths_refresh]). For preset/midi/pdf flows already inside a [Transaction], use [sync_preset_library_after_paths_refresh_tx] / [sync_midi_library_after_paths_refresh_tx] / [sync_pdf_library_after_paths_refresh_tx] via [exec_sync_paths_refresh_tx] — do not nest another BEGIN (SQLite rejects it).

Source

const SYNC_PDF_LIBRARY_PATHS_SQL: &'static str = r#"DELETE FROM pdf_library WHERE path IN (SELECT path FROM _pdf_lib_refresh_paths) AND path NOT IN (SELECT DISTINCT path FROM pdfs); INSERT OR REPLACE INTO pdf_library (path, pdf_id) SELECT path, MAX(id) FROM pdfs WHERE path IN (SELECT path FROM _pdf_lib_refresh_paths) GROUP BY path; DROP TABLE _pdf_lib_refresh_paths;"#

Source

const SYNC_MIDI_LIBRARY_PATHS_SQL: &'static str = r#"DELETE FROM midi_library WHERE path IN (SELECT path FROM _midi_lib_refresh_paths) AND path NOT IN (SELECT DISTINCT path FROM midi_files); INSERT OR REPLACE INTO midi_library (path, midi_id) SELECT path, MAX(id) FROM midi_files WHERE path IN (SELECT path FROM _midi_lib_refresh_paths) GROUP BY path; DROP TABLE _midi_lib_refresh_paths;"#

Source

const SYNC_PRESET_LIBRARY_PATHS_SQL: &'static str = r#"DELETE FROM preset_library WHERE path IN (SELECT path FROM _preset_lib_refresh_paths) AND path NOT IN (SELECT DISTINCT path FROM presets); INSERT OR REPLACE INTO preset_library (path, preset_id) SELECT path, MAX(id) FROM presets WHERE path IN (SELECT path FROM _preset_lib_refresh_paths) GROUP BY path; DROP TABLE _preset_lib_refresh_paths;"#

Source

const SYNC_DAW_LIBRARY_PATHS_SQL: &'static str = r#"DELETE FROM daw_library WHERE path IN (SELECT path FROM _dl_refresh_paths) AND path NOT IN (SELECT DISTINCT path FROM daw_projects); INSERT OR REPLACE INTO daw_library (path, project_id) SELECT path, MAX(id) FROM daw_projects WHERE path IN (SELECT path FROM _dl_refresh_paths) GROUP BY path; DROP TABLE _dl_refresh_paths;"#

Source

const SYNC_PLUGIN_LIBRARY_PATHS_SQL: &'static str = r#"DELETE FROM plugin_library WHERE path IN (SELECT path FROM _pl_refresh_paths) AND path NOT IN (SELECT DISTINCT path FROM plugins); INSERT OR REPLACE INTO plugin_library (path, plugin_id) SELECT path, MAX(id) FROM plugins WHERE path IN (SELECT path FROM _pl_refresh_paths) GROUP BY path; DROP TABLE _pl_refresh_paths;"#

Source

fn read_pool_extra() -> usize

User pref: additional read pool slots beyond the mandatory first reader (1 + this, min 1).

Source

pub fn sqlite_read_pool_extra_slots(&self) -> usize

Count of read-pool connections (each participates in [read_conn] round-robin only).

Source

pub fn sqlite_read_pool_total_handles(&self) -> usize

Primary writer + read pool (1 + read.len() open file handles).

Source

fn write_conn(&self) -> MutexGuard<'_, Connection>

Exclusive writer — migrations, cache writes, and anything that should not compete with Self::read_conn for the same Mutex.

Source

fn read_conn(&self) -> MutexGuard<'_, Connection>

Round-robin read pool only (never the primary write handle — see Database docs). Resets the per-slot query-timeout deadline so the progress handler measures from now.

Source

fn midi_library_total_rows(&self, conn: &Connection) -> Result<u64, String>

Source

fn invalidate_midi_library_total_cache(&self)

Source

fn pdf_library_total_rows(&self, conn: &Connection) -> Result<u64, String>

Source

fn invalidate_pdf_library_total_cache(&self)

Source

fn audio_library_total_rows(&self, conn: &Connection) -> Result<u64, String>

Source

fn invalidate_audio_library_total_cache(&self)

Source

fn preset_inventory_total_rows(&self, conn: &Connection) -> Result<u64, String>

Source

fn invalidate_preset_inventory_total_cache(&self)

Source

fn daw_library_total_rows(&self, conn: &Connection) -> Result<u64, String>

Source

fn invalidate_daw_library_total_cache(&self)

Source

fn plugin_library_total_rows(&self, conn: &Connection) -> Result<u64, String>

Source

fn invalidate_plugin_library_total_cache(&self)

Source

fn exec_sync_paths_refresh(conn: &Connection, sql: &str) -> Result<(), String>

Source

fn exec_sync_paths_refresh_tx( tx: &Transaction<'_>, sql: &str, ) -> Result<(), String>

Source

fn sync_audio_library_after_paths_refresh( conn: &Connection, ) -> Result<(), String>

_al_refresh_paths lists paths touched by removing audio_samples for a scan; those rows must already be deleted. Reconciles audio_library with remaining audio_samples rows.

Source

fn sync_pdf_library_after_paths_refresh(conn: &Connection) -> Result<(), String>

Source

fn sync_pdf_library_after_paths_refresh_tx( tx: &Transaction<'_>, ) -> Result<(), String>

Source

fn sync_midi_library_after_paths_refresh( conn: &Connection, ) -> Result<(), String>

Source

fn sync_midi_library_after_paths_refresh_tx( tx: &Transaction<'_>, ) -> Result<(), String>

Source

fn sync_preset_library_after_paths_refresh( conn: &Connection, ) -> Result<(), String>

Source

fn sync_preset_library_after_paths_refresh_tx( tx: &Transaction<'_>, ) -> Result<(), String>

Source

fn sync_daw_library_after_paths_refresh(conn: &Connection) -> Result<(), String>

_dl_refresh_paths lists paths touched by removing daw_projects rows for a scan; those rows must already be deleted. Reconciles daw_library with remaining daw_projects rows.

Source

fn rebuild_daw_library(conn: &Connection) -> Result<(), String>

Source

fn sync_plugin_library_after_paths_refresh( conn: &Connection, ) -> Result<(), String>

_pl_refresh_paths lists paths touched by removing plugins rows for a scan; reconciles plugin_library with remaining plugins rows (same pattern as sync_daw_library_after_paths_refresh).

Source

fn rebuild_plugin_library(conn: &Connection) -> Result<(), String>

Source

fn rebuild_pdf_midi_preset_daw_libraries( conn: &mut Connection, ) -> Result<(), String>

Full rebuild after bulk deletes (e.g. prune_old_scans) where per-path sync is impractical.

One transaction: without it, each DELETE/INSERT autocommits separately — a crash or killed process after DELETE FROM midi_library but before INSERT could leave *_library empty while midi_files (etc.) still had rows.

Source

pub fn open() -> Result<Self, String>

Open or create the database in the app data directory.

Source

pub fn housekeep_light(&self)

Quick startup path: query planner refresh + cache touch. Safe from any thread; keep fast.

Source

pub fn housekeep_heavy(&self)

Expensive path: prune old scans (DELETE + full *_library rebuild) and optional VACUUM. Run well after the window and setup() have finished so pooled read_conn() scopes are not held across first-frame IPC (long prune batches still contend on SQLite + pool slots).

Source

fn prune_old_scans_pref_enabled() -> bool

Source

fn prune_old_scans_keep_pref() -> usize

[performance]pruneOldScansKeep (default 3, clamped 1..=100).

Source

pub fn housekeep(&self)

Full sequence (manual / tests). Startup uses Self::housekeep_light + delayed Self::housekeep_heavy.

Source

pub fn prune_old_scans(&self, keep: usize)

Prune old scans — keep only the N most recent complete scans per type. Incomplete (user-stopped) runs are retained until superseded or cleared so library rows stay addressable.

Source

pub fn set_audio_scan_complete( &self, id: &str, complete: bool, ) -> Result<(), String>

Mark whether a streaming scan finished normally (complete) or was user-stopped (partial).

Source

pub fn set_plugin_scan_complete( &self, id: &str, complete: bool, ) -> Result<(), String>

Source

pub fn set_daw_scan_complete( &self, id: &str, complete: bool, ) -> Result<(), String>

Source

pub fn set_preset_scan_complete( &self, id: &str, complete: bool, ) -> Result<(), String>

Source

pub fn set_midi_scan_complete( &self, id: &str, complete: bool, ) -> Result<(), String>

Source

pub fn set_pdf_scan_complete( &self, id: &str, complete: bool, ) -> Result<(), String>

Source

pub fn prewarm(&self)

Checkpoint WAL to merge it into the main DB file. Keeps WAL small. Warm the page cache by touching each table + FTS index root. First real query returns ~1 ms instead of the 50-200 ms cold-cache penalty.

Source

pub fn checkpoint(&self)

Source

pub fn get_app_strings( &self, locale: &str, ) -> Result<HashMap<String, String>, String>

Resolved app UI strings for the given locale (merged with English fallback).

Source

pub fn get_toast_strings( &self, locale: &str, ) -> Result<HashMap<String, String>, String>

Alias for Self::get_app_strings (legacy command name).

Source

pub fn vacuum_if_needed(&self)

VACUUM if >20% of pages are free (dead space from deleted rows).

Source

fn migrate_plugin_paths_canonical(conn: &Connection) -> Result<(), String>

One-time migration: normalize plugins.path and plugin_scans directories/roots JSON to normalize_path_for_db form; remove duplicate (canonical path, scan_id) rows (keep max id).

Source

fn migrate(&self) -> Result<(), String>

Run schema migrations.

Source

pub fn audio_scan_parent_create( &self, id: &str, timestamp: &str, roots: &[String], ) -> Result<(), String>

Insert a batch of audio samples in a single transaction.

Source

pub fn audio_scan_parent_finalize( &self, id: &str, _sample_count: u64, _total_bytes: u64, _format_counts: &HashMap<String, usize>, ) -> Result<(), String>

Source

pub fn insert_audio_batch( &self, scan_id: &str, samples: &[AudioSample], ) -> Result<u64, String>

Source

pub fn save_scan( &self, id: &str, timestamp: &str, sample_count: u64, total_bytes: u64, format_counts: &HashMap<String, usize>, roots: &[String], ) -> Result<(), String>

Save scan metadata.

Source

pub fn latest_scan_id(&self) -> Result<Option<String>, String>

Get the most recent scan ID.

Source

pub fn list_scans(&self) -> Result<Vec<ScanInfo>, String>

List all scans (metadata only).

Source

fn audio_fts_bounded_count_scan( conn: &Connection, fts_match: &str, scan_id: &str, ) -> Result<(u64, bool), String>

Bounded FTS hit count for one scan (audio_samples_fts.scan_id).

Source

fn audio_fts_bounded_count_library( conn: &Connection, fts_match: &str, format_filter: Option<&str>, ) -> Result<(u64, bool), String>

Bounded FTS hit count for library scope (same format_filter rules as Self::query_audio).

Source

fn preset_fts_bounded_count_library( conn: &Connection, fts_match: &str, format_filter: Option<&str>, ) -> Result<(u64, bool), String>

Bounded FTS hit count for presets library (non-MIDI formats only; matches Self::query_presets).

Source

fn midi_fts_bounded_count_library( conn: &Connection, fts_match: &str, format_filter: Option<&str>, ) -> Result<(u64, bool), String>

Bounded FTS hit count for MIDI library (same format_filter rules as Self::query_midi).

Source

fn pdf_fts_bounded_count_library( conn: &Connection, fts_match: &str, ) -> Result<(u64, bool), String>

Bounded FTS hit count for PDF library (Self::query_pdfs has no format filter).

Source

fn daw_fts_bounded_count_library( conn: &Connection, fts_match: &str, daw_filter: Option<&str>, ) -> Result<(u64, bool), String>

Bounded FTS hit count for DAW project library (Self::query_daw daw_filter rules).

Source

fn plugin_search_bounded_count_library( conn: &Connection, from_sql: &str, where_cl: &str, regex_pat: &Option<String>, like_pat: &Option<String>, type_filter: Option<&str>, ) -> Result<(u64, bool), String>

Bounded COUNT for plugin tab search (LIKE / REGEXP; no FTS). Same cap as inventory FTS paths.

Source

pub fn query_audio( &self, params: &AudioQueryParams, ) -> Result<AudioQueryResult, String>

Paginated, sortable, filterable query for audio samples.

scan_id Some(non-empty) → rows for that scan only (history detail). scan_id None or empty → library mode: all rows across scans, deduped by path (MAX(id) per path).

Source

pub fn audio_stats( &self, scan_id: Option<&str>, ) -> Result<AudioStatsResult, String>

Get aggregate stats. scan_id None or empty → full library (deduped by path). Otherwise that scan only.

Source

pub fn daw_stats(&self, scan_id: Option<&str>) -> Result<DawStatsResult, String>

DAW aggregate stats. scan_id None or empty → full library (deduped by path).

Source

pub fn preset_stats( &self, scan_id: Option<&str>, ) -> Result<PresetStatsResult, String>

Preset aggregate stats. scan_id None or empty → full library (deduped by path). MIDI excluded.

Source

pub fn update_bpm(&self, path: &str, bpm: Option<f64>) -> Result<(), String>

Update BPM for a sample (all rows for that path).

Source

pub fn update_key(&self, path: &str, key: Option<&str>) -> Result<(), String>

Update musical key for a sample.

Source

pub fn update_audio_meta( &self, path: &str, duration: Option<f64>, channels: Option<u16>, sample_rate: Option<u32>, bits_per_sample: Option<u16>, ) -> Result<(), String>

Update core audio metadata (duration, channels, sample_rate, bits_per_sample) for a sample.

Source

pub fn paths_missing_audio_meta( &self, paths: &[String], ) -> Result<Vec<String>, String>

Get paths that are missing duration metadata (among the given paths).

Source

pub fn update_lufs(&self, path: &str, lufs: Option<f64>) -> Result<(), String>

Update LUFS for a sample (all rows for that path).

Source

pub fn get_analysis(&self, path: &str) -> Result<Value, String>

Get analysis data for a single sample.

Source

pub fn unanalyzed_paths(&self, limit: u64) -> Result<Vec<String>, String>

Get paths of samples that still need BPM/Key/LUFS analysis (library rows).

Rows where key and LUFS are filled but BPM is still NULL after a batch run are marked bpm_exhausted so we do not spin on the same paths forever when tempo detection fails. Clearing the BPM cache resets bpm_exhausted so analysis can retry.

Source

pub fn audio_library_paths(&self) -> Result<Vec<String>, String>

All canonical path values in the audio library (one row per path via audio_library).

Source

pub fn delete_scan(&self, scan_id: &str) -> Result<(), String>

Delete a scan and its samples.

Source

pub fn query_plugins( &self, search: Option<&str>, type_filter: Option<&str>, status_filter: Option<&str>, sort_key: &str, sort_asc: bool, search_regex: bool, offset: u64, limit: u64, ) -> Result<PluginQueryResult, String>

Source

pub fn query_daw( &self, search: Option<&str>, daw_filter: Option<&str>, sort_key: &str, sort_asc: bool, search_regex: bool, offset: u64, limit: u64, ) -> Result<DawQueryResult, String>

Full library (deduped by path). Same pattern as query_audio without scan_id.

Source

pub fn query_presets( &self, search: Option<&str>, format_filter: Option<&str>, sort_key: &str, sort_asc: bool, search_regex: bool, offset: u64, limit: u64, ) -> Result<PresetQueryResult, String>

Source

pub fn save_plugin_scan(&self, snap: &ScanSnapshot) -> Result<(), String>

Source

pub fn plugin_scan_parent_create( &self, id: &str, timestamp: &str, roots: &[String], ) -> Result<(), String>

Begin a streaming plugin scan: parent row + clear prior rows for this id.

Source

pub fn insert_plugin_batch( &self, scan_id: &str, batch: &[PluginInfo], ) -> Result<u64, String>

Append plugins for a streaming scan; updates plugin_scans.plugin_count incrementally.

Source

pub fn plugin_scan_parent_finalize( &self, id: &str, _plugin_count: usize, directories: &[String], roots: &[String], ) -> Result<(), String>

Finalize directory list and counts after streaming inserts (matches non-streaming snapshot shape).

Source

pub fn get_plugin_scans(&self) -> Result<Vec<Value>, String>

Source

pub fn get_plugin_scan_detail(&self, id: &str) -> Result<ScanSnapshot, String>

Source

pub fn get_latest_plugin_scan(&self) -> Result<Option<ScanSnapshot>, String>

Source

pub fn delete_plugin_scan(&self, id: &str) -> Result<(), String>

Source

pub fn clear_plugin_history(&self) -> Result<(), String>

Source

pub fn save_audio_scan_full( &self, snap: &AudioScanSnapshot, ) -> Result<(), String>

Source

pub fn get_audio_scans_list(&self) -> Result<Vec<Value>, String>

Source

pub fn get_audio_scan_detail( &self, id: &str, ) -> Result<AudioScanSnapshot, String>

Source

pub fn get_latest_audio_scan(&self) -> Result<Option<AudioScanSnapshot>, String>

Source

pub fn delete_audio_scan(&self, id: &str) -> Result<(), String>

Source

pub fn clear_audio_history(&self) -> Result<(), String>

Source

pub fn daw_scan_parent_create( &self, id: &str, timestamp: &str, roots: &[String], ) -> Result<(), String>

Create (or re-create) a parent daw_scans row with zero counts. Used by streaming scans that don’t know totals up front.

Source

pub fn daw_scan_parent_finalize( &self, id: &str, _project_count: usize, _total_bytes: u64, _daw_counts: &HashMap<String, usize>, ) -> Result<(), String>

Finalize a parent daw_scans row with aggregate counts after streaming is complete.

Source

pub fn insert_daw_batch( &self, scan_id: &str, projects: &[DawProject], ) -> Result<Vec<usize>, String>

Stream-insert a batch of DawProject rows under an existing scan_id.

Source

pub fn save_daw_scan(&self, snap: &DawScanSnapshot) -> Result<(), String>

Source

pub fn get_daw_scans(&self) -> Result<Vec<Value>, String>

Source

pub fn get_daw_scan_detail(&self, id: &str) -> Result<DawScanSnapshot, String>

Source

pub fn get_latest_daw_scan(&self) -> Result<Option<DawScanSnapshot>, String>

Source

pub fn delete_daw_scan(&self, id: &str) -> Result<(), String>

Source

pub fn clear_daw_history(&self) -> Result<(), String>

Source

pub fn preset_scan_parent_create( &self, id: &str, timestamp: &str, roots: &[String], ) -> Result<(), String>

Source

pub fn preset_scan_parent_finalize( &self, id: &str, _preset_count: usize, _total_bytes: u64, _format_counts: &HashMap<String, usize>, ) -> Result<(), String>

Source

pub fn insert_preset_batch( &self, scan_id: &str, presets: &[PresetFile], ) -> Result<u64, String>

Source

pub fn save_preset_scan(&self, snap: &PresetScanSnapshot) -> Result<(), String>

Source

pub fn get_preset_scans(&self) -> Result<Vec<Value>, String>

Source

pub fn get_preset_scan_detail( &self, id: &str, ) -> Result<PresetScanSnapshot, String>

Source

pub fn get_latest_preset_scan( &self, ) -> Result<Option<PresetScanSnapshot>, String>

Source

pub fn delete_preset_scan(&self, id: &str) -> Result<(), String>

Source

pub fn clear_preset_history(&self) -> Result<(), String>

Source

pub fn midi_scan_parent_create( &self, id: &str, timestamp: &str, roots: &[String], ) -> Result<(), String>

Source

pub fn midi_scan_parent_finalize( &self, id: &str, _midi_count: usize, _total_bytes: u64, _format_counts: &HashMap<String, usize>, ) -> Result<(), String>

Source

pub fn insert_midi_batch( &self, scan_id: &str, midi_files: &[MidiFile], ) -> Result<(), String>

Source

pub fn save_midi_scan(&self, snap: &MidiScanSnapshot) -> Result<(), String>

Source

pub fn get_midi_scans(&self) -> Result<Vec<Value>, String>

Source

pub fn get_midi_scan_detail(&self, id: &str) -> Result<MidiScanSnapshot, String>

Source

pub fn get_latest_midi_scan(&self) -> Result<Option<MidiScanSnapshot>, String>

Source

pub fn delete_midi_scan(&self, id: &str) -> Result<(), String>

Source

pub fn clear_midi_history(&self) -> Result<(), String>

Source

pub fn query_midi( &self, search: Option<&str>, format_filter: Option<&str>, sort_key: &str, sort_asc: bool, search_regex: bool, offset: u64, limit: u64, ) -> Result<MidiQueryResult, String>

Source

pub fn midi_filter_stats( &self, search: Option<&str>, format_filter: Option<&str>, search_regex: bool, ) -> Result<FilterStatsResult, String>

Source

pub fn pdf_scan_parent_create( &self, id: &str, timestamp: &str, roots: &[String], ) -> Result<(), String>

Source

pub fn pdf_scan_parent_finalize( &self, id: &str, _pdf_count: usize, _total_bytes: u64, ) -> Result<(), String>

Source

pub fn insert_pdf_batch( &self, scan_id: &str, pdfs: &[PdfFile], ) -> Result<u64, String>

Source

pub fn load_directory_scan_snapshot( &self, domain: &str, ) -> Result<HashMap<String, i64>, String>

Load stored directory mtimes for a domain (e.g. "unified").

Source

pub fn upsert_directory_scan_batch( &self, domain: &str, rows: &[(String, i64)], last_scan_id: Option<&str>, ) -> Result<(), String>

Source

pub fn delete_directory_scan_state_domain( &self, domain: &str, ) -> Result<u64, String>

Remove all incremental directory rows for a domain (e.g. "unified").

Source

pub fn unified_scan_incremental_snapshot_is_trusted( &self, ) -> Result<bool, String>

True when the last persisted unified scan finished successfully; incremental mtime snapshots are only trusted in that case.

Source

pub fn unified_scan_run_start( &self, run_id: &str, started_at: &str, audio_scan_id: &str, daw_scan_id: &str, preset_scan_id: &str, pdf_scan_id: &str, roots_json: &str, ) -> Result<(), String>

Source

pub fn unified_scan_run_finish( &self, finished_at: &str, outcome: &str, error_message: Option<&str>, last_directory_path: Option<&str>, ) -> Result<(), String>

Persists final unified scan outcome. When outcome is not complete, clears incremental directory_scan_state rows for domain "unified" so partial walks are not reused.

Source

pub fn get_unified_scan_run(&self) -> Result<UnifiedScanRunRow, String>

Source

pub fn save_pdf_scan(&self, snap: &PdfScanSnapshot) -> Result<(), String>

Source

pub fn get_pdf_scans(&self) -> Result<Vec<Value>, String>

Source

pub fn get_pdf_scan_detail(&self, id: &str) -> Result<PdfScanSnapshot, String>

Source

pub fn get_latest_pdf_scan(&self) -> Result<Option<PdfScanSnapshot>, String>

Source

pub fn delete_pdf_scan(&self, id: &str) -> Result<(), String>

Source

pub fn clear_pdf_history(&self) -> Result<(), String>

Source

pub fn unindexed_pdf_paths(&self, limit: u64) -> Result<Vec<String>, String>

Paths in the materialized PDF library (newest row per filesystem path) that have no pdf_metadata row yet. Uses pdf_library, not “latest scan only”, so PDFs whose canonical pdfs row belongs to an older completed scan are still queued for page counts.

Source

pub fn save_pdf_metadata( &self, batch: &[(String, Option<u32>)], ) -> Result<(), String>

Batch upsert PDF page counts. Entries with None page count are still inserted (as a negative marker) so we don’t re-attempt broken files.

Source

pub fn get_pdf_metadata( &self, paths: &[String], ) -> Result<HashMap<String, Option<u32>>, String>

Get page counts for a set of paths (returns only entries that exist).

Source

pub fn clear_pdf_metadata(&self) -> Result<(), String>

Source

pub fn query_pdfs( &self, search: Option<&str>, sort_key: &str, sort_asc: bool, search_regex: bool, offset: u64, limit: u64, ) -> Result<PdfQueryResult, String>

Source

pub fn pdf_stats(&self, scan_id: Option<&str>) -> Result<PdfStatsResult, String>

PDF aggregate stats. scan_id None or empty → full library (deduped by path).

Source

fn in_list_sql(values: &str) -> String

Source

fn heatmap_audio_folder_key(dir: &str) -> String

First three path segments of directory, matching heatmap-dashboard.js buildFolderCard.

Source

fn audio_heatmap_aggregates( conn: &Connection, where_cl: &str, fts_match: &Option<String>, regex_pat: &Option<String>, like_pat: &Option<String>, format_filter: Option<&str>, ) -> Result<(Vec<u64>, u64, HashMap<String, u64>, u64, Vec<TopFolderRow>), String>

BPM/key/folder aggregates for the heatmap dashboard (same where_cl as audio_filter_stats).

Source

pub fn audio_filter_stats( &self, search: Option<&str>, format_filter: Option<&str>, search_regex: bool, ) -> Result<FilterStatsResult, String>

Source

pub fn daw_filter_stats( &self, search: Option<&str>, daw_filter: Option<&str>, search_regex: bool, ) -> Result<FilterStatsResult, String>

Source

pub fn preset_filter_stats( &self, search: Option<&str>, format_filter: Option<&str>, search_regex: bool, ) -> Result<FilterStatsResult, String>

Source

pub fn plugin_filter_stats( &self, search: Option<&str>, type_filter: Option<&str>, search_regex: bool, ) -> Result<FilterStatsResult, String>

Source

pub fn pdf_filter_stats( &self, search: Option<&str>, search_regex: bool, ) -> Result<FilterStatsResult, String>

Source

pub fn load_kvr_cache(&self) -> Result<HashMap<String, KvrCacheEntry>, String>

Source

pub fn update_kvr_cache( &self, entries: &[KvrCacheUpdateEntry], ) -> Result<(), String>

Source

pub fn read_cache(&self, name: &str) -> Result<Value, String>

Source

pub fn write_cache(&self, name: &str, data: &Value) -> Result<(), String>

Source

fn read_analysis_as_cache(&self, field: &str) -> Result<Value, String>

Source

fn write_analysis_from_cache( &self, data: &Value, field: &str, ) -> Result<(), String>

Source

fn read_kv_cache(&self, name: &str) -> Result<Value, String>

Source

fn write_kv_cache(&self, name: &str, data: &Value) -> Result<(), String>

Source

pub fn table_counts(&self) -> Result<Value, String>

Get row counts for all tables.

Source

pub fn active_scan_inventory_counts(&self) -> Result<Value, String>

Row counts per inventory category for the library view: one canonical row per path. Audio uses audio_library (v14); DAW uses daw_library (v16); PDF, MIDI, and presets use pdf_library, midi_library, and preset_library (v15); plugins use plugin_library (v17). Not scoped to a single scan_id. Presets exclude MID/MIDI (same tab rules as elsewhere). Matches default scan_id handling on paginated queries and *_filter_stats, not raw COUNT(*) on whole tables.

Source

pub fn library_paths_for_content_hash( &self, ) -> Result<Vec<(String, u64, String)>, String>

All library paths with byte sizes for content-hash duplicate detection. Uses the same per-domain library rules as Database::active_scan_inventory_counts.

Source

pub fn cache_stats(&self) -> Result<Vec<CacheStat>, String>

Get stats for all caches: item count and estimated size.

Uses the primary write connection (not the read pool). Read-pool handles install a SQLITE_QUERY_TIMEOUT_SECS progress-handler budget per acquisition; cache_stats runs many sequential full-table COUNTs and dbstat passes — cumulative time exceeded 30s on large libraries and surfaced as an empty/error cache table in Settings.

Source

pub fn batch_update_analysis( &self, results: &[AnalysisBatchRow], ) -> Result<u32, String>

Batch update BPM/Key/LUFS for multiple files in a single transaction.

Returns the sum of sqlite3_changes() for each UPDATE (rows modified), not the number of input paths — a path matching multiple audio_samples rows updates all of them.

Source

pub fn clear_cache_table(&self, table: &str) -> Result<(), String>

Clear a specific cache table.

Source

pub fn clear_all_caches(&self) -> Result<(), String>

Clear all analysis and cache data from SQLite.

Source

fn cache_table_for(&self, name: &str) -> (&str, &str, &str)

Source

pub fn migrate_from_json(&self) -> Result<usize, String>

One-time migration of ALL JSON history/cache files to SQLite.

Source

fn migrate_audio_json(&self, data_dir: &Path) -> Result<usize, String>

Source

fn migrate_plugin_json(&self, data_dir: &Path) -> Result<usize, String>

Source

fn migrate_daw_json(&self, data_dir: &Path) -> Result<usize, String>

Source

fn migrate_preset_json(&self, data_dir: &Path) -> Result<usize, String>

Source

fn migrate_kvr_json(&self, data_dir: &Path) -> Result<usize, String>

Source

fn migrate_kv_cache( &self, data_dir: &Path, filename: &str, table: &str, key_col: &str, val_col: &str, ) -> Result<usize, String>

Generic key→value JSON cache migration (xref, waveform, spectrogram, fingerprint).

Source

fn migrate_analysis_cache( &self, data_dir: &Path, filename: &str, field: &str, ) -> Result<(), String>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

§

fn into_sample(self) -> T

§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
Source§

impl<T> AutoreleaseSafe for T
where T: ?Sized,