Completed database types
This commit is contained in:
parent
be009f32c7
commit
665f622d00
|
@ -3,7 +3,7 @@
|
|||
Music library and metadata database.
|
||||
|
||||
## Dependencies
|
||||
### Go >= 1.17
|
||||
### Go >= 1.18
|
||||
### [Hibiki](https://git.gammaspectra.live/S.O.N.G/Hibiki) dependencies
|
||||
Hibiki is an implementation of Panako in Go, and other audio utilities.
|
||||
|
||||
|
|
210
database/album.go
Normal file
210
database/album.go
Normal file
|
@ -0,0 +1,210 @@
|
|||
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)
|
||||
}
|
|
@ -6,22 +6,62 @@ import (
|
|||
)
|
||||
|
||||
type Artist struct {
|
||||
DatabaseType
|
||||
id int64
|
||||
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 artist DEFAULT VALUES RETURNING id;")
|
||||
rows, err := db.Query("INSERT INTO artists DEFAULT VALUES RETURNING id;")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Next()
|
||||
var id int64
|
||||
var id int
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
return nil
|
||||
|
@ -54,7 +94,7 @@ func GetArtistsFromDatabaseByName(db *Database, name string) (artists []*Artist)
|
|||
return
|
||||
}
|
||||
|
||||
func GetArtistFromDatabase(db *Database, id int64) *Artist {
|
||||
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
|
||||
|
@ -70,7 +110,7 @@ func GetArtistFromDatabase(db *Database, id int64) *Artist {
|
|||
|
||||
func GetArtistFromRow(db *Database, row *sql.Rows) (*Artist, error) {
|
||||
r := &Artist{
|
||||
DatabaseType: DatabaseType{
|
||||
Type: Type{
|
||||
db: db,
|
||||
},
|
||||
}
|
||||
|
@ -81,7 +121,7 @@ func GetArtistFromRow(db *Database, row *sql.Rows) (*Artist, error) {
|
|||
return r, nil
|
||||
}
|
||||
|
||||
func (r *Artist) GetId() int64 {
|
||||
func (r *Artist) GetId() int {
|
||||
return r.id
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
type Release struct {
|
||||
DatabaseType
|
||||
Type
|
||||
id int64
|
||||
identifiers []string
|
||||
metadata []byte
|
||||
|
@ -60,7 +60,7 @@ func GetReleaseFromDatabase(db *Database, id int64) *Release {
|
|||
|
||||
func GetReleaseFromRow(db *Database, row *sql.Rows) (*Release, error) {
|
||||
r := &Release{
|
||||
DatabaseType: DatabaseType{
|
||||
Type: Type{
|
||||
db: db,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ func (h ResourceHashIdentifier) ToBytes() []byte {
|
|||
}
|
||||
|
||||
type Resource struct {
|
||||
DatabaseType
|
||||
Type
|
||||
id int64
|
||||
hash ResourceHashIdentifier
|
||||
size int64
|
||||
|
@ -79,7 +79,7 @@ func GetResourceFromDatabaseByHash(db *Database, hash ResourceHashIdentifier) *R
|
|||
|
||||
func GetResourceFromRow(db *Database, row *sql.Rows) (*Resource, error) {
|
||||
r := &Resource{
|
||||
DatabaseType: DatabaseType{
|
||||
Type: Type{
|
||||
db: db,
|
||||
},
|
||||
}
|
||||
|
|
220
database/song.go
Normal file
220
database/song.go
Normal file
|
@ -0,0 +1,220 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type Song struct {
|
||||
Type
|
||||
id int64
|
||||
resource int64
|
||||
cover int64
|
||||
album int
|
||||
metadata []byte
|
||||
}
|
||||
|
||||
func InsertSongToDatabase(db *Database, resourceId int64, names map[string]string) *Song {
|
||||
|
||||
//TODO: do it in single tx
|
||||
|
||||
rows, err := db.Query("INSERT INTO songs (resource) VALUES ($1) RETURNING id;", resourceId)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Next()
|
||||
var id int64
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
song := GetSongFromDatabase(db, id)
|
||||
if song == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for k, n := range names {
|
||||
song.AddName(k, n)
|
||||
}
|
||||
|
||||
return song
|
||||
}
|
||||
|
||||
func GetSongsFromDatabaseByName(db *Database, name string) (songs []*Song) {
|
||||
rows, err := db.Query("SELECT id, resource, cover, album, metadata FROM songs WHERE id IN(SELECT song FROM songs_names WHERE name ILIKE $1);", name)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
song, err := GetSongFromRow(db, rows)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
songs = append(songs, song)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetSongFromDatabase(db *Database, id int64) *Song {
|
||||
rows, err := db.Query("SELECT id, resource, cover, album, metadata FROM songs WHERE id = $1;", id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Next()
|
||||
r, err := GetSongFromRow(db, rows)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetSongFromRow(db *Database, row *sql.Rows) (*Song, error) {
|
||||
r := &Song{
|
||||
Type: Type{
|
||||
db: db,
|
||||
},
|
||||
}
|
||||
var cover sql.NullInt64
|
||||
err := row.Scan(&r.id, &r.resource, &cover, &r.album, &r.metadata)
|
||||
|
||||
if cover.Valid {
|
||||
r.cover = cover.Int64
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *Song) GetId() int64 {
|
||||
return r.id
|
||||
}
|
||||
|
||||
func (r *Song) GetResource() *Resource {
|
||||
return GetResourceFromDatabase(r.db, r.resource)
|
||||
}
|
||||
|
||||
func (r *Song) GetCover() *Resource {
|
||||
if r.cover == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return GetResourceFromDatabase(r.db, r.cover)
|
||||
}
|
||||
|
||||
func (r *Song) SetCover(resource *Resource) {
|
||||
if resource == nil {
|
||||
r.db.Exec("UPDATE songs SET cover = NULL WHERE id = $1;", r.id)
|
||||
return
|
||||
}
|
||||
|
||||
r.db.Exec("UPDATE songs SET cover = $2 WHERE id = $1;", r.id, resource.id)
|
||||
}
|
||||
|
||||
func (r *Song) GetAlbum() *Album {
|
||||
if r.album == 0 {
|
||||
return nil
|
||||
}
|
||||
return GetAlbumFromDatabase(r.db, r.album)
|
||||
}
|
||||
|
||||
func (r *Song) SetAlbum(album *Album) {
|
||||
if album == nil {
|
||||
r.db.Exec("UPDATE songs SET album = NULL WHERE id = $1;", r.id)
|
||||
return
|
||||
}
|
||||
|
||||
r.db.Exec("UPDATE songs SET album = $2 WHERE id = $1;", r.id, album.id)
|
||||
}
|
||||
|
||||
func (r *Song) GetNames() map[string]string {
|
||||
|
||||
result := make(map[string]string)
|
||||
|
||||
rows, err := r.db.Query("SELECT kind, name FROM song_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 *Song) RemoveName(kind string) {
|
||||
r.db.Exec("DELETE FROM song_names WHERE id = $1 AND kind = $2;", r.id, kind)
|
||||
}
|
||||
|
||||
func (r *Song) AddName(kind, name string) {
|
||||
r.db.Exec("INSERT INTO song_names (song, kind, name) VALUES ($1, $2, $3) ON CONFLICT (song, kind) DO UPDATE SET name = $3;", r.id, kind, name)
|
||||
}
|
||||
|
||||
func (r *Song) GetMetadata() (result map[string]interface{}) {
|
||||
json.Unmarshal(r.metadata, &result)
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *Song) SetMetadata(value map[string]interface{}) {
|
||||
r.metadata, _ = json.Marshal(value)
|
||||
r.db.Exec("UPDATE songs SET metadata = $2::jsonb WHERE id = $1;", r.id, r.metadata)
|
||||
}
|
||||
|
||||
func (r *Song) GetTags() (tags []*Tag) {
|
||||
rows, err := r.db.Query("SELECT id, name FROM tags WHERE id IN(SELECT tag FROM song_taggings WHERE song = $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 *Song) RemoveTag(tag *Tag) {
|
||||
r.db.Exec("DELETE FROM song_taggings WHERE song = $1 AND tag = $2;", r.id, tag.id)
|
||||
}
|
||||
|
||||
func (r *Song) AddTag(tag *Tag) {
|
||||
r.db.Exec("INSERT INTO song_taggings (tag, song) VALUES ($2, $1) ON CONFLICT (tag, song) DO NOTHING;", r.id, tag.id)
|
||||
}
|
||||
|
||||
func (r *Song) GetArtists() (artists []*SongArtist) {
|
||||
rows, err := r.db.Query("SELECT artist as id, (SELECT artists.metadata FROM artists WHERE artists.id = song_artists.artist) as metadata, kind FROM song_artists WHERE song_artists.song = $1;", r.id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
artist, err := GetSongArtistFromRow(r.db, rows)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
artists = append(artists, artist)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Song) RemoveArtist(artist *SongArtist) {
|
||||
r.db.Exec("DELETE FROM song_artists WHERE song = $1 AND kind = $3 AND tag = $2;", r.id, artist.id, artist.kind)
|
||||
}
|
||||
|
||||
func (r *Song) AddArtist(artist *SongArtist) {
|
||||
r.db.Exec("INSERT INTO song_artists (song, artist, kind) VALUES ($1, $2, $3) ON CONFLICT (song, artist, kind) DO NOTHING;", r.id, artist.id, artist.kind)
|
||||
}
|
104
database/tag.go
Normal file
104
database/tag.go
Normal file
|
@ -0,0 +1,104 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type Tag struct {
|
||||
Type
|
||||
id int64
|
||||
name string
|
||||
}
|
||||
|
||||
func InsertTagToDatabase(db *Database, name string) *Tag {
|
||||
|
||||
rows, err := db.Query("INSERT INTO tags (name) VALUES ($1) RETURNING id;", name)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Next()
|
||||
var id int64
|
||||
err = rows.Scan(&id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
tag := GetTagFromDatabase(db, id)
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
func GetOrCreateTagFromDatabaseByName(db *Database, name string) (tag *Tag) {
|
||||
tag = GetTagFromDatabaseByName(db, name)
|
||||
if tag == nil {
|
||||
tag = InsertTagToDatabase(db, name)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetTagFromDatabaseByName(db *Database, name string) *Tag {
|
||||
rows, err := db.Query("SELECT id, name FROM tags WHERE name ILIKE $1;", name)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Next()
|
||||
r, err := GetTagFromRow(db, rows)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetTagFromDatabase(db *Database, id int64) *Tag {
|
||||
rows, err := db.Query("SELECT id, name FROM tags WHERE id = $1;", id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
rows.Next()
|
||||
r, err := GetTagFromRow(db, rows)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetTagFromRow(db *Database, row *sql.Rows) (*Tag, error) {
|
||||
r := &Tag{
|
||||
Type: Type{
|
||||
db: db,
|
||||
},
|
||||
}
|
||||
err := row.Scan(&r.id, &r.name)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *Tag) GetId() int64 {
|
||||
return r.id
|
||||
}
|
||||
|
||||
func (r *Tag) GetName() string {
|
||||
return r.name
|
||||
}
|
||||
|
||||
func (r *Tag) GetAlbums() (albums []*Album) {
|
||||
rows, err := r.db.Query("SELECT id, cover, identifiers, metadata FROM albums WHERE id IN(SELECT album FROM album_taggings WHERE tag = $1);", r.id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
album, err := GetAlbumFromRow(r.db, rows)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
albums = append(albums, album)
|
||||
}
|
||||
return
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
package database
|
||||
|
||||
type DatabaseType struct {
|
||||
type Type struct {
|
||||
db *Database
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue