songs.go 2.9 KB

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