songs.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package repository
  2. import (
  3. "errors"
  4. "github.com/felamaslen/go-music-player/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 SelectAlbumsByArtist(db *sqlx.DB, artist string) (albums *[]string, err error) {
  56. albums = &[]string{}
  57. err = db.Select(albums, `
  58. select distinct album
  59. from songs
  60. where artist = $1
  61. order by album
  62. `, artist)
  63. return
  64. }
  65. func SelectSongsByArtist(db *sqlx.DB, artist string) (songs *[]*read.SongExternal, err error) {
  66. songs = &[]*read.SongExternal{}
  67. err = db.Select(songs, `
  68. select
  69. id
  70. ,track_number
  71. ,title
  72. ,artist
  73. ,album
  74. ,duration
  75. from songs
  76. where artist = $1
  77. order by track_number, title, album
  78. `, artist)
  79. return
  80. }
  81. func BatchUpsertSongs(db *sqlx.DB, batch *[BATCH_SIZE]*read.Song, batchSize int) error {
  82. var trackNumbers pq.Int64Array
  83. var titles pq.StringArray
  84. var artists pq.StringArray
  85. var albums pq.StringArray
  86. var durations pq.Int64Array
  87. var modifiedDates pq.Int64Array
  88. var basePaths pq.StringArray
  89. var relativePaths pq.StringArray
  90. for i := 0; i < batchSize; i++ {
  91. trackNumbers = append(trackNumbers, int64((*batch)[i].TrackNumber))
  92. titles = append(titles, (*batch)[i].Title)
  93. artists = append(artists, (*batch)[i].Artist)
  94. albums = append(albums, (*batch)[i].Album)
  95. durations = append(durations, int64((*batch)[i].Duration))
  96. modifiedDates = append(modifiedDates, (*batch)[i].ModifiedDate)
  97. basePaths = append(basePaths, (*batch)[i].BasePath)
  98. relativePaths = append(relativePaths, (*batch)[i].RelativePath)
  99. }
  100. _, err := db.Exec(
  101. `
  102. insert into songs (
  103. track_number
  104. ,title
  105. ,artist
  106. ,album
  107. ,duration
  108. ,modified_date
  109. ,base_path
  110. ,relative_path
  111. )
  112. select * from unnest(
  113. $1::integer[]
  114. ,$2::varchar[]
  115. ,$3::varchar[]
  116. ,$4::varchar[]
  117. ,$5::integer[]
  118. ,$6::bigint[]
  119. ,$7::varchar[]
  120. ,$8::varchar[]
  121. )
  122. on conflict (base_path, relative_path) do update
  123. set
  124. track_number = excluded.track_number
  125. ,title = excluded.title
  126. ,artist = excluded.artist
  127. ,album = excluded.album
  128. ,duration = excluded.duration
  129. ,modified_date = excluded.modified_date
  130. `,
  131. trackNumbers,
  132. titles,
  133. artists,
  134. albums,
  135. durations,
  136. modifiedDates,
  137. basePaths,
  138. relativePaths,
  139. )
  140. return err
  141. }