From fb49a394920fd7419ce4d73ed00068c3b1e6be39 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 21 Apr 2026 00:01:15 -0400 Subject: [PATCH] feat(db): add paged + count queries for library reads --- internal/db/dbq/albums.sql.go | 11 ++++ internal/db/dbq/artists.sql.go | 95 +++++++++++++++++++++++++++++++++ internal/db/dbq/tracks.sql.go | 11 ++++ internal/db/queries/albums.sql | 3 ++ internal/db/queries/artists.sql | 13 +++++ internal/db/queries/tracks.sql | 3 ++ 6 files changed, 136 insertions(+) diff --git a/internal/db/dbq/albums.sql.go b/internal/db/dbq/albums.sql.go index 3d80f654..f94956b6 100644 --- a/internal/db/dbq/albums.sql.go +++ b/internal/db/dbq/albums.sql.go @@ -11,6 +11,17 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) +const countAlbumsMatching = `-- name: CountAlbumsMatching :one +SELECT COUNT(*) FROM albums WHERE title ILIKE '%' || $1::text || '%' +` + +func (q *Queries) CountAlbumsMatching(ctx context.Context, dollar_1 string) (int64, error) { + row := q.db.QueryRow(ctx, countAlbumsMatching, dollar_1) + var count int64 + err := row.Scan(&count) + return count, err +} + const getAlbumByArtistAndTitle = `-- name: GetAlbumByArtistAndTitle :one SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums WHERE artist_id = $1 AND title = $2 LIMIT 1 ` diff --git a/internal/db/dbq/artists.sql.go b/internal/db/dbq/artists.sql.go index a435e5fc..259efbc4 100644 --- a/internal/db/dbq/artists.sql.go +++ b/internal/db/dbq/artists.sql.go @@ -11,6 +11,28 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) +const countArtists = `-- name: CountArtists :one +SELECT COUNT(*) FROM artists +` + +func (q *Queries) CountArtists(ctx context.Context) (int64, error) { + row := q.db.QueryRow(ctx, countArtists) + var count int64 + err := row.Scan(&count) + return count, err +} + +const countArtistsMatching = `-- name: CountArtistsMatching :one +SELECT COUNT(*) FROM artists WHERE name ILIKE '%' || $1::text || '%' +` + +func (q *Queries) CountArtistsMatching(ctx context.Context, dollar_1 string) (int64, error) { + row := q.db.QueryRow(ctx, countArtistsMatching, dollar_1) + var count int64 + err := row.Scan(&count) + return count, err +} + const getArtistByID = `-- name: GetArtistByID :one SELECT id, name, sort_name, mbid, created_at, updated_at FROM artists WHERE id = $1 ` @@ -78,6 +100,79 @@ func (q *Queries) ListArtists(ctx context.Context) ([]Artist, error) { return items, nil } +const listArtistsAlpha = `-- name: ListArtistsAlpha :many +SELECT id, name, sort_name, mbid, created_at, updated_at FROM artists ORDER BY sort_name, name, id LIMIT $1 OFFSET $2 +` + +type ListArtistsAlphaParams struct { + Limit int32 + Offset int32 +} + +func (q *Queries) ListArtistsAlpha(ctx context.Context, arg ListArtistsAlphaParams) ([]Artist, error) { + rows, err := q.db.Query(ctx, listArtistsAlpha, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Artist + for rows.Next() { + var i Artist + if err := rows.Scan( + &i.ID, + &i.Name, + &i.SortName, + &i.Mbid, + &i.CreatedAt, + &i.UpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listArtistsNewest = `-- name: ListArtistsNewest :many +SELECT id, name, sort_name, mbid, created_at, updated_at FROM artists ORDER BY created_at DESC, id DESC LIMIT $1 OFFSET $2 +` + +type ListArtistsNewestParams struct { + Limit int32 + Offset int32 +} + +// Secondary id tiebreaker keeps pagination stable when created_at ties. +func (q *Queries) ListArtistsNewest(ctx context.Context, arg ListArtistsNewestParams) ([]Artist, error) { + rows, err := q.db.Query(ctx, listArtistsNewest, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Artist + for rows.Next() { + var i Artist + if err := rows.Scan( + &i.ID, + &i.Name, + &i.SortName, + &i.Mbid, + &i.CreatedAt, + &i.UpdatedAt, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const searchArtists = `-- name: SearchArtists :many SELECT id, name, sort_name, mbid, created_at, updated_at FROM artists WHERE name ILIKE '%' || $1 || '%' diff --git a/internal/db/dbq/tracks.sql.go b/internal/db/dbq/tracks.sql.go index e56d12d5..5254bb50 100644 --- a/internal/db/dbq/tracks.sql.go +++ b/internal/db/dbq/tracks.sql.go @@ -22,6 +22,17 @@ func (q *Queries) CountTracksByAlbum(ctx context.Context, albumID pgtype.UUID) ( return count, err } +const countTracksMatching = `-- name: CountTracksMatching :one +SELECT COUNT(*) FROM tracks WHERE title ILIKE '%' || $1::text || '%' +` + +func (q *Queries) CountTracksMatching(ctx context.Context, dollar_1 string) (int64, error) { + row := q.db.QueryRow(ctx, countTracksMatching, dollar_1) + var count int64 + err := row.Scan(&count) + return count, err +} + const getTrackByID = `-- name: GetTrackByID :one SELECT id, title, album_id, artist_id, track_number, disc_number, duration_ms, file_path, file_size, file_format, bitrate, mbid, genre, added_at, updated_at FROM tracks WHERE id = $1 ` diff --git a/internal/db/queries/albums.sql b/internal/db/queries/albums.sql index 4c07569e..63b8ec6f 100644 --- a/internal/db/queries/albums.sql +++ b/internal/db/queries/albums.sql @@ -53,3 +53,6 @@ SELECT * FROM albums WHERE title ILIKE '%' || $1 || '%' ORDER BY sort_title LIMIT $2 OFFSET $3; + +-- name: CountAlbumsMatching :one +SELECT COUNT(*) FROM albums WHERE title ILIKE '%' || $1::text || '%'; diff --git a/internal/db/queries/artists.sql b/internal/db/queries/artists.sql index b24c289f..f089d46e 100644 --- a/internal/db/queries/artists.sql +++ b/internal/db/queries/artists.sql @@ -24,3 +24,16 @@ SELECT * FROM artists WHERE name ILIKE '%' || $1 || '%' ORDER BY sort_name LIMIT $2 OFFSET $3; + +-- name: ListArtistsAlpha :many +SELECT * FROM artists ORDER BY sort_name, name, id LIMIT $1 OFFSET $2; + +-- name: ListArtistsNewest :many +-- Secondary id tiebreaker keeps pagination stable when created_at ties. +SELECT * FROM artists ORDER BY created_at DESC, id DESC LIMIT $1 OFFSET $2; + +-- name: CountArtists :one +SELECT COUNT(*) FROM artists; + +-- name: CountArtistsMatching :one +SELECT COUNT(*) FROM artists WHERE name ILIKE '%' || $1::text || '%'; diff --git a/internal/db/queries/tracks.sql b/internal/db/queries/tracks.sql index dde57e53..04bffc56 100644 --- a/internal/db/queries/tracks.sql +++ b/internal/db/queries/tracks.sql @@ -36,3 +36,6 @@ SELECT * FROM tracks WHERE title ILIKE '%' || $1 || '%' ORDER BY title LIMIT $2 OFFSET $3; + +-- name: CountTracksMatching :one +SELECT COUNT(*) FROM tracks WHERE title ILIKE '%' || $1::text || '%';