feat(13-01): add library-filtered sqlc queries for all browse views
- GetAllTracksWithFullMetadataByLibrary for tracks filtered by library - GetAudioFilesByReleaseGroupByLibrary for album tracks in a library - GetAllAlbumsWithDetailsByLibrary for albums with tracks in a library - GetAlbumsByArtistByLibrary for artist albums in a library - GetAlbumArtistsByLibrary for artists with albums in a library - GetAllGenresWithCountsByLibrary for genre counts within a library - GetTracksByGenreByLibrary for genre tracks within a library
This commit is contained in:
@@ -38,3 +38,21 @@ JOIN artist_credit_artist aca ON aca.artist_id = a.id
|
|||||||
JOIN artist_credit ac ON ac.id = aca.credit_id
|
JOIN artist_credit ac ON ac.id = aca.credit_id
|
||||||
JOIN release_groups rg ON rg.album_artist_credit_id = ac.id
|
JOIN release_groups rg ON rg.album_artist_credit_id = ac.id
|
||||||
ORDER BY a.name;
|
ORDER BY a.name;
|
||||||
|
|
||||||
|
-- name: GetAlbumArtistsByLibrary :many
|
||||||
|
SELECT DISTINCT a.id, a.name
|
||||||
|
FROM artists a
|
||||||
|
JOIN artist_credit_artist aca ON aca.artist_id = a.id
|
||||||
|
JOIN artist_credit ac ON ac.id = aca.credit_id
|
||||||
|
JOIN release_groups rg ON rg.album_artist_credit_id = ac.id
|
||||||
|
WHERE a.id IN (
|
||||||
|
SELECT DISTINCT aca2.artist_id
|
||||||
|
FROM artist_credit_artist aca2
|
||||||
|
JOIN artist_credit ac2 ON ac2.id = aca2.credit_id
|
||||||
|
JOIN release_groups rg2 ON rg2.album_artist_credit_id = ac2.id
|
||||||
|
JOIN release_group_recordings rgr2 ON rgr2.release_group_id = rg2.id
|
||||||
|
JOIN recordings r2 ON r2.id = rgr2.recording_id
|
||||||
|
JOIN audio_files af2 ON af2.recording_id = r2.id
|
||||||
|
WHERE af2.library_id = ?
|
||||||
|
)
|
||||||
|
ORDER BY a.name;
|
||||||
|
|||||||
@@ -136,6 +136,38 @@ SELECT COUNT(*) AS count FROM audio_files WHERE library_id = ?;
|
|||||||
-- name: DeleteAllAudioFiles :exec
|
-- name: DeleteAllAudioFiles :exec
|
||||||
DELETE FROM audio_files;
|
DELETE FROM audio_files;
|
||||||
|
|
||||||
|
-- name: GetAllTracksWithFullMetadataByLibrary :many
|
||||||
|
SELECT
|
||||||
|
af.file_path,
|
||||||
|
af.length_milliseconds,
|
||||||
|
COALESCE(r.name, '') AS title,
|
||||||
|
COALESCE(ac.text, '') AS artist_name,
|
||||||
|
r.track_number,
|
||||||
|
r.disc_number,
|
||||||
|
COALESCE(rg.name, '') AS album,
|
||||||
|
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,
|
||||||
|
af.sample_rate,
|
||||||
|
af.bit_depth,
|
||||||
|
af.channels,
|
||||||
|
af.bitrate,
|
||||||
|
af.file_size
|
||||||
|
FROM audio_files af
|
||||||
|
JOIN recordings r ON af.recording_id = r.id
|
||||||
|
JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
||||||
|
LEFT JOIN release_group_recordings rgr ON r.id = rgr.recording_id
|
||||||
|
LEFT JOIN release_groups rg ON rgr.release_group_id = rg.id
|
||||||
|
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||||
|
WHERE af.library_id = ?;
|
||||||
|
|
||||||
-- name: GetAudioFilesByReleaseGroup :many
|
-- name: GetAudioFilesByReleaseGroup :many
|
||||||
SELECT
|
SELECT
|
||||||
af.file_path,
|
af.file_path,
|
||||||
@@ -168,3 +200,36 @@ LEFT JOIN release_groups rg ON rgr.release_group_id = rg.id
|
|||||||
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||||
WHERE rgr.release_group_id = ?
|
WHERE rgr.release_group_id = ?
|
||||||
ORDER BY rgr.disc_number, rgr.track_number;
|
ORDER BY rgr.disc_number, rgr.track_number;
|
||||||
|
|
||||||
|
-- name: GetAudioFilesByReleaseGroupByLibrary :many
|
||||||
|
SELECT
|
||||||
|
af.file_path,
|
||||||
|
af.length_milliseconds,
|
||||||
|
COALESCE(r.name, '') AS title,
|
||||||
|
COALESCE(ac.text, '') AS artist_name,
|
||||||
|
rgr.track_number,
|
||||||
|
rgr.disc_number,
|
||||||
|
COALESCE(rg.name, '') AS album,
|
||||||
|
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,
|
||||||
|
af.sample_rate,
|
||||||
|
af.bit_depth,
|
||||||
|
af.channels,
|
||||||
|
af.bitrate,
|
||||||
|
af.file_size
|
||||||
|
FROM release_group_recordings rgr
|
||||||
|
JOIN recordings r ON rgr.recording_id = r.id
|
||||||
|
JOIN audio_files af ON af.recording_id = r.id
|
||||||
|
LEFT JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
||||||
|
LEFT JOIN release_groups rg ON rgr.release_group_id = rg.id
|
||||||
|
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||||
|
WHERE rgr.release_group_id = ? AND af.library_id = ?
|
||||||
|
ORDER BY rgr.disc_number, rgr.track_number;
|
||||||
|
|||||||
@@ -63,9 +63,59 @@ LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
|||||||
WHERE g.name = ?
|
WHERE g.name = ?
|
||||||
ORDER BY r.name;
|
ORDER BY r.name;
|
||||||
|
|
||||||
|
-- name: GetTracksByGenreByLibrary :many
|
||||||
|
SELECT
|
||||||
|
af.file_path,
|
||||||
|
af.length_milliseconds,
|
||||||
|
COALESCE(r.name, '') AS title,
|
||||||
|
COALESCE(ac.text, '') AS artist_name,
|
||||||
|
r.track_number,
|
||||||
|
r.disc_number,
|
||||||
|
COALESCE(rlg.name, '') AS album,
|
||||||
|
CAST(COALESCE(
|
||||||
|
(SELECT GROUP_CONCAT(g2.name, '||')
|
||||||
|
FROM recording_genres rg2
|
||||||
|
JOIN genres g2 ON rg2.genre_id = g2.id
|
||||||
|
WHERE rg2.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,
|
||||||
|
af.sample_rate,
|
||||||
|
af.bit_depth,
|
||||||
|
af.channels,
|
||||||
|
af.bitrate,
|
||||||
|
af.file_size
|
||||||
|
FROM genres g
|
||||||
|
JOIN recording_genres rg ON g.id = rg.genre_id
|
||||||
|
JOIN recordings r ON rg.recording_id = r.id
|
||||||
|
JOIN audio_files af ON af.recording_id = r.id
|
||||||
|
JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT recording_id,
|
||||||
|
MIN(release_group_id) AS release_group_id
|
||||||
|
FROM release_group_recordings
|
||||||
|
GROUP BY recording_id
|
||||||
|
) rgr ON r.id = rgr.recording_id
|
||||||
|
LEFT JOIN release_groups rlg ON rgr.release_group_id = rlg.id
|
||||||
|
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||||
|
WHERE g.name = ? AND af.library_id = ?
|
||||||
|
ORDER BY r.name;
|
||||||
|
|
||||||
-- name: GetAllGenresWithCounts :many
|
-- name: GetAllGenresWithCounts :many
|
||||||
SELECT g.name, COUNT(rg.recording_id) AS track_count
|
SELECT g.name, COUNT(rg.recording_id) AS track_count
|
||||||
FROM genres g
|
FROM genres g
|
||||||
JOIN recording_genres rg ON g.id = rg.genre_id
|
JOIN recording_genres rg ON g.id = rg.genre_id
|
||||||
GROUP BY g.id, g.name
|
GROUP BY g.id, g.name
|
||||||
ORDER BY g.name;
|
ORDER BY g.name;
|
||||||
|
|
||||||
|
-- name: GetAllGenresWithCountsByLibrary :many
|
||||||
|
SELECT g.name, COUNT(rg.recording_id) AS track_count
|
||||||
|
FROM genres g
|
||||||
|
JOIN recording_genres rg ON g.id = rg.genre_id
|
||||||
|
JOIN recordings r ON rg.recording_id = r.id
|
||||||
|
JOIN audio_files af ON af.recording_id = r.id
|
||||||
|
WHERE af.library_id = ?
|
||||||
|
GROUP BY g.id, g.name
|
||||||
|
ORDER BY g.name;
|
||||||
|
|||||||
@@ -64,6 +64,32 @@ LEFT JOIN (
|
|||||||
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
||||||
ORDER BY rg.name;
|
ORDER BY rg.name;
|
||||||
|
|
||||||
|
-- name: GetAllAlbumsWithDetailsByLibrary :many
|
||||||
|
SELECT
|
||||||
|
rg.id,
|
||||||
|
rg.name,
|
||||||
|
rg.year,
|
||||||
|
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
|
||||||
|
COALESCE(ca.file_path, '') as cover_art_path
|
||||||
|
FROM release_groups rg
|
||||||
|
LEFT JOIN artist_credit ac ON rg.album_artist_credit_id = ac.id
|
||||||
|
LEFT JOIN cover_art ca ON rg.cover_art_id = ca.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT rgr.release_group_id, ac2.text
|
||||||
|
FROM release_group_recordings rgr
|
||||||
|
JOIN recordings rec ON rec.id = rgr.recording_id
|
||||||
|
JOIN artist_credit ac2 ON ac2.id = rec.artist_credit_id
|
||||||
|
GROUP BY rgr.release_group_id
|
||||||
|
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
||||||
|
WHERE rg.id IN (
|
||||||
|
SELECT DISTINCT rgr2.release_group_id
|
||||||
|
FROM release_group_recordings rgr2
|
||||||
|
JOIN recordings r2 ON r2.id = rgr2.recording_id
|
||||||
|
JOIN audio_files af2 ON af2.recording_id = r2.id
|
||||||
|
WHERE af2.library_id = ?
|
||||||
|
)
|
||||||
|
ORDER BY rg.name;
|
||||||
|
|
||||||
-- name: GetAlbumsByArtist :many
|
-- name: GetAlbumsByArtist :many
|
||||||
SELECT
|
SELECT
|
||||||
rg.id,
|
rg.id,
|
||||||
@@ -84,3 +110,31 @@ LEFT JOIN (
|
|||||||
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
||||||
WHERE aca.artist_id = ?
|
WHERE aca.artist_id = ?
|
||||||
ORDER BY rg.name;
|
ORDER BY rg.name;
|
||||||
|
|
||||||
|
-- name: GetAlbumsByArtistByLibrary :many
|
||||||
|
SELECT
|
||||||
|
rg.id,
|
||||||
|
rg.name,
|
||||||
|
rg.year,
|
||||||
|
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
|
||||||
|
COALESCE(ca.file_path, '') as cover_art_path
|
||||||
|
FROM release_groups rg
|
||||||
|
JOIN artist_credit ac ON rg.album_artist_credit_id = ac.id
|
||||||
|
JOIN artist_credit_artist aca ON aca.credit_id = ac.id
|
||||||
|
LEFT JOIN cover_art ca ON rg.cover_art_id = ca.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT rgr.release_group_id, ac2.text
|
||||||
|
FROM release_group_recordings rgr
|
||||||
|
JOIN recordings rec ON rec.id = rgr.recording_id
|
||||||
|
JOIN artist_credit ac2 ON ac2.id = rec.artist_credit_id
|
||||||
|
GROUP BY rgr.release_group_id
|
||||||
|
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
||||||
|
WHERE aca.artist_id = ?
|
||||||
|
AND rg.id IN (
|
||||||
|
SELECT DISTINCT rgr2.release_group_id
|
||||||
|
FROM release_group_recordings rgr2
|
||||||
|
JOIN recordings r2 ON r2.id = rgr2.recording_id
|
||||||
|
JOIN audio_files af2 ON af2.recording_id = r2.id
|
||||||
|
WHERE af2.library_id = ?
|
||||||
|
)
|
||||||
|
ORDER BY rg.name;
|
||||||
|
|||||||
@@ -72,6 +72,48 @@ func (q *Queries) GetAlbumArtists(ctx context.Context) ([]Artist, error) {
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAlbumArtistsByLibrary = `-- name: GetAlbumArtistsByLibrary :many
|
||||||
|
SELECT DISTINCT a.id, a.name
|
||||||
|
FROM artists a
|
||||||
|
JOIN artist_credit_artist aca ON aca.artist_id = a.id
|
||||||
|
JOIN artist_credit ac ON ac.id = aca.credit_id
|
||||||
|
JOIN release_groups rg ON rg.album_artist_credit_id = ac.id
|
||||||
|
WHERE a.id IN (
|
||||||
|
SELECT DISTINCT aca2.artist_id
|
||||||
|
FROM artist_credit_artist aca2
|
||||||
|
JOIN artist_credit ac2 ON ac2.id = aca2.credit_id
|
||||||
|
JOIN release_groups rg2 ON rg2.album_artist_credit_id = ac2.id
|
||||||
|
JOIN release_group_recordings rgr2 ON rgr2.release_group_id = rg2.id
|
||||||
|
JOIN recordings r2 ON r2.id = rgr2.recording_id
|
||||||
|
JOIN audio_files af2 ON af2.recording_id = r2.id
|
||||||
|
WHERE af2.library_id = ?
|
||||||
|
)
|
||||||
|
ORDER BY a.name
|
||||||
|
`
|
||||||
|
|
||||||
|
func (q *Queries) GetAlbumArtistsByLibrary(ctx context.Context, libraryID int64) ([]Artist, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getAlbumArtistsByLibrary, libraryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []Artist
|
||||||
|
for rows.Next() {
|
||||||
|
var i Artist
|
||||||
|
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 getAllArtists = `-- name: GetAllArtists :many
|
const getAllArtists = `-- name: GetAllArtists :many
|
||||||
SELECT id, name FROM artists
|
SELECT id, name FROM artists
|
||||||
ORDER BY name
|
ORDER BY name
|
||||||
|
|||||||
@@ -321,6 +321,98 @@ func (q *Queries) GetAllTracksWithFullMetadata(ctx context.Context) ([]GetAllTra
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAllTracksWithFullMetadataByLibrary = `-- name: GetAllTracksWithFullMetadataByLibrary :many
|
||||||
|
SELECT
|
||||||
|
af.file_path,
|
||||||
|
af.length_milliseconds,
|
||||||
|
COALESCE(r.name, '') AS title,
|
||||||
|
COALESCE(ac.text, '') AS artist_name,
|
||||||
|
r.track_number,
|
||||||
|
r.disc_number,
|
||||||
|
COALESCE(rg.name, '') AS album,
|
||||||
|
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,
|
||||||
|
af.sample_rate,
|
||||||
|
af.bit_depth,
|
||||||
|
af.channels,
|
||||||
|
af.bitrate,
|
||||||
|
af.file_size
|
||||||
|
FROM audio_files af
|
||||||
|
JOIN recordings r ON af.recording_id = r.id
|
||||||
|
JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
||||||
|
LEFT JOIN release_group_recordings rgr ON r.id = rgr.recording_id
|
||||||
|
LEFT JOIN release_groups rg ON rgr.release_group_id = rg.id
|
||||||
|
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||||
|
WHERE af.library_id = ?
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetAllTracksWithFullMetadataByLibraryRow struct {
|
||||||
|
FilePath string
|
||||||
|
LengthMilliseconds int64
|
||||||
|
Title string
|
||||||
|
ArtistName string
|
||||||
|
TrackNumber sql.NullInt64
|
||||||
|
DiscNumber sql.NullInt64
|
||||||
|
Album string
|
||||||
|
Genre string
|
||||||
|
Year int64
|
||||||
|
Composer string
|
||||||
|
FileType string
|
||||||
|
SampleRate int64
|
||||||
|
BitDepth int64
|
||||||
|
Channels int64
|
||||||
|
Bitrate int64
|
||||||
|
FileSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetAllTracksWithFullMetadataByLibrary(ctx context.Context, libraryID int64) ([]GetAllTracksWithFullMetadataByLibraryRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getAllTracksWithFullMetadataByLibrary, libraryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetAllTracksWithFullMetadataByLibraryRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetAllTracksWithFullMetadataByLibraryRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.FilePath,
|
||||||
|
&i.LengthMilliseconds,
|
||||||
|
&i.Title,
|
||||||
|
&i.ArtistName,
|
||||||
|
&i.TrackNumber,
|
||||||
|
&i.DiscNumber,
|
||||||
|
&i.Album,
|
||||||
|
&i.Genre,
|
||||||
|
&i.Year,
|
||||||
|
&i.Composer,
|
||||||
|
&i.FileType,
|
||||||
|
&i.SampleRate,
|
||||||
|
&i.BitDepth,
|
||||||
|
&i.Channels,
|
||||||
|
&i.Bitrate,
|
||||||
|
&i.FileSize,
|
||||||
|
); 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 getAudioFile = `-- name: GetAudioFile :one
|
const getAudioFile = `-- name: GetAudioFile :one
|
||||||
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id FROM audio_files
|
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id FROM audio_files
|
||||||
WHERE id = ? LIMIT 1
|
WHERE id = ? LIMIT 1
|
||||||
@@ -504,6 +596,104 @@ func (q *Queries) GetAudioFilesByReleaseGroup(ctx context.Context, releaseGroupI
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAudioFilesByReleaseGroupByLibrary = `-- name: GetAudioFilesByReleaseGroupByLibrary :many
|
||||||
|
SELECT
|
||||||
|
af.file_path,
|
||||||
|
af.length_milliseconds,
|
||||||
|
COALESCE(r.name, '') AS title,
|
||||||
|
COALESCE(ac.text, '') AS artist_name,
|
||||||
|
rgr.track_number,
|
||||||
|
rgr.disc_number,
|
||||||
|
COALESCE(rg.name, '') AS album,
|
||||||
|
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,
|
||||||
|
af.sample_rate,
|
||||||
|
af.bit_depth,
|
||||||
|
af.channels,
|
||||||
|
af.bitrate,
|
||||||
|
af.file_size
|
||||||
|
FROM release_group_recordings rgr
|
||||||
|
JOIN recordings r ON rgr.recording_id = r.id
|
||||||
|
JOIN audio_files af ON af.recording_id = r.id
|
||||||
|
LEFT JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
||||||
|
LEFT JOIN release_groups rg ON rgr.release_group_id = rg.id
|
||||||
|
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||||
|
WHERE rgr.release_group_id = ? AND af.library_id = ?
|
||||||
|
ORDER BY rgr.disc_number, rgr.track_number
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetAudioFilesByReleaseGroupByLibraryParams struct {
|
||||||
|
ReleaseGroupID int64
|
||||||
|
LibraryID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAudioFilesByReleaseGroupByLibraryRow struct {
|
||||||
|
FilePath string
|
||||||
|
LengthMilliseconds int64
|
||||||
|
Title string
|
||||||
|
ArtistName string
|
||||||
|
TrackNumber sql.NullInt64
|
||||||
|
DiscNumber sql.NullInt64
|
||||||
|
Album string
|
||||||
|
Genre string
|
||||||
|
Year int64
|
||||||
|
Composer string
|
||||||
|
FileType string
|
||||||
|
SampleRate int64
|
||||||
|
BitDepth int64
|
||||||
|
Channels int64
|
||||||
|
Bitrate int64
|
||||||
|
FileSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetAudioFilesByReleaseGroupByLibrary(ctx context.Context, arg GetAudioFilesByReleaseGroupByLibraryParams) ([]GetAudioFilesByReleaseGroupByLibraryRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getAudioFilesByReleaseGroupByLibrary, arg.ReleaseGroupID, arg.LibraryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetAudioFilesByReleaseGroupByLibraryRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetAudioFilesByReleaseGroupByLibraryRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.FilePath,
|
||||||
|
&i.LengthMilliseconds,
|
||||||
|
&i.Title,
|
||||||
|
&i.ArtistName,
|
||||||
|
&i.TrackNumber,
|
||||||
|
&i.DiscNumber,
|
||||||
|
&i.Album,
|
||||||
|
&i.Genre,
|
||||||
|
&i.Year,
|
||||||
|
&i.Composer,
|
||||||
|
&i.FileType,
|
||||||
|
&i.SampleRate,
|
||||||
|
&i.BitDepth,
|
||||||
|
&i.Channels,
|
||||||
|
&i.Bitrate,
|
||||||
|
&i.FileSize,
|
||||||
|
); 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 getAudioFilesNeedingMetadata = `-- name: GetAudioFilesNeedingMetadata :many
|
const getAudioFilesNeedingMetadata = `-- name: GetAudioFilesNeedingMetadata :many
|
||||||
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id FROM audio_files
|
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id FROM audio_files
|
||||||
WHERE recording_id = 0
|
WHERE recording_id = 0
|
||||||
|
|||||||
@@ -89,6 +89,45 @@ func (q *Queries) GetAllGenresWithCounts(ctx context.Context) ([]GetAllGenresWit
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAllGenresWithCountsByLibrary = `-- name: GetAllGenresWithCountsByLibrary :many
|
||||||
|
SELECT g.name, COUNT(rg.recording_id) AS track_count
|
||||||
|
FROM genres g
|
||||||
|
JOIN recording_genres rg ON g.id = rg.genre_id
|
||||||
|
JOIN recordings r ON rg.recording_id = r.id
|
||||||
|
JOIN audio_files af ON af.recording_id = r.id
|
||||||
|
WHERE af.library_id = ?
|
||||||
|
GROUP BY g.id, g.name
|
||||||
|
ORDER BY g.name
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetAllGenresWithCountsByLibraryRow struct {
|
||||||
|
Name string
|
||||||
|
TrackCount int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetAllGenresWithCountsByLibrary(ctx context.Context, libraryID int64) ([]GetAllGenresWithCountsByLibraryRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getAllGenresWithCountsByLibrary, libraryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetAllGenresWithCountsByLibraryRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetAllGenresWithCountsByLibraryRow
|
||||||
|
if err := rows.Scan(&i.Name, &i.TrackCount); 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 getGenresByRecordingID = `-- name: GetGenresByRecordingID :many
|
const getGenresByRecordingID = `-- name: GetGenresByRecordingID :many
|
||||||
SELECT g.id, g.name
|
SELECT g.id, g.name
|
||||||
FROM genres g
|
FROM genres g
|
||||||
@@ -219,6 +258,111 @@ func (q *Queries) GetTracksByGenre(ctx context.Context, name string) ([]GetTrack
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getTracksByGenreByLibrary = `-- name: GetTracksByGenreByLibrary :many
|
||||||
|
SELECT
|
||||||
|
af.file_path,
|
||||||
|
af.length_milliseconds,
|
||||||
|
COALESCE(r.name, '') AS title,
|
||||||
|
COALESCE(ac.text, '') AS artist_name,
|
||||||
|
r.track_number,
|
||||||
|
r.disc_number,
|
||||||
|
COALESCE(rlg.name, '') AS album,
|
||||||
|
CAST(COALESCE(
|
||||||
|
(SELECT GROUP_CONCAT(g2.name, '||')
|
||||||
|
FROM recording_genres rg2
|
||||||
|
JOIN genres g2 ON rg2.genre_id = g2.id
|
||||||
|
WHERE rg2.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,
|
||||||
|
af.sample_rate,
|
||||||
|
af.bit_depth,
|
||||||
|
af.channels,
|
||||||
|
af.bitrate,
|
||||||
|
af.file_size
|
||||||
|
FROM genres g
|
||||||
|
JOIN recording_genres rg ON g.id = rg.genre_id
|
||||||
|
JOIN recordings r ON rg.recording_id = r.id
|
||||||
|
JOIN audio_files af ON af.recording_id = r.id
|
||||||
|
JOIN artist_credit ac ON r.artist_credit_id = ac.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT recording_id,
|
||||||
|
MIN(release_group_id) AS release_group_id
|
||||||
|
FROM release_group_recordings
|
||||||
|
GROUP BY recording_id
|
||||||
|
) rgr ON r.id = rgr.recording_id
|
||||||
|
LEFT JOIN release_groups rlg ON rgr.release_group_id = rlg.id
|
||||||
|
LEFT JOIN file_types ft ON af.file_type_id = ft.id
|
||||||
|
WHERE g.name = ? AND af.library_id = ?
|
||||||
|
ORDER BY r.name
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetTracksByGenreByLibraryParams struct {
|
||||||
|
Name string
|
||||||
|
LibraryID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetTracksByGenreByLibraryRow struct {
|
||||||
|
FilePath string
|
||||||
|
LengthMilliseconds int64
|
||||||
|
Title string
|
||||||
|
ArtistName string
|
||||||
|
TrackNumber sql.NullInt64
|
||||||
|
DiscNumber sql.NullInt64
|
||||||
|
Album string
|
||||||
|
Genre string
|
||||||
|
Year int64
|
||||||
|
Composer string
|
||||||
|
FileType string
|
||||||
|
SampleRate int64
|
||||||
|
BitDepth int64
|
||||||
|
Channels int64
|
||||||
|
Bitrate int64
|
||||||
|
FileSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetTracksByGenreByLibrary(ctx context.Context, arg GetTracksByGenreByLibraryParams) ([]GetTracksByGenreByLibraryRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getTracksByGenreByLibrary, arg.Name, arg.LibraryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetTracksByGenreByLibraryRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetTracksByGenreByLibraryRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.FilePath,
|
||||||
|
&i.LengthMilliseconds,
|
||||||
|
&i.Title,
|
||||||
|
&i.ArtistName,
|
||||||
|
&i.TrackNumber,
|
||||||
|
&i.DiscNumber,
|
||||||
|
&i.Album,
|
||||||
|
&i.Genre,
|
||||||
|
&i.Year,
|
||||||
|
&i.Composer,
|
||||||
|
&i.FileType,
|
||||||
|
&i.SampleRate,
|
||||||
|
&i.BitDepth,
|
||||||
|
&i.Channels,
|
||||||
|
&i.Bitrate,
|
||||||
|
&i.FileSize,
|
||||||
|
); 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
|
const upsertGenre = `-- name: UpsertGenre :one
|
||||||
INSERT INTO genres (name) VALUES (?)
|
INSERT INTO genres (name) VALUES (?)
|
||||||
ON CONFLICT(name) DO UPDATE SET name = name
|
ON CONFLICT(name) DO UPDATE SET name = name
|
||||||
|
|||||||
@@ -146,6 +146,77 @@ func (q *Queries) GetAlbumsByArtist(ctx context.Context, artistID int64) ([]GetA
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAlbumsByArtistByLibrary = `-- name: GetAlbumsByArtistByLibrary :many
|
||||||
|
SELECT
|
||||||
|
rg.id,
|
||||||
|
rg.name,
|
||||||
|
rg.year,
|
||||||
|
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
|
||||||
|
COALESCE(ca.file_path, '') as cover_art_path
|
||||||
|
FROM release_groups rg
|
||||||
|
JOIN artist_credit ac ON rg.album_artist_credit_id = ac.id
|
||||||
|
JOIN artist_credit_artist aca ON aca.credit_id = ac.id
|
||||||
|
LEFT JOIN cover_art ca ON rg.cover_art_id = ca.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT rgr.release_group_id, ac2.text
|
||||||
|
FROM release_group_recordings rgr
|
||||||
|
JOIN recordings rec ON rec.id = rgr.recording_id
|
||||||
|
JOIN artist_credit ac2 ON ac2.id = rec.artist_credit_id
|
||||||
|
GROUP BY rgr.release_group_id
|
||||||
|
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
||||||
|
WHERE aca.artist_id = ?
|
||||||
|
AND rg.id IN (
|
||||||
|
SELECT DISTINCT rgr2.release_group_id
|
||||||
|
FROM release_group_recordings rgr2
|
||||||
|
JOIN recordings r2 ON r2.id = rgr2.recording_id
|
||||||
|
JOIN audio_files af2 ON af2.recording_id = r2.id
|
||||||
|
WHERE af2.library_id = ?
|
||||||
|
)
|
||||||
|
ORDER BY rg.name
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetAlbumsByArtistByLibraryParams struct {
|
||||||
|
ArtistID int64
|
||||||
|
LibraryID int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetAlbumsByArtistByLibraryRow struct {
|
||||||
|
ID int64
|
||||||
|
Name string
|
||||||
|
Year sql.NullInt64
|
||||||
|
ArtistName string
|
||||||
|
CoverArtPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetAlbumsByArtistByLibrary(ctx context.Context, arg GetAlbumsByArtistByLibraryParams) ([]GetAlbumsByArtistByLibraryRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getAlbumsByArtistByLibrary, arg.ArtistID, arg.LibraryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetAlbumsByArtistByLibraryRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetAlbumsByArtistByLibraryRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Name,
|
||||||
|
&i.Year,
|
||||||
|
&i.ArtistName,
|
||||||
|
&i.CoverArtPath,
|
||||||
|
); 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 getAllAlbumsWithDetails = `-- name: GetAllAlbumsWithDetails :many
|
const getAllAlbumsWithDetails = `-- name: GetAllAlbumsWithDetails :many
|
||||||
SELECT
|
SELECT
|
||||||
rg.id,
|
rg.id,
|
||||||
@@ -203,6 +274,70 @@ func (q *Queries) GetAllAlbumsWithDetails(ctx context.Context) ([]GetAllAlbumsWi
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAllAlbumsWithDetailsByLibrary = `-- name: GetAllAlbumsWithDetailsByLibrary :many
|
||||||
|
SELECT
|
||||||
|
rg.id,
|
||||||
|
rg.name,
|
||||||
|
rg.year,
|
||||||
|
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
|
||||||
|
COALESCE(ca.file_path, '') as cover_art_path
|
||||||
|
FROM release_groups rg
|
||||||
|
LEFT JOIN artist_credit ac ON rg.album_artist_credit_id = ac.id
|
||||||
|
LEFT JOIN cover_art ca ON rg.cover_art_id = ca.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT rgr.release_group_id, ac2.text
|
||||||
|
FROM release_group_recordings rgr
|
||||||
|
JOIN recordings rec ON rec.id = rgr.recording_id
|
||||||
|
JOIN artist_credit ac2 ON ac2.id = rec.artist_credit_id
|
||||||
|
GROUP BY rgr.release_group_id
|
||||||
|
) fallback_ac ON fallback_ac.release_group_id = rg.id
|
||||||
|
WHERE rg.id IN (
|
||||||
|
SELECT DISTINCT rgr2.release_group_id
|
||||||
|
FROM release_group_recordings rgr2
|
||||||
|
JOIN recordings r2 ON r2.id = rgr2.recording_id
|
||||||
|
JOIN audio_files af2 ON af2.recording_id = r2.id
|
||||||
|
WHERE af2.library_id = ?
|
||||||
|
)
|
||||||
|
ORDER BY rg.name
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetAllAlbumsWithDetailsByLibraryRow struct {
|
||||||
|
ID int64
|
||||||
|
Name string
|
||||||
|
Year sql.NullInt64
|
||||||
|
ArtistName string
|
||||||
|
CoverArtPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetAllAlbumsWithDetailsByLibrary(ctx context.Context, libraryID int64) ([]GetAllAlbumsWithDetailsByLibraryRow, error) {
|
||||||
|
rows, err := q.db.QueryContext(ctx, getAllAlbumsWithDetailsByLibrary, libraryID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetAllAlbumsWithDetailsByLibraryRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetAllAlbumsWithDetailsByLibraryRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.Name,
|
||||||
|
&i.Year,
|
||||||
|
&i.ArtistName,
|
||||||
|
&i.CoverArtPath,
|
||||||
|
); 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 getAllReleaseGroups = `-- name: GetAllReleaseGroups :many
|
const getAllReleaseGroups = `-- name: GetAllReleaseGroups :many
|
||||||
SELECT id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs FROM release_groups
|
SELECT id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs FROM release_groups
|
||||||
ORDER BY name
|
ORDER BY name
|
||||||
|
|||||||
Reference in New Issue
Block a user