songs.go 3.3 KB

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