METANOIA/database/album.go

211 lines
4.7 KiB
Go

package database
import (
"database/sql"
"encoding/json"
"github.com/lib/pq"
)
type Album struct {
Type
id int
cover int64
identifiers []string
metadata []byte
}
func InsertAlbumToDatabase(db *Database, names map[string]string) *Album {
//TODO: do it in single tx
rows, err := db.Query("INSERT INTO albums 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
}
album := GetAlbumFromDatabase(db, id)
if album == nil {
return nil
}
for k, n := range names {
album.AddName(k, n)
}
return album
}
func GetAlbumsFromDatabaseByName(db *Database, name string) (albums []*Album) {
rows, err := db.Query("SELECT id, cover, identifiers, metadata FROM albums WHERE id IN(SELECT album FROM albums_names WHERE name ILIKE $1);", name)
if err != nil {
return nil
}
defer rows.Close()
for rows.Next() {
album, err := GetAlbumFromRow(db, rows)
if err != nil {
break
}
albums = append(albums, album)
}
return
}
func GetAlbumFromDatabase(db *Database, id int) *Album {
rows, err := db.Query("SELECT id, cover, identifiers, metadata FROM albums WHERE id = $1;", id)
if err != nil {
return nil
}
defer rows.Close()
rows.Next()
r, err := GetAlbumFromRow(db, rows)
if err != nil {
return nil
}
return r
}
func GetAlbumFromRow(db *Database, row *sql.Rows) (*Album, error) {
r := &Album{
Type: Type{
db: db,
},
}
var cover sql.NullInt64
err := row.Scan(&r.id, &cover, pq.Array(&r.identifiers), &r.metadata)
if cover.Valid {
r.cover = cover.Int64
}
if err != nil {
return nil, err
}
return r, nil
}
func (r *Album) GetId() int {
return r.id
}
func (r *Album) GetCover() *Resource {
if r.cover == 0 {
return nil
}
return GetResourceFromDatabase(r.db, r.cover)
}
func (r *Album) SetCover(resource *Resource) {
if resource == nil {
r.db.Exec("UPDATE albums SET cover = NULL WHERE id = $1;", r.id)
return
}
r.db.Exec("UPDATE albums SET cover = $2 WHERE id = $1;", r.id, resource.id)
}
func (r *Album) GetNames() map[string]string {
result := make(map[string]string)
rows, err := r.db.Query("SELECT kind, name FROM albums_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 *Album) RemoveName(kind string) {
r.db.Exec("DELETE FROM albums_names WHERE id = $1 AND kind = $2;", r.id, kind)
}
func (r *Album) AddName(kind, name string) {
r.db.Exec("INSERT INTO albums_names (album, kind, name) VALUES ($1, $2, $3) ON CONFLICT (album, kind) DO UPDATE SET name = $3;", r.id, kind, name)
}
func (r *Album) GetMetadata() (result map[string]interface{}) {
json.Unmarshal(r.metadata, &result)
return result
}
func (r *Album) SetMetadata(value map[string]interface{}) {
r.metadata, _ = json.Marshal(value)
r.db.Exec("UPDATE albums SET metadata = $2::jsonb WHERE id = $1;", r.id, r.metadata)
}
func (r *Album) GetIdentifiers() []string {
return r.identifiers
}
func (r *Album) SetIdentifiers(identifiers []string) {
r.identifiers = identifiers
r.db.Exec("UPDATE albums SET identifiers = $2 WHERE id = $1;", r.id, pq.Array(r.identifiers))
}
func (r *Album) GetTags() (tags []*Tag) {
rows, err := r.db.Query("SELECT id, name FROM tags WHERE id IN(SELECT tag FROM album_taggings WHERE album = $1);", r.id)
if err != nil {
return nil
}
defer rows.Close()
for rows.Next() {
tag, err := GetTagFromRow(r.db, rows)
if err != nil {
break
}
tags = append(tags, tag)
}
return
}
func (r *Album) RemoveTag(tag *Tag) {
r.db.Exec("DELETE FROM album_taggings WHERE album = $1 AND tag = $2;", r.id, tag.id)
}
func (r *Album) AddTag(tag *Tag) {
r.db.Exec("INSERT INTO album_taggings (tag, album) VALUES ($2, $1) ON CONFLICT (tag, album) DO NOTHING;", r.id, tag.id)
}
func (r *Album) GetArtists() (artists []*AlbumArtist) {
rows, err := r.db.Query("SELECT artist as id, (SELECT artists.metadata FROM artists WHERE artists.id = album_artists.artist) as metadata, kind FROM album_artists WHERE song_artists.album = $1;", r.id)
if err != nil {
return nil
}
defer rows.Close()
for rows.Next() {
artist, err := GetAlbumArtistFromRow(r.db, rows)
if err != nil {
break
}
artists = append(artists, artist)
}
return
}
func (r *Album) RemoveArtist(artist *AlbumArtist) {
r.db.Exec("DELETE FROM album_artists WHERE album = $1 AND kind = $3 AND tag = $2;", r.id, artist.id, artist.kind)
}
func (r *Album) AddArtist(artist *AlbumArtist) {
r.db.Exec("INSERT INTO album_artists (album, artist, kind) VALUES ($1, $2, $3) ON CONFLICT (album, artist, kind) DO NOTHING;", r.id, artist.id, artist.kind)
}