fix(pglite): pick random songs by id instead of rowid

PostgreSQL has no rowid; getRandomSongs failed with 'column
media_file.rowid does not exist'. The two-pass shape is kept on the
primary key.
This commit is contained in:
Deluan 2026-09-05 02:19:30 -04:00
parent 0628dd61ce
commit 5e3dc77f1d

View File

@ -238,33 +238,32 @@ func (r *mediaFileRepository) hydrateArtwork(mfs model.MediaFiles) {
hydrateMediaFileArtwork(r.ctx, r.db, mfs)
}
// GetRandom uses two passes so the random sort runs over a narrow rowid index instead of the
// wide media_file row: pick random rowids first, then hydrate only those.
// GetRandom uses two passes so the random sort runs over the narrow primary key index instead
// of the wide media_file row: pick random ids first, then hydrate only those.
func (r *mediaFileRepository) GetRandom(options ...model.QueryOptions) (model.MediaFiles, error) {
var opt model.QueryOptions
if len(options) > 0 {
opt = options[0]
}
rowidQuery := Select("media_file.rowid").From(r.tableName)
rowidQuery = r.applyFilters(rowidQuery, model.QueryOptions{Filters: opt.Filters})
rowidQuery = r.applyLibraryFilter(rowidQuery)
rowidQuery = rowidQuery.OrderBy("random()")
idQuery := Select("media_file.id").From(r.tableName)
idQuery = r.applyFilters(idQuery, model.QueryOptions{Filters: opt.Filters})
idQuery = r.applyLibraryFilter(idQuery)
idQuery = idQuery.OrderBy("random()")
if opt.Max > 0 {
rowidQuery = rowidQuery.Limit(uint64(opt.Max))
idQuery = idQuery.Limit(uint64(opt.Max))
}
var rowids []int64
if err := r.queryAllSlice(rowidQuery, &rowids); err != nil {
var ids []string
if err := r.queryAllSlice(idQuery, &ids); err != nil {
return nil, err
}
if len(rowids) == 0 {
if len(ids) == 0 {
return model.MediaFiles{}, nil
}
// Re-shuffle in Phase 2: `WHERE rowid IN (...)` returns rows in ascending rowid order, not
// the random order from Phase 1. Sorting only the (<=Max) hydrated rows is negligible.
sq := r.selectMediaFile().Where(Eq{"media_file.rowid": rowids}).OrderBy("random()")
// Re-shuffle in Phase 2: `WHERE id IN (...)` does not keep the random order from Phase 1.
sq := r.selectMediaFile().Where(Eq{"media_file.id": ids}).OrderBy("random()")
var res dbMediaFiles
if err := r.queryAll(sq, &res); err != nil {
return nil, err