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>
71 lines
3.5 KiB
SQL
71 lines
3.5 KiB
SQL
-- name: UpsertTrackFingerprint :exec
|
|
-- Written whenever a track's fingerprint is derived: by the scan when a file is
|
|
-- new or its bytes changed, and by the backfill for rows derived by an
|
|
-- older method. Replaces the row wholesale — a fingerprint of the old bytes has
|
|
-- no standing once the file has changed.
|
|
INSERT INTO track_fingerprints (
|
|
track_id, audio_stream_sha256, chromaprint, fingerprint_version, chromaprint_length_sec
|
|
) VALUES (
|
|
sqlc.arg(track_id), sqlc.narg(audio_stream_sha256), sqlc.narg(chromaprint),
|
|
sqlc.arg(fingerprint_version), sqlc.arg(chromaprint_length_sec)
|
|
)
|
|
ON CONFLICT (track_id) DO UPDATE SET
|
|
audio_stream_sha256 = EXCLUDED.audio_stream_sha256,
|
|
chromaprint = EXCLUDED.chromaprint,
|
|
fingerprint_version = EXCLUDED.fingerprint_version,
|
|
chromaprint_length_sec = EXCLUDED.chromaprint_length_sec,
|
|
computed_at = now();
|
|
|
|
-- name: DeleteTrackFingerprint :exec
|
|
-- A file changed but could not be fingerprinted, for a reason unrelated to the
|
|
-- file. The stored row describes the OLD bytes, so it goes and the backfill
|
|
-- re-derives it — nothing may keep trusting a stale identity.
|
|
DELETE FROM track_fingerprints WHERE track_id = $1;
|
|
|
|
-- name: ListTracksNeedingFingerprint :many
|
|
-- The backfill's work queue: tracks with no fingerprint, or one derived
|
|
-- by an older method. Keyset-paged on id so a pass visits each track at most
|
|
-- once. That cursor is load-bearing: an inconclusive attempt writes no row, so
|
|
-- without it a file that keeps timing out would be listed again straight away
|
|
-- and retried in a tight loop. Missing tracks are skipped — there is no file to
|
|
-- read.
|
|
SELECT t.id, t.file_path
|
|
FROM tracks t
|
|
LEFT JOIN track_fingerprints f ON f.track_id = t.id
|
|
WHERE t.missing_since IS NULL
|
|
-- A row taken at another length is as stale as one from an older method:
|
|
-- chromaprints at two lengths cannot be compared.
|
|
AND (f.track_id IS NULL
|
|
OR f.fingerprint_version < sqlc.arg(current_version)
|
|
OR f.chromaprint_length_sec <> sqlc.arg(chromaprint_length_sec))
|
|
AND t.id > sqlc.arg(after_id)
|
|
ORDER BY t.id
|
|
LIMIT sqlc.arg(batch_limit);
|
|
|
|
-- name: GetFingerprintCoverage :one
|
|
-- The admin gauge for the backfill. fingerprinted + rejected + pending = total.
|
|
-- "Current" means derived by the current method AT the current length: a row at
|
|
-- another length is pending, because the backfill will re-derive it. rejected is
|
|
-- a current row with a NULL half: a tool ran and refused the file, which is
|
|
-- settled rather than waiting. Missing tracks are excluded, or the gauge could
|
|
-- never reach the end.
|
|
SELECT count(*)::bigint AS total,
|
|
count(*) FILTER (
|
|
WHERE f.fingerprint_version >= sqlc.arg(current_version)
|
|
AND f.chromaprint_length_sec = sqlc.arg(chromaprint_length_sec)
|
|
AND f.audio_stream_sha256 IS NOT NULL AND f.chromaprint IS NOT NULL
|
|
)::bigint AS fingerprinted,
|
|
count(*) FILTER (
|
|
WHERE f.fingerprint_version >= sqlc.arg(current_version)
|
|
AND f.chromaprint_length_sec = sqlc.arg(chromaprint_length_sec)
|
|
AND (f.audio_stream_sha256 IS NULL OR f.chromaprint IS NULL)
|
|
)::bigint AS rejected,
|
|
count(*) FILTER (
|
|
WHERE f.track_id IS NULL
|
|
OR f.fingerprint_version < sqlc.arg(current_version)
|
|
OR f.chromaprint_length_sec <> sqlc.arg(chromaprint_length_sec)
|
|
)::bigint AS pending
|
|
FROM tracks t
|
|
LEFT JOIN track_fingerprints f ON f.track_id = t.id
|
|
WHERE t.missing_since IS NULL;
|