feat(db/m7-353): sqlc queries for album cover enrichment
This commit is contained in:
@@ -72,7 +72,7 @@ func (q *Queries) DeleteAlbumIfEmpty(ctx context.Context, id pgtype.UUID) (Delet
|
||||
}
|
||||
|
||||
const getAlbumByArtistAndTitle = `-- name: GetAlbumByArtistAndTitle :one
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums WHERE artist_id = $1 AND title = $2 LIMIT 1
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source FROM albums WHERE artist_id = $1 AND title = $2 LIMIT 1
|
||||
`
|
||||
|
||||
type GetAlbumByArtistAndTitleParams struct {
|
||||
@@ -94,12 +94,13 @@ func (q *Queries) GetAlbumByArtistAndTitle(ctx context.Context, arg GetAlbumByAr
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getAlbumByID = `-- name: GetAlbumByID :one
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums WHERE id = $1
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source FROM albums WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAlbumByID(ctx context.Context, id pgtype.UUID) (Album, error) {
|
||||
@@ -115,12 +116,13 @@ func (q *Queries) GetAlbumByID(ctx context.Context, id pgtype.UUID) (Album, erro
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listAlbumsAlphaByArtist = `-- name: ListAlbumsAlphaByArtist :many
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, artists.sort_name AS artist_sort_name
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, artists.sort_name AS artist_sort_name
|
||||
FROM albums
|
||||
JOIN artists ON artists.id = albums.artist_id
|
||||
ORDER BY artists.sort_name, albums.sort_title
|
||||
@@ -158,6 +160,7 @@ func (q *Queries) ListAlbumsAlphaByArtist(ctx context.Context, arg ListAlbumsAlp
|
||||
&i.Album.CoverArtPath,
|
||||
&i.Album.CreatedAt,
|
||||
&i.Album.UpdatedAt,
|
||||
&i.Album.CoverArtSource,
|
||||
&i.ArtistSortName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -171,7 +174,7 @@ func (q *Queries) ListAlbumsAlphaByArtist(ctx context.Context, arg ListAlbumsAlp
|
||||
}
|
||||
|
||||
const listAlbumsAlphaByName = `-- name: ListAlbumsAlphaByName :many
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums ORDER BY sort_title LIMIT $1 OFFSET $2
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source FROM albums ORDER BY sort_title LIMIT $1 OFFSET $2
|
||||
`
|
||||
|
||||
type ListAlbumsAlphaByNameParams struct {
|
||||
@@ -198,6 +201,7 @@ func (q *Queries) ListAlbumsAlphaByName(ctx context.Context, arg ListAlbumsAlpha
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -210,7 +214,7 @@ func (q *Queries) ListAlbumsAlphaByName(ctx context.Context, arg ListAlbumsAlpha
|
||||
}
|
||||
|
||||
const listAlbumsAlphaWithArtist = `-- name: ListAlbumsAlphaWithArtist :many
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, artists.name AS artist_name
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, artists.name AS artist_name
|
||||
FROM albums
|
||||
JOIN artists ON artists.id = albums.artist_id
|
||||
ORDER BY albums.sort_title, albums.id
|
||||
@@ -248,6 +252,7 @@ func (q *Queries) ListAlbumsAlphaWithArtist(ctx context.Context, arg ListAlbumsA
|
||||
&i.Album.CoverArtPath,
|
||||
&i.Album.CreatedAt,
|
||||
&i.Album.UpdatedAt,
|
||||
&i.Album.CoverArtSource,
|
||||
&i.ArtistName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -261,7 +266,7 @@ func (q *Queries) ListAlbumsAlphaWithArtist(ctx context.Context, arg ListAlbumsA
|
||||
}
|
||||
|
||||
const listAlbumsByArtist = `-- name: ListAlbumsByArtist :many
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums WHERE artist_id = $1 ORDER BY release_date NULLS LAST, sort_title
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source FROM albums WHERE artist_id = $1 ORDER BY release_date NULLS LAST, sort_title
|
||||
`
|
||||
|
||||
func (q *Queries) ListAlbumsByArtist(ctx context.Context, artistID pgtype.UUID) ([]Album, error) {
|
||||
@@ -283,6 +288,7 @@ func (q *Queries) ListAlbumsByArtist(ctx context.Context, artistID pgtype.UUID)
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -295,7 +301,7 @@ func (q *Queries) ListAlbumsByArtist(ctx context.Context, artistID pgtype.UUID)
|
||||
}
|
||||
|
||||
const listAlbumsByGenre = `-- name: ListAlbumsByGenre :many
|
||||
SELECT DISTINCT ON (albums.id) albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at
|
||||
SELECT DISTINCT ON (albums.id) albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source
|
||||
FROM albums
|
||||
JOIN tracks ON tracks.album_id = albums.id
|
||||
WHERE tracks.genre = $1
|
||||
@@ -329,6 +335,7 @@ func (q *Queries) ListAlbumsByGenre(ctx context.Context, arg ListAlbumsByGenrePa
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -341,7 +348,7 @@ func (q *Queries) ListAlbumsByGenre(ctx context.Context, arg ListAlbumsByGenrePa
|
||||
}
|
||||
|
||||
const listAlbumsNewest = `-- name: ListAlbumsNewest :many
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums ORDER BY created_at DESC LIMIT $1 OFFSET $2
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source FROM albums ORDER BY created_at DESC LIMIT $1 OFFSET $2
|
||||
`
|
||||
|
||||
type ListAlbumsNewestParams struct {
|
||||
@@ -368,6 +375,7 @@ func (q *Queries) ListAlbumsNewest(ctx context.Context, arg ListAlbumsNewestPara
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -380,7 +388,7 @@ func (q *Queries) ListAlbumsNewest(ctx context.Context, arg ListAlbumsNewestPara
|
||||
}
|
||||
|
||||
const listAlbumsRandom = `-- name: ListAlbumsRandom :many
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums ORDER BY random() LIMIT $1
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source FROM albums ORDER BY random() LIMIT $1
|
||||
`
|
||||
|
||||
func (q *Queries) ListAlbumsRandom(ctx context.Context, limit int32) ([]Album, error) {
|
||||
@@ -402,6 +410,7 @@ func (q *Queries) ListAlbumsRandom(ctx context.Context, limit int32) ([]Album, e
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -414,7 +423,7 @@ func (q *Queries) ListAlbumsRandom(ctx context.Context, limit int32) ([]Album, e
|
||||
}
|
||||
|
||||
const listRecentlyAddedAlbumsWithArtist = `-- name: ListRecentlyAddedAlbumsWithArtist :many
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, artists.name AS artist_name
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, artists.name AS artist_name
|
||||
FROM albums
|
||||
JOIN artists ON artists.id = albums.artist_id
|
||||
ORDER BY albums.created_at DESC, albums.id
|
||||
@@ -449,6 +458,7 @@ func (q *Queries) ListRecentlyAddedAlbumsWithArtist(ctx context.Context, limit i
|
||||
&i.Album.CoverArtPath,
|
||||
&i.Album.CreatedAt,
|
||||
&i.Album.UpdatedAt,
|
||||
&i.Album.CoverArtSource,
|
||||
&i.ArtistName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -462,7 +472,7 @@ func (q *Queries) ListRecentlyAddedAlbumsWithArtist(ctx context.Context, limit i
|
||||
}
|
||||
|
||||
const searchAlbums = `-- name: SearchAlbums :many
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source FROM albums
|
||||
WHERE title ILIKE '%' || $1 || '%'
|
||||
ORDER BY sort_title
|
||||
LIMIT $2 OFFSET $3
|
||||
@@ -493,6 +503,7 @@ func (q *Queries) SearchAlbums(ctx context.Context, arg SearchAlbumsParams) ([]A
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -515,7 +526,7 @@ DO UPDATE SET
|
||||
release_date = EXCLUDED.release_date,
|
||||
cover_art_path = EXCLUDED.cover_art_path,
|
||||
updated_at = now()
|
||||
RETURNING id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at
|
||||
RETURNING id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at, cover_art_source
|
||||
`
|
||||
|
||||
type UpsertAlbumParams struct {
|
||||
@@ -547,6 +558,7 @@ func (q *Queries) UpsertAlbum(ctx context.Context, arg UpsertAlbumParams) (Album
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: covers.sql
|
||||
|
||||
package dbq
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const clearAlbumCover = `-- name: ClearAlbumCover :exec
|
||||
UPDATE albums
|
||||
SET cover_art_path = NULL,
|
||||
cover_art_source = NULL
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
// Used by the admin retry endpoint to wipe state before re-running the
|
||||
// enricher. Sets both fields to NULL.
|
||||
func (q *Queries) ClearAlbumCover(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, clearAlbumCover, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const countAlbumCoverSources = `-- name: CountAlbumCoverSources :one
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE cover_art_source IS NULL) ::bigint AS untried,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'sidecar') ::bigint AS sidecar,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'embedded')::bigint AS embedded,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'mbcaa') ::bigint AS mbcaa,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'none') ::bigint AS none
|
||||
FROM albums
|
||||
`
|
||||
|
||||
type CountAlbumCoverSourcesRow struct {
|
||||
Untried int64
|
||||
Sidecar int64
|
||||
Embedded int64
|
||||
Mbcaa int64
|
||||
None int64
|
||||
}
|
||||
|
||||
// Diagnostic for the admin overview: counts by source, including NULL.
|
||||
// Returns one row with named tallies.
|
||||
func (q *Queries) CountAlbumCoverSources(ctx context.Context) (CountAlbumCoverSourcesRow, error) {
|
||||
row := q.db.QueryRow(ctx, countAlbumCoverSources)
|
||||
var i CountAlbumCoverSourcesRow
|
||||
err := row.Scan(
|
||||
&i.Untried,
|
||||
&i.Sidecar,
|
||||
&i.Embedded,
|
||||
&i.Mbcaa,
|
||||
&i.None,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getAlbumWithFirstTrackPath = `-- name: GetAlbumWithFirstTrackPath :one
|
||||
SELECT a.id, a.mbid, a.title, a.cover_art_path, a.cover_art_source,
|
||||
t.file_path AS track_file_path
|
||||
FROM albums a
|
||||
LEFT JOIN tracks t ON t.album_id = a.id
|
||||
WHERE a.id = $1
|
||||
ORDER BY t.disc_number NULLS LAST, t.track_number NULLS LAST, t.id
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetAlbumWithFirstTrackPathRow struct {
|
||||
ID pgtype.UUID
|
||||
Mbid *string
|
||||
Title string
|
||||
CoverArtPath *string
|
||||
CoverArtSource *string
|
||||
TrackFilePath *string
|
||||
}
|
||||
|
||||
// Returns the album row and one of its track file paths (used to derive
|
||||
// the album directory). Pick lowest position track for determinism.
|
||||
func (q *Queries) GetAlbumWithFirstTrackPath(ctx context.Context, id pgtype.UUID) (GetAlbumWithFirstTrackPathRow, error) {
|
||||
row := q.db.QueryRow(ctx, getAlbumWithFirstTrackPath, id)
|
||||
var i GetAlbumWithFirstTrackPathRow
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Mbid,
|
||||
&i.Title,
|
||||
&i.CoverArtPath,
|
||||
&i.CoverArtSource,
|
||||
&i.TrackFilePath,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listAlbumsMissingCover = `-- name: ListAlbumsMissingCover :many
|
||||
|
||||
SELECT a.id, a.mbid, a.title, a.artist_id
|
||||
FROM albums a
|
||||
WHERE a.cover_art_source IS NULL
|
||||
ORDER BY a.created_at ASC
|
||||
LIMIT $1
|
||||
`
|
||||
|
||||
type ListAlbumsMissingCoverRow struct {
|
||||
ID pgtype.UUID
|
||||
Mbid *string
|
||||
Title string
|
||||
ArtistID pgtype.UUID
|
||||
}
|
||||
|
||||
// M7 #353: album cover enrichment queries.
|
||||
// Albums where cover_art_source has never been set. Used by the boot
|
||||
// backfill and post-scan enrichment passes. LIMIT supplied by caller.
|
||||
func (q *Queries) ListAlbumsMissingCover(ctx context.Context, limit int32) ([]ListAlbumsMissingCoverRow, error) {
|
||||
rows, err := q.db.Query(ctx, listAlbumsMissingCover, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListAlbumsMissingCoverRow
|
||||
for rows.Next() {
|
||||
var i ListAlbumsMissingCoverRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Mbid,
|
||||
&i.Title,
|
||||
&i.ArtistID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listAlbumsRetryMissing = `-- name: ListAlbumsRetryMissing :many
|
||||
SELECT a.id, a.mbid, a.title, a.artist_id
|
||||
FROM albums a
|
||||
WHERE a.cover_art_source IS NULL OR a.cover_art_source = 'none'
|
||||
ORDER BY a.created_at ASC
|
||||
LIMIT $1
|
||||
`
|
||||
|
||||
type ListAlbumsRetryMissingRow struct {
|
||||
ID pgtype.UUID
|
||||
Mbid *string
|
||||
Title string
|
||||
ArtistID pgtype.UUID
|
||||
}
|
||||
|
||||
// Bulk-retry candidates: NULL (never tried) plus 'none' (tried, failed).
|
||||
// Used by the admin "refetch missing covers" endpoint. LIMIT supplied.
|
||||
func (q *Queries) ListAlbumsRetryMissing(ctx context.Context, limit int32) ([]ListAlbumsRetryMissingRow, error) {
|
||||
rows, err := q.db.Query(ctx, listAlbumsRetryMissing, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListAlbumsRetryMissingRow
|
||||
for rows.Next() {
|
||||
var i ListAlbumsRetryMissingRow
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Mbid,
|
||||
&i.Title,
|
||||
&i.ArtistID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const setAlbumCover = `-- name: SetAlbumCover :exec
|
||||
UPDATE albums
|
||||
SET cover_art_path = NULLIF($2::text, ''),
|
||||
cover_art_source = $3
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type SetAlbumCoverParams struct {
|
||||
ID pgtype.UUID
|
||||
Column2 string
|
||||
CoverArtSource *string
|
||||
}
|
||||
|
||||
// Persist enrichment result. Pass cover_art_path = ” to clear (turns into NULL).
|
||||
func (q *Queries) SetAlbumCover(ctx context.Context, arg SetAlbumCoverParams) error {
|
||||
_, err := q.db.Exec(ctx, setAlbumCover, arg.ID, arg.Column2, arg.CoverArtSource)
|
||||
return err
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (q *Queries) ListLikedAlbumIDs(ctx context.Context, userID pgtype.UUID) ([]
|
||||
}
|
||||
|
||||
const listLikedAlbumRows = `-- name: ListLikedAlbumRows :many
|
||||
SELECT a.id, a.title, a.sort_title, a.artist_id, a.release_date, a.mbid, a.cover_art_path, a.created_at, a.updated_at FROM albums a
|
||||
SELECT a.id, a.title, a.sort_title, a.artist_id, a.release_date, a.mbid, a.cover_art_path, a.created_at, a.updated_at, a.cover_art_source FROM albums a
|
||||
JOIN general_likes_albums l ON l.album_id = a.id
|
||||
WHERE l.user_id = $1
|
||||
ORDER BY l.liked_at DESC
|
||||
@@ -152,6 +152,7 @@ func (q *Queries) ListLikedAlbumRows(ctx context.Context, arg ListLikedAlbumRows
|
||||
&i.CoverArtPath,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.CoverArtSource,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -188,15 +188,16 @@ func (ns NullLidarrRequestStatus) Value() (driver.Value, error) {
|
||||
}
|
||||
|
||||
type Album struct {
|
||||
ID pgtype.UUID
|
||||
Title string
|
||||
SortTitle string
|
||||
ArtistID pgtype.UUID
|
||||
ReleaseDate pgtype.Date
|
||||
Mbid *string
|
||||
CoverArtPath *string
|
||||
CreatedAt pgtype.Timestamptz
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
ID pgtype.UUID
|
||||
Title string
|
||||
SortTitle string
|
||||
ArtistID pgtype.UUID
|
||||
ReleaseDate pgtype.Date
|
||||
Mbid *string
|
||||
CoverArtPath *string
|
||||
CreatedAt pgtype.Timestamptz
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
CoverArtSource *string
|
||||
}
|
||||
|
||||
type Artist struct {
|
||||
|
||||
@@ -157,7 +157,7 @@ func (q *Queries) ListMostPlayedTracksForUser(ctx context.Context, arg ListMostP
|
||||
}
|
||||
|
||||
const listRediscoverAlbumsFallbackForUser = `-- name: ListRediscoverAlbumsFallbackForUser :many
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, artists.name AS artist_name
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, artists.name AS artist_name
|
||||
FROM general_likes_albums gla
|
||||
JOIN albums ON albums.id = gla.album_id
|
||||
JOIN artists ON artists.id = albums.artist_id
|
||||
@@ -198,6 +198,7 @@ func (q *Queries) ListRediscoverAlbumsFallbackForUser(ctx context.Context, arg L
|
||||
&i.Album.CoverArtPath,
|
||||
&i.Album.CreatedAt,
|
||||
&i.Album.UpdatedAt,
|
||||
&i.Album.CoverArtSource,
|
||||
&i.ArtistName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
@@ -225,7 +226,7 @@ WITH eligible AS (
|
||||
HAVING COALESCE(max(pe.started_at), '1970-01-01'::timestamptz)
|
||||
< now() - interval '14 days'
|
||||
)
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, artists.name AS artist_name
|
||||
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, artists.name AS artist_name
|
||||
FROM eligible e
|
||||
JOIN albums ON albums.id = e.album_id
|
||||
JOIN artists ON artists.id = albums.artist_id
|
||||
@@ -266,6 +267,7 @@ func (q *Queries) ListRediscoverAlbumsForUser(ctx context.Context, arg ListRedis
|
||||
&i.Album.CoverArtPath,
|
||||
&i.Album.CreatedAt,
|
||||
&i.Album.UpdatedAt,
|
||||
&i.Album.CoverArtSource,
|
||||
&i.ArtistName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -201,7 +201,11 @@ type ListPlaylistsByUserAndKindRow struct {
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
}
|
||||
|
||||
// Powers GET /api/me/playlists?kind=. Sorted by updated_at DESC.
|
||||
// Used in integration tests; production filter applied in Go
|
||||
// (api.handleListPlaylists fetches via Service.List and filters by Kind in
|
||||
// memory so it can also surface other users' public playlists alongside
|
||||
// the caller's own kind-filtered ones).
|
||||
// Sorted by updated_at DESC.
|
||||
func (q *Queries) ListPlaylistsByUserAndKind(ctx context.Context, arg ListPlaylistsByUserAndKindParams) ([]ListPlaylistsByUserAndKindRow, error) {
|
||||
rows, err := q.db.Query(ctx, listPlaylistsByUserAndKind, arg.UserID, arg.Column2)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
-- M7 #353: album cover enrichment queries.
|
||||
|
||||
-- name: ListAlbumsMissingCover :many
|
||||
-- Albums where cover_art_source has never been set. Used by the boot
|
||||
-- backfill and post-scan enrichment passes. LIMIT supplied by caller.
|
||||
SELECT a.id, a.mbid, a.title, a.artist_id
|
||||
FROM albums a
|
||||
WHERE a.cover_art_source IS NULL
|
||||
ORDER BY a.created_at ASC
|
||||
LIMIT $1;
|
||||
|
||||
-- name: ListAlbumsRetryMissing :many
|
||||
-- Bulk-retry candidates: NULL (never tried) plus 'none' (tried, failed).
|
||||
-- Used by the admin "refetch missing covers" endpoint. LIMIT supplied.
|
||||
SELECT a.id, a.mbid, a.title, a.artist_id
|
||||
FROM albums a
|
||||
WHERE a.cover_art_source IS NULL OR a.cover_art_source = 'none'
|
||||
ORDER BY a.created_at ASC
|
||||
LIMIT $1;
|
||||
|
||||
-- name: GetAlbumWithFirstTrackPath :one
|
||||
-- Returns the album row and one of its track file paths (used to derive
|
||||
-- the album directory). Pick lowest position track for determinism.
|
||||
SELECT a.id, a.mbid, a.title, a.cover_art_path, a.cover_art_source,
|
||||
t.file_path AS track_file_path
|
||||
FROM albums a
|
||||
LEFT JOIN tracks t ON t.album_id = a.id
|
||||
WHERE a.id = $1
|
||||
ORDER BY t.disc_number NULLS LAST, t.track_number NULLS LAST, t.id
|
||||
LIMIT 1;
|
||||
|
||||
-- name: SetAlbumCover :exec
|
||||
-- Persist enrichment result. Pass cover_art_path = '' to clear (turns into NULL).
|
||||
UPDATE albums
|
||||
SET cover_art_path = NULLIF($2::text, ''),
|
||||
cover_art_source = $3
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: ClearAlbumCover :exec
|
||||
-- Used by the admin retry endpoint to wipe state before re-running the
|
||||
-- enricher. Sets both fields to NULL.
|
||||
UPDATE albums
|
||||
SET cover_art_path = NULL,
|
||||
cover_art_source = NULL
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: CountAlbumCoverSources :one
|
||||
-- Diagnostic for the admin overview: counts by source, including NULL.
|
||||
-- Returns one row with named tallies.
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE cover_art_source IS NULL) ::bigint AS untried,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'sidecar') ::bigint AS sidecar,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'embedded')::bigint AS embedded,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'mbcaa') ::bigint AS mbcaa,
|
||||
COUNT(*) FILTER (WHERE cover_art_source = 'none') ::bigint AS none
|
||||
FROM albums;
|
||||
Reference in New Issue
Block a user