chore: initial public commit

This commit is contained in:
Gabe Farrell 2025-06-11 19:45:39 -04:00
commit fc9054b78c
250 changed files with 32809 additions and 0 deletions

View file

@ -0,0 +1,316 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: alias.sql
package repository
import (
"context"
)
const deleteArtistAlias = `-- name: DeleteArtistAlias :exec
DELETE FROM artist_aliases
WHERE artist_id = $1
AND alias = $2
AND is_primary = false
`
type DeleteArtistAliasParams struct {
ArtistID int32
Alias string
}
func (q *Queries) DeleteArtistAlias(ctx context.Context, arg DeleteArtistAliasParams) error {
_, err := q.db.Exec(ctx, deleteArtistAlias, arg.ArtistID, arg.Alias)
return err
}
const deleteReleaseAlias = `-- name: DeleteReleaseAlias :exec
DELETE FROM release_aliases
WHERE release_id = $1
AND alias = $2
AND is_primary = false
`
type DeleteReleaseAliasParams struct {
ReleaseID int32
Alias string
}
func (q *Queries) DeleteReleaseAlias(ctx context.Context, arg DeleteReleaseAliasParams) error {
_, err := q.db.Exec(ctx, deleteReleaseAlias, arg.ReleaseID, arg.Alias)
return err
}
const deleteTrackAlias = `-- name: DeleteTrackAlias :exec
DELETE FROM track_aliases
WHERE track_id = $1
AND alias = $2
AND is_primary = false
`
type DeleteTrackAliasParams struct {
TrackID int32
Alias string
}
func (q *Queries) DeleteTrackAlias(ctx context.Context, arg DeleteTrackAliasParams) error {
_, err := q.db.Exec(ctx, deleteTrackAlias, arg.TrackID, arg.Alias)
return err
}
const getAllArtistAliases = `-- name: GetAllArtistAliases :many
SELECT artist_id, alias, source, is_primary FROM artist_aliases
WHERE artist_id = $1 ORDER BY is_primary DESC
`
func (q *Queries) GetAllArtistAliases(ctx context.Context, artistID int32) ([]ArtistAlias, error) {
rows, err := q.db.Query(ctx, getAllArtistAliases, artistID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ArtistAlias
for rows.Next() {
var i ArtistAlias
if err := rows.Scan(
&i.ArtistID,
&i.Alias,
&i.Source,
&i.IsPrimary,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getAllReleaseAliases = `-- name: GetAllReleaseAliases :many
SELECT release_id, alias, source, is_primary FROM release_aliases
WHERE release_id = $1 ORDER BY is_primary DESC
`
func (q *Queries) GetAllReleaseAliases(ctx context.Context, releaseID int32) ([]ReleaseAlias, error) {
rows, err := q.db.Query(ctx, getAllReleaseAliases, releaseID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ReleaseAlias
for rows.Next() {
var i ReleaseAlias
if err := rows.Scan(
&i.ReleaseID,
&i.Alias,
&i.Source,
&i.IsPrimary,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getAllTrackAliases = `-- name: GetAllTrackAliases :many
SELECT track_id, alias, is_primary, source FROM track_aliases
WHERE track_id = $1 ORDER BY is_primary DESC
`
func (q *Queries) GetAllTrackAliases(ctx context.Context, trackID int32) ([]TrackAlias, error) {
rows, err := q.db.Query(ctx, getAllTrackAliases, trackID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []TrackAlias
for rows.Next() {
var i TrackAlias
if err := rows.Scan(
&i.TrackID,
&i.Alias,
&i.IsPrimary,
&i.Source,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getArtistAlias = `-- name: GetArtistAlias :one
SELECT artist_id, alias, source, is_primary FROM artist_aliases
WHERE alias = $1 LIMIT 1
`
func (q *Queries) GetArtistAlias(ctx context.Context, alias string) (ArtistAlias, error) {
row := q.db.QueryRow(ctx, getArtistAlias, alias)
var i ArtistAlias
err := row.Scan(
&i.ArtistID,
&i.Alias,
&i.Source,
&i.IsPrimary,
)
return i, err
}
const getReleaseAlias = `-- name: GetReleaseAlias :one
SELECT release_id, alias, source, is_primary FROM release_aliases
WHERE alias = $1 LIMIT 1
`
func (q *Queries) GetReleaseAlias(ctx context.Context, alias string) (ReleaseAlias, error) {
row := q.db.QueryRow(ctx, getReleaseAlias, alias)
var i ReleaseAlias
err := row.Scan(
&i.ReleaseID,
&i.Alias,
&i.Source,
&i.IsPrimary,
)
return i, err
}
const getTrackAlias = `-- name: GetTrackAlias :one
SELECT track_id, alias, is_primary, source FROM track_aliases
WHERE alias = $1 LIMIT 1
`
func (q *Queries) GetTrackAlias(ctx context.Context, alias string) (TrackAlias, error) {
row := q.db.QueryRow(ctx, getTrackAlias, alias)
var i TrackAlias
err := row.Scan(
&i.TrackID,
&i.Alias,
&i.IsPrimary,
&i.Source,
)
return i, err
}
const insertArtistAlias = `-- name: InsertArtistAlias :exec
INSERT INTO artist_aliases (artist_id, alias, source, is_primary)
VALUES ($1, $2, $3, $4)
ON CONFLICT DO NOTHING
`
type InsertArtistAliasParams struct {
ArtistID int32
Alias string
Source string
IsPrimary bool
}
func (q *Queries) InsertArtistAlias(ctx context.Context, arg InsertArtistAliasParams) error {
_, err := q.db.Exec(ctx, insertArtistAlias,
arg.ArtistID,
arg.Alias,
arg.Source,
arg.IsPrimary,
)
return err
}
const insertReleaseAlias = `-- name: InsertReleaseAlias :exec
INSERT INTO release_aliases (release_id, alias, source, is_primary)
VALUES ($1, $2, $3, $4)
ON CONFLICT DO NOTHING
`
type InsertReleaseAliasParams struct {
ReleaseID int32
Alias string
Source string
IsPrimary bool
}
func (q *Queries) InsertReleaseAlias(ctx context.Context, arg InsertReleaseAliasParams) error {
_, err := q.db.Exec(ctx, insertReleaseAlias,
arg.ReleaseID,
arg.Alias,
arg.Source,
arg.IsPrimary,
)
return err
}
const insertTrackAlias = `-- name: InsertTrackAlias :exec
INSERT INTO track_aliases (track_id, alias, source, is_primary)
VALUES ($1, $2, $3, $4)
ON CONFLICT DO NOTHING
`
type InsertTrackAliasParams struct {
TrackID int32
Alias string
Source string
IsPrimary bool
}
func (q *Queries) InsertTrackAlias(ctx context.Context, arg InsertTrackAliasParams) error {
_, err := q.db.Exec(ctx, insertTrackAlias,
arg.TrackID,
arg.Alias,
arg.Source,
arg.IsPrimary,
)
return err
}
const setArtistAliasPrimaryStatus = `-- name: SetArtistAliasPrimaryStatus :exec
UPDATE artist_aliases SET is_primary = $1 WHERE artist_id = $2 AND alias = $3
`
type SetArtistAliasPrimaryStatusParams struct {
IsPrimary bool
ArtistID int32
Alias string
}
func (q *Queries) SetArtistAliasPrimaryStatus(ctx context.Context, arg SetArtistAliasPrimaryStatusParams) error {
_, err := q.db.Exec(ctx, setArtistAliasPrimaryStatus, arg.IsPrimary, arg.ArtistID, arg.Alias)
return err
}
const setReleaseAliasPrimaryStatus = `-- name: SetReleaseAliasPrimaryStatus :exec
UPDATE release_aliases SET is_primary = $1 WHERE release_id = $2 AND alias = $3
`
type SetReleaseAliasPrimaryStatusParams struct {
IsPrimary bool
ReleaseID int32
Alias string
}
func (q *Queries) SetReleaseAliasPrimaryStatus(ctx context.Context, arg SetReleaseAliasPrimaryStatusParams) error {
_, err := q.db.Exec(ctx, setReleaseAliasPrimaryStatus, arg.IsPrimary, arg.ReleaseID, arg.Alias)
return err
}
const setTrackAliasPrimaryStatus = `-- name: SetTrackAliasPrimaryStatus :exec
UPDATE track_aliases SET is_primary = $1 WHERE track_id = $2 AND alias = $3
`
type SetTrackAliasPrimaryStatusParams struct {
IsPrimary bool
TrackID int32
Alias string
}
func (q *Queries) SetTrackAliasPrimaryStatus(ctx context.Context, arg SetTrackAliasPrimaryStatusParams) error {
_, err := q.db.Exec(ctx, setTrackAliasPrimaryStatus, arg.IsPrimary, arg.TrackID, arg.Alias)
return err
}

View file

@ -0,0 +1,418 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: artist.sql
package repository
import (
"context"
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
const countTopArtists = `-- name: CountTopArtists :one
SELECT COUNT(DISTINCT at.artist_id) AS total_count
FROM listens l
JOIN artist_tracks at ON l.track_id = at.track_id
WHERE l.listened_at BETWEEN $1 AND $2
`
type CountTopArtistsParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
}
func (q *Queries) CountTopArtists(ctx context.Context, arg CountTopArtistsParams) (int64, error) {
row := q.db.QueryRow(ctx, countTopArtists, arg.ListenedAt, arg.ListenedAt_2)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const deleteArtist = `-- name: DeleteArtist :exec
DELETE FROM artists WHERE id = $1
`
func (q *Queries) DeleteArtist(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, deleteArtist, id)
return err
}
const deleteConflictingArtistReleases = `-- name: DeleteConflictingArtistReleases :exec
DELETE FROM artist_releases ar
WHERE ar.artist_id = $1
AND release_id IN (
SELECT ar.release_id FROM artist_releases ar WHERE ar.artist_id = $2
)
`
type DeleteConflictingArtistReleasesParams struct {
ArtistID int32
ArtistID_2 int32
}
func (q *Queries) DeleteConflictingArtistReleases(ctx context.Context, arg DeleteConflictingArtistReleasesParams) error {
_, err := q.db.Exec(ctx, deleteConflictingArtistReleases, arg.ArtistID, arg.ArtistID_2)
return err
}
const deleteConflictingArtistTracks = `-- name: DeleteConflictingArtistTracks :exec
DELETE FROM artist_tracks at
WHERE at.artist_id = $1
AND track_id IN (
SELECT at.track_id FROM artist_tracks at WHERE at.artist_id = $2
)
`
type DeleteConflictingArtistTracksParams struct {
ArtistID int32
ArtistID_2 int32
}
func (q *Queries) DeleteConflictingArtistTracks(ctx context.Context, arg DeleteConflictingArtistTracksParams) error {
_, err := q.db.Exec(ctx, deleteConflictingArtistTracks, arg.ArtistID, arg.ArtistID_2)
return err
}
const getArtist = `-- name: GetArtist :one
SELECT
a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
array_agg(aa.alias)::text[] AS aliases
FROM artists_with_name a
LEFT JOIN artist_aliases aa ON a.id = aa.artist_id
WHERE a.id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
`
type GetArtistRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
ImageSource pgtype.Text
Name string
Aliases []string
}
func (q *Queries) GetArtist(ctx context.Context, id int32) (GetArtistRow, error) {
row := q.db.QueryRow(ctx, getArtist, id)
var i GetArtistRow
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.ImageSource,
&i.Name,
&i.Aliases,
)
return i, err
}
const getArtistByImage = `-- name: GetArtistByImage :one
SELECT id, musicbrainz_id, image, image_source FROM artists WHERE image = $1 LIMIT 1
`
func (q *Queries) GetArtistByImage(ctx context.Context, image *uuid.UUID) (Artist, error) {
row := q.db.QueryRow(ctx, getArtistByImage, image)
var i Artist
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.ImageSource,
)
return i, err
}
const getArtistByMbzID = `-- name: GetArtistByMbzID :one
SELECT
a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
array_agg(aa.alias)::text[] AS aliases
FROM artists_with_name a
LEFT JOIN artist_aliases aa ON a.id = aa.artist_id
WHERE a.musicbrainz_id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
`
type GetArtistByMbzIDRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
ImageSource pgtype.Text
Name string
Aliases []string
}
func (q *Queries) GetArtistByMbzID(ctx context.Context, musicbrainzID *uuid.UUID) (GetArtistByMbzIDRow, error) {
row := q.db.QueryRow(ctx, getArtistByMbzID, musicbrainzID)
var i GetArtistByMbzIDRow
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.ImageSource,
&i.Name,
&i.Aliases,
)
return i, err
}
const getArtistByName = `-- name: GetArtistByName :one
WITH artist_with_aliases AS (
SELECT
a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
COALESCE(array_agg(aa.alias), '{}')::text[] AS aliases
FROM artists_with_name a
LEFT JOIN artist_aliases aa ON a.id = aa.artist_id
WHERE a.id IN (
SELECT aa2.artist_id FROM artist_aliases aa2 WHERE aa2.alias = $1
)
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
)
SELECT id, musicbrainz_id, image, image_source, name, aliases FROM artist_with_aliases
`
type GetArtistByNameRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
ImageSource pgtype.Text
Name string
Aliases []string
}
func (q *Queries) GetArtistByName(ctx context.Context, alias string) (GetArtistByNameRow, error) {
row := q.db.QueryRow(ctx, getArtistByName, alias)
var i GetArtistByNameRow
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.ImageSource,
&i.Name,
&i.Aliases,
)
return i, err
}
const getReleaseArtists = `-- name: GetReleaseArtists :many
SELECT
a.id, a.musicbrainz_id, a.image, a.image_source, a.name
FROM artists_with_name a
LEFT JOIN artist_releases ar ON a.id = ar.artist_id
WHERE ar.release_id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
`
func (q *Queries) GetReleaseArtists(ctx context.Context, releaseID int32) ([]ArtistsWithName, error) {
rows, err := q.db.Query(ctx, getReleaseArtists, releaseID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ArtistsWithName
for rows.Next() {
var i ArtistsWithName
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.ImageSource,
&i.Name,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopArtistsPaginated = `-- name: GetTopArtistsPaginated :many
SELECT
a.id,
a.name,
a.musicbrainz_id,
a.image,
COUNT(*) AS listen_count
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN artist_tracks at ON at.track_id = t.id
JOIN artists_with_name a ON a.id = at.artist_id
WHERE l.listened_at BETWEEN $1 AND $2
GROUP BY a.id, a.name, a.musicbrainz_id, a.image, a.image_source, a.name
ORDER BY listen_count DESC
LIMIT $3 OFFSET $4
`
type GetTopArtistsPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
}
type GetTopArtistsPaginatedRow struct {
ID int32
Name string
MusicBrainzID *uuid.UUID
Image *uuid.UUID
ListenCount int64
}
func (q *Queries) GetTopArtistsPaginated(ctx context.Context, arg GetTopArtistsPaginatedParams) ([]GetTopArtistsPaginatedRow, error) {
rows, err := q.db.Query(ctx, getTopArtistsPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopArtistsPaginatedRow
for rows.Next() {
var i GetTopArtistsPaginatedRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.MusicBrainzID,
&i.Image,
&i.ListenCount,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTrackArtists = `-- name: GetTrackArtists :many
SELECT
a.id, a.musicbrainz_id, a.image, a.image_source, a.name
FROM artists_with_name a
LEFT JOIN artist_tracks at ON a.id = at.artist_id
WHERE at.track_id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
`
func (q *Queries) GetTrackArtists(ctx context.Context, trackID int32) ([]ArtistsWithName, error) {
rows, err := q.db.Query(ctx, getTrackArtists, trackID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ArtistsWithName
for rows.Next() {
var i ArtistsWithName
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.ImageSource,
&i.Name,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertArtist = `-- name: InsertArtist :one
INSERT INTO artists (musicbrainz_id, image, image_source)
VALUES ($1, $2, $3)
RETURNING id, musicbrainz_id, image, image_source
`
type InsertArtistParams struct {
MusicBrainzID *uuid.UUID
Image *uuid.UUID
ImageSource pgtype.Text
}
func (q *Queries) InsertArtist(ctx context.Context, arg InsertArtistParams) (Artist, error) {
row := q.db.QueryRow(ctx, insertArtist, arg.MusicBrainzID, arg.Image, arg.ImageSource)
var i Artist
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.ImageSource,
)
return i, err
}
const updateArtistImage = `-- name: UpdateArtistImage :exec
UPDATE artists SET image = $2, image_source = $3
WHERE id = $1
`
type UpdateArtistImageParams struct {
ID int32
Image *uuid.UUID
ImageSource pgtype.Text
}
func (q *Queries) UpdateArtistImage(ctx context.Context, arg UpdateArtistImageParams) error {
_, err := q.db.Exec(ctx, updateArtistImage, arg.ID, arg.Image, arg.ImageSource)
return err
}
const updateArtistMbzID = `-- name: UpdateArtistMbzID :exec
UPDATE artists SET musicbrainz_id = $2
WHERE id = $1
`
type UpdateArtistMbzIDParams struct {
ID int32
MusicBrainzID *uuid.UUID
}
func (q *Queries) UpdateArtistMbzID(ctx context.Context, arg UpdateArtistMbzIDParams) error {
_, err := q.db.Exec(ctx, updateArtistMbzID, arg.ID, arg.MusicBrainzID)
return err
}
const updateArtistReleases = `-- name: UpdateArtistReleases :exec
UPDATE artist_releases
SET artist_id = $2
WHERE artist_id = $1
`
type UpdateArtistReleasesParams struct {
ArtistID int32
ArtistID_2 int32
}
func (q *Queries) UpdateArtistReleases(ctx context.Context, arg UpdateArtistReleasesParams) error {
_, err := q.db.Exec(ctx, updateArtistReleases, arg.ArtistID, arg.ArtistID_2)
return err
}
const updateArtistTracks = `-- name: UpdateArtistTracks :exec
UPDATE artist_tracks
SET artist_id = $2
WHERE artist_id = $1
`
type UpdateArtistTracksParams struct {
ArtistID int32
ArtistID_2 int32
}
func (q *Queries) UpdateArtistTracks(ctx context.Context, arg UpdateArtistTracksParams) error {
_, err := q.db.Exec(ctx, updateArtistTracks, arg.ArtistID, arg.ArtistID_2)
return err
}

32
internal/repository/db.go Normal file
View file

@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
package repository
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

View file

@ -0,0 +1,26 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: etc.sql
package repository
import (
"context"
)
const cleanOrphanedEntries = `-- name: CleanOrphanedEntries :exec
DO $$
BEGIN
DELETE FROM tracks WHERE id NOT IN (SELECT l.track_id FROM listens l);
DELETE FROM releases WHERE id NOT IN (SELECT t.release_id FROM tracks t);
DELETE FROM artists WHERE id NOT IN (SELECT at.artist_id FROM artist_tracks at);
END $$
`
// DELETE FROM releases WHERE release_group_id NOT IN (SELECT t.release_group_id FROM tracks t);
// DELETE FROM releases WHERE release_group_id NOT IN (SELECT rg.id FROM release_groups rg);
func (q *Queries) CleanOrphanedEntries(ctx context.Context) error {
_, err := q.db.Exec(ctx, cleanOrphanedEntries)
return err
}

View file

@ -0,0 +1,742 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: listen.sql
package repository
import (
"context"
"time"
"github.com/jackc/pgx/v5/pgtype"
)
const countListens = `-- name: CountListens :one
SELECT COUNT(*) AS total_count
FROM listens l
WHERE l.listened_at BETWEEN $1 AND $2
`
type CountListensParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
}
func (q *Queries) CountListens(ctx context.Context, arg CountListensParams) (int64, error) {
row := q.db.QueryRow(ctx, countListens, arg.ListenedAt, arg.ListenedAt_2)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const countListensFromArtist = `-- name: CountListensFromArtist :one
SELECT COUNT(*) AS total_count
FROM listens l
JOIN artist_tracks at ON l.track_id = at.track_id
WHERE l.listened_at BETWEEN $1 AND $2
AND at.artist_id = $3
`
type CountListensFromArtistParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
ArtistID int32
}
func (q *Queries) CountListensFromArtist(ctx context.Context, arg CountListensFromArtistParams) (int64, error) {
row := q.db.QueryRow(ctx, countListensFromArtist, arg.ListenedAt, arg.ListenedAt_2, arg.ArtistID)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const countListensFromRelease = `-- name: CountListensFromRelease :one
SELECT COUNT(*) AS total_count
FROM listens l
JOIN tracks t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
AND t.release_id = $3
`
type CountListensFromReleaseParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
ReleaseID int32
}
func (q *Queries) CountListensFromRelease(ctx context.Context, arg CountListensFromReleaseParams) (int64, error) {
row := q.db.QueryRow(ctx, countListensFromRelease, arg.ListenedAt, arg.ListenedAt_2, arg.ReleaseID)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const countListensFromTrack = `-- name: CountListensFromTrack :one
SELECT COUNT(*) AS total_count
FROM listens l
WHERE l.listened_at BETWEEN $1 AND $2
AND l.track_id = $3
`
type CountListensFromTrackParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
TrackID int32
}
func (q *Queries) CountListensFromTrack(ctx context.Context, arg CountListensFromTrackParams) (int64, error) {
row := q.db.QueryRow(ctx, countListensFromTrack, arg.ListenedAt, arg.ListenedAt_2, arg.TrackID)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const countTimeListened = `-- name: CountTimeListened :one
SELECT COALESCE(SUM(t.duration), 0)::BIGINT AS seconds_listened
FROM listens l
JOIN tracks t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
`
type CountTimeListenedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
}
func (q *Queries) CountTimeListened(ctx context.Context, arg CountTimeListenedParams) (int64, error) {
row := q.db.QueryRow(ctx, countTimeListened, arg.ListenedAt, arg.ListenedAt_2)
var seconds_listened int64
err := row.Scan(&seconds_listened)
return seconds_listened, err
}
const countTimeListenedToArtist = `-- name: CountTimeListenedToArtist :one
SELECT COALESCE(SUM(t.duration), 0)::BIGINT AS seconds_listened
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN artist_tracks at ON t.id = at.track_id
WHERE l.listened_at BETWEEN $1 AND $2
AND at.artist_id = $3
`
type CountTimeListenedToArtistParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
ArtistID int32
}
func (q *Queries) CountTimeListenedToArtist(ctx context.Context, arg CountTimeListenedToArtistParams) (int64, error) {
row := q.db.QueryRow(ctx, countTimeListenedToArtist, arg.ListenedAt, arg.ListenedAt_2, arg.ArtistID)
var seconds_listened int64
err := row.Scan(&seconds_listened)
return seconds_listened, err
}
const countTimeListenedToRelease = `-- name: CountTimeListenedToRelease :one
SELECT COALESCE(SUM(t.duration), 0)::BIGINT AS seconds_listened
FROM listens l
JOIN tracks t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
AND t.release_id = $3
`
type CountTimeListenedToReleaseParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
ReleaseID int32
}
func (q *Queries) CountTimeListenedToRelease(ctx context.Context, arg CountTimeListenedToReleaseParams) (int64, error) {
row := q.db.QueryRow(ctx, countTimeListenedToRelease, arg.ListenedAt, arg.ListenedAt_2, arg.ReleaseID)
var seconds_listened int64
err := row.Scan(&seconds_listened)
return seconds_listened, err
}
const countTimeListenedToTrack = `-- name: CountTimeListenedToTrack :one
SELECT COALESCE(SUM(t.duration), 0)::BIGINT AS seconds_listened
FROM listens l
JOIN tracks t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
AND t.id = $3
`
type CountTimeListenedToTrackParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
ID int32
}
func (q *Queries) CountTimeListenedToTrack(ctx context.Context, arg CountTimeListenedToTrackParams) (int64, error) {
row := q.db.QueryRow(ctx, countTimeListenedToTrack, arg.ListenedAt, arg.ListenedAt_2, arg.ID)
var seconds_listened int64
err := row.Scan(&seconds_listened)
return seconds_listened, err
}
const deleteListen = `-- name: DeleteListen :exec
DELETE FROM listens WHERE track_id = $1 AND listened_at = $2
`
type DeleteListenParams struct {
TrackID int32
ListenedAt time.Time
}
func (q *Queries) DeleteListen(ctx context.Context, arg DeleteListenParams) error {
_, err := q.db.Exec(ctx, deleteListen, arg.TrackID, arg.ListenedAt)
return err
}
const getLastListensFromArtistPaginated = `-- name: GetLastListensFromArtistPaginated :many
SELECT
l.track_id, l.listened_at, l.client, l.user_id,
t.title AS track_title,
t.release_id AS release_id,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at
JOIN artists_with_name a ON a.id = at.artist_id
WHERE at.track_id = t.id
) AS artists
FROM listens l
JOIN tracks_with_title t ON l.track_id = t.id
JOIN artist_tracks at ON t.id = at.track_id
WHERE at.artist_id = $5
AND l.listened_at BETWEEN $1 AND $2
ORDER BY l.listened_at DESC
LIMIT $3 OFFSET $4
`
type GetLastListensFromArtistPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
ArtistID int32
}
type GetLastListensFromArtistPaginatedRow struct {
TrackID int32
ListenedAt time.Time
Client *string
UserID int32
TrackTitle string
ReleaseID int32
Artists []byte
}
func (q *Queries) GetLastListensFromArtistPaginated(ctx context.Context, arg GetLastListensFromArtistPaginatedParams) ([]GetLastListensFromArtistPaginatedRow, error) {
rows, err := q.db.Query(ctx, getLastListensFromArtistPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
arg.ArtistID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetLastListensFromArtistPaginatedRow
for rows.Next() {
var i GetLastListensFromArtistPaginatedRow
if err := rows.Scan(
&i.TrackID,
&i.ListenedAt,
&i.Client,
&i.UserID,
&i.TrackTitle,
&i.ReleaseID,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getLastListensFromReleasePaginated = `-- name: GetLastListensFromReleasePaginated :many
SELECT
l.track_id, l.listened_at, l.client, l.user_id,
t.title AS track_title,
t.release_id AS release_id,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at
JOIN artists_with_name a ON a.id = at.artist_id
WHERE at.track_id = t.id
) AS artists
FROM listens l
JOIN tracks_with_title t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
AND t.release_id = $5
ORDER BY l.listened_at DESC
LIMIT $3 OFFSET $4
`
type GetLastListensFromReleasePaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
ReleaseID int32
}
type GetLastListensFromReleasePaginatedRow struct {
TrackID int32
ListenedAt time.Time
Client *string
UserID int32
TrackTitle string
ReleaseID int32
Artists []byte
}
func (q *Queries) GetLastListensFromReleasePaginated(ctx context.Context, arg GetLastListensFromReleasePaginatedParams) ([]GetLastListensFromReleasePaginatedRow, error) {
rows, err := q.db.Query(ctx, getLastListensFromReleasePaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
arg.ReleaseID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetLastListensFromReleasePaginatedRow
for rows.Next() {
var i GetLastListensFromReleasePaginatedRow
if err := rows.Scan(
&i.TrackID,
&i.ListenedAt,
&i.Client,
&i.UserID,
&i.TrackTitle,
&i.ReleaseID,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getLastListensFromTrackPaginated = `-- name: GetLastListensFromTrackPaginated :many
SELECT
l.track_id, l.listened_at, l.client, l.user_id,
t.title AS track_title,
t.release_id AS release_id,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at
JOIN artists_with_name a ON a.id = at.artist_id
WHERE at.track_id = t.id
) AS artists
FROM listens l
JOIN tracks_with_title t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
AND t.id = $5
ORDER BY l.listened_at DESC
LIMIT $3 OFFSET $4
`
type GetLastListensFromTrackPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
ID int32
}
type GetLastListensFromTrackPaginatedRow struct {
TrackID int32
ListenedAt time.Time
Client *string
UserID int32
TrackTitle string
ReleaseID int32
Artists []byte
}
func (q *Queries) GetLastListensFromTrackPaginated(ctx context.Context, arg GetLastListensFromTrackPaginatedParams) ([]GetLastListensFromTrackPaginatedRow, error) {
rows, err := q.db.Query(ctx, getLastListensFromTrackPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
arg.ID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetLastListensFromTrackPaginatedRow
for rows.Next() {
var i GetLastListensFromTrackPaginatedRow
if err := rows.Scan(
&i.TrackID,
&i.ListenedAt,
&i.Client,
&i.UserID,
&i.TrackTitle,
&i.ReleaseID,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getLastListensPaginated = `-- name: GetLastListensPaginated :many
SELECT
l.track_id, l.listened_at, l.client, l.user_id,
t.title AS track_title,
t.release_id AS release_id,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at
JOIN artists_with_name a ON a.id = at.artist_id
WHERE at.track_id = t.id
) AS artists
FROM listens l
JOIN tracks_with_title t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
ORDER BY l.listened_at DESC
LIMIT $3 OFFSET $4
`
type GetLastListensPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
}
type GetLastListensPaginatedRow struct {
TrackID int32
ListenedAt time.Time
Client *string
UserID int32
TrackTitle string
ReleaseID int32
Artists []byte
}
func (q *Queries) GetLastListensPaginated(ctx context.Context, arg GetLastListensPaginatedParams) ([]GetLastListensPaginatedRow, error) {
rows, err := q.db.Query(ctx, getLastListensPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetLastListensPaginatedRow
for rows.Next() {
var i GetLastListensPaginatedRow
if err := rows.Scan(
&i.TrackID,
&i.ListenedAt,
&i.Client,
&i.UserID,
&i.TrackTitle,
&i.ReleaseID,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertListen = `-- name: InsertListen :exec
INSERT INTO listens (track_id, listened_at, user_id, client)
VALUES ($1, $2, $3, $4)
ON CONFLICT DO NOTHING
`
type InsertListenParams struct {
TrackID int32
ListenedAt time.Time
UserID int32
Client *string
}
func (q *Queries) InsertListen(ctx context.Context, arg InsertListenParams) error {
_, err := q.db.Exec(ctx, insertListen,
arg.TrackID,
arg.ListenedAt,
arg.UserID,
arg.Client,
)
return err
}
const listenActivity = `-- name: ListenActivity :many
WITH buckets AS (
SELECT generate_series($1::timestamptz, $2::timestamptz, $3::interval) AS bucket_start
),
bucketed_listens AS (
SELECT
b.bucket_start,
COUNT(l.listened_at) AS listen_count
FROM buckets b
LEFT JOIN listens l
ON l.listened_at >= b.bucket_start
AND l.listened_at < b.bucket_start + $3::interval
GROUP BY b.bucket_start
ORDER BY b.bucket_start
)
SELECT bucket_start, listen_count FROM bucketed_listens
`
type ListenActivityParams struct {
Column1 time.Time
Column2 time.Time
Column3 pgtype.Interval
}
type ListenActivityRow struct {
BucketStart time.Time
ListenCount int64
}
func (q *Queries) ListenActivity(ctx context.Context, arg ListenActivityParams) ([]ListenActivityRow, error) {
rows, err := q.db.Query(ctx, listenActivity, arg.Column1, arg.Column2, arg.Column3)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListenActivityRow
for rows.Next() {
var i ListenActivityRow
if err := rows.Scan(&i.BucketStart, &i.ListenCount); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listenActivityForArtist = `-- name: ListenActivityForArtist :many
WITH buckets AS (
SELECT generate_series($1::timestamptz, $2::timestamptz, $3::interval) AS bucket_start
),
filtered_listens AS (
SELECT l.track_id, l.listened_at, l.client, l.user_id
FROM listens l
JOIN artist_tracks t ON l.track_id = t.track_id
WHERE t.artist_id = $4
),
bucketed_listens AS (
SELECT
b.bucket_start,
COUNT(l.listened_at) AS listen_count
FROM buckets b
LEFT JOIN filtered_listens l
ON l.listened_at >= b.bucket_start
AND l.listened_at < b.bucket_start + $3::interval
GROUP BY b.bucket_start
ORDER BY b.bucket_start
)
SELECT bucket_start, listen_count FROM bucketed_listens
`
type ListenActivityForArtistParams struct {
Column1 time.Time
Column2 time.Time
Column3 pgtype.Interval
ArtistID int32
}
type ListenActivityForArtistRow struct {
BucketStart time.Time
ListenCount int64
}
func (q *Queries) ListenActivityForArtist(ctx context.Context, arg ListenActivityForArtistParams) ([]ListenActivityForArtistRow, error) {
rows, err := q.db.Query(ctx, listenActivityForArtist,
arg.Column1,
arg.Column2,
arg.Column3,
arg.ArtistID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListenActivityForArtistRow
for rows.Next() {
var i ListenActivityForArtistRow
if err := rows.Scan(&i.BucketStart, &i.ListenCount); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listenActivityForRelease = `-- name: ListenActivityForRelease :many
WITH buckets AS (
SELECT generate_series($1::timestamptz, $2::timestamptz, $3::interval) AS bucket_start
),
filtered_listens AS (
SELECT l.track_id, l.listened_at, l.client, l.user_id
FROM listens l
JOIN tracks t ON l.track_id = t.id
WHERE t.release_id = $4
),
bucketed_listens AS (
SELECT
b.bucket_start,
COUNT(l.listened_at) AS listen_count
FROM buckets b
LEFT JOIN filtered_listens l
ON l.listened_at >= b.bucket_start
AND l.listened_at < b.bucket_start + $3::interval
GROUP BY b.bucket_start
ORDER BY b.bucket_start
)
SELECT bucket_start, listen_count FROM bucketed_listens
`
type ListenActivityForReleaseParams struct {
Column1 time.Time
Column2 time.Time
Column3 pgtype.Interval
ReleaseID int32
}
type ListenActivityForReleaseRow struct {
BucketStart time.Time
ListenCount int64
}
func (q *Queries) ListenActivityForRelease(ctx context.Context, arg ListenActivityForReleaseParams) ([]ListenActivityForReleaseRow, error) {
rows, err := q.db.Query(ctx, listenActivityForRelease,
arg.Column1,
arg.Column2,
arg.Column3,
arg.ReleaseID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListenActivityForReleaseRow
for rows.Next() {
var i ListenActivityForReleaseRow
if err := rows.Scan(&i.BucketStart, &i.ListenCount); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listenActivityForTrack = `-- name: ListenActivityForTrack :many
WITH buckets AS (
SELECT generate_series($1::timestamptz, $2::timestamptz, $3::interval) AS bucket_start
),
filtered_listens AS (
SELECT l.track_id, l.listened_at, l.client, l.user_id
FROM listens l
JOIN tracks t ON l.track_id = t.id
WHERE t.id = $4
),
bucketed_listens AS (
SELECT
b.bucket_start,
COUNT(l.listened_at) AS listen_count
FROM buckets b
LEFT JOIN filtered_listens l
ON l.listened_at >= b.bucket_start
AND l.listened_at < b.bucket_start + $3::interval
GROUP BY b.bucket_start
ORDER BY b.bucket_start
)
SELECT bucket_start, listen_count FROM bucketed_listens
`
type ListenActivityForTrackParams struct {
Column1 time.Time
Column2 time.Time
Column3 pgtype.Interval
ID int32
}
type ListenActivityForTrackRow struct {
BucketStart time.Time
ListenCount int64
}
func (q *Queries) ListenActivityForTrack(ctx context.Context, arg ListenActivityForTrackParams) ([]ListenActivityForTrackRow, error) {
rows, err := q.db.Query(ctx, listenActivityForTrack,
arg.Column1,
arg.Column2,
arg.Column3,
arg.ID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListenActivityForTrackRow
for rows.Next() {
var i ListenActivityForTrackRow
if err := rows.Scan(&i.BucketStart, &i.ListenCount); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateTrackIdForListens = `-- name: UpdateTrackIdForListens :exec
UPDATE listens SET track_id = $2
WHERE track_id = $1
`
type UpdateTrackIdForListensParams struct {
TrackID int32
TrackID_2 int32
}
func (q *Queries) UpdateTrackIdForListens(ctx context.Context, arg UpdateTrackIdForListensParams) error {
_, err := q.db.Exec(ctx, updateTrackIdForListens, arg.TrackID, arg.TrackID_2)
return err
}

View file

@ -0,0 +1,164 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
package repository
import (
"database/sql/driver"
"fmt"
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
type Role string
const (
RoleAdmin Role = "admin"
RoleUser Role = "user"
)
func (e *Role) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = Role(s)
case string:
*e = Role(s)
default:
return fmt.Errorf("unsupported scan type for Role: %T", src)
}
return nil
}
type NullRole struct {
Role Role
Valid bool // Valid is true if Role is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullRole) Scan(value interface{}) error {
if value == nil {
ns.Role, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.Role.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullRole) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.Role), nil
}
type ApiKey struct {
ID int32
Key string
UserID int32
CreatedAt pgtype.Timestamp
Label string
}
type Artist struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
ImageSource pgtype.Text
}
type ArtistAlias struct {
ArtistID int32
Alias string
Source string
IsPrimary bool
}
type ArtistRelease struct {
ArtistID int32
ReleaseID int32
}
type ArtistTrack struct {
ArtistID int32
TrackID int32
}
type ArtistsWithName struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
ImageSource pgtype.Text
Name string
}
type Listen struct {
TrackID int32
ListenedAt time.Time
Client *string
UserID int32
}
type Release struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
}
type ReleaseAlias struct {
ReleaseID int32
Alias string
Source string
IsPrimary bool
}
type ReleasesWithTitle struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
}
type Session struct {
ID uuid.UUID
UserID int32
CreatedAt time.Time
ExpiresAt time.Time
Persistent bool
}
type Track struct {
ID int32
MusicBrainzID *uuid.UUID
Duration int32
ReleaseID int32
}
type TrackAlias struct {
TrackID int32
Alias string
IsPrimary bool
Source string
}
type TracksWithTitle struct {
ID int32
MusicBrainzID *uuid.UUID
Duration int32
ReleaseID int32
Title string
}
type User struct {
ID int32
Username string
Role Role
Password []byte
}

View file

@ -0,0 +1,462 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: release.sql
package repository
import (
"context"
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
const associateArtistToRelease = `-- name: AssociateArtistToRelease :exec
INSERT INTO artist_releases (artist_id, release_id)
VALUES ($1, $2)
ON CONFLICT DO NOTHING
`
type AssociateArtistToReleaseParams struct {
ArtistID int32
ReleaseID int32
}
func (q *Queries) AssociateArtistToRelease(ctx context.Context, arg AssociateArtistToReleaseParams) error {
_, err := q.db.Exec(ctx, associateArtistToRelease, arg.ArtistID, arg.ReleaseID)
return err
}
const countReleasesFromArtist = `-- name: CountReleasesFromArtist :one
SELECT COUNT(*)
FROM releases r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE ar.artist_id = $1
`
func (q *Queries) CountReleasesFromArtist(ctx context.Context, artistID int32) (int64, error) {
row := q.db.QueryRow(ctx, countReleasesFromArtist, artistID)
var count int64
err := row.Scan(&count)
return count, err
}
const countTopReleases = `-- name: CountTopReleases :one
SELECT COUNT(DISTINCT r.id) AS total_count
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN releases r ON t.release_id = r.id
WHERE l.listened_at BETWEEN $1 AND $2
`
type CountTopReleasesParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
}
func (q *Queries) CountTopReleases(ctx context.Context, arg CountTopReleasesParams) (int64, error) {
row := q.db.QueryRow(ctx, countTopReleases, arg.ListenedAt, arg.ListenedAt_2)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const deleteRelease = `-- name: DeleteRelease :exec
DELETE FROM releases WHERE id = $1
`
func (q *Queries) DeleteRelease(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, deleteRelease, id)
return err
}
const deleteReleasesFromArtist = `-- name: DeleteReleasesFromArtist :exec
DELETE FROM releases r
USING artist_releases ar
WHERE ar.release_id = r.id
AND ar.artist_id = $1
`
func (q *Queries) DeleteReleasesFromArtist(ctx context.Context, artistID int32) error {
_, err := q.db.Exec(ctx, deleteReleasesFromArtist, artistID)
return err
}
const getRelease = `-- name: GetRelease :one
SELECT id, musicbrainz_id, image, various_artists, image_source, title FROM releases_with_title
WHERE id = $1 LIMIT 1
`
func (q *Queries) GetRelease(ctx context.Context, id int32) (ReleasesWithTitle, error) {
row := q.db.QueryRow(ctx, getRelease, id)
var i ReleasesWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
)
return i, err
}
const getReleaseByArtistAndTitle = `-- name: GetReleaseByArtistAndTitle :one
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
FROM releases_with_title r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE r.title = $1 AND ar.artist_id = $2
LIMIT 1
`
type GetReleaseByArtistAndTitleParams struct {
Title string
ArtistID int32
}
func (q *Queries) GetReleaseByArtistAndTitle(ctx context.Context, arg GetReleaseByArtistAndTitleParams) (ReleasesWithTitle, error) {
row := q.db.QueryRow(ctx, getReleaseByArtistAndTitle, arg.Title, arg.ArtistID)
var i ReleasesWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
)
return i, err
}
const getReleaseByArtistAndTitles = `-- name: GetReleaseByArtistAndTitles :one
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
FROM releases_with_title r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE r.title = ANY ($1::TEXT[]) AND ar.artist_id = $2
LIMIT 1
`
type GetReleaseByArtistAndTitlesParams struct {
Column1 []string
ArtistID int32
}
func (q *Queries) GetReleaseByArtistAndTitles(ctx context.Context, arg GetReleaseByArtistAndTitlesParams) (ReleasesWithTitle, error) {
row := q.db.QueryRow(ctx, getReleaseByArtistAndTitles, arg.Column1, arg.ArtistID)
var i ReleasesWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
)
return i, err
}
const getReleaseByImageID = `-- name: GetReleaseByImageID :one
SELECT id, musicbrainz_id, image, various_artists, image_source FROM releases
WHERE image = $1 LIMIT 1
`
func (q *Queries) GetReleaseByImageID(ctx context.Context, image *uuid.UUID) (Release, error) {
row := q.db.QueryRow(ctx, getReleaseByImageID, image)
var i Release
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
)
return i, err
}
const getReleaseByMbzID = `-- name: GetReleaseByMbzID :one
SELECT id, musicbrainz_id, image, various_artists, image_source, title FROM releases_with_title
WHERE musicbrainz_id = $1 LIMIT 1
`
func (q *Queries) GetReleaseByMbzID(ctx context.Context, musicbrainzID *uuid.UUID) (ReleasesWithTitle, error) {
row := q.db.QueryRow(ctx, getReleaseByMbzID, musicbrainzID)
var i ReleasesWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
)
return i, err
}
const getReleasesWithoutImages = `-- name: GetReleasesWithoutImages :many
SELECT
r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
(
SELECT json_agg(DISTINCT jsonb_build_object('id', a.id, 'name', a.name))
FROM artists_with_name a
JOIN artist_releases ar ON a.id = ar.artist_id
WHERE ar.release_id = r.id
) AS artists
FROM releases_with_title r
WHERE r.image IS NULL
AND r.id > $2
ORDER BY r.id ASC
LIMIT $1
`
type GetReleasesWithoutImagesParams struct {
Limit int32
ID int32
}
type GetReleasesWithoutImagesRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
Artists []byte
}
func (q *Queries) GetReleasesWithoutImages(ctx context.Context, arg GetReleasesWithoutImagesParams) ([]GetReleasesWithoutImagesRow, error) {
rows, err := q.db.Query(ctx, getReleasesWithoutImages, arg.Limit, arg.ID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetReleasesWithoutImagesRow
for rows.Next() {
var i GetReleasesWithoutImagesRow
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopReleasesFromArtist = `-- name: GetTopReleasesFromArtist :many
SELECT
r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
COUNT(*) AS listen_count,
(
SELECT json_agg(DISTINCT jsonb_build_object('id', a.id, 'name', a.name))
FROM artists_with_name a
JOIN artist_releases ar ON ar.artist_id = a.id
WHERE ar.release_id = r.id
) AS artists
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN releases_with_title r ON t.release_id = r.id
JOIN artist_releases ar ON r.id = ar.release_id
WHERE ar.artist_id = $5
AND l.listened_at BETWEEN $1 AND $2
GROUP BY r.id, r.title, r.musicbrainz_id, r.various_artists, r.image, r.image_source
ORDER BY listen_count DESC
LIMIT $3 OFFSET $4
`
type GetTopReleasesFromArtistParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
ArtistID int32
}
type GetTopReleasesFromArtistRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
ListenCount int64
Artists []byte
}
func (q *Queries) GetTopReleasesFromArtist(ctx context.Context, arg GetTopReleasesFromArtistParams) ([]GetTopReleasesFromArtistRow, error) {
rows, err := q.db.Query(ctx, getTopReleasesFromArtist,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
arg.ArtistID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopReleasesFromArtistRow
for rows.Next() {
var i GetTopReleasesFromArtistRow
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
&i.ListenCount,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopReleasesPaginated = `-- name: GetTopReleasesPaginated :many
SELECT
r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
COUNT(*) AS listen_count,
(
SELECT json_agg(DISTINCT jsonb_build_object('id', a.id, 'name', a.name))
FROM artists_with_name a
JOIN artist_releases ar ON ar.artist_id = a.id
WHERE ar.release_id = r.id
) AS artists
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN releases_with_title r ON t.release_id = r.id
WHERE l.listened_at BETWEEN $1 AND $2
GROUP BY r.id, r.title, r.musicbrainz_id, r.various_artists, r.image, r.image_source
ORDER BY listen_count DESC
LIMIT $3 OFFSET $4
`
type GetTopReleasesPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
}
type GetTopReleasesPaginatedRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
ListenCount int64
Artists []byte
}
func (q *Queries) GetTopReleasesPaginated(ctx context.Context, arg GetTopReleasesPaginatedParams) ([]GetTopReleasesPaginatedRow, error) {
rows, err := q.db.Query(ctx, getTopReleasesPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopReleasesPaginatedRow
for rows.Next() {
var i GetTopReleasesPaginatedRow
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
&i.ListenCount,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertRelease = `-- name: InsertRelease :one
INSERT INTO releases (musicbrainz_id, various_artists, image, image_source)
VALUES ($1, $2, $3, $4)
RETURNING id, musicbrainz_id, image, various_artists, image_source
`
type InsertReleaseParams struct {
MusicBrainzID *uuid.UUID
VariousArtists bool
Image *uuid.UUID
ImageSource pgtype.Text
}
func (q *Queries) InsertRelease(ctx context.Context, arg InsertReleaseParams) (Release, error) {
row := q.db.QueryRow(ctx, insertRelease,
arg.MusicBrainzID,
arg.VariousArtists,
arg.Image,
arg.ImageSource,
)
var i Release
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
)
return i, err
}
const updateReleaseImage = `-- name: UpdateReleaseImage :exec
UPDATE releases SET image = $2, image_source = $3
WHERE id = $1
`
type UpdateReleaseImageParams struct {
ID int32
Image *uuid.UUID
ImageSource pgtype.Text
}
func (q *Queries) UpdateReleaseImage(ctx context.Context, arg UpdateReleaseImageParams) error {
_, err := q.db.Exec(ctx, updateReleaseImage, arg.ID, arg.Image, arg.ImageSource)
return err
}
const updateReleaseMbzID = `-- name: UpdateReleaseMbzID :exec
UPDATE releases SET musicbrainz_id = $2
WHERE id = $1
`
type UpdateReleaseMbzIDParams struct {
ID int32
MusicBrainzID *uuid.UUID
}
func (q *Queries) UpdateReleaseMbzID(ctx context.Context, arg UpdateReleaseMbzIDParams) error {
_, err := q.db.Exec(ctx, updateReleaseMbzID, arg.ID, arg.MusicBrainzID)
return err
}

View file

@ -0,0 +1,431 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: search.sql
package repository
import (
"context"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
const searchArtists = `-- name: SearchArtists :many
SELECT id, name, musicbrainz_id, image, score
FROM (
SELECT
a.id,
a.name,
a.musicbrainz_id,
a.image,
similarity(aa.alias, $1) AS score,
ROW_NUMBER() OVER (PARTITION BY a.id ORDER BY similarity(aa.alias, $1) DESC) AS rn
FROM artist_aliases aa
JOIN artists_with_name a ON aa.artist_id = a.id
WHERE similarity(aa.alias, $1) > 0.28
) ranked
WHERE rn = 1
ORDER BY score DESC
LIMIT $2
`
type SearchArtistsParams struct {
Similarity string
Limit int32
}
type SearchArtistsRow struct {
ID int32
Name string
MusicBrainzID *uuid.UUID
Image *uuid.UUID
Score float32
}
func (q *Queries) SearchArtists(ctx context.Context, arg SearchArtistsParams) ([]SearchArtistsRow, error) {
rows, err := q.db.Query(ctx, searchArtists, arg.Similarity, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SearchArtistsRow
for rows.Next() {
var i SearchArtistsRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.MusicBrainzID,
&i.Image,
&i.Score,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchArtistsBySubstring = `-- name: SearchArtistsBySubstring :many
SELECT id, name, musicbrainz_id, image, score
FROM (
SELECT
a.id,
a.name,
a.musicbrainz_id,
a.image,
1.0 AS score, -- why
ROW_NUMBER() OVER (PARTITION BY a.id ORDER BY aa.alias) AS rn
FROM artist_aliases aa
JOIN artists_with_name a ON aa.artist_id = a.id
WHERE aa.alias ILIKE $1 || '%'
) ranked
WHERE rn = 1
ORDER BY score DESC
LIMIT $2
`
type SearchArtistsBySubstringParams struct {
Column1 pgtype.Text
Limit int32
}
type SearchArtistsBySubstringRow struct {
ID int32
Name string
MusicBrainzID *uuid.UUID
Image *uuid.UUID
Score float64
}
func (q *Queries) SearchArtistsBySubstring(ctx context.Context, arg SearchArtistsBySubstringParams) ([]SearchArtistsBySubstringRow, error) {
rows, err := q.db.Query(ctx, searchArtistsBySubstring, arg.Column1, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SearchArtistsBySubstringRow
for rows.Next() {
var i SearchArtistsBySubstringRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.MusicBrainzID,
&i.Image,
&i.Score,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchReleases = `-- name: SearchReleases :many
SELECT
ranked.id,
ranked.title,
ranked.musicbrainz_id,
ranked.image,
ranked.various_artists,
ranked.score,
(
SELECT json_agg(DISTINCT jsonb_build_object('id', a.id, 'name', a.name))
FROM artists_with_name a
JOIN artist_releases ar ON ar.artist_id = a.id
WHERE ar.release_id = ranked.id
) AS artists
FROM (
SELECT
r.id,
r.title,
r.musicbrainz_id,
r.image,
r.various_artists,
similarity(ra.alias, $1) AS score,
ROW_NUMBER() OVER (PARTITION BY r.id ORDER BY similarity(ra.alias, $1) DESC) AS rn
FROM release_aliases ra
JOIN releases_with_title r ON ra.release_id = r.id
WHERE similarity(ra.alias, $1) > 0.28
) ranked
WHERE rn = 1
ORDER BY score DESC, title
LIMIT $2
`
type SearchReleasesParams struct {
Similarity string
Limit int32
}
type SearchReleasesRow struct {
ID int32
Title string
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
Score float32
Artists []byte
}
func (q *Queries) SearchReleases(ctx context.Context, arg SearchReleasesParams) ([]SearchReleasesRow, error) {
rows, err := q.db.Query(ctx, searchReleases, arg.Similarity, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SearchReleasesRow
for rows.Next() {
var i SearchReleasesRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.Score,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchReleasesBySubstring = `-- name: SearchReleasesBySubstring :many
SELECT
ranked.id,
ranked.title,
ranked.musicbrainz_id,
ranked.image,
ranked.various_artists,
ranked.score,
(
SELECT json_agg(DISTINCT jsonb_build_object('id', a.id, 'name', a.name))
FROM artists_with_name a
JOIN artist_releases ar ON ar.artist_id = a.id
WHERE ar.release_id = ranked.id
) AS artists
FROM (
SELECT
r.id,
r.title,
r.musicbrainz_id,
r.image,
r.various_artists,
1.0 AS score, -- idk why
ROW_NUMBER() OVER (PARTITION BY r.id ORDER BY ra.alias) AS rn
FROM release_aliases ra
JOIN releases_with_title r ON ra.release_id = r.id
WHERE ra.alias ILIKE $1 || '%'
) ranked
WHERE rn = 1
ORDER BY score DESC, title
LIMIT $2
`
type SearchReleasesBySubstringParams struct {
Column1 pgtype.Text
Limit int32
}
type SearchReleasesBySubstringRow struct {
ID int32
Title string
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
Score float64
Artists []byte
}
func (q *Queries) SearchReleasesBySubstring(ctx context.Context, arg SearchReleasesBySubstringParams) ([]SearchReleasesBySubstringRow, error) {
rows, err := q.db.Query(ctx, searchReleasesBySubstring, arg.Column1, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SearchReleasesBySubstringRow
for rows.Next() {
var i SearchReleasesBySubstringRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.Score,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchTracks = `-- name: SearchTracks :many
SELECT
ranked.id,
ranked.title,
ranked.musicbrainz_id,
ranked.release_id,
ranked.image,
ranked.score,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at
JOIN artists_with_name a ON a.id = at.artist_id
WHERE at.track_id = ranked.id
) AS artists
FROM (
SELECT
t.id,
t.title,
t.musicbrainz_id,
t.release_id,
r.image,
similarity(ta.alias, $1) AS score,
ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY similarity(ta.alias, $1) DESC) AS rn
FROM track_aliases ta
JOIN tracks_with_title t ON ta.track_id = t.id
JOIN releases r ON t.release_id = r.id
WHERE similarity(ta.alias, $1) > 0.28
) ranked
WHERE rn = 1
ORDER BY score DESC, title
LIMIT $2
`
type SearchTracksParams struct {
Similarity string
Limit int32
}
type SearchTracksRow struct {
ID int32
Title string
MusicBrainzID *uuid.UUID
ReleaseID int32
Image *uuid.UUID
Score float32
Artists []byte
}
func (q *Queries) SearchTracks(ctx context.Context, arg SearchTracksParams) ([]SearchTracksRow, error) {
rows, err := q.db.Query(ctx, searchTracks, arg.Similarity, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SearchTracksRow
for rows.Next() {
var i SearchTracksRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.MusicBrainzID,
&i.ReleaseID,
&i.Image,
&i.Score,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const searchTracksBySubstring = `-- name: SearchTracksBySubstring :many
SELECT
ranked.id,
ranked.title,
ranked.musicbrainz_id,
ranked.release_id,
ranked.image,
ranked.score,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at
JOIN artists_with_name a ON a.id = at.artist_id
WHERE at.track_id = ranked.id
) AS artists
FROM (
SELECT
t.id,
t.title,
t.musicbrainz_id,
t.release_id,
r.image,
1.0 AS score,
ROW_NUMBER() OVER (PARTITION BY t.id ORDER BY ta.alias) AS rn
FROM track_aliases ta
JOIN tracks_with_title t ON ta.track_id = t.id
JOIN releases r ON t.release_id = r.id
WHERE ta.alias ILIKE $1 || '%'
) ranked
WHERE rn = 1
ORDER BY score DESC, title
LIMIT $2
`
type SearchTracksBySubstringParams struct {
Column1 pgtype.Text
Limit int32
}
type SearchTracksBySubstringRow struct {
ID int32
Title string
MusicBrainzID *uuid.UUID
ReleaseID int32
Image *uuid.UUID
Score float64
Artists []byte
}
func (q *Queries) SearchTracksBySubstring(ctx context.Context, arg SearchTracksBySubstringParams) ([]SearchTracksBySubstringRow, error) {
rows, err := q.db.Query(ctx, searchTracksBySubstring, arg.Column1, arg.Limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SearchTracksBySubstringRow
for rows.Next() {
var i SearchTracksBySubstringRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.MusicBrainzID,
&i.ReleaseID,
&i.Image,
&i.Score,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View file

@ -0,0 +1,120 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: sessions.sql
package repository
import (
"context"
"time"
"github.com/google/uuid"
)
const deleteSession = `-- name: DeleteSession :exec
DELETE FROM sessions WHERE id = $1
`
func (q *Queries) DeleteSession(ctx context.Context, id uuid.UUID) error {
_, err := q.db.Exec(ctx, deleteSession, id)
return err
}
const getSession = `-- name: GetSession :one
SELECT id, user_id, created_at, expires_at, persistent FROM sessions WHERE id = $1 AND expires_at > NOW()
`
func (q *Queries) GetSession(ctx context.Context, id uuid.UUID) (Session, error) {
row := q.db.QueryRow(ctx, getSession, id)
var i Session
err := row.Scan(
&i.ID,
&i.UserID,
&i.CreatedAt,
&i.ExpiresAt,
&i.Persistent,
)
return i, err
}
const getUserBySession = `-- name: GetUserBySession :one
SELECT u.id, username, role, password, s.id, user_id, created_at, expires_at, persistent
FROM users u
JOIN sessions s ON u.id = s.user_id
WHERE s.id = $1
`
type GetUserBySessionRow struct {
ID int32
Username string
Role Role
Password []byte
ID_2 uuid.UUID
UserID int32
CreatedAt time.Time
ExpiresAt time.Time
Persistent bool
}
func (q *Queries) GetUserBySession(ctx context.Context, id uuid.UUID) (GetUserBySessionRow, error) {
row := q.db.QueryRow(ctx, getUserBySession, id)
var i GetUserBySessionRow
err := row.Scan(
&i.ID,
&i.Username,
&i.Role,
&i.Password,
&i.ID_2,
&i.UserID,
&i.CreatedAt,
&i.ExpiresAt,
&i.Persistent,
)
return i, err
}
const insertSession = `-- name: InsertSession :one
INSERT INTO sessions (id, user_id, expires_at, persistent)
VALUES ($1, $2, $3, $4)
RETURNING id, user_id, created_at, expires_at, persistent
`
type InsertSessionParams struct {
ID uuid.UUID
UserID int32
ExpiresAt time.Time
Persistent bool
}
func (q *Queries) InsertSession(ctx context.Context, arg InsertSessionParams) (Session, error) {
row := q.db.QueryRow(ctx, insertSession,
arg.ID,
arg.UserID,
arg.ExpiresAt,
arg.Persistent,
)
var i Session
err := row.Scan(
&i.ID,
&i.UserID,
&i.CreatedAt,
&i.ExpiresAt,
&i.Persistent,
)
return i, err
}
const updateSessionExpiry = `-- name: UpdateSessionExpiry :exec
UPDATE sessions SET expires_at = $2 WHERE id = $1
`
type UpdateSessionExpiryParams struct {
ID uuid.UUID
ExpiresAt time.Time
}
func (q *Queries) UpdateSessionExpiry(ctx context.Context, arg UpdateSessionExpiryParams) error {
_, err := q.db.Exec(ctx, updateSessionExpiry, arg.ID, arg.ExpiresAt)
return err
}

View file

@ -0,0 +1,504 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: track.sql
package repository
import (
"context"
"time"
"github.com/google/uuid"
)
const associateArtistToTrack = `-- name: AssociateArtistToTrack :exec
INSERT INTO artist_tracks (artist_id, track_id)
VALUES ($1, $2)
ON CONFLICT DO NOTHING
`
type AssociateArtistToTrackParams struct {
ArtistID int32
TrackID int32
}
func (q *Queries) AssociateArtistToTrack(ctx context.Context, arg AssociateArtistToTrackParams) error {
_, err := q.db.Exec(ctx, associateArtistToTrack, arg.ArtistID, arg.TrackID)
return err
}
const countTopTracks = `-- name: CountTopTracks :one
SELECT COUNT(DISTINCT l.track_id) AS total_count
FROM listens l
WHERE l.listened_at BETWEEN $1 AND $2
`
type CountTopTracksParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
}
func (q *Queries) CountTopTracks(ctx context.Context, arg CountTopTracksParams) (int64, error) {
row := q.db.QueryRow(ctx, countTopTracks, arg.ListenedAt, arg.ListenedAt_2)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const countTopTracksByArtist = `-- name: CountTopTracksByArtist :one
SELECT COUNT(DISTINCT l.track_id) AS total_count
FROM listens l
JOIN artist_tracks at ON l.track_id = at.track_id
WHERE l.listened_at BETWEEN $1 AND $2
AND at.artist_id = $3
`
type CountTopTracksByArtistParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
ArtistID int32
}
func (q *Queries) CountTopTracksByArtist(ctx context.Context, arg CountTopTracksByArtistParams) (int64, error) {
row := q.db.QueryRow(ctx, countTopTracksByArtist, arg.ListenedAt, arg.ListenedAt_2, arg.ArtistID)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const countTopTracksByRelease = `-- name: CountTopTracksByRelease :one
SELECT COUNT(DISTINCT l.track_id) AS total_count
FROM listens l
JOIN tracks t ON l.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
AND t.release_id = $3
`
type CountTopTracksByReleaseParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
ReleaseID int32
}
func (q *Queries) CountTopTracksByRelease(ctx context.Context, arg CountTopTracksByReleaseParams) (int64, error) {
row := q.db.QueryRow(ctx, countTopTracksByRelease, arg.ListenedAt, arg.ListenedAt_2, arg.ReleaseID)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const deleteTrack = `-- name: DeleteTrack :exec
DELETE FROM tracks WHERE id = $1
`
func (q *Queries) DeleteTrack(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, deleteTrack, id)
return err
}
const getAllTracksFromArtist = `-- name: GetAllTracksFromArtist :many
SELECT t.id, t.musicbrainz_id, t.duration, t.release_id, t.title
FROM tracks_with_title t
JOIN artist_tracks at ON t.id = at.track_id
WHERE at.artist_id = $1
`
func (q *Queries) GetAllTracksFromArtist(ctx context.Context, artistID int32) ([]TracksWithTitle, error) {
rows, err := q.db.Query(ctx, getAllTracksFromArtist, artistID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []TracksWithTitle
for rows.Next() {
var i TracksWithTitle
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Duration,
&i.ReleaseID,
&i.Title,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopTracksByArtistPaginated = `-- name: GetTopTracksByArtistPaginated :many
SELECT
t.id,
t.title,
t.musicbrainz_id,
t.release_id,
r.image,
COUNT(*) AS listen_count,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at2
JOIN artists_with_name a ON a.id = at2.artist_id
WHERE at2.track_id = t.id
) AS artists
FROM listens l
JOIN tracks_with_title t ON l.track_id = t.id
JOIN releases r ON t.release_id = r.id
JOIN artist_tracks at ON at.track_id = t.id
WHERE l.listened_at BETWEEN $1 AND $2
AND at.artist_id = $5
GROUP BY t.id, t.title, t.musicbrainz_id, t.release_id, r.image
ORDER BY listen_count DESC
LIMIT $3 OFFSET $4
`
type GetTopTracksByArtistPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
ArtistID int32
}
type GetTopTracksByArtistPaginatedRow struct {
ID int32
Title string
MusicBrainzID *uuid.UUID
ReleaseID int32
Image *uuid.UUID
ListenCount int64
Artists []byte
}
func (q *Queries) GetTopTracksByArtistPaginated(ctx context.Context, arg GetTopTracksByArtistPaginatedParams) ([]GetTopTracksByArtistPaginatedRow, error) {
rows, err := q.db.Query(ctx, getTopTracksByArtistPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
arg.ArtistID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopTracksByArtistPaginatedRow
for rows.Next() {
var i GetTopTracksByArtistPaginatedRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.MusicBrainzID,
&i.ReleaseID,
&i.Image,
&i.ListenCount,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopTracksInReleasePaginated = `-- name: GetTopTracksInReleasePaginated :many
SELECT
t.id,
t.title,
t.musicbrainz_id,
t.release_id,
r.image,
COUNT(*) AS listen_count,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at2
JOIN artists_with_name a ON a.id = at2.artist_id
WHERE at2.track_id = t.id
) AS artists
FROM listens l
JOIN tracks_with_title t ON l.track_id = t.id
JOIN releases r ON t.release_id = r.id
WHERE l.listened_at BETWEEN $1 AND $2
AND t.release_id = $5
GROUP BY t.id, t.title, t.musicbrainz_id, t.release_id, r.image
ORDER BY listen_count DESC
LIMIT $3 OFFSET $4
`
type GetTopTracksInReleasePaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
ReleaseID int32
}
type GetTopTracksInReleasePaginatedRow struct {
ID int32
Title string
MusicBrainzID *uuid.UUID
ReleaseID int32
Image *uuid.UUID
ListenCount int64
Artists []byte
}
func (q *Queries) GetTopTracksInReleasePaginated(ctx context.Context, arg GetTopTracksInReleasePaginatedParams) ([]GetTopTracksInReleasePaginatedRow, error) {
rows, err := q.db.Query(ctx, getTopTracksInReleasePaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
arg.ReleaseID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopTracksInReleasePaginatedRow
for rows.Next() {
var i GetTopTracksInReleasePaginatedRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.MusicBrainzID,
&i.ReleaseID,
&i.Image,
&i.ListenCount,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopTracksPaginated = `-- name: GetTopTracksPaginated :many
SELECT
t.id,
t.title,
t.musicbrainz_id,
t.release_id,
r.image,
COUNT(*) AS listen_count,
(
SELECT json_agg(json_build_object('id', a.id, 'name', a.name))
FROM artist_tracks at
JOIN artists_with_name a ON a.id = at.artist_id
WHERE at.track_id = t.id
) AS artists
FROM listens l
JOIN tracks_with_title t ON l.track_id = t.id
JOIN releases r ON t.release_id = r.id
WHERE l.listened_at BETWEEN $1 AND $2
GROUP BY t.id, t.title, t.musicbrainz_id, t.release_id, r.image
ORDER BY listen_count DESC
LIMIT $3 OFFSET $4
`
type GetTopTracksPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
}
type GetTopTracksPaginatedRow struct {
ID int32
Title string
MusicBrainzID *uuid.UUID
ReleaseID int32
Image *uuid.UUID
ListenCount int64
Artists []byte
}
func (q *Queries) GetTopTracksPaginated(ctx context.Context, arg GetTopTracksPaginatedParams) ([]GetTopTracksPaginatedRow, error) {
rows, err := q.db.Query(ctx, getTopTracksPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopTracksPaginatedRow
for rows.Next() {
var i GetTopTracksPaginatedRow
if err := rows.Scan(
&i.ID,
&i.Title,
&i.MusicBrainzID,
&i.ReleaseID,
&i.Image,
&i.ListenCount,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTrack = `-- name: GetTrack :one
SELECT
t.id, t.musicbrainz_id, t.duration, t.release_id, t.title,
r.image
FROM tracks_with_title t
JOIN releases r ON t.release_id = r.id
WHERE t.id = $1 LIMIT 1
`
type GetTrackRow struct {
ID int32
MusicBrainzID *uuid.UUID
Duration int32
ReleaseID int32
Title string
Image *uuid.UUID
}
func (q *Queries) GetTrack(ctx context.Context, id int32) (GetTrackRow, error) {
row := q.db.QueryRow(ctx, getTrack, id)
var i GetTrackRow
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Duration,
&i.ReleaseID,
&i.Title,
&i.Image,
)
return i, err
}
const getTrackByMbzID = `-- name: GetTrackByMbzID :one
SELECT id, musicbrainz_id, duration, release_id, title FROM tracks_with_title
WHERE musicbrainz_id = $1 LIMIT 1
`
func (q *Queries) GetTrackByMbzID(ctx context.Context, musicbrainzID *uuid.UUID) (TracksWithTitle, error) {
row := q.db.QueryRow(ctx, getTrackByMbzID, musicbrainzID)
var i TracksWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Duration,
&i.ReleaseID,
&i.Title,
)
return i, err
}
const getTrackByTitleAndArtists = `-- name: GetTrackByTitleAndArtists :one
SELECT t.id, t.musicbrainz_id, t.duration, t.release_id, t.title
FROM tracks_with_title t
JOIN artist_tracks at ON at.track_id = t.id
WHERE t.title = $1
AND at.artist_id = ANY($2::int[])
GROUP BY t.id, t.title, t.musicbrainz_id, t.duration, t.release_id
HAVING COUNT(DISTINCT at.artist_id) = cardinality($2::int[])
`
type GetTrackByTitleAndArtistsParams struct {
Title string
Column2 []int32
}
func (q *Queries) GetTrackByTitleAndArtists(ctx context.Context, arg GetTrackByTitleAndArtistsParams) (TracksWithTitle, error) {
row := q.db.QueryRow(ctx, getTrackByTitleAndArtists, arg.Title, arg.Column2)
var i TracksWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Duration,
&i.ReleaseID,
&i.Title,
)
return i, err
}
const insertTrack = `-- name: InsertTrack :one
INSERT INTO tracks (musicbrainz_id, release_id, duration)
VALUES ($1, $2, $3)
RETURNING id, musicbrainz_id, duration, release_id
`
type InsertTrackParams struct {
MusicBrainzID *uuid.UUID
ReleaseID int32
Duration int32
}
func (q *Queries) InsertTrack(ctx context.Context, arg InsertTrackParams) (Track, error) {
row := q.db.QueryRow(ctx, insertTrack, arg.MusicBrainzID, arg.ReleaseID, arg.Duration)
var i Track
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Duration,
&i.ReleaseID,
)
return i, err
}
const updateReleaseForAll = `-- name: UpdateReleaseForAll :exec
UPDATE tracks SET release_id = $2
WHERE release_id = $1
`
type UpdateReleaseForAllParams struct {
ReleaseID int32
ReleaseID_2 int32
}
func (q *Queries) UpdateReleaseForAll(ctx context.Context, arg UpdateReleaseForAllParams) error {
_, err := q.db.Exec(ctx, updateReleaseForAll, arg.ReleaseID, arg.ReleaseID_2)
return err
}
const updateTrackDuration = `-- name: UpdateTrackDuration :exec
UPDATE tracks SET duration = $2
WHERE id = $1
`
type UpdateTrackDurationParams struct {
ID int32
Duration int32
}
func (q *Queries) UpdateTrackDuration(ctx context.Context, arg UpdateTrackDurationParams) error {
_, err := q.db.Exec(ctx, updateTrackDuration, arg.ID, arg.Duration)
return err
}
const updateTrackMbzID = `-- name: UpdateTrackMbzID :exec
UPDATE tracks SET musicbrainz_id = $2
WHERE id = $1
`
type UpdateTrackMbzIDParams struct {
ID int32
MusicBrainzID *uuid.UUID
}
func (q *Queries) UpdateTrackMbzID(ctx context.Context, arg UpdateTrackMbzIDParams) error {
_, err := q.db.Exec(ctx, updateTrackMbzID, arg.ID, arg.MusicBrainzID)
return err
}

View file

@ -0,0 +1,210 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.29.0
// source: users.sql
package repository
import (
"context"
)
const countApiKeys = `-- name: CountApiKeys :one
SELECT COUNT(*) FROM api_keys WHERE user_id = $1
`
func (q *Queries) CountApiKeys(ctx context.Context, userID int32) (int64, error) {
row := q.db.QueryRow(ctx, countApiKeys, userID)
var count int64
err := row.Scan(&count)
return count, err
}
const countUsers = `-- name: CountUsers :one
SELECT COUNT(*) FROM users
`
func (q *Queries) CountUsers(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, countUsers)
var count int64
err := row.Scan(&count)
return count, err
}
const deleteApiKey = `-- name: DeleteApiKey :exec
DELETE FROM api_keys WHERE id = $1
`
func (q *Queries) DeleteApiKey(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, deleteApiKey, id)
return err
}
const deleteUser = `-- name: DeleteUser :exec
DELETE FROM users WHERE id = $1
`
func (q *Queries) DeleteUser(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, deleteUser, id)
return err
}
const getAllApiKeysByUserID = `-- name: GetAllApiKeysByUserID :many
SELECT ak.id, ak.key, ak.user_id, ak.created_at, ak.label
FROM api_keys ak
JOIN users u ON ak.user_id = u.id
WHERE u.id = $1
`
func (q *Queries) GetAllApiKeysByUserID(ctx context.Context, id int32) ([]ApiKey, error) {
rows, err := q.db.Query(ctx, getAllApiKeysByUserID, id)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ApiKey
for rows.Next() {
var i ApiKey
if err := rows.Scan(
&i.ID,
&i.Key,
&i.UserID,
&i.CreatedAt,
&i.Label,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getUserByApiKey = `-- name: GetUserByApiKey :one
SELECT u.id, u.username, u.role, u.password
FROM users u
JOIN api_keys ak ON u.id = ak.user_id
WHERE ak.key = $1
`
func (q *Queries) GetUserByApiKey(ctx context.Context, key string) (User, error) {
row := q.db.QueryRow(ctx, getUserByApiKey, key)
var i User
err := row.Scan(
&i.ID,
&i.Username,
&i.Role,
&i.Password,
)
return i, err
}
const getUserByUsername = `-- name: GetUserByUsername :one
SELECT id, username, role, password FROM users WHERE username = $1
`
func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User, error) {
row := q.db.QueryRow(ctx, getUserByUsername, username)
var i User
err := row.Scan(
&i.ID,
&i.Username,
&i.Role,
&i.Password,
)
return i, err
}
const insertApiKey = `-- name: InsertApiKey :one
INSERT INTO api_keys (user_id, key, label)
VALUES ($1, $2, $3)
RETURNING id, key, user_id, created_at, label
`
type InsertApiKeyParams struct {
UserID int32
Key string
Label string
}
func (q *Queries) InsertApiKey(ctx context.Context, arg InsertApiKeyParams) (ApiKey, error) {
row := q.db.QueryRow(ctx, insertApiKey, arg.UserID, arg.Key, arg.Label)
var i ApiKey
err := row.Scan(
&i.ID,
&i.Key,
&i.UserID,
&i.CreatedAt,
&i.Label,
)
return i, err
}
const insertUser = `-- name: InsertUser :one
INSERT INTO users (username, password, role)
VALUES ($1, $2, $3)
RETURNING id, username, role, password
`
type InsertUserParams struct {
Username string
Password []byte
Role Role
}
func (q *Queries) InsertUser(ctx context.Context, arg InsertUserParams) (User, error) {
row := q.db.QueryRow(ctx, insertUser, arg.Username, arg.Password, arg.Role)
var i User
err := row.Scan(
&i.ID,
&i.Username,
&i.Role,
&i.Password,
)
return i, err
}
const updateApiKeyLabel = `-- name: UpdateApiKeyLabel :exec
UPDATE api_keys SET label = $3 WHERE id = $1 AND user_id = $2
`
type UpdateApiKeyLabelParams struct {
ID int32
UserID int32
Label string
}
func (q *Queries) UpdateApiKeyLabel(ctx context.Context, arg UpdateApiKeyLabelParams) error {
_, err := q.db.Exec(ctx, updateApiKeyLabel, arg.ID, arg.UserID, arg.Label)
return err
}
const updateUserPassword = `-- name: UpdateUserPassword :exec
UPDATE users SET password = $2 WHERE id = $1
`
type UpdateUserPasswordParams struct {
ID int32
Password []byte
}
func (q *Queries) UpdateUserPassword(ctx context.Context, arg UpdateUserPasswordParams) error {
_, err := q.db.Exec(ctx, updateUserPassword, arg.ID, arg.Password)
return err
}
const updateUserUsername = `-- name: UpdateUserUsername :exec
UPDATE users SET username = $2 WHERE id = $1
`
type UpdateUserUsernameParams struct {
ID int32
Username string
}
func (q *Queries) UpdateUserUsername(ctx context.Context, arg UpdateUserUsernameParams) error {
_, err := q.db.Exec(ctx, updateUserUsername, arg.ID, arg.Username)
return err
}