Files
yellowjacket/backend/database/sql/sqlcgen/audio_files.sql.go
T
logan 9e0e4d5bb8 perf(library): resolve album and genre file paths in one query
"Play this artist" awaited `GetAlbumTracks` inside a for loop — 13
sequential round trips for a 12-album artist — and every one of the
four sites doing that asked for whole track rows to read `FilePath`
off them. Five genres cost 6 MB across the IPC.

`GetFilePathsByAlbums(ids, libraryID)` and `GetFilePathsByGenres(names,
libraryID)` answer once and carry only the paths. Measured at 50 000
tracks: an artist 13 calls / 74.2 kB -> 2 / 19.2 kB, twenty albums
20 / 117.5 kB / 7.8 ms -> 1 / 26.0 kB / 1.7 ms, five genres
5 / 6 014 kB / 213 ms -> 1 / 1 291 kB / 32.6 ms, with the returned path
lists identical.

They return the paths grouped by album id or genre name rather than
flattened, because the caller owns the order — an album list is sorted
by name, not by id, and a flattened result would silently reorder a
queue — and because the album drag cache stores them per album. A
libraryID of 0 means "every library", matching an unset filter.
2026-08-12 01:18:17 -04:00

1322 lines
35 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: audio_files.sql
package sqlcgen
import (
"context"
"database/sql"
"strings"
)
const countAudioFiles = `-- name: CountAudioFiles :one
SELECT count(*) FROM audio_files
`
func (q *Queries) CountAudioFiles(ctx context.Context) (int64, error) {
row := q.db.QueryRowContext(ctx, countAudioFiles)
var count int64
err := row.Scan(&count)
return count, err
}
const countAudioFilesByLibrary = `-- name: CountAudioFilesByLibrary :one
SELECT COUNT(*) AS count FROM audio_files WHERE library_id = ?
`
func (q *Queries) CountAudioFilesByLibrary(ctx context.Context, libraryID int64) (int64, error) {
row := q.db.QueryRowContext(ctx, countAudioFilesByLibrary, libraryID)
var count int64
err := row.Scan(&count)
return count, err
}
const createAudioFile = `-- name: CreateAudioFile :one
INSERT INTO audio_files (file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key, modified_at
`
type CreateAudioFileParams struct {
FilePath string
LengthMilliseconds int64
FileTypeID int64
RecordingID int64
SampleRate int64
BitDepth int64
Channels int64
Bitrate int64
FileSize int64
Basename string
LibraryID int64
}
func (q *Queries) CreateAudioFile(ctx context.Context, arg CreateAudioFileParams) (AudioFile, error) {
row := q.db.QueryRowContext(ctx, createAudioFile,
arg.FilePath,
arg.LengthMilliseconds,
arg.FileTypeID,
arg.RecordingID,
arg.SampleRate,
arg.BitDepth,
arg.Channels,
arg.Bitrate,
arg.FileSize,
arg.Basename,
arg.LibraryID,
)
var i AudioFile
err := row.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
&i.ModifiedAt,
)
return i, err
}
const createAudioFileWithGroupKey = `-- name: CreateAudioFileWithGroupKey :one
INSERT INTO audio_files (
file_path, length_milliseconds, file_type_id, recording_id,
sample_rate, bit_depth, channels, bitrate, file_size, basename,
library_id, group_key, tag_status, modified_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key, modified_at
`
type CreateAudioFileWithGroupKeyParams struct {
FilePath string
LengthMilliseconds int64
FileTypeID int64
RecordingID int64
SampleRate int64
BitDepth int64
Channels int64
Bitrate int64
FileSize int64
Basename string
LibraryID int64
GroupKey string
TagStatus string
ModifiedAt int64
}
func (q *Queries) CreateAudioFileWithGroupKey(ctx context.Context, arg CreateAudioFileWithGroupKeyParams) (AudioFile, error) {
row := q.db.QueryRowContext(ctx, createAudioFileWithGroupKey,
arg.FilePath,
arg.LengthMilliseconds,
arg.FileTypeID,
arg.RecordingID,
arg.SampleRate,
arg.BitDepth,
arg.Channels,
arg.Bitrate,
arg.FileSize,
arg.Basename,
arg.LibraryID,
arg.GroupKey,
arg.TagStatus,
arg.ModifiedAt,
)
var i AudioFile
err := row.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
&i.ModifiedAt,
)
return i, err
}
const deleteAllAudioFiles = `-- name: DeleteAllAudioFiles :exec
DELETE FROM audio_files
`
func (q *Queries) DeleteAllAudioFiles(ctx context.Context) error {
_, err := q.db.ExecContext(ctx, deleteAllAudioFiles)
return err
}
const deleteAudioFile = `-- name: DeleteAudioFile :exec
DELETE FROM audio_files
WHERE id = ?
`
func (q *Queries) DeleteAudioFile(ctx context.Context, id int64) error {
_, err := q.db.ExecContext(ctx, deleteAudioFile, id)
return err
}
const getAllAudioFilePaths = `-- name: GetAllAudioFilePaths :many
SELECT id, file_path FROM audio_files
`
type GetAllAudioFilePathsRow struct {
ID int64
FilePath string
}
func (q *Queries) GetAllAudioFilePaths(ctx context.Context) ([]GetAllAudioFilePathsRow, error) {
rows, err := q.db.QueryContext(ctx, getAllAudioFilePaths)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetAllAudioFilePathsRow
for rows.Next() {
var i GetAllAudioFilePathsRow
if err := rows.Scan(&i.ID, &i.FilePath); 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 getAllAudioFiles = `-- name: GetAllAudioFiles :many
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key, modified_at FROM audio_files
`
func (q *Queries) GetAllAudioFiles(ctx context.Context) ([]AudioFile, error) {
rows, err := q.db.QueryContext(ctx, getAllAudioFiles)
if err != nil {
return nil, err
}
defer rows.Close()
var items []AudioFile
for rows.Next() {
var i AudioFile
if err := rows.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
&i.ModifiedAt,
); 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 getAllAudioFilesWithArtist = `-- name: GetAllAudioFilesWithArtist :many
SELECT
af.id,
af.file_path,
af.length_milliseconds,
af.file_type_id,
af.recording_id,
COALESCE(ac.text, '') AS artist_name,
COALESCE(r.name, '') AS title
FROM audio_files af
JOIN recordings r ON af.recording_id = r.id
JOIN artist_credit ac ON r.artist_credit_id = ac.id
`
type GetAllAudioFilesWithArtistRow struct {
ID int64
FilePath string
LengthMilliseconds int64
FileTypeID int64
RecordingID int64
ArtistName string
Title string
}
func (q *Queries) GetAllAudioFilesWithArtist(ctx context.Context) ([]GetAllAudioFilesWithArtistRow, error) {
rows, err := q.db.QueryContext(ctx, getAllAudioFilesWithArtist)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetAllAudioFilesWithArtistRow
for rows.Next() {
var i GetAllAudioFilesWithArtistRow
if err := rows.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.ArtistName,
&i.Title,
); 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 getAllTracksWithFullMetadata = `-- name: GetAllTracksWithFullMetadata :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,
af.play_count,
af.last_played,
COALESCE(ca.file_path, '') AS cover_art_path,
COALESCE(a.mbid, '') AS artist_mbid,
COALESCE(rg.mbid, '') AS release_group_mbid,
COALESCE(r.mbid, '') AS recording_mbid
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 artist_credit_artist aca ON aca.credit_id = ac.id
LEFT JOIN artists a ON a.id = aca.artist_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 cover_art ca ON rg.cover_art_id = ca.id
LEFT JOIN file_types ft ON af.file_type_id = ft.id
`
type GetAllTracksWithFullMetadataRow 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
PlayCount int64
LastPlayed sql.NullTime
CoverArtPath string
ArtistMbid string
ReleaseGroupMbid string
RecordingMbid string
}
func (q *Queries) GetAllTracksWithFullMetadata(ctx context.Context) ([]GetAllTracksWithFullMetadataRow, error) {
rows, err := q.db.QueryContext(ctx, getAllTracksWithFullMetadata)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetAllTracksWithFullMetadataRow
for rows.Next() {
var i GetAllTracksWithFullMetadataRow
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,
&i.PlayCount,
&i.LastPlayed,
&i.CoverArtPath,
&i.ArtistMbid,
&i.ReleaseGroupMbid,
&i.RecordingMbid,
); 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 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,
af.play_count,
af.last_played,
COALESCE(ca.file_path, '') AS cover_art_path,
COALESCE(a.mbid, '') AS artist_mbid,
COALESCE(rg.mbid, '') AS release_group_mbid,
COALESCE(r.mbid, '') AS recording_mbid
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 artist_credit_artist aca ON aca.credit_id = ac.id
LEFT JOIN artists a ON a.id = aca.artist_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 cover_art ca ON rg.cover_art_id = ca.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
PlayCount int64
LastPlayed sql.NullTime
CoverArtPath string
ArtistMbid string
ReleaseGroupMbid string
RecordingMbid string
}
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,
&i.PlayCount,
&i.LastPlayed,
&i.CoverArtPath,
&i.ArtistMbid,
&i.ReleaseGroupMbid,
&i.RecordingMbid,
); 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
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key, modified_at FROM audio_files
WHERE id = ? LIMIT 1
`
func (q *Queries) GetAudioFile(ctx context.Context, id int64) (AudioFile, error) {
row := q.db.QueryRowContext(ctx, getAudioFile, id)
var i AudioFile
err := row.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
&i.ModifiedAt,
)
return i, err
}
const getAudioFileByPath = `-- name: GetAudioFileByPath :one
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key, modified_at FROM audio_files
WHERE file_path = ? LIMIT 1
`
func (q *Queries) GetAudioFileByPath(ctx context.Context, filePath string) (AudioFile, error) {
row := q.db.QueryRowContext(ctx, getAudioFileByPath, filePath)
var i AudioFile
err := row.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
&i.ModifiedAt,
)
return i, err
}
const getAudioFileGroupKey = `-- name: GetAudioFileGroupKey :one
SELECT group_key FROM audio_files
WHERE id = ? LIMIT 1
`
func (q *Queries) GetAudioFileGroupKey(ctx context.Context, id int64) (string, error) {
row := q.db.QueryRowContext(ctx, getAudioFileGroupKey, id)
var group_key string
err := row.Scan(&group_key)
return group_key, err
}
const getAudioFilesByLibrary = `-- name: GetAudioFilesByLibrary :many
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key, modified_at FROM audio_files WHERE library_id = ?
`
func (q *Queries) GetAudioFilesByLibrary(ctx context.Context, libraryID int64) ([]AudioFile, error) {
rows, err := q.db.QueryContext(ctx, getAudioFilesByLibrary, libraryID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []AudioFile
for rows.Next() {
var i AudioFile
if err := rows.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
&i.ModifiedAt,
); 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 getAudioFilesByReleaseGroup = `-- name: GetAudioFilesByReleaseGroup :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,
COALESCE(a.mbid, '') AS artist_mbid,
COALESCE(rg.mbid, '') AS release_group_mbid,
COALESCE(r.mbid, '') AS recording_mbid
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 artist_credit_artist aca ON aca.credit_id = ac.id
LEFT JOIN artists a ON a.id = aca.artist_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 = ?
ORDER BY rgr.disc_number, rgr.track_number
`
type GetAudioFilesByReleaseGroupRow 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
ArtistMbid string
ReleaseGroupMbid string
RecordingMbid string
}
func (q *Queries) GetAudioFilesByReleaseGroup(ctx context.Context, releaseGroupID int64) ([]GetAudioFilesByReleaseGroupRow, error) {
rows, err := q.db.QueryContext(ctx, getAudioFilesByReleaseGroup, releaseGroupID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetAudioFilesByReleaseGroupRow
for rows.Next() {
var i GetAudioFilesByReleaseGroupRow
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,
&i.ArtistMbid,
&i.ReleaseGroupMbid,
&i.RecordingMbid,
); 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 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,
COALESCE(a.mbid, '') AS artist_mbid,
COALESCE(rg.mbid, '') AS release_group_mbid,
COALESCE(r.mbid, '') AS recording_mbid
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 artist_credit_artist aca ON aca.credit_id = ac.id
LEFT JOIN artists a ON a.id = aca.artist_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
ArtistMbid string
ReleaseGroupMbid string
RecordingMbid string
}
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,
&i.ArtistMbid,
&i.ReleaseGroupMbid,
&i.RecordingMbid,
); 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
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key, modified_at FROM audio_files
WHERE recording_id = 0
`
func (q *Queries) GetAudioFilesNeedingMetadata(ctx context.Context) ([]AudioFile, error) {
rows, err := q.db.QueryContext(ctx, getAudioFilesNeedingMetadata)
if err != nil {
return nil, err
}
defer rows.Close()
var items []AudioFile
for rows.Next() {
var i AudioFile
if err := rows.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
&i.ModifiedAt,
); 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 getFilePathsByReleaseGroups = `-- name: GetFilePathsByReleaseGroups :many
SELECT rgr.release_group_id, af.file_path
FROM release_group_recordings rgr
JOIN recordings r ON rgr.recording_id = r.id
JOIN audio_files af ON af.recording_id = r.id
WHERE rgr.release_group_id IN (/*SLICE:release_group_ids*/?)
ORDER BY rgr.disc_number, rgr.track_number
`
type GetFilePathsByReleaseGroupsRow struct {
ReleaseGroupID int64
FilePath string
}
// "Play this artist" and "play these albums" wanted file paths and asked
// for whole track rows to get them, one round trip per album (perf.m2).
// These answer the same question in one query and carry only what the
// caller uses; the release group id comes back so the caller can keep
// its own album ordering.
func (q *Queries) GetFilePathsByReleaseGroups(ctx context.Context, releaseGroupIds []int64) ([]GetFilePathsByReleaseGroupsRow, error) {
query := getFilePathsByReleaseGroups
var queryParams []interface{}
if len(releaseGroupIds) > 0 {
for _, v := range releaseGroupIds {
queryParams = append(queryParams, v)
}
query = strings.Replace(query, "/*SLICE:release_group_ids*/?", strings.Repeat(",?", len(releaseGroupIds))[1:], 1)
} else {
query = strings.Replace(query, "/*SLICE:release_group_ids*/?", "NULL", 1)
}
rows, err := q.db.QueryContext(ctx, query, queryParams...)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetFilePathsByReleaseGroupsRow
for rows.Next() {
var i GetFilePathsByReleaseGroupsRow
if err := rows.Scan(&i.ReleaseGroupID, &i.FilePath); 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 getFilePathsByReleaseGroupsByLibrary = `-- name: GetFilePathsByReleaseGroupsByLibrary :many
SELECT rgr.release_group_id, af.file_path
FROM release_group_recordings rgr
JOIN recordings r ON rgr.recording_id = r.id
JOIN audio_files af ON af.recording_id = r.id
WHERE rgr.release_group_id IN (/*SLICE:release_group_ids*/?)
AND af.library_id = ?
ORDER BY rgr.disc_number, rgr.track_number
`
type GetFilePathsByReleaseGroupsByLibraryParams struct {
ReleaseGroupIds []int64
LibraryID int64
}
type GetFilePathsByReleaseGroupsByLibraryRow struct {
ReleaseGroupID int64
FilePath string
}
func (q *Queries) GetFilePathsByReleaseGroupsByLibrary(ctx context.Context, arg GetFilePathsByReleaseGroupsByLibraryParams) ([]GetFilePathsByReleaseGroupsByLibraryRow, error) {
query := getFilePathsByReleaseGroupsByLibrary
var queryParams []interface{}
if len(arg.ReleaseGroupIds) > 0 {
for _, v := range arg.ReleaseGroupIds {
queryParams = append(queryParams, v)
}
query = strings.Replace(query, "/*SLICE:release_group_ids*/?", strings.Repeat(",?", len(arg.ReleaseGroupIds))[1:], 1)
} else {
query = strings.Replace(query, "/*SLICE:release_group_ids*/?", "NULL", 1)
}
queryParams = append(queryParams, arg.LibraryID)
rows, err := q.db.QueryContext(ctx, query, queryParams...)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetFilePathsByReleaseGroupsByLibraryRow
for rows.Next() {
var i GetFilePathsByReleaseGroupsByLibraryRow
if err := rows.Scan(&i.ReleaseGroupID, &i.FilePath); 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 getLibraryMaxModifiedAt = `-- name: GetLibraryMaxModifiedAt :one
SELECT CAST(COALESCE(MAX(modified_at), 0) AS INTEGER) FROM audio_files
WHERE library_id = ?
`
// Newest recorded mtime in a library, for the startup soft scan. 0 when
// the library is empty or no row has a baseline yet.
func (q *Queries) GetLibraryMaxModifiedAt(ctx context.Context, libraryID int64) (int64, error) {
row := q.db.QueryRowContext(ctx, getLibraryMaxModifiedAt, libraryID)
var column_1 int64
err := row.Scan(&column_1)
return column_1, err
}
const getRandomAudioFilePath = `-- name: GetRandomAudioFilePath :one
SELECT file_path FROM audio_files
ORDER BY RANDOM()
LIMIT 1
`
func (q *Queries) GetRandomAudioFilePath(ctx context.Context) (string, error) {
row := q.db.QueryRowContext(ctx, getRandomAudioFilePath)
var file_path string
err := row.Scan(&file_path)
return file_path, err
}
const getTrackMetadataByPath = `-- name: GetTrackMetadataByPath :one
SELECT
af.file_path,
af.length_milliseconds,
COALESCE(r.name, '') AS title,
COALESCE(ac.text, '') AS artist,
COALESCE(rg.name, '') AS album,
COALESCE(ca.file_path, '') AS cover_art_path,
COALESCE(a.mbid, '') AS artist_mbid,
COALESCE(rg.mbid, '') AS release_group_mbid,
COALESCE(r.mbid, '') AS recording_mbid
FROM audio_files af
LEFT JOIN recordings r ON af.recording_id = r.id
LEFT JOIN artist_credit ac ON r.artist_credit_id = ac.id
LEFT JOIN artist_credit_artist aca ON aca.credit_id = ac.id
LEFT JOIN artists a ON a.id = aca.artist_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 cover_art ca ON rg.cover_art_id = ca.id
WHERE af.file_path = ?
LIMIT 1
`
type GetTrackMetadataByPathRow struct {
FilePath string
LengthMilliseconds int64
Title string
Artist string
Album string
CoverArtPath string
ArtistMbid string
ReleaseGroupMbid string
RecordingMbid string
}
func (q *Queries) GetTrackMetadataByPath(ctx context.Context, filePath string) (GetTrackMetadataByPathRow, error) {
row := q.db.QueryRowContext(ctx, getTrackMetadataByPath, filePath)
var i GetTrackMetadataByPathRow
err := row.Scan(
&i.FilePath,
&i.LengthMilliseconds,
&i.Title,
&i.Artist,
&i.Album,
&i.CoverArtPath,
&i.ArtistMbid,
&i.ReleaseGroupMbid,
&i.RecordingMbid,
)
return i, err
}
const lookupTrackMetaByPaths = `-- name: LookupTrackMetaByPaths :many
SELECT id, file_path, title, artist_name, album, cover_art_path, artist_mbid, release_group_mbid, recording_mbid
FROM track_metadata
WHERE file_path IN (/*SLICE:paths*/?)
`
type LookupTrackMetaByPathsRow struct {
ID int64
FilePath string
Title string
ArtistName string
Album string
CoverArtPath string
ArtistMbid string
ReleaseGroupMbid string
RecordingMbid string
}
func (q *Queries) LookupTrackMetaByPaths(ctx context.Context, paths []string) ([]LookupTrackMetaByPathsRow, error) {
query := lookupTrackMetaByPaths
var queryParams []interface{}
if len(paths) > 0 {
for _, v := range paths {
queryParams = append(queryParams, v)
}
query = strings.Replace(query, "/*SLICE:paths*/?", strings.Repeat(",?", len(paths))[1:], 1)
} else {
query = strings.Replace(query, "/*SLICE:paths*/?", "NULL", 1)
}
rows, err := q.db.QueryContext(ctx, query, queryParams...)
if err != nil {
return nil, err
}
defer rows.Close()
var items []LookupTrackMetaByPathsRow
for rows.Next() {
var i LookupTrackMetaByPathsRow
if err := rows.Scan(
&i.ID,
&i.FilePath,
&i.Title,
&i.ArtistName,
&i.Album,
&i.CoverArtPath,
&i.ArtistMbid,
&i.ReleaseGroupMbid,
&i.RecordingMbid,
); 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 searchAudioFilesByBasename = `-- name: SearchAudioFilesByBasename :many
SELECT
af.file_path,
af.length_milliseconds,
COALESCE(r.name, '') AS title,
COALESCE(ac.text, '') AS artist,
COALESCE(rg.name, '') AS album
FROM audio_files af
LEFT JOIN recordings r ON af.recording_id = r.id
LEFT 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 rg ON rgr.release_group_id = rg.id
WHERE af.basename = ?
LIMIT ?
`
type SearchAudioFilesByBasenameParams struct {
Basename string
Limit int64
}
type SearchAudioFilesByBasenameRow struct {
FilePath string
LengthMilliseconds int64
Title string
Artist string
Album string
}
func (q *Queries) SearchAudioFilesByBasename(ctx context.Context, arg SearchAudioFilesByBasenameParams) ([]SearchAudioFilesByBasenameRow, error) {
rows, err := q.db.QueryContext(ctx, searchAudioFilesByBasename, arg.Basename, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SearchAudioFilesByBasenameRow
for rows.Next() {
var i SearchAudioFilesByBasenameRow
if err := rows.Scan(
&i.FilePath,
&i.LengthMilliseconds,
&i.Title,
&i.Artist,
&i.Album,
); 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 setAudioFileGroupKey = `-- name: SetAudioFileGroupKey :exec
UPDATE audio_files SET group_key = ? WHERE id = ?
`
type SetAudioFileGroupKeyParams struct {
GroupKey string
ID int64
}
func (q *Queries) SetAudioFileGroupKey(ctx context.Context, arg SetAudioFileGroupKeyParams) error {
_, err := q.db.ExecContext(ctx, setAudioFileGroupKey, arg.GroupKey, arg.ID)
return err
}
const updateAudioFile = `-- name: UpdateAudioFile :exec
UPDATE audio_files
SET file_path = ?, length_milliseconds = ?, file_type_id = ?, recording_id = ?, sample_rate = ?, bit_depth = ?, channels = ?, bitrate = ?, file_size = ?, basename = ?
WHERE id = ?
`
type UpdateAudioFileParams struct {
FilePath string
LengthMilliseconds int64
FileTypeID int64
RecordingID int64
SampleRate int64
BitDepth int64
Channels int64
Bitrate int64
FileSize int64
Basename string
ID int64
}
func (q *Queries) UpdateAudioFile(ctx context.Context, arg UpdateAudioFileParams) error {
_, err := q.db.ExecContext(ctx, updateAudioFile,
arg.FilePath,
arg.LengthMilliseconds,
arg.FileTypeID,
arg.RecordingID,
arg.SampleRate,
arg.BitDepth,
arg.Channels,
arg.Bitrate,
arg.FileSize,
arg.Basename,
arg.ID,
)
return err
}
const updateAudioFileRecording = `-- name: UpdateAudioFileRecording :exec
UPDATE audio_files
SET recording_id = ?, sample_rate = ?, bit_depth = ?, channels = ?, bitrate = ?, file_size = ?, length_milliseconds = ?, modified_at = ?
WHERE id = ?
`
type UpdateAudioFileRecordingParams struct {
RecordingID int64
SampleRate int64
BitDepth int64
Channels int64
Bitrate int64
FileSize int64
LengthMilliseconds int64
ModifiedAt int64
ID int64
}
func (q *Queries) UpdateAudioFileRecording(ctx context.Context, arg UpdateAudioFileRecordingParams) error {
_, err := q.db.ExecContext(ctx, updateAudioFileRecording,
arg.RecordingID,
arg.SampleRate,
arg.BitDepth,
arg.Channels,
arg.Bitrate,
arg.FileSize,
arg.LengthMilliseconds,
arg.ModifiedAt,
arg.ID,
)
return err
}
const updateAudioFileStat = `-- name: UpdateAudioFileStat :exec
UPDATE audio_files
SET modified_at = ?, file_size = ?
WHERE id = ?
`
type UpdateAudioFileStatParams struct {
ModifiedAt int64
FileSize int64
ID int64
}
// Records the on-disk mtime/size without re-reading tags. Used to
// backfill the staleness baseline for files the scan skipped, and to
// re-baseline after YellowJacket's own tag writer rewrites a file.
func (q *Queries) UpdateAudioFileStat(ctx context.Context, arg UpdateAudioFileStatParams) error {
_, err := q.db.ExecContext(ctx, updateAudioFileStat, arg.ModifiedAt, arg.FileSize, arg.ID)
return err
}