diff --git a/Makefile b/Makefile index 42b1ad57..ac425514 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: generate test test-short lint build -SQLC_VERSION := 1.27.0 +SQLC_VERSION := 1.31.1 generate: docker run --rm -v "$(CURDIR):/src" -w /src sqlc/sqlc:$(SQLC_VERSION) generate diff --git a/internal/db/dbq/albums.sql.go b/internal/db/dbq/albums.sql.go index 91d8513f..37c4a3a7 100644 --- a/internal/db/dbq/albums.sql.go +++ b/internal/db/dbq/albums.sql.go @@ -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 diff --git a/internal/db/queries/albums.sql b/internal/db/queries/albums.sql index 527fb4e5..0716205b 100644 --- a/internal/db/queries/albums.sql +++ b/internal/db/queries/albums.sql @@ -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; +