fix(library): multi-genre local index with track_genre and backfill (#1059)

* fix(library): multi-genre local index with track_genre and backfill

Restore atomic genre browse, filters, and counts via track_genre:
OpenSubsonic genres[] first with Navidrome-default split fallback, sync
write path, read-path query switches, blocking startup backfill with
progress, and v12 repair migration for DBs that recorded legacy 002–011.
TS fallback adds genreTagsFor and migration gate i18n across locales.

* fix(library): address multi-genre review — robust TS genres and scope join

genreTagsFor routes raw genres through parseItemGenres (single-object
Subsonic quirk and bare strings). Library-scoped genre browse/counts join
track for raw_json library_id fallback. Statistics keeps empty-genre bucket.

* docs: CHANGELOG and credits for multi-genre local index (PR #1059)

* docs(changelog): credit HiveMind on Discord for multi-genre report (PR #1059)
This commit is contained in:
cucadmuh
2026-06-11 01:02:35 +03:00
committed by GitHub
parent 8593858f3a
commit 5cd01c90ac
55 changed files with 1322 additions and 145 deletions
@@ -248,6 +248,23 @@ CREATE TABLE play_session (
CHECK (completion IN ('partial', 'full'))
);
CREATE TABLE track_genre (
server_id TEXT NOT NULL,
track_id TEXT NOT NULL,
genre TEXT NOT NULL,
album_id TEXT,
library_id TEXT,
PRIMARY KEY (server_id, track_id, genre COLLATE NOCASE),
FOREIGN KEY (server_id, track_id) REFERENCES track(server_id, id) ON DELETE CASCADE
);
CREATE TABLE library_data_migration (
id TEXT PRIMARY KEY,
cursor_rowid INTEGER NOT NULL DEFAULT 0,
completed_at INTEGER,
started_at INTEGER
);
CREATE INDEX idx_track_album ON track(server_id, album_id) WHERE deleted = 0;
CREATE INDEX idx_track_artist ON track(server_id, artist_id) WHERE deleted = 0;
CREATE INDEX idx_track_updated ON track(server_id, server_updated_at DESC) WHERE deleted = 0;
@@ -293,3 +310,7 @@ CREATE INDEX idx_play_session_started
CREATE INDEX idx_track_fact_mood_tag
ON track_fact(server_id, fact_kind, value_text, track_id)
WHERE fact_kind = 'mood_tag';
CREATE INDEX idx_track_genre_browse
ON track_genre(server_id, genre COLLATE NOCASE, album_id, track_id)
WHERE album_id IS NOT NULL AND album_id != '';