songs.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package repository
  2. import (
  3. "errors"
  4. "github.com/felamaslen/gmus-backend/pkg/read"
  5. "github.com/jmoiron/sqlx"
  6. "github.com/lib/pq"
  7. )
  8. const BATCH_SIZE = 100
  9. func SelectSong(db *sqlx.DB, id int) (song *read.Song, err error) {
  10. var songs []*read.Song
  11. err = db.Select(&songs, `
  12. select
  13. track_number
  14. ,title
  15. ,artist
  16. ,album
  17. ,duration
  18. ,modified_date
  19. ,base_path
  20. ,relative_path
  21. from songs
  22. where id = $1
  23. `, int64(id))
  24. if len(songs) == 0 {
  25. err = errors.New("No such ID")
  26. } else {
  27. song = songs[0]
  28. }
  29. return
  30. }
  31. func SelectPagedArtists(db *sqlx.DB, limit int, offset int) (artists *[]string, err error) {
  32. artists = &[]string{}
  33. err = db.Select(artists, `
  34. select distinct artist
  35. from songs
  36. order by artist
  37. limit $1
  38. offset $2
  39. `, limit, offset)
  40. return
  41. }
  42. type CountRow struct {
  43. Count int `db:"count"`
  44. }
  45. func SelectArtistCount(db *sqlx.DB) (count int, err error) {
  46. var countRow CountRow
  47. err = db.QueryRowx(`
  48. select count(*) as count from (
  49. select distinct artist from songs
  50. ) distinct_artists
  51. `).StructScan(&countRow)
  52. count = countRow.Count
  53. return
  54. }
  55. func SelectAllArtists(db *sqlx.DB) (artists *[]string, err error) {
  56. artists = &[]string{}
  57. err = db.Select(artists, `select distinct artist from songs order by artist`)
  58. return
  59. }
  60. func SelectAlbumsByArtist(db *sqlx.DB, artist string) (albums *[]string, err error) {
  61. albums = &[]string{}
  62. err = db.Select(albums, `
  63. select distinct album
  64. from songs
  65. where artist = $1
  66. order by album
  67. `, artist)
  68. return
  69. }
  70. func SelectSongsByArtist(db *sqlx.DB, artist string) (songs *[]*read.SongExternal, err error) {
  71. songs = &[]*read.SongExternal{}
  72. err = db.Select(songs, `
  73. select
  74. id
  75. ,track_number
  76. ,title
  77. ,artist
  78. ,album
  79. ,duration
  80. from songs
  81. where artist = $1
  82. order by album, track_number, title
  83. `, artist)
  84. return
  85. }
  86. func BatchUpsertSongs(db *sqlx.DB, batch *[BATCH_SIZE]*read.Song, batchSize int) error {
  87. var trackNumbers pq.Int64Array
  88. var titles pq.StringArray
  89. var artists pq.StringArray
  90. var albums pq.StringArray
  91. var durations pq.Int64Array
  92. var modifiedDates pq.Int64Array
  93. var basePaths pq.StringArray
  94. var relativePaths pq.StringArray
  95. for i := 0; i < batchSize; i++ {
  96. trackNumbers = append(trackNumbers, int64((*batch)[i].TrackNumber))
  97. titles = append(titles, (*batch)[i].Title)
  98. artists = append(artists, (*batch)[i].Artist)
  99. albums = append(albums, (*batch)[i].Album)
  100. durations = append(durations, int64((*batch)[i].Duration))
  101. modifiedDates = append(modifiedDates, (*batch)[i].ModifiedDate)
  102. basePaths = append(basePaths, (*batch)[i].BasePath)
  103. relativePaths = append(relativePaths, (*batch)[i].RelativePath)
  104. }
  105. _, err := db.Exec(
  106. `
  107. insert into songs (
  108. track_number
  109. ,title
  110. ,artist
  111. ,album
  112. ,duration
  113. ,modified_date
  114. ,base_path
  115. ,relative_path
  116. )
  117. select * from unnest(
  118. $1::integer[]
  119. ,$2::varchar[]
  120. ,$3::varchar[]
  121. ,$4::varchar[]
  122. ,$5::integer[]
  123. ,$6::bigint[]
  124. ,$7::varchar[]
  125. ,$8::varchar[]
  126. )
  127. on conflict (base_path, relative_path) do update
  128. set
  129. track_number = excluded.track_number
  130. ,title = excluded.title
  131. ,artist = excluded.artist
  132. ,album = excluded.album
  133. ,duration = excluded.duration
  134. ,modified_date = excluded.modified_date
  135. `,
  136. trackNumbers,
  137. titles,
  138. artists,
  139. albums,
  140. durations,
  141. modifiedDates,
  142. basePaths,
  143. relativePaths,
  144. )
  145. return err
  146. }