refactor: adding back artist and album tables
This commit is contained in:
+7
-8
@@ -6,8 +6,8 @@ type Album struct {
|
|||||||
ID string `json:"id" orm:"column(id)"`
|
ID string `json:"id" orm:"column(id)"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ArtistID string `json:"artistId" orm:"pk;column(artist_id)"`
|
ArtistID string `json:"artistId" orm:"pk;column(artist_id)"`
|
||||||
CoverArtPath string `json:"-"`
|
CoverArtPath string `json:"coverArtPath"`
|
||||||
CoverArtId string `json:"-"`
|
CoverArtId string `json:"coverArtId"`
|
||||||
Artist string `json:"artist"`
|
Artist string `json:"artist"`
|
||||||
AlbumArtist string `json:"albumArtist"`
|
AlbumArtist string `json:"albumArtist"`
|
||||||
Year int `json:"year"`
|
Year int `json:"year"`
|
||||||
@@ -19,11 +19,11 @@ type Album struct {
|
|||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
|
|
||||||
// Annotations
|
// Annotations
|
||||||
PlayCount int `orm:"-"`
|
PlayCount int `json:"-" orm:"-"`
|
||||||
PlayDate time.Time `orm:"-"`
|
PlayDate time.Time `json:"-" orm:"-"`
|
||||||
Rating int `orm:"-"`
|
Rating int `json:"-" orm:"-"`
|
||||||
Starred bool `orm:"-"`
|
Starred bool `json:"-" orm:"-"`
|
||||||
StarredAt time.Time `orm:"-"`
|
StarredAt time.Time `json:"-" orm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Albums []Album
|
type Albums []Album
|
||||||
@@ -35,7 +35,6 @@ type AlbumRepository interface {
|
|||||||
Get(id string) (*Album, error)
|
Get(id string) (*Album, error)
|
||||||
FindByArtist(artistId string) (Albums, error)
|
FindByArtist(artistId string) (Albums, error)
|
||||||
GetAll(...QueryOptions) (Albums, error)
|
GetAll(...QueryOptions) (Albums, error)
|
||||||
GetMap(ids []string) (map[string]Album, error)
|
|
||||||
GetRandom(...QueryOptions) (Albums, error)
|
GetRandom(...QueryOptions) (Albums, error)
|
||||||
GetStarred(options ...QueryOptions) (Albums, error)
|
GetStarred(options ...QueryOptions) (Albums, error)
|
||||||
Search(q string, offset int, size int) (Albums, error)
|
Search(q string, offset int, size int) (Albums, error)
|
||||||
|
|||||||
+5
-5
@@ -8,11 +8,11 @@ type Artist struct {
|
|||||||
AlbumCount int `json:"albumCount" orm:"column(album_count)"`
|
AlbumCount int `json:"albumCount" orm:"column(album_count)"`
|
||||||
|
|
||||||
// Annotations
|
// Annotations
|
||||||
PlayCount int `json:"playCount"`
|
PlayCount int `json:"-" orm:"-"`
|
||||||
PlayDate time.Time `json:"playDate"`
|
PlayDate time.Time `json:"-" orm:"-"`
|
||||||
Rating int `json:"rating"`
|
Rating int `json:"-" orm:"-"`
|
||||||
Starred bool `json:"starred"`
|
Starred bool `json:"-" orm:"-"`
|
||||||
StarredAt time.Time `json:"starredAt"`
|
StarredAt time.Time `json:"-" orm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Artists []Artist
|
type Artists []Artist
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package persistence
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
. "github.com/Masterminds/squirrel"
|
. "github.com/Masterminds/squirrel"
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
"github.com/deluan/rest"
|
"github.com/deluan/rest"
|
||||||
)
|
)
|
||||||
@@ -17,7 +20,7 @@ func NewAlbumRepository(ctx context.Context, o orm.Ormer) model.AlbumRepository
|
|||||||
r := &albumRepository{}
|
r := &albumRepository{}
|
||||||
r.ctx = ctx
|
r.ctx = ctx
|
||||||
r.ormer = o
|
r.ormer = o
|
||||||
r.tableName = "media_file"
|
r.tableName = "album"
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,28 +30,19 @@ func (r *albumRepository) CountAll(options ...model.QueryOptions) (int64, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) Exists(id string) (bool, error) {
|
func (r *albumRepository) Exists(id string) (bool, error) {
|
||||||
return r.exists(Select().Where(Eq{"album_id": id}))
|
return r.exists(Select().Where(Eq{"id": id}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) Put(a *model.Album) error {
|
func (r *albumRepository) Put(a *model.Album) error {
|
||||||
return nil
|
return r.put(a.ID, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) selectAlbum(options ...model.QueryOptions) SelectBuilder {
|
func (r *albumRepository) selectAlbum(options ...model.QueryOptions) SelectBuilder {
|
||||||
//select album_id as id, album as name, f.artist, f.album_artist, f.artist_id, f.compilation, f.genre,
|
return r.newSelectWithAnnotation(model.AlbumItemType, "id", options...).Columns("*")
|
||||||
// max(f.year) as year, sum(f.duration) as duration, max(f.updated_at) as updated_at,
|
|
||||||
// min(f.created_at) as created_at, count(*) as song_count, a.id as current_id, f.id as cover_art_id,
|
|
||||||
// f.path as cover_art_path, f.has_cover_art
|
|
||||||
// group by album_id
|
|
||||||
return r.newSelectWithAnnotation(model.AlbumItemType, "album_id", options...).
|
|
||||||
Columns("album_id as id", "album as name", "artist", "album_artist", "artist", "artist_id",
|
|
||||||
"compilation", "genre", "id as cover_art_id", "path as cover_art_path", "has_cover_art",
|
|
||||||
"max(year) as year", "sum(duration) as duration", "max(updated_at) as updated_at",
|
|
||||||
"min(created_at) as created_at", "count(*) as song_count").GroupBy("album_id")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) Get(id string) (*model.Album, error) {
|
func (r *albumRepository) Get(id string) (*model.Album, error) {
|
||||||
sq := r.selectAlbum().Where(Eq{"album_id": id})
|
sq := r.selectAlbum().Where(Eq{"id": id})
|
||||||
var res model.Album
|
var res model.Album
|
||||||
err := r.queryOne(sq, &res)
|
err := r.queryOne(sq, &res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -58,7 +52,7 @@ func (r *albumRepository) Get(id string) (*model.Album, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) FindByArtist(artistId string) (model.Albums, error) {
|
func (r *albumRepository) FindByArtist(artistId string) (model.Albums, error) {
|
||||||
sq := r.selectAlbum().Where(Eq{"artist_id": artistId}).OrderBy("album")
|
sq := r.selectAlbum().Where(Eq{"artist_id": artistId}).OrderBy("year")
|
||||||
var res model.Albums
|
var res model.Albums
|
||||||
err := r.queryAll(sq, &res)
|
err := r.queryAll(sq, &res)
|
||||||
return res, err
|
return res, err
|
||||||
@@ -71,10 +65,6 @@ func (r *albumRepository) GetAll(options ...model.QueryOptions) (model.Albums, e
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) GetMap(ids []string) (map[string]model.Album, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Keep order when paginating
|
// TODO Keep order when paginating
|
||||||
func (r *albumRepository) GetRandom(options ...model.QueryOptions) (model.Albums, error) {
|
func (r *albumRepository) GetRandom(options ...model.QueryOptions) (model.Albums, error) {
|
||||||
sq := r.selectAlbum(options...)
|
sq := r.selectAlbum(options...)
|
||||||
@@ -94,11 +84,67 @@ func (r *albumRepository) GetRandom(options ...model.QueryOptions) (model.Albums
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) Refresh(ids ...string) error {
|
func (r *albumRepository) Refresh(ids ...string) error {
|
||||||
return nil
|
type refreshAlbum struct {
|
||||||
|
model.Album
|
||||||
|
CurrentId string
|
||||||
|
HasCoverArt bool
|
||||||
|
}
|
||||||
|
var albums []refreshAlbum
|
||||||
|
o := r.ormer
|
||||||
|
sql := fmt.Sprintf(`
|
||||||
|
select album_id as id, album as name, f.artist, f.album_artist, f.artist_id, f.compilation, f.genre,
|
||||||
|
max(f.year) as year, sum(f.duration) as duration, max(f.updated_at) as updated_at,
|
||||||
|
min(f.created_at) as created_at, count(*) as song_count, a.id as current_id, f.id as cover_art_id,
|
||||||
|
f.path as cover_art_path, f.has_cover_art
|
||||||
|
from media_file f left outer join album a on f.album_id = a.id
|
||||||
|
where f.album_id in ('%s')
|
||||||
|
group by album_id order by f.id`, strings.Join(ids, "','"))
|
||||||
|
_, err := o.Raw(sql).QueryRows(&albums)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
toInsert := 0
|
||||||
|
toUpdate := 0
|
||||||
|
for _, al := range albums {
|
||||||
|
if !al.HasCoverArt {
|
||||||
|
al.CoverArtId = ""
|
||||||
|
}
|
||||||
|
if al.Compilation {
|
||||||
|
al.AlbumArtist = "Various Artists"
|
||||||
|
}
|
||||||
|
if al.AlbumArtist == "" {
|
||||||
|
al.AlbumArtist = al.Artist
|
||||||
|
}
|
||||||
|
if al.CurrentId != "" {
|
||||||
|
toUpdate++
|
||||||
|
} else {
|
||||||
|
toInsert++
|
||||||
|
}
|
||||||
|
//err := r.addToIndex(r.tableName, al.ID, al.Name) TODO: Search
|
||||||
|
err := r.Put(&al.Album)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if toInsert > 0 {
|
||||||
|
log.Debug(r.ctx, "Inserted new albums", "num", toInsert)
|
||||||
|
}
|
||||||
|
if toUpdate > 0 {
|
||||||
|
log.Debug(r.ctx, "Updated albums", "num", toUpdate)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) PurgeEmpty() error {
|
func (r *albumRepository) PurgeEmpty() error {
|
||||||
return nil
|
rs, err := r.ormer.Raw("delete from album where id not in (select distinct(album_id) from media_file)").Exec()
|
||||||
|
if err == nil {
|
||||||
|
c, _ := rs.RowsAffected()
|
||||||
|
if c > 0 {
|
||||||
|
log.Debug(r.ctx, "Purged empty albums", "num", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) GetStarred(options ...model.QueryOptions) (model.Albums, error) {
|
func (r *albumRepository) GetStarred(options ...model.QueryOptions) (model.Albums, error) {
|
||||||
@@ -109,7 +155,7 @@ func (r *albumRepository) GetStarred(options ...model.QueryOptions) (model.Album
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) Search(q string, offset int, size int) (model.Albums, error) {
|
func (r *albumRepository) Search(q string, offset int, size int) (model.Albums, error) {
|
||||||
return nil, nil
|
return nil, nil // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *albumRepository) Count(options ...rest.QueryOptions) (int64, error) {
|
func (r *albumRepository) Count(options ...rest.QueryOptions) (int64, error) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@@ -13,7 +14,7 @@ var _ = Describe("AlbumRepository", func() {
|
|||||||
var repo model.AlbumRepository
|
var repo model.AlbumRepository
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx := context.WithValue(context.Background(), "user", &model.User{ID: "userid"})
|
ctx := context.WithValue(log.NewContext(nil), "user", &model.User{ID: "userid"})
|
||||||
repo = NewAlbumRepository(ctx, orm.NewOrm())
|
repo = NewAlbumRepository(ctx, orm.NewOrm())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -66,8 +67,8 @@ var _ = Describe("AlbumRepository", func() {
|
|||||||
Describe("FindByArtist", func() {
|
Describe("FindByArtist", func() {
|
||||||
It("returns all records from a given ArtistID", func() {
|
It("returns all records from a given ArtistID", func() {
|
||||||
Expect(repo.FindByArtist("3")).To(Equal(model.Albums{
|
Expect(repo.FindByArtist("3")).To(Equal(model.Albums{
|
||||||
albumAbbeyRoad,
|
|
||||||
albumSgtPeppers,
|
albumSgtPeppers,
|
||||||
|
albumAbbeyRoad,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ package persistence
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
. "github.com/Masterminds/squirrel"
|
. "github.com/Masterminds/squirrel"
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
"github.com/deluan/navidrome/conf"
|
"github.com/deluan/navidrome/conf"
|
||||||
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
"github.com/deluan/navidrome/utils"
|
"github.com/deluan/navidrome/utils"
|
||||||
"github.com/deluan/rest"
|
"github.com/deluan/rest"
|
||||||
@@ -23,24 +25,21 @@ func NewArtistRepository(ctx context.Context, o orm.Ormer) model.ArtistRepositor
|
|||||||
r.ctx = ctx
|
r.ctx = ctx
|
||||||
r.ormer = o
|
r.ormer = o
|
||||||
r.indexGroups = utils.ParseIndexGroups(conf.Server.IndexGroups)
|
r.indexGroups = utils.ParseIndexGroups(conf.Server.IndexGroups)
|
||||||
r.tableName = "media_file"
|
r.tableName = "artist"
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) selectArtist(options ...model.QueryOptions) SelectBuilder {
|
func (r *artistRepository) selectArtist(options ...model.QueryOptions) SelectBuilder {
|
||||||
// FIXME Handle AlbumArtist/Various Artists...
|
return r.newSelectWithAnnotation(model.ArtistItemType, "id", options...).Columns("*")
|
||||||
return r.newSelectWithAnnotation(model.ArtistItemType, "album_id", options...).
|
|
||||||
Columns("artist_id as id", "artist as name", "count(distinct album_id) as album_count").
|
|
||||||
GroupBy("artist_id").Where(Eq{"compilation": false})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) CountAll(options ...model.QueryOptions) (int64, error) {
|
func (r *artistRepository) CountAll(options ...model.QueryOptions) (int64, error) {
|
||||||
sel := r.selectArtist(options...).Where(Eq{"compilation": false})
|
sel := r.selectArtist(options...)
|
||||||
return r.count(sel, options...)
|
return r.count(sel, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) Exists(id string) (bool, error) {
|
func (r *artistRepository) Exists(id string) (bool, error) {
|
||||||
return r.exists(Select().Where(Eq{"artist_id": id}))
|
return r.exists(Select().Where(Eq{"id": id}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) getIndexKey(a *model.Artist) string {
|
func (r *artistRepository) getIndexKey(a *model.Artist) string {
|
||||||
@@ -55,12 +54,11 @@ func (r *artistRepository) getIndexKey(a *model.Artist) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) Put(a *model.Artist) error {
|
func (r *artistRepository) Put(a *model.Artist) error {
|
||||||
return nil
|
return r.put(a.ID, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) Get(id string) (*model.Artist, error) {
|
func (r *artistRepository) Get(id string) (*model.Artist, error) {
|
||||||
sel := Select("artist_id as id", "artist as name", "count(distinct album_id) as album_count").
|
sel := r.selectArtist().Where(Eq{"id": id})
|
||||||
From("media_file").GroupBy("artist_id").Where(Eq{"artist_id": id})
|
|
||||||
var res model.Artist
|
var res model.Artist
|
||||||
err := r.queryOne(sel, &res)
|
err := r.queryOne(sel, &res)
|
||||||
return &res, err
|
return &res, err
|
||||||
@@ -105,7 +103,56 @@ func (r *artistRepository) GetIndex() (model.ArtistIndexes, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) Refresh(ids ...string) error {
|
func (r *artistRepository) Refresh(ids ...string) error {
|
||||||
return nil
|
type refreshArtist struct {
|
||||||
|
model.Artist
|
||||||
|
CurrentId string
|
||||||
|
AlbumArtist string
|
||||||
|
Compilation bool
|
||||||
|
}
|
||||||
|
var artists []refreshArtist
|
||||||
|
o := r.ormer
|
||||||
|
sql := fmt.Sprintf(`
|
||||||
|
select f.artist_id as id,
|
||||||
|
f.artist as name,
|
||||||
|
f.album_artist,
|
||||||
|
f.compilation,
|
||||||
|
count(*) as album_count,
|
||||||
|
a.id as current_id
|
||||||
|
from album f
|
||||||
|
left outer join artist a on f.artist_id = a.id
|
||||||
|
where f.artist_id in ('%s') group by f.artist_id order by f.id`, strings.Join(ids, "','"))
|
||||||
|
_, err := o.Raw(sql).QueryRows(&artists)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
toInsert := 0
|
||||||
|
toUpdate := 0
|
||||||
|
for _, ar := range artists {
|
||||||
|
if ar.Compilation {
|
||||||
|
ar.AlbumArtist = "Various Artists"
|
||||||
|
}
|
||||||
|
if ar.AlbumArtist != "" {
|
||||||
|
ar.Name = ar.AlbumArtist
|
||||||
|
}
|
||||||
|
if ar.CurrentId != "" {
|
||||||
|
toUpdate++
|
||||||
|
} else {
|
||||||
|
toInsert++
|
||||||
|
}
|
||||||
|
//err := r.addToIndex(r.tableName, ar.ID, ar.Name)
|
||||||
|
err := r.Put(&ar.Artist)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if toInsert > 0 {
|
||||||
|
log.Debug(r.ctx, "Inserted new artists", "num", toInsert)
|
||||||
|
}
|
||||||
|
if toUpdate > 0 {
|
||||||
|
log.Debug(r.ctx, "Updated artists", "num", toUpdate)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) GetStarred(options ...model.QueryOptions) (model.Artists, error) {
|
func (r *artistRepository) GetStarred(options ...model.QueryOptions) (model.Artists, error) {
|
||||||
@@ -113,7 +160,8 @@ func (r *artistRepository) GetStarred(options ...model.QueryOptions) (model.Arti
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) PurgeEmpty() error {
|
func (r *artistRepository) PurgeEmpty() error {
|
||||||
return nil
|
_, err := r.ormer.Raw("delete from artist where id not in (select distinct(artist_id) from album)").Exec()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *artistRepository) Search(q string, offset int, size int) (model.Artists, error) {
|
func (r *artistRepository) Search(q string, offset int, size int) (model.Artists, error) {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package persistence
|
package persistence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@@ -13,7 +12,7 @@ var _ = Describe("ArtistRepository", func() {
|
|||||||
var repo model.ArtistRepository
|
var repo model.ArtistRepository
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
repo = NewArtistRepository(context.Background(), orm.NewOrm())
|
repo = NewArtistRepository(log.NewContext(nil), orm.NewOrm())
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Count", func() {
|
Describe("Count", func() {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package persistence_test
|
package persistence_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
"github.com/deluan/navidrome/persistence"
|
"github.com/deluan/navidrome/persistence"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
@@ -14,7 +13,7 @@ var _ = Describe("GenreRepository", func() {
|
|||||||
var repo model.GenreRepository
|
var repo model.GenreRepository
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
repo = persistence.NewGenreRepository(context.Background(), orm.NewOrm())
|
repo = persistence.NewGenreRepository(log.NewContext(nil), orm.NewOrm())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns all records", func() {
|
It("returns all records", func() {
|
||||||
|
|||||||
@@ -32,18 +32,7 @@ func (r mediaFileRepository) Exists(id string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r mediaFileRepository) Put(m *model.MediaFile) error {
|
func (r mediaFileRepository) Put(m *model.MediaFile) error {
|
||||||
values, _ := toSqlArgs(*m)
|
return r.put(m.ID, m)
|
||||||
update := Update(r.tableName).Where(Eq{"id": m.ID}).SetMap(values)
|
|
||||||
count, err := r.executeSQL(update)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if count > 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
insert := Insert(r.tableName).SetMap(values)
|
|
||||||
_, err = r.executeSQL(insert)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r mediaFileRepository) selectMediaFile(options ...model.QueryOptions) SelectBuilder {
|
func (r mediaFileRepository) selectMediaFile(options ...model.QueryOptions) SelectBuilder {
|
||||||
@@ -65,7 +54,7 @@ func (r mediaFileRepository) GetAll(options ...model.QueryOptions) (model.MediaF
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r mediaFileRepository) FindByAlbum(albumId string) (model.MediaFiles, error) {
|
func (r mediaFileRepository) FindByAlbum(albumId string) (model.MediaFiles, error) {
|
||||||
sel := r.selectMediaFile().Where(Eq{"album_id": albumId})
|
sel := r.selectMediaFile().Where(Eq{"album_id": albumId}).OrderBy("disc_number", "track_number")
|
||||||
var res model.MediaFiles
|
var res model.MediaFiles
|
||||||
err := r.queryAll(sel, &res)
|
err := r.queryAll(sel, &res)
|
||||||
return res, err
|
return res, err
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
@@ -14,7 +15,7 @@ var _ = Describe("MediaRepository", func() {
|
|||||||
var mr model.MediaFileRepository
|
var mr model.MediaFileRepository
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx := context.WithValue(context.Background(), "user", &model.User{ID: "userid"})
|
ctx := context.WithValue(log.NewContext(nil), "user", &model.User{ID: "userid"})
|
||||||
mr = NewMediaFileRepository(ctx, orm.NewOrm())
|
mr = NewMediaFileRepository(ctx, orm.NewOrm())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,13 @@ func TestPersistence(t *testing.T) {
|
|||||||
|
|
||||||
var artistKraftwerk = model.Artist{ID: "2", Name: "Kraftwerk", AlbumCount: 1}
|
var artistKraftwerk = model.Artist{ID: "2", Name: "Kraftwerk", AlbumCount: 1}
|
||||||
var artistBeatles = model.Artist{ID: "3", Name: "The Beatles", AlbumCount: 2}
|
var artistBeatles = model.Artist{ID: "3", Name: "The Beatles", AlbumCount: 2}
|
||||||
|
var testArtists = model.Artists{
|
||||||
|
artistKraftwerk,
|
||||||
|
artistBeatles,
|
||||||
|
}
|
||||||
|
|
||||||
var albumSgtPeppers = model.Album{ID: "1", Name: "Sgt Peppers", Artist: "The Beatles", ArtistID: "3", Genre: "Rock", CoverArtId: "1", CoverArtPath: P("/beatles/1/sgt/a day.mp3"), SongCount: 1}
|
var albumSgtPeppers = model.Album{ID: "1", Name: "Sgt Peppers", Artist: "The Beatles", ArtistID: "3", Genre: "Rock", CoverArtId: "1", CoverArtPath: P("/beatles/1/sgt/a day.mp3"), SongCount: 1, Year: 1967}
|
||||||
var albumAbbeyRoad = model.Album{ID: "2", Name: "Abbey Road", Artist: "The Beatles", ArtistID: "3", Genre: "Rock", CoverArtId: "2", CoverArtPath: P("/beatles/1/come together.mp3"), SongCount: 1}
|
var albumAbbeyRoad = model.Album{ID: "2", Name: "Abbey Road", Artist: "The Beatles", ArtistID: "3", Genre: "Rock", CoverArtId: "2", CoverArtPath: P("/beatles/1/come together.mp3"), SongCount: 1, Year: 1969}
|
||||||
var albumRadioactivity = model.Album{ID: "3", Name: "Radioactivity", Artist: "Kraftwerk", ArtistID: "2", Genre: "Electronic", CoverArtId: "3", CoverArtPath: P("/kraft/radio/radio.mp3"), SongCount: 2, Starred: true}
|
var albumRadioactivity = model.Album{ID: "3", Name: "Radioactivity", Artist: "Kraftwerk", ArtistID: "2", Genre: "Electronic", CoverArtId: "3", CoverArtPath: P("/kraft/radio/radio.mp3"), SongCount: 2, Starred: true}
|
||||||
var testAlbums = model.Albums{
|
var testAlbums = model.Albums{
|
||||||
albumSgtPeppers,
|
albumSgtPeppers,
|
||||||
@@ -81,7 +85,8 @@ func P(path string) string {
|
|||||||
var _ = Describe("Initialize test DB", func() {
|
var _ = Describe("Initialize test DB", func() {
|
||||||
BeforeSuite(func() {
|
BeforeSuite(func() {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
mr := NewMediaFileRepository(nil, o)
|
ctx := log.NewContext(nil)
|
||||||
|
mr := NewMediaFileRepository(ctx, o)
|
||||||
for _, s := range testSongs {
|
for _, s := range testSongs {
|
||||||
err := mr.Put(&s)
|
err := mr.Put(&s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -89,6 +94,22 @@ var _ = Describe("Initialize test DB", func() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alr := NewAlbumRepository(ctx, o)
|
||||||
|
for _, a := range testAlbums {
|
||||||
|
err := alr.Put(&a)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arr := NewArtistRepository(ctx, o)
|
||||||
|
for _, a := range testArtists {
|
||||||
|
err := arr.Put(&a)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, a := range testAnnotations {
|
for _, a := range testAnnotations {
|
||||||
values, _ := toSqlArgs(a)
|
values, _ := toSqlArgs(a)
|
||||||
ins := squirrel.Insert("annotation").SetMap(values)
|
ins := squirrel.Insert("annotation").SetMap(values)
|
||||||
@@ -102,7 +123,7 @@ var _ = Describe("Initialize test DB", func() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pr := NewPlaylistRepository(nil, o)
|
pr := NewPlaylistRepository(ctx, o)
|
||||||
for _, pls := range testPlaylists {
|
for _, pls := range testPlaylists {
|
||||||
err := pr.Put(&pls)
|
err := pr.Put(&pls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -49,18 +49,8 @@ func (r *playlistRepository) Put(p *model.Playlist) error {
|
|||||||
id, _ := uuid.NewRandom()
|
id, _ := uuid.NewRandom()
|
||||||
p.ID = id.String()
|
p.ID = id.String()
|
||||||
}
|
}
|
||||||
values, _ := toSqlArgs(r.fromModel(p))
|
pls := r.fromModel(p)
|
||||||
update := Update(r.tableName).Where(Eq{"id": p.ID}).SetMap(values)
|
return r.put(p.ID, &pls)
|
||||||
count, err := r.executeSQL(update)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if count > 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
insert := Insert(r.tableName).SetMap(values)
|
|
||||||
_, err = r.executeSQL(insert)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *playlistRepository) Get(id string) (*model.Playlist, error) {
|
func (r *playlistRepository) Get(id string) (*model.Playlist, error) {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package persistence
|
package persistence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@@ -13,7 +12,7 @@ var _ = Describe("PlaylistRepository", func() {
|
|||||||
var repo model.PlaylistRepository
|
var repo model.PlaylistRepository
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
repo = NewPlaylistRepository(context.Background(), orm.NewOrm())
|
repo = NewPlaylistRepository(log.NewContext(nil), orm.NewOrm())
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("Count", func() {
|
Describe("Count", func() {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package persistence
|
package persistence
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
|
. "github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@@ -13,7 +12,7 @@ var _ = Describe("Property Repository", func() {
|
|||||||
var pr model.PropertyRepository
|
var pr model.PropertyRepository
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
pr = NewPropertyRepository(context.Background(), orm.NewOrm())
|
pr = NewPropertyRepository(NewContext(nil), orm.NewOrm())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("saves and restore a new property", func() {
|
It("saves and restore a new property", func() {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/deluan/navidrome/log"
|
"github.com/deluan/navidrome/log"
|
||||||
"github.com/deluan/navidrome/model"
|
"github.com/deluan/navidrome/model"
|
||||||
"github.com/deluan/rest"
|
"github.com/deluan/rest"
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sqlRepository struct {
|
type sqlRepository struct {
|
||||||
@@ -131,6 +132,28 @@ func (r sqlRepository) count(countQuery SelectBuilder, options ...model.QueryOpt
|
|||||||
return res.Count, nil
|
return res.Count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *sqlRepository) put(id string, m interface{}) error {
|
||||||
|
values, _ := toSqlArgs(m)
|
||||||
|
if id != "" {
|
||||||
|
update := Update(r.tableName).Where(Eq{"id": id}).SetMap(values)
|
||||||
|
count, err := r.executeSQL(update)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if does not have an id OR could not update (new record with predefined id)
|
||||||
|
if id == "" {
|
||||||
|
rand, _ := uuid.NewRandom()
|
||||||
|
values["id"] = rand.String()
|
||||||
|
}
|
||||||
|
insert := Insert(r.tableName).SetMap(values)
|
||||||
|
_, err := r.executeSQL(insert)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (r sqlRepository) delete(cond Sqlizer) error {
|
func (r sqlRepository) delete(cond Sqlizer) error {
|
||||||
del := Delete(r.tableName).Where(cond)
|
del := Delete(r.tableName).Where(cond)
|
||||||
_, err := r.executeSQL(del)
|
_, err := r.executeSQL(del)
|
||||||
@@ -167,9 +190,11 @@ func (r sqlRepository) parseRestOptions(options ...rest.QueryOptions) model.Quer
|
|||||||
qo.Max = options[0].Max
|
qo.Max = options[0].Max
|
||||||
qo.Offset = options[0].Offset
|
qo.Offset = options[0].Offset
|
||||||
if len(options[0].Filters) > 0 {
|
if len(options[0].Filters) > 0 {
|
||||||
|
filters := And{}
|
||||||
for f, v := range options[0].Filters {
|
for f, v := range options[0].Filters {
|
||||||
qo.Filters = Like{f: fmt.Sprintf("%s%%", v)}
|
qo.Filters = append(filters, Like{f: fmt.Sprintf("%s%%", v)})
|
||||||
}
|
}
|
||||||
|
qo.Filters = filters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return qo
|
return qo
|
||||||
|
|||||||
Reference in New Issue
Block a user