167 lines
3.1 KiB
Go
167 lines
3.1 KiB
Go
package database
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
)
|
|
|
|
type Artist struct {
|
|
Type
|
|
id int
|
|
metadata []byte
|
|
}
|
|
|
|
type SongArtist struct {
|
|
Artist
|
|
kind string
|
|
}
|
|
|
|
type AlbumArtist struct {
|
|
Artist
|
|
kind string
|
|
}
|
|
|
|
func GetSongArtistFromRow(db *Database, row *sql.Rows) (*SongArtist, error) {
|
|
r := &SongArtist{
|
|
Artist: Artist{
|
|
Type: Type{
|
|
db: db,
|
|
},
|
|
},
|
|
}
|
|
err := row.Scan(&r.id, &r.metadata, &r.kind)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func GetAlbumArtistFromRow(db *Database, row *sql.Rows) (*AlbumArtist, error) {
|
|
r := &AlbumArtist{
|
|
Artist: Artist{
|
|
Type: Type{
|
|
db: db,
|
|
},
|
|
},
|
|
}
|
|
err := row.Scan(&r.id, &r.metadata, &r.kind)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func InsertArtistToDatabase(db *Database, names map[string]string) *Artist {
|
|
|
|
//TODO: do it in single tx
|
|
|
|
rows, err := db.Query("INSERT INTO artists DEFAULT VALUES RETURNING id;")
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer rows.Close()
|
|
rows.Next()
|
|
var id int
|
|
err = rows.Scan(&id)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
artist := GetArtistFromDatabase(db, id)
|
|
if artist == nil {
|
|
return nil
|
|
}
|
|
|
|
for k, n := range names {
|
|
artist.AddName(k, n)
|
|
}
|
|
|
|
return artist
|
|
}
|
|
|
|
func GetArtistsFromDatabaseByName(db *Database, name string) (artists []*Artist) {
|
|
rows, err := db.Query("SELECT id, metadata FROM artists WHERE id IN(SELECT artist FROM artists_names WHERE name ILIKE $1);", name)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
artist, err := GetArtistFromRow(db, rows)
|
|
if err != nil {
|
|
break
|
|
}
|
|
artists = append(artists, artist)
|
|
}
|
|
return
|
|
}
|
|
|
|
func GetArtistFromDatabase(db *Database, id int) *Artist {
|
|
rows, err := db.Query("SELECT id, metadata FROM artists WHERE id = $1;", id)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer rows.Close()
|
|
rows.Next()
|
|
r, err := GetArtistFromRow(db, rows)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return r
|
|
}
|
|
|
|
func GetArtistFromRow(db *Database, row *sql.Rows) (*Artist, error) {
|
|
r := &Artist{
|
|
Type: Type{
|
|
db: db,
|
|
},
|
|
}
|
|
err := row.Scan(&r.id, &r.metadata)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func (r *Artist) GetId() int {
|
|
return r.id
|
|
}
|
|
|
|
func (r *Artist) GetNames() map[string]string {
|
|
|
|
result := make(map[string]string)
|
|
|
|
rows, err := r.db.Query("SELECT kind, name FROM artists_names WHERE id $1;", r.id)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer rows.Close()
|
|
for rows.Next() {
|
|
var kind string
|
|
var name string
|
|
err = rows.Scan(&kind, &name)
|
|
if err != nil {
|
|
break
|
|
}
|
|
result[kind] = name
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (r *Artist) RemoveName(kind string) {
|
|
r.db.Exec("DELETE FROM artists_names WHERE id = $1 AND kind = $2;", r.id, kind)
|
|
}
|
|
|
|
func (r *Artist) AddName(kind, name string) {
|
|
r.db.Exec("INSERT INTO artists_names (artist, kind, name) VALUES ($1, $2, $3) ON CONFLICT (artist, kind) DO UPDATE SET name = $3;", r.id, kind, name)
|
|
}
|
|
|
|
func (r *Artist) GetMetadata() (result map[string]interface{}) {
|
|
json.Unmarshal(r.metadata, &result)
|
|
return result
|
|
}
|
|
|
|
func (r *Artist) SetMetadata(value map[string]interface{}) {
|
|
r.metadata, _ = json.Marshal(value)
|
|
r.db.Exec("UPDATE artists SET metadata = $2::jsonb WHERE id = $1;", r.id, r.metadata)
|
|
}
|