Skip to main content

Db

Struct Db 

Source
pub struct Db<M = ReadWrite> { /* private fields */ }
Expand description

A SQLite connection whose mode parameter says whether write APIs resolve.

Read methods are available in both modes; write methods only on Db<ReadWrite> (the default, so Db spelled bare means writable):

let db = musefs_db::Db::open_in_memory().unwrap().into_read_only();
db.data_version().unwrap();
let db = musefs_db::Db::open_in_memory().unwrap().into_read_only();
db.upsert_track(unimplemented!());

Implementations§

Source§

impl<M> Db<M>

Source

pub fn get_art(&self, id: i64) -> Result<Option<Art>>

Source

pub fn get_art_meta(&self, id: i64) -> Result<Option<ArtMeta>>

Art row metadata without loading the image blob — used to build synthesis inputs at resolve time without materializing art in memory.

Source

pub fn read_art_chunk_into( &self, art_id: i64, offset: u64, buf: &mut [u8], ) -> Result<()>

Stream art-blob bytes at offset directly into buf via SQLite incremental blob I/O — no intermediate allocation (#70). A short read means the row no longer matches the layout; read_at_exact surfaces that as an error rather than silently zero-filling.

Source

pub fn read_art_chunk( &self, art_id: i64, offset: u64, len: usize, ) -> Result<Vec<u8>>

Allocating convenience form of read_art_chunk_into (non-hot-path callers).

Source

pub fn get_track_art(&self, track_id: i64) -> Result<Vec<TrackArt>>

Source

pub fn get_track_art_with_meta( &self, track_id: i64, ) -> Result<Vec<(TrackArt, Option<ArtMeta>)>>

A track’s track_art links joined with their art row metadata (no image blob), in one query — collapses the former N+1 (get_track_art plus one get_art_meta per row) on the resolve hot path. The art side is None for an orphaned link: SQLite FK enforcement is per-connection, so an external writer can leave a track_art row dangling, and the caller surfaces that rather than silently dropping the art.

Source§

impl Db<ReadWrite>

Source

pub fn upsert_art(&self, a: &NewArt) -> Result<i64>

Source

pub fn set_track_art(&self, track_id: i64, items: &[TrackArt]) -> Result<()>

Source

pub fn gc_orphan_art(&self) -> Result<usize>

Delete art rows no longer referenced by any track_art. Returns the number of rows removed.

Uses NOT EXISTS rather than NOT IN (subquery): SQLite’s NOT IN evaluates to UNKNOWN for the whole row if any subquery value is NULL, which would silently delete nothing should a NULL art_id ever reach track_art (#507). NOT EXISTS is NULL-safe.

Source§

impl Db<ReadWrite>

Source

pub fn apply_bulk_pragmas_self(&self) -> Result<()>

Apply bulk pragmas to this DB’s own connection.

Source

pub fn bulk_writer(&self) -> Result<BulkWriter<'_>>

Begin a batch transaction. All writes go through the returned handle and land atomically on commit().

Source§

impl Db<ReadWrite>

Source

pub fn vacuum(&self) -> Result<()>

Compact the store: reclaim free pages left by deletions, then truncate the WAL. Runs a full VACUUM (rewrites the whole database — transiently needs free disk roughly equal to the store size) followed by PRAGMA wal_checkpoint(TRUNCATE). The TRUNCATE checkpoint after VACUUM is what actually shrinks the main .db file on disk and zeroes the -wal. A busy/locked store (e.g. a live mount) maps to DbError::StoreInUse.

Source§

impl<M> Db<M>

Source

pub fn track_ids_with_structural_blocks(&self) -> Result<HashSet<i64>>

Track ids that have at least one structural block row. Used by revalidate to detect legacy FLAC tracks (scanned under V1) that still need a backfill.

Source

pub fn get_structural_blocks( &self, track_id: i64, ) -> Result<Vec<StructuralBlock>>

Structural blocks for a track, ordered by (kind, ordinal). Empty when a FLAC track has not been (re)scanned under V2 — callers fall back to a front read in that case.

Source§

impl Db<ReadWrite>

Source

pub fn set_structural_blocks( &self, track_id: i64, blocks: &[StructuralBlock], ) -> Result<()>

Replace the track’s structural blocks (FLAC STREAMINFO/SEEKTABLE).

Source§

impl<M> Db<M>

Source

pub fn get_tags(&self, track_id: i64) -> Result<Vec<Tag>>

Source

pub fn tags_for_tracks( &self, track_ids: &[i64], ) -> Result<HashMap<i64, Vec<Tag>>>

Source

pub fn tags_grouped(&self) -> Result<HashMap<i64, Vec<Tag>>>

Source

pub fn tags_grouped_for_keys( &self, keys: &[&str], ) -> Result<HashMap<i64, Vec<Tag>>>

Source

pub fn get_binary_tags(&self, track_id: i64) -> Result<Vec<BinaryTagRow>>

Binary tag rows for a track: streaming handle (rowid), key, and payload length. Ordered by (key, ordinal) to match the layout builder’s emission order. The blob bytes stream at read time; only key (materialized here) is length-guarded, plus the per-track row count.

Source

pub fn read_binary_tag_chunk_into( &self, payload_id: i64, offset: u64, buf: &mut [u8], ) -> Result<()>

Stream binary-tag bytes at offset directly into buf via incremental blob I/O — no intermediate allocation (#70). A short read means the row changed underneath the resolved layout; read_at_exact surfaces it as an error rather than zero-filling. (payload_id is the tags rowid; see the spec’s “payload_id validity invariant”.)

Source

pub fn read_binary_tag_chunk( &self, payload_id: i64, offset: u64, len: usize, ) -> Result<Vec<u8>>

Allocating convenience form of read_binary_tag_chunk_into (non-hot-path callers).

Source§

impl Db<ReadWrite>

Source

pub fn replace_tags(&self, track_id: i64, tags: &[Tag]) -> Result<()>

Source

pub fn set_binary_tags(&self, track_id: i64, tags: &[BinaryTag]) -> Result<()>

Replace the track’s binary tag rows (value_blob IS NOT NULL); text rows (managed by replace_tags) are untouched. Binary rows store ‘’ in value.

Source§

impl<M> Db<M>

Source

pub fn get_track(&self, id: i64) -> Result<Option<Track>>

Source

pub fn get_track_by_path(&self, path: &str) -> Result<Option<Track>>

Source

pub fn list_tracks(&self) -> Result<Vec<Track>>

Source

pub fn track_content_version(&self, id: i64) -> Result<i64>

Source

pub fn track_version_and_path(&self, id: i64) -> Result<Option<(i64, String)>>

The two columns getattr needs to validate cached attrs — the freshness stamp (content_version) and the path to re-stat (backing_path) — without materializing a full Track (no format parse, no TrackBounds) on the hottest metadata op. None if the id is unknown.

Source

pub fn begin_read(&self) -> Result<()>

Begin a deferred (read) transaction: subsequent reads on this connection see a single consistent snapshot until end_read. Used to make a binary-tag read’s content_version check and its blob reads mutually consistent.

Source

pub fn end_read(&self) -> Result<()>

End the read transaction opened by begin_read (rollback — it is read-only).

Source

pub fn list_render_keys(&self) -> Result<Vec<(i64, i64, Format)>>

Cheap render-key identity scan for incremental refresh: (id, content_version, format) for every track, ordered by id. No tags, no path columns — just the two track-level inputs that determine a rendered path. See SP2 Component 1.

Source

pub fn changelog_since(&self, last_seq: i64) -> Result<ChangelogRead>

One read of the changelog ring past last_seq: the distinct changed track ids (ascending) plus the table’s retained seq bounds (0/0 when empty). The caller derives gap detection from min_seq (see musefs-core’s refresh).

Source

pub fn render_keys_for(&self, ids: &[i64]) -> Result<Vec<(i64, i64, Format)>>

Render keys for a specific id set (the changelog ids); ids no longer in tracks are simply absent from the result. Chunked like tags_for_tracks.

Source§

impl Db<ReadWrite>

Source

pub fn upsert_track(&self, t: &NewTrack) -> Result<i64>

Source

pub fn delete_track(&self, id: i64) -> Result<()>

Delete a track row. Foreign keys cascade to its tags and track_art rows; the referenced art rows are left for gc_orphan_art.

Source

pub fn tracks_by_fingerprint(&self, fp: &str) -> Result<Vec<Track>>

All tracks whose stored fingerprint equals fp (rows with NULL fingerprint never match). Used by the scan refind to find move candidates.

Source

pub fn set_track_checksums( &self, id: i64, fingerprint: Option<&str>, content_hash: Option<&str>, ) -> Result<()>

Set the scanner-owned checksums for a track. A None argument leaves the existing column value intact (COALESCE), so a lower-tier pass never clears a higher tier’s value.

Source

pub fn retarget_track( &self, id: i64, new_backing_path: &str, backing_size: u64, backing_mtime_ns: i64, backing_ctime_ns: i64, audio_offset: u64, audio_length: u64, fingerprint: Option<&str>, content_hash: Option<&str>, ) -> Result<()>

Point an existing track at a relocated backing file: update its path, validation stamp, and audio bounds in place, preserving its id (and thus its tags/art/structural blocks). Checksum args COALESCE like set_track_checksums. updated_at is refreshed; content_version is left to the geometry trigger (it bumps only if backing_mtime_ns actually changed — a pure move preserves mtime, so no bump).

Source§

impl Db<ReadWrite>

Source

pub fn open<P: AsRef<Path>>(path: P) -> Result<Db>

Source

pub fn open_in_memory() -> Result<Db>

Source

pub fn into_read_only(self) -> Db<ReadOnly>

Degrade to the read-only surface, keeping the same connection. The change is type-level only — runtime behavior is unchanged. The only intended caller is musefs_core’s DbPool::new, which strips write access from the mount connection before the serve path can see it.

Source§

impl Db<ReadOnly>

Source

pub fn open_readonly<P: AsRef<Path>>(path: P) -> Result<Db<ReadOnly>>

Open an additional read-only connection to an existing file-backed DB. WAL (set by the writer) lets these run concurrently without blocking. No migration is run — the schema already exists and the connection is RO. Note: even with SQLITE_OPEN_READ_ONLY, SQLite needs write access to the directory (to create/use the -shm wal-index) when the DB is in WAL mode; a strictly read-only DB directory will make this fail.

Source§

impl<M> Db<M>

Source

pub fn user_version(&self) -> Result<i64>

Source

pub fn data_version(&self) -> Result<i64>

Source

pub fn path(&self) -> Option<&Path>

The backing file path, or None for an in-memory database.

Trait Implementations§

Source§

impl<M: Debug> Debug for Db<M>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<M = ReadWrite> !Freeze for Db<M>

§

impl<M = ReadWrite> !RefUnwindSafe for Db<M>

§

impl<M = ReadWrite> !Sync for Db<M>

§

impl<M = ReadWrite> !UnwindSafe for Db<M>

§

impl<M> Send for Db<M>
where M: Send,

§

impl<M> Unpin for Db<M>
where M: Unpin,

§

impl<M> UnsafeUnpin for Db<M>

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.

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