feat(db/m7-coverage-gauge): GetAlbumCoverageRollup query

FILTER-aggregate count over albums.cover_art_source and albums.mbid
returning total, with_art, pending, settled, pending_no_mbid in a
single round-trip. Sub-millisecond on realistic libraries; no index
needed for v1. pending_no_mbid is a subset of pending — the UI
tooltip uses it to show how many "pending" rows are blocked on
missing MBID and won't be moved by another scan.

Also bumps the Makefile sqlc pin from 1.27.0 to 1.31.1 to match the
version that produced all existing committed dbq/*.go files. The
prior pin was stale; running make generate against 1.27.0 silently
rolled the codegen back (cosmetic version headers on most files
plus a real codegen shape change in DeleteArtistIfEmpty).
This commit is contained in:
2026-05-06 09:40:26 -04:00
parent 4481874482
commit 98ec64c658
3 changed files with 54 additions and 1 deletions
+37
View File
@@ -121,6 +121,43 @@ func (q *Queries) GetAlbumByID(ctx context.Context, id pgtype.UUID) (Album, erro
return i, err
}
const getAlbumCoverageRollup = `-- name: GetAlbumCoverageRollup :one
SELECT
COUNT(*) AS total,
COUNT(*) FILTER (WHERE cover_art_source IN ('sidecar','embedded','mbcaa')) AS with_art,
COUNT(*) FILTER (WHERE cover_art_source IS NULL) AS pending,
COUNT(*) FILTER (WHERE cover_art_source = 'none') AS settled,
COUNT(*) FILTER (WHERE cover_art_source IS NULL AND mbid IS NULL) AS pending_no_mbid
FROM albums
`
type GetAlbumCoverageRollupRow struct {
Total int64
WithArt int64
Pending int64
Settled int64
PendingNoMbid int64
}
// M7 coverage-gauge: library-wide cover-art coverage rollup for the
// admin gauge. Single sequential scan with FILTER aggregates —
// sub-millisecond on realistic libraries. pending_no_mbid is a SUBSET
// of pending; the UI surfaces it separately so operators can see how
// many "pending" albums are blocked on missing MBID and won't be
// helped by another scan.
func (q *Queries) GetAlbumCoverageRollup(ctx context.Context) (GetAlbumCoverageRollupRow, error) {
row := q.db.QueryRow(ctx, getAlbumCoverageRollup)
var i GetAlbumCoverageRollupRow
err := row.Scan(
&i.Total,
&i.WithArt,
&i.Pending,
&i.Settled,
&i.PendingNoMbid,
)
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, albums.cover_art_source, artists.sort_name AS artist_sort_name
FROM albums
+16
View File
@@ -124,3 +124,19 @@ SELECT a.id AS album_id,
WHERE a.mbid IS NULL
ORDER BY a.created_at ASC
LIMIT $1;
-- name: GetAlbumCoverageRollup :one
-- M7 coverage-gauge: library-wide cover-art coverage rollup for the
-- admin gauge. Single sequential scan with FILTER aggregates —
-- sub-millisecond on realistic libraries. pending_no_mbid is a SUBSET
-- of pending; the UI surfaces it separately so operators can see how
-- many "pending" albums are blocked on missing MBID and won't be
-- helped by another scan.
SELECT
COUNT(*) AS total,
COUNT(*) FILTER (WHERE cover_art_source IN ('sidecar','embedded','mbcaa')) AS with_art,
COUNT(*) FILTER (WHERE cover_art_source IS NULL) AS pending,
COUNT(*) FILTER (WHERE cover_art_source = 'none') AS settled,
COUNT(*) FILTER (WHERE cover_art_source IS NULL AND mbid IS NULL) AS pending_no_mbid
FROM albums;