Evaluate now issues a lean main SELECT over the joined metadata tables
with no genre column, then batch-fetches genres with a single query
using WHERE recording_id IN (...). Previously the track_metadata view's
correlated GROUP_CONCAT subquery ran per row and scaled with library
size rather than result size, producing multi-second load times for
100-track smart playlists.
- Inline the metadata joins instead of using the track_metadata view,
so the per-row GROUP_CONCAT never runs on the hot path. Other
callers of the view (search, library listing) are unaffected.
- Route all genre operators (is/is_not/is_any_of/contains/etc.)
through a recording_genres subquery against af.recording_id.
Previously text operators like "contains" matched against the
view's concatenated genre column, which is no longer in scope.
- Sort-by-genre falls back to Go-side sort after the batch genre
merge since there is no single SQL column to sort on.
- Log main_ms / genres_ms / total_ms at Debug for future tuning.
- Add (*DB).Logger() accessor so smartplaylist can reuse the DB's
structured logger without changing Evaluate's signature.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>