fix(tracks): match ISRC ignoring dashes and case, add functional index#832
Merged
Conversation
Normalize both the incoming ?isrc= query param (uppercase, strip non-alphanumerics) and the stored value in the SQL comparison so a row stored as "US-ANG-21-03742" matches a query of "USANG2103742" and vice versa. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a partial functional index matching the regexp_replace(upper(isrc), '[^A-Z0-9]', '', 'g') comparison so dash/case- insensitive ?isrc= lookups can index-scan instead of seq-scanning the tracks table. EXPLAIN on a 50k-row scratch table confirms the planner picks the index. Uses CREATE INDEX CONCURRENTLY (no transaction wrapper) to avoid taking an ACCESS EXCLUSIVE lock on tracks during the build. IF NOT EXISTS keeps the migration idempotent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
058c565 to
e95cb02
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ISRC lookup via
GET /v1/tracks?isrc=…failed when the stored value and the query disagreed on dash placement. Partner report (Thomas):Fixed purely on the search/query side (no normalization at write time):
isrcquery param in Go: uppercase + strip non-alphanumeric characters before passing to the DB.regexp_replace(upper(isrc), '[^A-Z0-9]', '', 'g')so the stored value is normalized at compare time.Net result: any combination of dashes/spaces/casing in either the request or the stored row matches.
US-ANG-21-03742,USANG2103742,usang2103742, andUS-ANG2103742all resolve to the same row.Index
Added
tracks_isrc_normalized_idx, a partial functional index matching the comparison expression so the new query can index-scan instead of seq-scanning all oftracks:Verified planner picks it on a 50k-row scratch table:
Index DDL uses
CREATE INDEX CONCURRENTLY(noBEGIN/COMMITwrapper) so the build does not take anACCESS EXCLUSIVElock ontracks.IF NOT EXISTSkeeps the migration idempotent. Partial onisrc IS NOT NULLsince most rows have no ISRC.Heads-up given #830: that PR moved
0201away fromCONCURRENTLYbecause the legacy Python Celery task onchallenge_disbursementswas keeping ~3-minute transactions open continuously, blocking the build'svirtualxidwait indefinitely.tracksis written by the Go indexer and isn't subject to that long-transaction pattern, soCONCURRENTLYshould complete normally here. If a stuck build needs to be aborted, drop the invalid index withDROP INDEX IF EXISTS tracks_isrc_normalized_idx;and re-run.ISWC
There is no
iswcquery-param lookup today (column exists and is exposed in API responses, but no handler or sqlc query reads it). Nothing to mirror — left as-is.Test plan
TestGetTracksByISRCcovers: stored-with-dashes queried undashed, queried with same dashes, queried lowercased; stored-without-dashes queried as-is and queried with inserted dashes.TestTracksEndpoint,TestGetTracksByPermalink,TestGetTracksExcludesAccessAuthorities,Test200UnAuthed) still pass.relation \"tracks_isrc_normalized_idx\" already exists, skipping).EXPLAINon a seeded scratch table showsBitmap Index Scan on tracks_isrc_normalized_idx.SELECT indexrelid::regclass, indisvalid FROM pg_index WHERE indexrelid::regclass::text = 'tracks_isrc_normalized_idx';returnsindisvalid = true.🤖 Generated with Claude Code