// Copyright (C) 2019-2022 Chrystian Huot // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see package main import ( "database/sql" "encoding/json" "fmt" "sort" "strings" ) type Unit struct { Id int `json:"id"` Label string `json:"label"` Order uint `json:"order"` } func (unit *Unit) FromMap(m map[string]interface{}) { switch v := m["id"].(type) { case float64: unit.Id = int(v) } switch v := m["label"].(type) { case string: unit.Label = v } } type Units []*Unit func (units *Units) Add(id int, label string) *Units { found := false for _, u := range *units { if u.Id == id { found = true break } } if !found { *units = append(*units, &Unit{Id: id, Label: label}) } return units } func (units *Units) FromMap(f []interface{}) { *units = Units{} for _, r := range f { switch m := r.(type) { case map[string]interface{}: unit := &Unit{} unit.FromMap(m) *units = append(*units, unit) } } } func (u *Units) Merge(units *Units) { for _, v := range *units { u.Add(v.Id, v.Label) } } func (units *Units) Read(db *Database, systemId uint) error { var ( err error rows *sql.Rows ) *units = Units{} formatError := func(err error) error { return fmt.Errorf("units.read: %v", err) } if rows, err = db.Sql.Query("select `id`, `label`, `order` from `rdioScannerUnits` where `systemId` = ?", systemId); err != nil { return formatError(err) } for rows.Next() { unit := &Unit{} if err = rows.Scan(&unit.Id, &unit.Label, &unit.Order); err != nil { break } *units = append(*units, unit) } rows.Close() if err != nil { return formatError(err) } sort.Slice(*units, func(i int, j int) bool { return (*units)[i].Order < (*units)[j].Order }) return nil } func (units *Units) Write(db *Database, systemId uint) error { var ( count uint err error ids = []int{} rows *sql.Rows ) formatError := func(err error) error { return fmt.Errorf("units.write: %v", err) } for _, unit := range *units { if err = db.Sql.QueryRow("select count(*) from `rdioScannerUnits` where `id` = ? and `systemId` = ?", unit.Id, systemId).Scan(&count); err != nil { break } if count == 0 { if _, err = db.Sql.Exec("insert into `rdioScannerUnits` (`id`, `label`, `order`, `systemId`) values (?, ?, ?, ?)", unit.Id, unit.Label, unit.Order, systemId); err != nil { break } } else if _, err = db.Sql.Exec("update `rdioScannerUnits` set `label` = ?, `order` = ? where `id` = ? and `systemId` = ?", unit.Label, unit.Order, unit.Id, systemId); err != nil { break } } if err != nil { return formatError(err) } if rows, err = db.Sql.Query("select `id` from `rdioScannerUnits` where `systemId` = ?", systemId); err != nil { return formatError(err) } for rows.Next() { var id int rows.Scan(&id) remove := true for _, unit := range *units { if unit.Id == id { remove = false break } } if remove { ids = append(ids, id) } } rows.Close() if err != nil { return formatError(err) } if len(ids) > 0 { if b, err := json.Marshal(ids); err == nil { s := string(b) s = strings.ReplaceAll(s, "[", "(") s = strings.ReplaceAll(s, "]", ")") q := fmt.Sprintf("delete from `rdioScannerUnits` where `id` in %v and `systemId` = %v", s, systemId) if _, err = db.Sql.Exec(q); err != nil { return formatError(err) } } } return nil }