Files
minstrel/internal/db/queries/acoustid.sql
T
bvandeusenandClaude Opus 5.5 1d4ef1a23f docs: query comments say what each query selects and why, not how it came to be (#6277)
Rewrites the internal/db/queries comments to rule 32 and regenerates
dbq, whose doc comments and embedded SQL carry them. The bugs behind the
tiered mixes, the md5 order seed, the score bands and the round-robin
arms are restated as the constraint each one enforces; counts from one
library and stale cross-references are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:31:13 -04:00

100 lines
4.3 KiB
SQL

-- AcoustID recording-id lookup. Migration 0069 says what each
-- lookup state means.
-- name: ListTracksNeedingAcoustIDLookup :many
-- The lookup worker's queue: present tracks with no tag MBID and no lookup
-- since their file last changed. A looked-up id is included once its row is
-- gone (the file changed), so the new bytes are checked rather than trusted.
-- Keyset-paged on id, as the loudness queue is, so a pass ends even when
-- every attempt is inconclusive and writes nothing.
SELECT t.id, t.file_path, t.title, t.duration_ms
FROM tracks t
WHERE (t.mbid IS NULL OR t.mbid_source = 'acoustid')
AND t.missing_since IS NULL
AND t.id > sqlc.arg(after_id)::uuid
AND NOT EXISTS (SELECT 1 FROM track_acoustid_lookups l WHERE l.track_id = t.id)
ORDER BY t.id
LIMIT sqlc.arg(batch_limit);
-- name: RecordAcoustIDLookup :exec
INSERT INTO track_acoustid_lookups (track_id, state, best_score, candidates, recording_mbid, detail)
VALUES (sqlc.arg(track_id), sqlc.arg(state), sqlc.narg(best_score), sqlc.arg(candidates),
sqlc.narg(recording_mbid), sqlc.narg(detail))
ON CONFLICT (track_id) DO UPDATE SET
state = EXCLUDED.state,
best_score = EXCLUDED.best_score,
candidates = EXCLUDED.candidates,
recording_mbid = EXCLUDED.recording_mbid,
detail = EXCLUDED.detail,
looked_up_at = now();
-- name: SetTrackMbidFromAcoustID :execrows
-- Never over a tag id: the guard is here, not only in the worker, so a
-- tag the scan read between the worker's list and this write still wins.
-- updated_at is left alone: it gates the scan's mtime skip, and moving it
-- past a file's mtime would hide a change made just before the lookup.
UPDATE tracks
SET mbid = sqlc.arg(mbid), mbid_source = 'acoustid'
WHERE id = sqlc.arg(id)
AND (mbid IS NULL OR mbid_source = 'acoustid');
-- name: ClearTrackAcoustIDMbid :exec
-- A re-lookup of changed bytes that no longer matches takes back the id an
-- earlier lookup wrote. A tag id is never touched.
UPDATE tracks
SET mbid = NULL, mbid_source = NULL
WHERE id = sqlc.arg(id)
AND mbid_source = 'acoustid';
-- name: DeleteAcoustIDLookup :exec
-- The scan drops the lookup of bytes that are gone, so the worker checks the
-- new ones.
DELETE FROM track_acoustid_lookups WHERE track_id = $1;
-- name: GetMbidCoverage :one
-- The admin gauge: present tracks by where their MBID came from, and the
-- lookup states of those a lookup has seen. pending is what the worker's
-- queue holds.
SELECT count(*)::bigint AS total,
count(*) FILTER (WHERE t.mbid_source = 'tag')::bigint AS from_tag,
count(*) FILTER (WHERE t.mbid_source = 'acoustid')::bigint AS from_acoustid,
count(*) FILTER (WHERE l.state = 'ambiguous')::bigint AS ambiguous,
count(*) FILTER (WHERE l.state = 'no_match')::bigint AS no_match,
count(*) FILTER (WHERE l.state = 'failed')::bigint AS failed,
count(*) FILTER (
WHERE l.track_id IS NULL AND (t.mbid IS NULL OR t.mbid_source = 'acoustid')
)::bigint AS pending
FROM tracks t
LEFT JOIN track_acoustid_lookups l ON l.track_id = t.id
WHERE t.missing_since IS NULL;
-- name: ListUnsettledAcoustIDLookups :many
-- The admin list of tracks a lookup could not settle (ambiguous or failed),
-- so they are findable rather than silently empty.
SELECT t.id, t.title, t.file_path, ar.name AS artist_name, al.title AS album_title,
l.state, l.best_score, l.candidates, l.detail, l.looked_up_at
FROM track_acoustid_lookups l
JOIN tracks t ON t.id = l.track_id
JOIN artists ar ON ar.id = t.artist_id
JOIN albums al ON al.id = t.album_id
WHERE l.state IN ('ambiguous', 'failed')
AND t.missing_since IS NULL
ORDER BY ar.name, al.title, t.disc_number NULLS FIRST, t.track_number NULLS FIRST, t.title
LIMIT sqlc.arg(row_limit);
-- name: GetAcoustIDSettings :one
SELECT * FROM acoustid_settings WHERE id = true;
-- name: UpdateAcoustIDSettings :one
-- The key is write-only from the admin card: set_api_key false keeps the
-- stored one, and an empty api_key with set_api_key true clears it.
UPDATE acoustid_settings
SET enabled = sqlc.arg(enabled),
min_score = sqlc.arg(min_score),
api_key = CASE WHEN sqlc.arg(set_api_key)::boolean
THEN NULLIF(sqlc.arg(api_key)::text, '')
ELSE api_key END,
updated_at = now()
WHERE id = true
RETURNING *;