#9 Major routes refactor and expansion, #15 Added API for statistics, Added search cache backend and functionality tests, Backend sync improvements
Build / build (push) Successful in 56s

This commit is contained in:
Sansan committed 2026-09-26 16:48:40 +02:00
1 parent e86c0f8e04
commit a8a2602f50
34 files changed
+1819 -1294

No files matched your search

@@ -1,33 +0,0 @@
-- Revert: Rename soundtrack table back to game
ALTER TABLE soundtrack RENAME TO game;
-- Revert primary key sequence
ALTER SEQUENCE soundtrack_id_seq RENAME TO game_id_seq;
-- Revert columns in game table
ALTER TABLE game RENAME COLUMN soundtrack_name TO game_name;
-- Revert song table: rename soundtrack_id back to game_id
ALTER TABLE song RENAME COLUMN soundtrack_id TO game_id;
-- Revert song primary key
ALTER TABLE song DROP CONSTRAINT IF EXISTS song_pkey;
ALTER TABLE song ADD PRIMARY KEY (game_id, path);
ALTER TABLE song RENAME CONSTRAINT song_pkey_soundtrack TO song_pkey;
-- Revert song_list table references
ALTER TABLE song_list RENAME COLUMN soundtrack_name TO game_name;
-- Revert foreign key constraint
ALTER TABLE song DROP CONSTRAINT IF EXISTS song_soundtrack_id_fkey;
ALTER TABLE song ADD CONSTRAINT song_game_id_fkey
FOREIGN KEY (game_id) REFERENCES game(id);
-- Revert indexes
ALTER INDEX IF EXISTS idx_soundtrack_deleted RENAME TO idx_game_deleted;
ALTER INDEX IF EXISTS idx_soundtrack_hash RENAME TO idx_game_hash;
ALTER INDEX IF EXISTS idx_soundtrack_path RENAME TO idx_game_path;
ALTER INDEX IF EXISTS idx_soundtrack_name RENAME TO idx_game_name;
ALTER INDEX IF EXISTS idx_song_soundtrack_id RENAME TO idx_song_game_id;
ALTER INDEX IF EXISTS idx_song_soundtrack_id_song_name RENAME TO idx_song_game_id_song_name;
ALTER INDEX IF EXISTS song_list_soundtrack_name_idx RENAME TO song_list_game_name_idx;
@@ -1,32 +0,0 @@
-- Rename game table to soundtrack
ALTER TABLE game RENAME TO soundtrack;
-- Rename primary key sequence
ALTER SEQUENCE game_id_seq RENAME TO soundtrack_id_seq;
-- Rename columns in soundtrack table
ALTER TABLE soundtrack RENAME COLUMN game_name TO soundtrack_name;
-- Update song table: rename game_id to soundtrack_id
ALTER TABLE song RENAME COLUMN game_id TO soundtrack_id;
-- Update song primary key
ALTER TABLE song DROP CONSTRAINT IF EXISTS song_pkey;
ALTER TABLE song ADD PRIMARY KEY (soundtrack_id, path);
-- Update song_list table references
ALTER TABLE song_list RENAME COLUMN game_name TO soundtrack_name;
-- Rename foreign key constraint
ALTER TABLE song DROP CONSTRAINT IF EXISTS song_game_id_fkey;
ALTER TABLE song ADD CONSTRAINT song_soundtrack_id_fkey
FOREIGN KEY (soundtrack_id) REFERENCES soundtrack(id);
-- Rename indexes
ALTER INDEX IF EXISTS idx_game_deleted RENAME TO idx_soundtrack_deleted;
ALTER INDEX IF EXISTS idx_game_hash RENAME TO idx_soundtrack_hash;
ALTER INDEX IF EXISTS idx_game_path RENAME TO idx_soundtrack_path;
ALTER INDEX IF EXISTS idx_game_name RENAME TO idx_soundtrack_name;
ALTER INDEX IF EXISTS idx_song_game_id RENAME TO idx_song_soundtrack_id;
ALTER INDEX IF EXISTS idx_song_game_id_song_name RENAME TO idx_song_soundtrack_id_song_name;
ALTER INDEX IF EXISTS song_list_game_name_idx RENAME TO song_list_soundtrack_name_idx;
@@ -1,24 +0,0 @@
-- Rollback: Remove id column and restore composite PK
-- Step 1: Drop indexes created in up migration
DROP INDEX IF EXISTS idx_song_soundtrack_id;
DROP INDEX IF EXISTS idx_song_path;
-- Step 2: Drop foreign key constraint
ALTER TABLE song DROP CONSTRAINT IF EXISTS song_soundtrack_id_fkey;
-- Step 3: Drop new primary key
ALTER TABLE song DROP CONSTRAINT song_pkey;
-- Step 4: Drop unique constraint on id
ALTER TABLE song DROP CONSTRAINT IF EXISTS song_id_unique;
-- Step 5: Restore composite primary key
ALTER TABLE song ADD CONSTRAINT song_pkey PRIMARY KEY (soundtrack_id, path);
-- Step 6: Drop the id column
ALTER TABLE song DROP COLUMN id;
-- Step 7: Recreate original foreign key (soundtrack_id references soundtrack.id)
ALTER TABLE song ADD CONSTRAINT song_soundtrack_id_fkey
FOREIGN KEY (soundtrack_id) REFERENCES soundtrack(id);
@@ -1,36 +0,0 @@
-- Migration: Add id column to song table and change PK from composite to single column
-- This prepares the song table for eventual UUID migration
-- Step 1: Add new id column (nullable initially)
ALTER TABLE song ADD COLUMN id serial4;
-- Step 2: Create unique constraint on id (allows backfilling)
ALTER TABLE song ADD CONSTRAINT song_id_unique UNIQUE (id);
-- Step 3: Backfill existing rows with sequential IDs
-- Use DEFAULT which pulls from the sequence
UPDATE song SET id = DEFAULT WHERE id IS NULL;
-- Step 4: Verify all rows have an id
-- If this returns 0, backfill worked
-- SELECT COUNT(*) FROM song WHERE id IS NULL;
-- Step 5: Drop the composite primary key (soundtrack_id, path)
ALTER TABLE song DROP CONSTRAINT song_pkey;
-- Step 6: Add new primary key on id column
ALTER TABLE song ADD CONSTRAINT song_pkey PRIMARY KEY (id);
-- Step 7: Ensure soundtrack_id remains a foreign key to soundtrack
-- First drop existing FK if it exists (from the rename migration)
ALTER TABLE song DROP CONSTRAINT IF EXISTS song_soundtrack_id_fkey;
-- Then recreate it
ALTER TABLE song ADD CONSTRAINT song_soundtrack_id_fkey
FOREIGN KEY (soundtrack_id) REFERENCES soundtrack(id);
-- Step 8: Create index on soundtrack_id for query performance
CREATE INDEX IF NOT EXISTS idx_song_soundtrack_id ON song(soundtrack_id);
-- Step 9: Create index on path for lookups (previously part of PK)
CREATE INDEX IF NOT EXISTS idx_song_path ON song(path);
+12 -4
View File
@@ -5,7 +5,7 @@ DELETE FROM song;
DELETE FROM song WHERE soundtrack_id = $1;
-- name: AddSong :exec
INSERT INTO song(soundtrack_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5);
INSERT INTO song(soundtrack_id, song_name, path, file_name, hash, uuid, soundtrack_uuid) VALUES ($1, $2, $3, $4, $5, $6, $7);
-- name: CheckSong :one
SELECT COUNT(*) FROM song WHERE soundtrack_id = $1 AND path = $2;
@@ -34,11 +34,19 @@ WHERE soundtrack_id = $1 AND song_name = $2;
-- name: FetchAllSongs :many
SELECT * FROM song;
-- name: GetSongById :one
SELECT * FROM song WHERE id = $1;
-- name: GetSongByUUID :one
SELECT * FROM song WHERE uuid = $1;
-- name: RemoveBrokenSong :exec
DELETE FROM song WHERE soundtrack_id = $1 AND path = $2;
-- name: RemoveBrokenSongs :exec
DELETE FROM song WHERE id = ANY($1);
DELETE FROM song WHERE uuid = ANY($1);
-- name: GetSongsBySoundtrackUUID :many
SELECT *
FROM song
WHERE soundtrack_uuid = $1;
-- name: GetSongUUIDsBySoundtrackId :many
SELECT uuid, soundtrack_uuid FROM song WHERE soundtrack_id = $1;
+10 -1
View File
@@ -29,7 +29,7 @@ UPDATE soundtrack SET deleted=NULL WHERE id=$1;
SELECT id FROM soundtrack WHERE soundtrack_name = $1;
-- name: InsertSoundtrack :one
INSERT INTO soundtrack (soundtrack_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id;
INSERT INTO soundtrack (soundtrack_name, path, hash, added, uuid) VALUES ($1, $2, $3, now(), $4) returning id, uuid;
-- name: InsertSoundtrackWithExistingId :exec
INSERT INTO soundtrack (id, soundtrack_name, path, hash, added) VALUES ($1, $2, $3, $4, now());
@@ -47,3 +47,12 @@ ORDER BY soundtrack_name;
-- name: AddSoundtrackPlayed :exec
UPDATE soundtrack SET times_played = times_played + 1, last_played = now() WHERE id = $1;
-- name: GetSoundtrackByUUID :one
SELECT *
FROM soundtrack
WHERE uuid = $1
AND deleted IS NULL;
-- name: GetSoundtrackUUIDById :one
SELECT uuid FROM soundtrack WHERE id = $1;
+10 -7
View File
@@ -7,6 +7,7 @@ package repository
import (
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
@@ -20,13 +21,14 @@ type Session struct {
}
type Song struct {
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
TimesPlayed int32 `json:"times_played"`
Hash string `json:"hash"`
FileName *string `json:"file_name"`
ID pgtype.Int4 `json:"id"`
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
TimesPlayed int32 `json:"times_played"`
Hash string `json:"hash"`
FileName *string `json:"file_name"`
Uuid uuid.UUID `json:"uuid"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
}
type SongList struct {
@@ -48,6 +50,7 @@ type Soundtrack struct {
LastPlayed *time.Time `json:"last_played"`
NumberOfSongs int32 `json:"number_of_songs"`
Hash string `json:"hash"`
Uuid uuid.UUID `json:"uuid"`
}
type Vgmq struct {
+93 -21
View File
@@ -8,7 +8,7 @@ package repository
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
"github.com/google/uuid"
)
const addHashToSong = `-- name: AddHashToSong :exec
@@ -27,15 +27,17 @@ func (q *Queries) AddHashToSong(ctx context.Context, arg AddHashToSongParams) er
}
const addSong = `-- name: AddSong :exec
INSERT INTO song(soundtrack_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5)
INSERT INTO song(soundtrack_id, song_name, path, file_name, hash, uuid, soundtrack_uuid) VALUES ($1, $2, $3, $4, $5, $6, $7)
`
type AddSongParams struct {
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
FileName *string `json:"file_name"`
Hash string `json:"hash"`
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
FileName *string `json:"file_name"`
Hash string `json:"hash"`
Uuid uuid.UUID `json:"uuid"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
}
func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error {
@@ -45,6 +47,8 @@ func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error {
arg.Path,
arg.FileName,
arg.Hash,
arg.Uuid,
arg.SoundtrackUuid,
)
return err
}
@@ -110,7 +114,7 @@ func (q *Queries) ClearSongsBySoundtrackId(ctx context.Context, soundtrackID int
}
const fetchAllSongs = `-- name: FetchAllSongs :many
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id FROM song
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid FROM song
`
func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
@@ -129,7 +133,8 @@ func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
); err != nil {
return nil, err
}
@@ -142,7 +147,7 @@ func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
}
const findSongsFromSoundtrack = `-- name: FindSongsFromSoundtrack :many
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid
FROM song
WHERE soundtrack_id = $1
`
@@ -163,7 +168,8 @@ func (q *Queries) FindSongsFromSoundtrack(ctx context.Context, soundtrackID int3
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
); err != nil {
return nil, err
}
@@ -175,12 +181,12 @@ func (q *Queries) FindSongsFromSoundtrack(ctx context.Context, soundtrackID int3
return items, nil
}
const getSongById = `-- name: GetSongById :one
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id FROM song WHERE id = $1
const getSongByUUID = `-- name: GetSongByUUID :one
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid FROM song WHERE uuid = $1
`
func (q *Queries) GetSongById(ctx context.Context, id pgtype.Int4) (Song, error) {
row := q.db.QueryRow(ctx, getSongById, id)
func (q *Queries) GetSongByUUID(ctx context.Context, argUuid uuid.UUID) (Song, error) {
row := q.db.QueryRow(ctx, getSongByUUID, argUuid)
var i Song
err := row.Scan(
&i.SoundtrackID,
@@ -189,13 +195,43 @@ func (q *Queries) GetSongById(ctx context.Context, id pgtype.Int4) (Song, error)
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
)
return i, err
}
const getSongUUIDsBySoundtrackId = `-- name: GetSongUUIDsBySoundtrackId :many
SELECT uuid, soundtrack_uuid FROM song WHERE soundtrack_id = $1
`
type GetSongUUIDsBySoundtrackIdRow struct {
Uuid uuid.UUID `json:"uuid"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
}
func (q *Queries) GetSongUUIDsBySoundtrackId(ctx context.Context, soundtrackID int32) ([]GetSongUUIDsBySoundtrackIdRow, error) {
rows, err := q.db.Query(ctx, getSongUUIDsBySoundtrackId, soundtrackID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetSongUUIDsBySoundtrackIdRow
for rows.Next() {
var i GetSongUUIDsBySoundtrackIdRow
if err := rows.Scan(&i.Uuid, &i.SoundtrackUuid); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getSongWithHash = `-- name: GetSongWithHash :one
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id FROM song WHERE hash = $1
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid FROM song WHERE hash = $1
`
func (q *Queries) GetSongWithHash(ctx context.Context, hash string) (Song, error) {
@@ -208,11 +244,47 @@ func (q *Queries) GetSongWithHash(ctx context.Context, hash string) (Song, error
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
)
return i, err
}
const getSongsBySoundtrackUUID = `-- name: GetSongsBySoundtrackUUID :many
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid
FROM song
WHERE soundtrack_uuid = $1
`
func (q *Queries) GetSongsBySoundtrackUUID(ctx context.Context, soundtrackUuid uuid.UUID) ([]Song, error) {
rows, err := q.db.Query(ctx, getSongsBySoundtrackUUID, soundtrackUuid)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Song
for rows.Next() {
var i Song
if err := rows.Scan(
&i.SoundtrackID,
&i.SongName,
&i.Path,
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.Uuid,
&i.SoundtrackUuid,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const removeBrokenSong = `-- name: RemoveBrokenSong :exec
DELETE FROM song WHERE soundtrack_id = $1 AND path = $2
`
@@ -228,11 +300,11 @@ func (q *Queries) RemoveBrokenSong(ctx context.Context, arg RemoveBrokenSongPara
}
const removeBrokenSongs = `-- name: RemoveBrokenSongs :exec
DELETE FROM song WHERE id = ANY($1)
DELETE FROM song WHERE uuid = ANY($1)
`
func (q *Queries) RemoveBrokenSongs(ctx context.Context, id pgtype.Int4) error {
_, err := q.db.Exec(ctx, removeBrokenSongs, id)
func (q *Queries) RemoveBrokenSongs(ctx context.Context, argUuid uuid.UUID) error {
_, err := q.db.Exec(ctx, removeBrokenSongs, argUuid)
return err
}
+65 -12
View File
@@ -7,6 +7,8 @@ package repository
import (
"context"
"github.com/google/uuid"
)
const addSoundtrackPlayed = `-- name: AddSoundtrackPlayed :exec
@@ -28,7 +30,7 @@ func (q *Queries) ClearSoundtracks(ctx context.Context) error {
}
const findAllSoundtracks = `-- name: FindAllSoundtracks :many
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
WHERE deleted IS NULL
ORDER BY soundtrack_name
@@ -54,6 +56,7 @@ func (q *Queries) FindAllSoundtracks(ctx context.Context) ([]Soundtrack, error)
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
); err != nil {
return nil, err
}
@@ -66,7 +69,7 @@ func (q *Queries) FindAllSoundtracks(ctx context.Context) ([]Soundtrack, error)
}
const getAllSoundtracksIncludingDeleted = `-- name: GetAllSoundtracksIncludingDeleted :many
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
ORDER BY soundtrack_name
`
@@ -91,6 +94,7 @@ func (q *Queries) GetAllSoundtracksIncludingDeleted(ctx context.Context) ([]Soun
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
); err != nil {
return nil, err
}
@@ -114,7 +118,7 @@ func (q *Queries) GetIdBySoundtrackName(ctx context.Context, soundtrackName stri
}
const getSoundtrackById = `-- name: GetSoundtrackById :one
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
WHERE id = $1
AND deleted IS NULL
@@ -134,6 +138,33 @@ func (q *Queries) GetSoundtrackById(ctx context.Context, id int32) (Soundtrack,
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
)
return i, err
}
const getSoundtrackByUUID = `-- name: GetSoundtrackByUUID :one
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
WHERE uuid = $1
AND deleted IS NULL
`
func (q *Queries) GetSoundtrackByUUID(ctx context.Context, argUuid uuid.UUID) (Soundtrack, error) {
row := q.db.QueryRow(ctx, getSoundtrackByUUID, argUuid)
var i Soundtrack
err := row.Scan(
&i.ID,
&i.SoundtrackName,
&i.Added,
&i.Deleted,
&i.LastChanged,
&i.Path,
&i.TimesPlayed,
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
)
return i, err
}
@@ -149,21 +180,43 @@ func (q *Queries) GetSoundtrackNameById(ctx context.Context, id int32) (string,
return soundtrack_name, err
}
const getSoundtrackUUIDById = `-- name: GetSoundtrackUUIDById :one
SELECT uuid FROM soundtrack WHERE id = $1
`
func (q *Queries) GetSoundtrackUUIDById(ctx context.Context, id int32) (uuid.UUID, error) {
row := q.db.QueryRow(ctx, getSoundtrackUUIDById, id)
var uuid uuid.UUID
err := row.Scan(&uuid)
return uuid, err
}
const insertSoundtrack = `-- name: InsertSoundtrack :one
INSERT INTO soundtrack (soundtrack_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id
INSERT INTO soundtrack (soundtrack_name, path, hash, added, uuid) VALUES ($1, $2, $3, now(), $4) returning id, uuid
`
type InsertSoundtrackParams struct {
SoundtrackName string `json:"soundtrack_name"`
Path string `json:"path"`
Hash string `json:"hash"`
SoundtrackName string `json:"soundtrack_name"`
Path string `json:"path"`
Hash string `json:"hash"`
Uuid uuid.UUID `json:"uuid"`
}
func (q *Queries) InsertSoundtrack(ctx context.Context, arg InsertSoundtrackParams) (int32, error) {
row := q.db.QueryRow(ctx, insertSoundtrack, arg.SoundtrackName, arg.Path, arg.Hash)
var id int32
err := row.Scan(&id)
return id, err
type InsertSoundtrackRow struct {
ID int32 `json:"id"`
Uuid uuid.UUID `json:"uuid"`
}
func (q *Queries) InsertSoundtrack(ctx context.Context, arg InsertSoundtrackParams) (InsertSoundtrackRow, error) {
row := q.db.QueryRow(ctx, insertSoundtrack,
arg.SoundtrackName,
arg.Path,
arg.Hash,
arg.Uuid,
)
var i InsertSoundtrackRow
err := row.Scan(&i.ID, &i.Uuid)
return i, err
}
const insertSoundtrackWithExistingId = `-- name: InsertSoundtrackWithExistingId :exec
+65 -65
View File
@@ -66,63 +66,6 @@ func (q *Queries) GetLastPlayedSoundtracks(ctx context.Context, limit int32) ([]
return items, nil
}
const getLeastPlayedSoundtracksWithSongs = `-- name: GetLeastPlayedSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.soundtrack_name,
g.times_played as soundtrack_played,
g.last_played as soundtrack_last_played,
json_agg(
json_build_object(
'song_name', s.song_name,
'path', s.path,
'times_played', s.times_played,
'file_name', s.file_name
)
) as songs
FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.times_played ASC, g.soundtrack_name
LIMIT $1
`
type GetLeastPlayedSoundtracksWithSongsRow struct {
SoundtrackID int32 `json:"soundtrack_id"`
SoundtrackName string `json:"soundtrack_name"`
SoundtrackPlayed int32 `json:"soundtrack_played"`
SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"`
Songs []byte `json:"songs"`
}
// Least played soundtracks with their songs
func (q *Queries) GetLeastPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetLeastPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getLeastPlayedSoundtracksWithSongs, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetLeastPlayedSoundtracksWithSongsRow
for rows.Next() {
var i GetLeastPlayedSoundtracksWithSongsRow
if err := rows.Scan(
&i.SoundtrackID,
&i.SoundtrackName,
&i.SoundtrackPlayed,
&i.SoundtrackLastPlayed,
&i.Songs,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getLeastPlayedSongsWithSoundtrack = `-- name: GetLeastPlayedSongsWithSoundtrack :many
SELECT
s.soundtrack_id as soundtrack_id,
@@ -175,7 +118,7 @@ func (q *Queries) GetLeastPlayedSongsWithSoundtrack(ctx context.Context, limit i
return items, nil
}
const getMostPlayedSoundtracksWithSongs = `-- name: GetMostPlayedSoundtracksWithSongs :many
const getLeastPlayedSoundtracksWithSongs = `-- name: GetLeastPlayedSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.soundtrack_name,
@@ -193,11 +136,11 @@ FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.times_played DESC, g.soundtrack_name
ORDER BY g.times_played ASC, g.soundtrack_name
LIMIT $1
`
type GetMostPlayedSoundtracksWithSongsRow struct {
type GetLeastPlayedSoundtracksWithSongsRow struct {
SoundtrackID int32 `json:"soundtrack_id"`
SoundtrackName string `json:"soundtrack_name"`
SoundtrackPlayed int32 `json:"soundtrack_played"`
@@ -205,16 +148,16 @@ type GetMostPlayedSoundtracksWithSongsRow struct {
Songs []byte `json:"songs"`
}
// Most played soundtracks with their songs
func (q *Queries) GetMostPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetMostPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getMostPlayedSoundtracksWithSongs, limit)
// Least played soundtracks with their songs
func (q *Queries) GetLeastPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetLeastPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getLeastPlayedSoundtracksWithSongs, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetMostPlayedSoundtracksWithSongsRow
var items []GetLeastPlayedSoundtracksWithSongsRow
for rows.Next() {
var i GetMostPlayedSoundtracksWithSongsRow
var i GetLeastPlayedSoundtracksWithSongsRow
if err := rows.Scan(
&i.SoundtrackID,
&i.SoundtrackName,
@@ -284,6 +227,63 @@ func (q *Queries) GetMostPlayedSongsWithSoundtrack(ctx context.Context, limit in
return items, nil
}
const getMostPlayedSoundtracksWithSongs = `-- name: GetMostPlayedSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.soundtrack_name,
g.times_played as soundtrack_played,
g.last_played as soundtrack_last_played,
json_agg(
json_build_object(
'song_name', s.song_name,
'path', s.path,
'times_played', s.times_played,
'file_name', s.file_name
)
) as songs
FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.times_played DESC, g.soundtrack_name
LIMIT $1
`
type GetMostPlayedSoundtracksWithSongsRow struct {
SoundtrackID int32 `json:"soundtrack_id"`
SoundtrackName string `json:"soundtrack_name"`
SoundtrackPlayed int32 `json:"soundtrack_played"`
SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"`
Songs []byte `json:"songs"`
}
// Most played soundtracks with their songs
func (q *Queries) GetMostPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetMostPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getMostPlayedSoundtracksWithSongs, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetMostPlayedSoundtracksWithSongsRow
for rows.Next() {
var i GetMostPlayedSoundtracksWithSongsRow
if err := rows.Scan(
&i.SoundtrackID,
&i.SoundtrackName,
&i.SoundtrackPlayed,
&i.SoundtrackLastPlayed,
&i.Songs,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getNeverPlayedSoundtracks = `-- name: GetNeverPlayedSoundtracks :many
SELECT
g.id as soundtrack_id,