navidrome/persistence/sql_genres.go

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

107 lines
2.6 KiB
Go
Raw Permalink Normal View History

2021-07-16 17:03:28 +02:00
package persistence
import (
. "github.com/Masterminds/squirrel"
"github.com/navidrome/navidrome/model"
"github.com/navidrome/navidrome/utils/slice"
2021-07-16 17:03:28 +02:00
)
2021-07-17 02:20:33 +02:00
func (r sqlRepository) withGenres(sql SelectBuilder) SelectBuilder {
return sql.LeftJoin(r.tableName + "_genres ag on " + r.tableName + ".id = ag." + r.tableName + "_id").
LeftJoin("genre on ag.genre_id = genre.id")
}
func (r *sqlRepository) updateGenres(id string, genres model.Genres) error {
tableName := r.getTableName()
del := Delete(tableName + "_genres").Where(Eq{tableName + "_id": id})
2021-07-16 17:03:28 +02:00
_, err := r.executeSQL(del)
if err != nil {
return err
}
if len(genres) == 0 {
return nil
}
var genreIds []string
2021-07-16 17:03:28 +02:00
for _, g := range genres {
genreIds = append(genreIds, g.ID)
2021-07-16 17:03:28 +02:00
}
err = slice.RangeByChunks(genreIds, 100, func(ids []string) error {
2021-09-29 16:54:54 +02:00
ins := Insert(tableName+"_genres").Columns("genre_id", tableName+"_id")
for _, gid := range ids {
ins = ins.Values(gid, id)
}
_, err = r.executeSQL(ins)
return err
})
2021-07-16 17:03:28 +02:00
return err
}
type baseRepository interface {
queryAll(SelectBuilder, any, ...model.QueryOptions) error
getTableName() string
}
2021-07-16 17:03:28 +02:00
type modelWithGenres interface {
model.Album | model.Artist | model.MediaFile
}
2021-07-16 17:03:28 +02:00
func getID[T modelWithGenres](item T) string {
switch v := any(item).(type) {
case model.Album:
return v.ID
case model.Artist:
return v.ID
case model.MediaFile:
return v.ID
}
return ""
2021-07-16 17:03:28 +02:00
}
2021-07-16 23:15:34 +02:00
func appendGenre[T modelWithGenres](item *T, genre model.Genre) {
switch v := any(item).(type) {
case *model.Album:
v.Genres = append(v.Genres, genre)
case *model.Artist:
v.Genres = append(v.Genres, genre)
case *model.MediaFile:
v.Genres = append(v.Genres, genre)
2021-07-16 23:15:34 +02:00
}
}
2021-07-16 23:15:34 +02:00
func loadGenres[T modelWithGenres](r baseRepository, ids []string, items map[string]*T) error {
tableName := r.getTableName()
return slice.RangeByChunks(ids, 900, func(ids []string) error {
sql := Select("genre.*", tableName+"_id as item_id").From("genre").
Join(tableName+"_genres ig on genre.id = ig.genre_id").
OrderBy(tableName+"_id", "ig.rowid").Where(Eq{tableName + "_id": ids})
var genres []struct {
model.Genre
ItemID string
}
err := r.queryAll(sql, &genres)
if err != nil {
return err
}
for _, g := range genres {
appendGenre(items[g.ItemID], g.Genre)
}
return nil
})
2021-07-16 23:15:34 +02:00
}
2021-07-17 00:18:22 +02:00
func loadAllGenres[T modelWithGenres](r baseRepository, items []T) error {
// Map references to items by ID and collect all IDs
m := map[string]*T{}
2021-07-17 00:18:22 +02:00
var ids []string
for i := range items {
item := &(items)[i]
id := getID(*item)
ids = append(ids, id)
m[id] = item
2021-07-17 00:18:22 +02:00
}
return loadGenres(r, ids, m)
2021-07-17 00:18:22 +02:00
}