diff --git a/db/migrations/20260719005427_add_album_replaygain.go b/db/migrations/20260719005427_add_album_replaygain.go index 79c8b8b3e..7f5665947 100644 --- a/db/migrations/20260719005427_add_album_replaygain.go +++ b/db/migrations/20260719005427_add_album_replaygain.go @@ -12,28 +12,25 @@ func init() { } func upAddAlbumReplaygain(ctx context.Context, tx *sql.Tx) error { - // Backfill the most-frequent non-null value per album, matching MediaFiles.ToAlbum. A plain - // max() would pick a minority outlier, and GetTouchedAlbums never re-derives an unchanged album, - // so a wrong value would persist. The CTEs group media_file once instead of scanning it per album. + // Backfill the most-frequent value per album (matching MediaFiles.ToAlbum), staging RG-bearing rows + // into an indexed temp table — a correlated subquery over a windowed CTE re-scans media_file per album. _, err := tx.ExecContext(ctx, ` ALTER TABLE album ADD COLUMN rg_album_gain real; ALTER TABLE album ADD COLUMN rg_album_peak real; -WITH gain_mode AS ( - SELECT album_id, rg_album_gain AS val, - row_number() OVER (PARTITION BY album_id ORDER BY count(*) DESC, rg_album_gain) AS rn - FROM media_file WHERE rg_album_gain IS NOT NULL - GROUP BY album_id, rg_album_gain -), -peak_mode AS ( - SELECT album_id, rg_album_peak AS val, - row_number() OVER (PARTITION BY album_id ORDER BY count(*) DESC, rg_album_peak) AS rn - FROM media_file WHERE rg_album_peak IS NOT NULL - GROUP BY album_id, rg_album_peak -) +CREATE TEMP TABLE _rg_backfill AS + SELECT album_id, rg_album_gain, rg_album_peak FROM media_file + WHERE rg_album_gain IS NOT NULL OR rg_album_peak IS NOT NULL; +CREATE INDEX _rg_backfill_album ON _rg_backfill(album_id); + UPDATE album SET - rg_album_gain = (SELECT val FROM gain_mode WHERE gain_mode.album_id = album.id AND gain_mode.rn = 1), - rg_album_peak = (SELECT val FROM peak_mode WHERE peak_mode.album_id = album.id AND peak_mode.rn = 1); + rg_album_gain = (SELECT rg_album_gain FROM _rg_backfill WHERE _rg_backfill.album_id = album.id AND rg_album_gain IS NOT NULL + GROUP BY rg_album_gain ORDER BY count(*) DESC, rg_album_gain LIMIT 1), + rg_album_peak = (SELECT rg_album_peak FROM _rg_backfill WHERE _rg_backfill.album_id = album.id AND rg_album_peak IS NOT NULL + GROUP BY rg_album_peak ORDER BY count(*) DESC, rg_album_peak LIMIT 1) +WHERE album.id IN (SELECT album_id FROM _rg_backfill); + +DROP TABLE _rg_backfill; `) return err }