changed genre scanning to parse multiple genres, updated db to accommodate.

This commit is contained in:
2026-02-22 13:59:28 -05:00
parent 3947c2d6aa
commit 9cb1c6674a
24 changed files with 457 additions and 40 deletions
+7 -1
View File
@@ -80,7 +80,13 @@ SELECT
r.track_number,
r.disc_number,
COALESCE(rg.name, '') AS album,
COALESCE(r.genre, '') AS genre,
CAST(COALESCE(
(SELECT GROUP_CONCAT(g.name, '||')
FROM recording_genres rg_sub
JOIN genres g ON rg_sub.genre_id = g.id
WHERE rg_sub.recording_id = r.id),
''
) AS TEXT) AS genre,
COALESCE(r.year, 0) AS year,
COALESCE(r.composer, '') AS composer,
COALESCE(ft.extension, '') AS file_type
+24
View File
@@ -0,0 +1,24 @@
-- name: UpsertGenre :one
INSERT INTO genres (name) VALUES (?)
ON CONFLICT(name) DO UPDATE SET name = name
RETURNING *;
-- name: CreateRecordingGenre :exec
INSERT OR IGNORE INTO recording_genres (recording_id, genre_id)
VALUES (?, ?);
-- name: DeleteRecordingGenres :exec
DELETE FROM recording_genres
WHERE recording_id = ?;
-- name: GetGenresByRecordingID :many
SELECT g.*
FROM genres g
JOIN recording_genres rg ON g.id = rg.genre_id
WHERE rg.recording_id = ?;
-- name: DeleteAllRecordingGenres :exec
DELETE FROM recording_genres;
-- name: DeleteAllGenres :exec
DELETE FROM genres;
@@ -5,3 +5,9 @@ CREATE TABLE IF NOT EXISTS artist_credit_artist (
FOREIGN KEY(artist_id) REFERENCES artists(id),
FOREIGN KEY(credit_id) REFERENCES artist_credit(id)
);
CREATE INDEX IF NOT EXISTS idx_artist_credit_artist_artist_id
ON artist_credit_artist(artist_id);
CREATE INDEX IF NOT EXISTS idx_artist_credit_artist_credit_id
ON artist_credit_artist(credit_id);
@@ -7,3 +7,6 @@ CREATE TABLE IF NOT EXISTS audio_files (
FOREIGN KEY(file_type_id) REFERENCES file_types(id),
FOREIGN KEY(recording_id) REFERENCES recordings(id)
);
CREATE INDEX IF NOT EXISTS idx_audio_files_recording_id
ON audio_files(recording_id);
@@ -2,3 +2,8 @@ CREATE TABLE IF NOT EXISTS file_types (
id integer PRIMARY KEY,
extension text NOT NULL UNIQUE
);
INSERT OR IGNORE INTO file_types (id, extension) VALUES (0, '.mp3');
INSERT OR IGNORE INTO file_types (id, extension) VALUES (1, '.flac');
INSERT OR IGNORE INTO file_types (id, extension) VALUES (2, '.ogg');
INSERT OR IGNORE INTO file_types (id, extension) VALUES (3, '.wav');
@@ -0,0 +1,14 @@
CREATE TABLE IF NOT EXISTS recording_genres (
id INTEGER PRIMARY KEY,
recording_id INTEGER NOT NULL,
genre_id INTEGER NOT NULL,
FOREIGN KEY(recording_id) REFERENCES recordings(id),
FOREIGN KEY(genre_id) REFERENCES genres(id),
UNIQUE(recording_id, genre_id)
);
CREATE INDEX IF NOT EXISTS idx_recording_genres_recording_id
ON recording_genres(recording_id);
CREATE INDEX IF NOT EXISTS idx_recording_genres_genre_id
ON recording_genres(genre_id);
+4
View File
@@ -0,0 +1,4 @@
CREATE TABLE IF NOT EXISTS genres (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE
);
-32
View File
@@ -1,32 +0,0 @@
CREATE INDEX IF NOT EXISTS idx_playlist_tracks_playlist_id
ON playlist_tracks(playlist_id);
CREATE INDEX IF NOT EXISTS idx_playlist_tracks_audio_file_id
ON playlist_tracks(audio_file_id);
CREATE INDEX IF NOT EXISTS idx_audio_files_recording_id
ON audio_files(recording_id);
CREATE INDEX IF NOT EXISTS idx_recordings_artist_credit_id
ON recordings(artist_credit_id);
CREATE INDEX IF NOT EXISTS idx_release_group_recordings_recording_id
ON release_group_recordings(recording_id);
CREATE INDEX IF NOT EXISTS idx_release_group_recordings_release_group_id
ON release_group_recordings(release_group_id);
CREATE INDEX IF NOT EXISTS idx_release_groups_cover_art_id
ON release_groups(cover_art_id);
CREATE INDEX IF NOT EXISTS idx_release_groups_album_artist_credit_id
ON release_groups(album_artist_credit_id);
CREATE INDEX IF NOT EXISTS idx_queue_tracks_audio_file_id
ON queue_tracks(audio_file_id);
CREATE INDEX IF NOT EXISTS idx_artist_credit_artist_artist_id
ON artist_credit_artist(artist_id);
CREATE INDEX IF NOT EXISTS idx_artist_credit_artist_credit_id
ON artist_credit_artist(credit_id);
@@ -6,3 +6,9 @@ CREATE TABLE IF NOT EXISTS playlist_tracks (
FOREIGN KEY(playlist_id) REFERENCES playlists(id) ON DELETE CASCADE,
FOREIGN KEY(audio_file_id) REFERENCES audio_files(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_playlist_tracks_playlist_id
ON playlist_tracks(playlist_id);
CREATE INDEX IF NOT EXISTS idx_playlist_tracks_audio_file_id
ON playlist_tracks(audio_file_id);
@@ -4,3 +4,6 @@ CREATE TABLE IF NOT EXISTS queue_tracks (
position INTEGER NOT NULL,
FOREIGN KEY(audio_file_id) REFERENCES audio_files(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_queue_tracks_audio_file_id
ON queue_tracks(audio_file_id);
@@ -11,3 +11,6 @@ CREATE TABLE IF NOT EXISTS recordings (
comment TEXT,
FOREIGN KEY(artist_credit_id) REFERENCES artist_credit(id)
);
CREATE INDEX IF NOT EXISTS idx_recordings_artist_credit_id
ON recordings(artist_credit_id);
@@ -7,3 +7,9 @@ CREATE TABLE IF NOT EXISTS release_group_recordings (
FOREIGN KEY(release_group_id) REFERENCES release_groups(id),
FOREIGN KEY(recording_id) REFERENCES recordings(id)
);
CREATE INDEX IF NOT EXISTS idx_release_group_recordings_recording_id
ON release_group_recordings(recording_id);
CREATE INDEX IF NOT EXISTS idx_release_group_recordings_release_group_id
ON release_group_recordings(release_group_id);
@@ -9,3 +9,9 @@ CREATE TABLE IF NOT EXISTS release_groups (
FOREIGN KEY(cover_art_id) REFERENCES cover_art(id),
FOREIGN KEY(album_artist_credit_id) REFERENCES artist_credit(id)
);
CREATE INDEX IF NOT EXISTS idx_release_groups_cover_art_id
ON release_groups(cover_art_id);
CREATE INDEX IF NOT EXISTS idx_release_groups_album_artist_credit_id
ON release_groups(album_artist_credit_id);
@@ -199,7 +199,13 @@ SELECT
r.track_number,
r.disc_number,
COALESCE(rg.name, '') AS album,
COALESCE(r.genre, '') AS genre,
CAST(COALESCE(
(SELECT GROUP_CONCAT(g.name, '||')
FROM recording_genres rg_sub
JOIN genres g ON rg_sub.genre_id = g.id
WHERE rg_sub.recording_id = r.id),
''
) AS TEXT) AS genre,
COALESCE(r.year, 0) AS year,
COALESCE(r.composer, '') AS composer,
COALESCE(ft.extension, '') AS file_type
@@ -0,0 +1,96 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: genres.sql
package sqlcgen
import (
"context"
)
const createRecordingGenre = `-- name: CreateRecordingGenre :exec
INSERT OR IGNORE INTO recording_genres (recording_id, genre_id)
VALUES (?, ?)
`
type CreateRecordingGenreParams struct {
RecordingID int64
GenreID int64
}
func (q *Queries) CreateRecordingGenre(ctx context.Context, arg CreateRecordingGenreParams) error {
_, err := q.db.ExecContext(ctx, createRecordingGenre, arg.RecordingID, arg.GenreID)
return err
}
const deleteAllGenres = `-- name: DeleteAllGenres :exec
DELETE FROM genres
`
func (q *Queries) DeleteAllGenres(ctx context.Context) error {
_, err := q.db.ExecContext(ctx, deleteAllGenres)
return err
}
const deleteAllRecordingGenres = `-- name: DeleteAllRecordingGenres :exec
DELETE FROM recording_genres
`
func (q *Queries) DeleteAllRecordingGenres(ctx context.Context) error {
_, err := q.db.ExecContext(ctx, deleteAllRecordingGenres)
return err
}
const deleteRecordingGenres = `-- name: DeleteRecordingGenres :exec
DELETE FROM recording_genres
WHERE recording_id = ?
`
func (q *Queries) DeleteRecordingGenres(ctx context.Context, recordingID int64) error {
_, err := q.db.ExecContext(ctx, deleteRecordingGenres, recordingID)
return err
}
const getGenresByRecordingID = `-- name: GetGenresByRecordingID :many
SELECT g.id, g.name
FROM genres g
JOIN recording_genres rg ON g.id = rg.genre_id
WHERE rg.recording_id = ?
`
func (q *Queries) GetGenresByRecordingID(ctx context.Context, recordingID int64) ([]Genre, error) {
rows, err := q.db.QueryContext(ctx, getGenresByRecordingID, recordingID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Genre
for rows.Next() {
var i Genre
if err := rows.Scan(&i.ID, &i.Name); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const upsertGenre = `-- name: UpsertGenre :one
INSERT INTO genres (name) VALUES (?)
ON CONFLICT(name) DO UPDATE SET name = name
RETURNING id, name
`
func (q *Queries) UpsertGenre(ctx context.Context, name string) (Genre, error) {
row := q.db.QueryRowContext(ctx, upsertGenre, name)
var i Genre
err := row.Scan(&i.ID, &i.Name)
return i, err
}
+11
View File
@@ -45,6 +45,11 @@ type FileType struct {
Extension string
}
type Genre struct {
ID int64
Name string
}
type PlayerState struct {
ID int64
Volume int64
@@ -95,6 +100,12 @@ type Recording struct {
Comment sql.NullString
}
type RecordingGenre struct {
ID int64
RecordingID int64
GenreID int64
}
type ReleaseGroup struct {
ID int64
Name string