Fix values from annotation table cannot be compared to 0

Solves this issue: https://github.com/navidrome/navidrome/issues/1417#issuecomment-974052454
This commit is contained in:
Deluan 2021-11-19 18:22:33 -05:00
parent 4bf4765442
commit 92c31c961d
3 changed files with 58 additions and 43 deletions

View file

@ -22,15 +22,25 @@ type Criteria struct {
} }
func (c Criteria) OrderBy() string { func (c Criteria) OrderBy() string {
if c.Sort == "" {
c.Sort = "title"
}
f := fieldMap[strings.ToLower(c.Sort)] f := fieldMap[strings.ToLower(c.Sort)]
if f == "" { var mapped string
if f == nil {
log.Error("Invalid field in 'sort' field", "field", c.Sort) log.Error("Invalid field in 'sort' field", "field", c.Sort)
f = c.Sort mapped = c.Sort
} else {
if f.order == "" {
mapped = f.field
} else {
mapped = f.order
}
} }
if c.Order != "" { if c.Order != "" {
f = f + " " + c.Order mapped = mapped + " " + c.Order
} }
return f return mapped
} }
func (c Criteria) ToSql() (sql string, args []interface{}, err error) { func (c Criteria) ToSql() (sql string, args []interface{}, err error) {

View file

@ -8,48 +8,53 @@ import (
"github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/log"
) )
var fieldMap = map[string]string{ var fieldMap = map[string]*mappedField{
"title": "media_file.title", "title": {field: "media_file.title"},
"album": "media_file.album", "album": {field: "media_file.album"},
"artist": "media_file.artist", "artist": {field: "media_file.artist"},
"albumartist": "media_file.album_artist", "albumartist": {field: "media_file.album_artist"},
"hascoverart": "media_file.has_cover_art", "hascoverart": {field: "media_file.has_cover_art"},
"tracknumber": "media_file.track_number", "tracknumber": {field: "media_file.track_number"},
"discnumber": "media_file.disc_number", "discnumber": {field: "media_file.disc_number"},
"year": "media_file.year", "year": {field: "media_file.year"},
"size": "media_file.size", "size": {field: "media_file.size"},
"compilation": "media_file.compilation", "compilation": {field: "media_file.compilation"},
"dateadded": "media_file.created_at", "dateadded": {field: "media_file.created_at"},
"datemodified": "media_file.updated_at", "datemodified": {field: "media_file.updated_at"},
"discsubtitle": "media_file.disc_subtitle", "discsubtitle": {field: "media_file.disc_subtitle"},
"comment": "media_file.comment", "comment": {field: "media_file.comment"},
"lyrics": "media_file.lyrics", "lyrics": {field: "media_file.lyrics"},
"sorttitle": "media_file.sort_title", "sorttitle": {field: "media_file.sort_title"},
"sortalbum": "media_file.sort_album_name", "sortalbum": {field: "media_file.sort_album_name"},
"sortartist": "media_file.sort_artist_name", "sortartist": {field: "media_file.sort_artist_name"},
"sortalbumartist": "media_file.sort_album_artist_name", "sortalbumartist": {field: "media_file.sort_album_artist_name"},
"albumtype": "media_file.mbz_album_type", "albumtype": {field: "media_file.mbz_album_type"},
"albumcomment": "media_file.mbz_album_comment", "albumcomment": {field: "media_file.mbz_album_comment"},
"catalognumber": "media_file.catalog_num", "catalognumber": {field: "media_file.catalog_num"},
"filepath": "media_file.path", "filepath": {field: "media_file.path"},
"filetype": "media_file.suffix", "filetype": {field: "media_file.suffix"},
"duration": "media_file.duration", "duration": {field: "media_file.duration"},
"bitrate": "media_file.bit_rate", "bitrate": {field: "media_file.bit_rate"},
"bpm": "media_file.bpm", "bpm": {field: "media_file.bpm"},
"channels": "media_file.channels", "channels": {field: "media_file.channels"},
"genre": "genre.name", "genre": {field: "genre.name"},
"loved": "annotation.starred", "loved": {field: "annotation.starred"},
"dateloved": "annotation.starred_at", "dateloved": {field: "annotation.starred_at"},
"lastplayed": "annotation.play_date", "lastplayed": {field: "annotation.play_date"},
"playcount": "annotation.play_count", "playcount": {field: "COALESCE(annotation.play_count, 0)", order: "annotation.play_count"},
"rating": "annotation.rating", "rating": {field: "COALESCE(annotation.rating, 0)", order: "annotation.rating"},
}
type mappedField struct {
field string
order string
} }
func mapFields(expr map[string]interface{}) map[string]interface{} { func mapFields(expr map[string]interface{}) map[string]interface{} {
m := make(map[string]interface{}) m := make(map[string]interface{})
for f, v := range expr { for f, v := range expr {
if dbf, found := fieldMap[strings.ToLower(f)]; found { if dbf := fieldMap[strings.ToLower(f)]; dbf != nil {
m[dbf] = v m[dbf.field] = v
} else { } else {
log.Error("Invalid field in criteria", "field", f) log.Error("Invalid field in criteria", "field", f)
} }

View file

@ -23,8 +23,8 @@ var _ = Describe("Operators", func() {
Entry("is [string]", Is{"title": "Low Rider"}, "media_file.title = ?", "Low Rider"), Entry("is [string]", Is{"title": "Low Rider"}, "media_file.title = ?", "Low Rider"),
Entry("is [bool]", Is{"loved": true}, "annotation.starred = ?", true), Entry("is [bool]", Is{"loved": true}, "annotation.starred = ?", true),
Entry("isNot", IsNot{"title": "Low Rider"}, "media_file.title <> ?", "Low Rider"), Entry("isNot", IsNot{"title": "Low Rider"}, "media_file.title <> ?", "Low Rider"),
Entry("gt", Gt{"playCount": 10}, "annotation.play_count > ?", 10), Entry("gt", Gt{"playCount": 10}, "COALESCE(annotation.play_count, 0) > ?", 10),
Entry("lt", Lt{"playCount": 10}, "annotation.play_count < ?", 10), Entry("lt", Lt{"playCount": 10}, "COALESCE(annotation.play_count, 0) < ?", 10),
Entry("contains", Contains{"title": "Low Rider"}, "media_file.title LIKE ?", "%Low Rider%"), Entry("contains", Contains{"title": "Low Rider"}, "media_file.title LIKE ?", "%Low Rider%"),
Entry("notContains", NotContains{"title": "Low Rider"}, "media_file.title NOT LIKE ?", "%Low Rider%"), Entry("notContains", NotContains{"title": "Low Rider"}, "media_file.title NOT LIKE ?", "%Low Rider%"),
Entry("startsWith", StartsWith{"title": "Low Rider"}, "media_file.title LIKE ?", "Low Rider%"), Entry("startsWith", StartsWith{"title": "Low Rider"}, "media_file.title LIKE ?", "Low Rider%"),