// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: browse.sql package dbq import ( "context" "github.com/jackc/pgx/v5/pgtype" ) const countAlbumsByGenre = `-- name: CountAlbumsByGenre :one SELECT COUNT(*) FROM albums WHERE EXISTS ( SELECT 1 FROM tracks JOIN LATERAL regexp_split_to_table(coalesce(tracks.genre, ''), '[;,]') AS g(genre) ON true WHERE tracks.album_id = albums.id AND trim(g.genre) = trim($1::text) ) ` // Total for the paging envelope. EXISTS mirrors the list query exactly; a // JOIN + DISTINCT here would count differently the moment an album has two // tracks carrying the same genre. func (q *Queries) CountAlbumsByGenre(ctx context.Context, genre string) (int64, error) { row := q.db.QueryRow(ctx, countAlbumsByGenre, genre) var count int64 err := row.Scan(&count) return count, err } const countAlbumsByYearRange = `-- name: CountAlbumsByYearRange :one SELECT COUNT(*) FROM albums WHERE release_date IS NOT NULL AND EXTRACT(YEAR FROM release_date)::int BETWEEN $1::int AND $2::int ` type CountAlbumsByYearRangeParams struct { YearFrom int32 YearTo int32 } func (q *Queries) CountAlbumsByYearRange(ctx context.Context, arg CountAlbumsByYearRangeParams) (int64, error) { row := q.db.QueryRow(ctx, countAlbumsByYearRange, arg.YearFrom, arg.YearTo) var count int64 err := row.Scan(&count) return count, err } const listAlbumYearsWithCount = `-- name: ListAlbumYearsWithCount :many SELECT EXTRACT(YEAR FROM release_date)::int AS year, COUNT(*)::bigint AS album_count FROM albums WHERE release_date IS NOT NULL GROUP BY year ORDER BY year DESC ` type ListAlbumYearsWithCountRow struct { Year int32 AlbumCount int64 } // Year browse index (#367). Only albums with a release_date appear — an // album with no date isn't "year unknown" as a browsable bucket, it's absent // from this axis, and the UI says so rather than inventing a 0 row. // Newest first: recent releases are the likelier browse target. func (q *Queries) ListAlbumYearsWithCount(ctx context.Context) ([]ListAlbumYearsWithCountRow, error) { rows, err := q.db.Query(ctx, listAlbumYearsWithCount) if err != nil { return nil, err } defer rows.Close() var items []ListAlbumYearsWithCountRow for rows.Next() { var i ListAlbumYearsWithCountRow if err := rows.Scan(&i.Year, &i.AlbumCount); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listAlbumsByGenreWithArtist = `-- name: ListAlbumsByGenreWithArtist :many SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, albums.cover_art_sources_version, artists.name AS artist_name FROM albums JOIN artists ON artists.id = albums.artist_id WHERE EXISTS ( SELECT 1 FROM tracks JOIN LATERAL regexp_split_to_table(coalesce(tracks.genre, ''), '[;,]') AS g(genre) ON true WHERE tracks.album_id = albums.id AND trim(g.genre) = trim($1::text) ) ORDER BY albums.sort_title, albums.id LIMIT $3 OFFSET $2 ` type ListAlbumsByGenreWithArtistParams struct { Genre string Off int32 Lim int32 } type ListAlbumsByGenreWithArtistRow struct { Album Album ArtistName string } // Albums for one genre, joined with artist_name for the browse grid. // An album belongs to a genre when ANY of its tracks carry it. Splits and // trims identically to ListGenresWithCount — if the list is built by // splitting and the detail matched exactly, every multi-genre track would // produce a genre row that leads to an empty page. func (q *Queries) ListAlbumsByGenreWithArtist(ctx context.Context, arg ListAlbumsByGenreWithArtistParams) ([]ListAlbumsByGenreWithArtistRow, error) { rows, err := q.db.Query(ctx, listAlbumsByGenreWithArtist, arg.Genre, arg.Off, arg.Lim) if err != nil { return nil, err } defer rows.Close() var items []ListAlbumsByGenreWithArtistRow for rows.Next() { var i ListAlbumsByGenreWithArtistRow if err := rows.Scan( &i.Album.ID, &i.Album.Title, &i.Album.SortTitle, &i.Album.ArtistID, &i.Album.ReleaseDate, &i.Album.Mbid, &i.Album.CoverArtPath, &i.Album.CreatedAt, &i.Album.UpdatedAt, &i.Album.CoverArtSource, &i.Album.CoverArtSourcesVersion, &i.ArtistName, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listAlbumsByYearRangeWithArtist = `-- name: ListAlbumsByYearRangeWithArtist :many SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, albums.cover_art_sources_version, artists.name AS artist_name FROM albums JOIN artists ON artists.id = albums.artist_id WHERE albums.release_date IS NOT NULL AND EXTRACT(YEAR FROM albums.release_date)::int BETWEEN $1::int AND $2::int ORDER BY albums.sort_title, albums.id LIMIT $4 OFFSET $3 ` type ListAlbumsByYearRangeWithArtistParams struct { YearFrom int32 YearTo int32 Off int32 Lim int32 } type ListAlbumsByYearRangeWithArtistRow struct { Album Album ArtistName string } // Albums released within an inclusive year range, for the albums-page filter. func (q *Queries) ListAlbumsByYearRangeWithArtist(ctx context.Context, arg ListAlbumsByYearRangeWithArtistParams) ([]ListAlbumsByYearRangeWithArtistRow, error) { rows, err := q.db.Query(ctx, listAlbumsByYearRangeWithArtist, arg.YearFrom, arg.YearTo, arg.Off, arg.Lim, ) if err != nil { return nil, err } defer rows.Close() var items []ListAlbumsByYearRangeWithArtistRow for rows.Next() { var i ListAlbumsByYearRangeWithArtistRow if err := rows.Scan( &i.Album.ID, &i.Album.Title, &i.Album.SortTitle, &i.Album.ArtistID, &i.Album.ReleaseDate, &i.Album.Mbid, &i.Album.CoverArtPath, &i.Album.CreatedAt, &i.Album.UpdatedAt, &i.Album.CoverArtSource, &i.Album.CoverArtSourcesVersion, &i.ArtistName, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGenresForAlbum = `-- name: ListGenresForAlbum :many SELECT DISTINCT trim(g.genre) AS genre FROM tracks JOIN LATERAL regexp_split_to_table(coalesce(tracks.genre, ''), '[;,]') AS g(genre) ON true WHERE tracks.album_id = $1 AND trim(g.genre) <> '' ORDER BY trim(g.genre) ` // Distinct genres carried by an album's tracks, for the album detail page's // quick-jump chips. Split and trimmed identically to ListGenresWithCount, so a // chip always leads to a page that actually contains this album — the two // diverging is exactly the bug #367 had to fix in ListAlbumsByGenre. func (q *Queries) ListGenresForAlbum(ctx context.Context, albumID pgtype.UUID) ([]string, error) { rows, err := q.db.Query(ctx, listGenresForAlbum, albumID) if err != nil { return nil, err } defer rows.Close() var items []string for rows.Next() { var genre string if err := rows.Scan(&genre); err != nil { return nil, err } items = append(items, genre) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGenresForArtist = `-- name: ListGenresForArtist :many SELECT DISTINCT trim(g.genre) AS genre FROM tracks JOIN LATERAL regexp_split_to_table(coalesce(tracks.genre, ''), '[;,]') AS g(genre) ON true WHERE tracks.artist_id = $1 AND trim(g.genre) <> '' ORDER BY trim(g.genre) ` // Same, across everything by one artist. Alphabetical rather than by count: // an artist's genre set is small, and a stable order reads better than a // frequency ranking nobody asked about. func (q *Queries) ListGenresForArtist(ctx context.Context, artistID pgtype.UUID) ([]string, error) { rows, err := q.db.Query(ctx, listGenresForArtist, artistID) if err != nil { return nil, err } defer rows.Close() var items []string for rows.Next() { var genre string if err := rows.Scan(&genre); err != nil { return nil, err } items = append(items, genre) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGenresWithCount = `-- name: ListGenresWithCount :many SELECT trim(g.genre) AS genre, COUNT(DISTINCT tracks.id)::bigint AS track_count FROM tracks JOIN LATERAL regexp_split_to_table(coalesce(tracks.genre, ''), '[;,]') AS g(genre) ON true WHERE trim(g.genre) <> '' GROUP BY trim(g.genre) ORDER BY track_count DESC, trim(g.genre) ` type ListGenresWithCountRow struct { Genre string TrackCount int64 } // Genre browse index (#367). // // Genres live inline on tracks.genre as a delimited string, so this splits on // the same [;,] pattern already used by recommendation.sql and discover.sql — // a track tagged "Rock;Pop" must count toward both, and diverging from the // established pattern here would make the browse surface disagree with what // the recommendation engine believes the library contains. // // trim() but deliberately NO lower(): trimming repairs an artifact of OUR // splitting ("Rock; Pop" yields " Pop", and showing that as a distinct genre // would be a bug), whereas case is what the tag actually says. Raw ID3 is // exposed as-is for v1, so "Rock" and "rock" appear as separate rows. // // COUNT(DISTINCT) because a sloppy tag like "Rock;Rock" would otherwise // inflate its own row. // // Ordered by count first: raw ID3 data has a long tail of one-off junk tags, // so alphabetical would bury the handful of genres an operator actually has a // library's worth of. Name breaks ties for a stable order. // Ordered by the expression, not the output alias: `ORDER BY genre` is // ambiguous between the alias and tracks.genre, and sqlc rejects it. func (q *Queries) ListGenresWithCount(ctx context.Context) ([]ListGenresWithCountRow, error) { rows, err := q.db.Query(ctx, listGenresWithCount) if err != nil { return nil, err } defer rows.Close() var items []ListGenresWithCountRow for rows.Next() { var i ListGenresWithCountRow if err := rows.Scan(&i.Genre, &i.TrackCount); err != nil { return nil, err } items = append(items, i) } if err := rows.Err(); err != nil { return nil, err } return items, nil }