mirror of
https://github.com/gabehf/Koito.git
synced 2026-04-22 12:01:52 -07:00
chore: initial public commit
This commit is contained in:
commit
fc9054b78c
250 changed files with 32809 additions and 0 deletions
316
internal/repository/alias.sql.go
Normal file
316
internal/repository/alias.sql.go
Normal 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
|
||||
}
|
||||
418
internal/repository/artist.sql.go
Normal file
418
internal/repository/artist.sql.go
Normal 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
32
internal/repository/db.go
Normal 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,
|
||||
}
|
||||
}
|
||||
26
internal/repository/etc.sql.go
Normal file
26
internal/repository/etc.sql.go
Normal 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
|
||||
}
|
||||
742
internal/repository/listen.sql.go
Normal file
742
internal/repository/listen.sql.go
Normal 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
|
||||
}
|
||||
164
internal/repository/models.go
Normal file
164
internal/repository/models.go
Normal 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
|
||||
}
|
||||
462
internal/repository/release.sql.go
Normal file
462
internal/repository/release.sql.go
Normal 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
|
||||
}
|
||||
431
internal/repository/search.sql.go
Normal file
431
internal/repository/search.sql.go
Normal 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
|
||||
}
|
||||
120
internal/repository/sessions.sql.go
Normal file
120
internal/repository/sessions.sql.go
Normal 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
|
||||
}
|
||||
504
internal/repository/track.sql.go
Normal file
504
internal/repository/track.sql.go
Normal 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
|
||||
}
|
||||
210
internal/repository/users.sql.go
Normal file
210
internal/repository/users.sql.go
Normal 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue