songs.go 3.0 KB

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