mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
db: collapse paged library queries into one builder per entity
Replace the thirty hand-written order variants with one query builder per entity plus a default and a downloaded @RawQuery entry point. The repository's sort dispatch trees and the duplicated positional filters in LibraryPaging are gone, and the SQL now lives in multi-line strings with named parameters. The generated statements are identical to the previous ones modulo whitespace: the downloaded variants keep the same CASE/download conditions, and the observed entities match what Room inferred for the old queries. A small helper rewrites the named parameters to RoomRawQuery's positional form, including the repeated :sourceId bindings.
This commit is contained in:
@@ -10,15 +10,21 @@ import androidx.room3.Transaction
|
||||
import androidx.room3.Upsert
|
||||
import androidx.room3.paging.PagingSourceDaoReturnTypeConverter
|
||||
import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.AlbumArtistRef
|
||||
import com.subtracks.data.model.AlbumSearch
|
||||
import com.subtracks.data.model.AlbumSongItem
|
||||
import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.ArtistBio
|
||||
import com.subtracks.data.model.ArtistSearch
|
||||
import com.subtracks.data.model.Disc
|
||||
import com.subtracks.data.model.DiscKey
|
||||
import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.data.model.PlaylistSearch
|
||||
import com.subtracks.data.model.PlaylistSong
|
||||
import com.subtracks.data.model.PlaylistSongItem
|
||||
import com.subtracks.data.model.Song
|
||||
import com.subtracks.data.model.SongArtistRef
|
||||
import com.subtracks.data.model.SongDownload
|
||||
import com.subtracks.data.model.Source
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@@ -36,20 +42,11 @@ internal const val DOWNLOADED_SONG =
|
||||
"EXISTS (SELECT 1 FROM song_downloads sd WHERE sd.sourceId = playlist_songs.sourceId " +
|
||||
"AND sd.songId = playlist_songs.songId AND sd.status = 'Completed')"
|
||||
|
||||
internal const val ALBUMS_FILTER =
|
||||
"FROM albums WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND (:downloadedFilter = 0 OR EXISTS (SELECT 1 FROM songs " +
|
||||
"JOIN song_downloads sd ON sd.sourceId = songs.sourceId AND sd.songId = songs.id " +
|
||||
"WHERE songs.sourceId = albums.sourceId AND songs.albumId = albums.id AND sd.status = 'Completed')) " +
|
||||
"AND (:search = '' " +
|
||||
"OR (length(:search) >= 3 AND rowid IN (SELECT rowid FROM album_search " +
|
||||
"WHERE album_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(:search) < 3 AND (instr(lower(name), lower(:search)) > 0 " +
|
||||
"OR instr(lower(albumArtist), lower(:search)) > 0 " +
|
||||
"OR instr(lower(sortName), lower(:search)) > 0 " +
|
||||
"OR instr(lower(albumArtistSort), lower(:search)) > 0))) "
|
||||
|
||||
internal const val ALBUM_ORDER_BY_NAME = "sortName COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_NAME_REVERSED = "sortName COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ALBUM_ORDER_BY_ARTIST = "albumArtistSort COLLATE NOCASE, year, sortName COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_ARTIST_REVERSED =
|
||||
"albumArtistSort COLLATE NOCASE DESC, year DESC, sortName COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ALBUM_ORDER_BY_YEAR = "year DESC, sortName COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_YEAR_REVERSED = "year ASC, sortName COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ALBUM_ORDER_BY_ADDED = "created DESC, sortName COLLATE NOCASE, id"
|
||||
@@ -154,7 +151,7 @@ internal const val DOWNLOADED_ALBUM_ROWS =
|
||||
"JOIN song_downloads sd ON sd.sourceId = songs.sourceId AND sd.songId = songs.id " +
|
||||
"WHERE song_artists.sourceId = :sourceId AND sd.status = 'Completed'"
|
||||
|
||||
private const val DOWNLOADED_ARTIST_ALBUMS =
|
||||
internal const val DOWNLOADED_ARTIST_ALBUMS =
|
||||
"SELECT albumId AS id FROM ($DOWNLOADED_ALBUM_ROWS) WHERE artistId = artists.id"
|
||||
|
||||
private const val DOWNLOADED_COVER_ALBUM_ROWS =
|
||||
@@ -300,33 +297,13 @@ internal const val DOWNLOADED_ARTIST_ART_UPDATE_SQL =
|
||||
"FROM desired WHERE artists.rowid = desired.rowid AND " +
|
||||
"artists.downloadedCoverArts != desired.downloadedCoverArts"
|
||||
|
||||
internal const val ARTISTS_FILTER =
|
||||
"FROM artists WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND $ARTIST_CREDITED " +
|
||||
"AND (:downloadedFilter = 0 OR EXISTS (" +
|
||||
"SELECT 1 FROM ($ARTIST_DOWNLOAD_ROWS) dl " +
|
||||
"WHERE dl.id = artists.id AND dl.status = 'Completed')) " +
|
||||
"AND (:search = '' " +
|
||||
"OR (length(:search) >= 3 AND rowid IN (SELECT rowid FROM artist_search " +
|
||||
"WHERE artist_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(:search) < 3 AND (instr(lower(name), lower(:search)) > 0 " +
|
||||
"OR instr(lower(sortName), lower(:search)) > 0))) "
|
||||
internal const val ARTIST_COLUMNS_TAIL =
|
||||
"artists.starred, artists.coverArt, artists.artistImageUrl, artists.coverArts, " +
|
||||
"artists.downloadedCoverArts, artists.playCount, artists.played, artists.songCount, " +
|
||||
"artists.sortName, artists.credited"
|
||||
|
||||
internal const val ARTIST_COLUMNS =
|
||||
"artists.sourceId, artists.id, artists.name, artists.albumCount, artists.starred, " +
|
||||
"artists.coverArt, artists.artistImageUrl, artists.coverArts, artists.downloadedCoverArts, " +
|
||||
"artists.playCount, artists.played, artists.songCount, artists.sortName, artists.credited"
|
||||
|
||||
// With the Downloaded filter on, count the albums that actually have a download so the number under
|
||||
// an artist matches the albums its detail screen lists.
|
||||
internal const val ARTISTS_SELECT =
|
||||
"SELECT artists.sourceId, artists.id, artists.name, " +
|
||||
"CASE WHEN :downloadedFilter = 1 THEN (" +
|
||||
"SELECT COUNT(*) FROM ($DOWNLOADED_ARTIST_ALBUMS)" +
|
||||
") ELSE artists.albumCount END AS albumCount, " +
|
||||
"artists.starred, artists.coverArt, artists.artistImageUrl, artists.coverArts, artists.downloadedCoverArts, " +
|
||||
"artists.playCount, artists.played, artists.songCount, artists.sortName, artists.credited "
|
||||
"artists.sourceId, artists.id, artists.name, artists.albumCount, $ARTIST_COLUMNS_TAIL"
|
||||
|
||||
internal const val ARTIST_ORDER_BY_ALBUM_COUNT = "albumCount DESC, sortName COLLATE NOCASE, id"
|
||||
internal const val ARTIST_ORDER_BY_ALBUM_COUNT_REVERSED = "albumCount ASC, sortName COLLATE NOCASE DESC, id DESC"
|
||||
@@ -346,27 +323,6 @@ private const val SONG_NAME_SORT_KEY_MODE =
|
||||
"(CASE :sortMode WHEN 'Name' THEN songs.title WHEN 'NonLatin' THEN (CASE WHEN songs.title GLOB '*[A-Za-z]*' THEN songs.title ELSE songs.sortName END) ELSE songs.sortName END) COLLATE NOCASE"
|
||||
internal const val SONG_SEARCH_ORDER_SORT_MODE = "$SONG_NAME_SORT_KEY_MODE, songs.id"
|
||||
|
||||
internal const val PLAYLISTS_FILTER =
|
||||
"FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:downloadedFilter = 0 OR EXISTS (SELECT 1 FROM playlist_songs ps " +
|
||||
"JOIN song_downloads sd ON sd.sourceId = ps.sourceId AND sd.songId = ps.songId " +
|
||||
"WHERE ps.sourceId = playlists.sourceId AND ps.playlistId = playlists.id AND sd.status = 'Completed')) " +
|
||||
"AND (:search = '' " +
|
||||
"OR (length(:search) >= 3 AND rowid IN (SELECT rowid FROM playlist_search " +
|
||||
"WHERE playlist_search MATCH '\"' || replace(:search, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(:search) < 3 AND instr(lower(name), lower(:search)) > 0)) "
|
||||
|
||||
// With the Downloaded filter on, count the songs that actually have a download so the number under
|
||||
// a playlist matches the songs its detail screen lists.
|
||||
internal const val PLAYLISTS_SELECT =
|
||||
"SELECT playlists.sourceId, playlists.id, playlists.name, playlists.comment, playlists.coverArt, " +
|
||||
"CASE WHEN :downloadedFilter = 1 THEN (" +
|
||||
"SELECT COUNT(DISTINCT ps.songId) FROM playlist_songs ps " +
|
||||
"JOIN song_downloads sd ON sd.sourceId = ps.sourceId AND sd.songId = ps.songId AND sd.status = 'Completed' " +
|
||||
"WHERE ps.sourceId = playlists.sourceId AND ps.playlistId = playlists.id " +
|
||||
") ELSE playlists.songCount END AS songCount, " +
|
||||
"playlists.created, playlists.changed, playlists.duration, playlists.owner, playlists.shared "
|
||||
|
||||
internal const val PLAYLIST_ORDER_BY_NAME = "name COLLATE NOCASE, id"
|
||||
internal const val PLAYLIST_ORDER_BY_NAME_REVERSED = "name COLLATE NOCASE DESC, id DESC"
|
||||
internal const val PLAYLIST_ORDER_BY_ADDED = "created DESC, name COLLATE NOCASE, id"
|
||||
@@ -804,245 +760,27 @@ interface LibraryDao {
|
||||
@RawQuery(observedEntities = [Playlist::class])
|
||||
fun playlistsPaging(query: RoomRawQuery): PagingSource<Int, Playlist>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_NAME_SORT_MODE")
|
||||
fun albumsByName(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
sortMode: String = "",
|
||||
): PagingSource<Int, Album>
|
||||
// These observe every table the statement reads, matching what Room inferred for the
|
||||
// hand-written downloaded queries, so download and library writes invalidate as before.
|
||||
@RawQuery(observedEntities = [Album::class, Song::class, SongDownload::class, AlbumSearch::class])
|
||||
fun downloadedAlbumsPaging(query: RoomRawQuery): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_NAME_SORT_MODE_REVERSED")
|
||||
fun albumsByNameReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
sortMode: String = "",
|
||||
): PagingSource<Int, Album>
|
||||
@RawQuery(
|
||||
observedEntities = [
|
||||
Album::class,
|
||||
Song::class,
|
||||
SongDownload::class,
|
||||
AlbumArtistRef::class,
|
||||
SongArtistRef::class,
|
||||
Artist::class,
|
||||
Source::class,
|
||||
ArtistSearch::class,
|
||||
],
|
||||
)
|
||||
fun downloadedArtistsPaging(query: RoomRawQuery): PagingSource<Int, Artist>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ARTIST_SORT_MODE")
|
||||
fun albumsByArtist(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
sortMode: String = "",
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ARTIST_SORT_MODE_REVERSED")
|
||||
fun albumsByArtistReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
sortMode: String = "",
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_YEAR")
|
||||
fun albumsByYear(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_YEAR_REVERSED")
|
||||
fun albumsByYearReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ADDED")
|
||||
fun albumsByRecentlyAdded(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ADDED_REVERSED")
|
||||
fun albumsByRecentlyAddedReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_STARRED")
|
||||
fun albumsByStarred(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_STARRED_REVERSED")
|
||||
fun albumsByStarredReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_FREQUENT")
|
||||
fun albumsByFrequent(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_FREQUENT_REVERSED")
|
||||
fun albumsByFrequentReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_RECENT")
|
||||
fun albumsByRecent(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_RECENT_REVERSED")
|
||||
fun albumsByRecentReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_NAME_SORT_MODE")
|
||||
fun artistsByName(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
sortMode: String = "",
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_NAME_SORT_MODE_REVERSED")
|
||||
fun artistsByNameReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
sortMode: String = "",
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_ALBUM_COUNT")
|
||||
fun artistsByAlbumCount(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_ALBUM_COUNT_REVERSED")
|
||||
fun artistsByAlbumCountReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_STARRED")
|
||||
fun artistsByStarred(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_STARRED_REVERSED")
|
||||
fun artistsByStarredReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_FREQUENT")
|
||||
fun artistsByFrequent(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_FREQUENT_REVERSED")
|
||||
fun artistsByFrequentReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_RECENT")
|
||||
fun artistsByRecent(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$ARTISTS_SELECT $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_RECENT_REVERSED")
|
||||
fun artistsByRecentReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query("$PLAYLISTS_SELECT $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_NAME")
|
||||
fun playlistsByName(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query("$PLAYLISTS_SELECT $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_NAME_REVERSED")
|
||||
fun playlistsByNameReversed(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query("$PLAYLISTS_SELECT $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_ADDED")
|
||||
fun playlistsByAdded(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query("$PLAYLISTS_SELECT $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_ADDED_REVERSED")
|
||||
fun playlistsByAddedReversed(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query("$PLAYLISTS_SELECT $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_UPDATED")
|
||||
fun playlistsByUpdated(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query("$PLAYLISTS_SELECT $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_UPDATED_REVERSED")
|
||||
fun playlistsByUpdatedReversed(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
downloadedFilter: Int = 0,
|
||||
): PagingSource<Int, Playlist>
|
||||
@RawQuery(observedEntities = [PlaylistSong::class, SongDownload::class, Playlist::class, PlaylistSearch::class])
|
||||
fun downloadedPlaylistsPaging(query: RoomRawQuery): PagingSource<Int, Playlist>
|
||||
|
||||
@Query("SELECT * FROM albums WHERE sourceId = :sourceId AND played IS NOT NULL ORDER BY played DESC, sortName COLLATE NOCASE, id")
|
||||
fun homeRecentlyPlayedAlbums(sourceId: Long): PagingSource<Int, Album>
|
||||
|
||||
@@ -7,49 +7,161 @@ import com.subtracks.data.prefs.ArtistSort
|
||||
import com.subtracks.data.prefs.PlaylistSort
|
||||
import com.subtracks.data.prefs.SortNameMode
|
||||
|
||||
// These filters mirror the download-aware ones in LibraryDao but never mention song_downloads, so
|
||||
// the resulting PagingSource is not invalidated by download writes (including progress updates).
|
||||
internal const val ALBUMS_FILTER_BASE =
|
||||
"FROM albums WHERE sourceId = ? " +
|
||||
"AND (? = 0 OR (? = 1 AND starred IS NOT NULL) OR (? = 2 AND starred IS NULL)) " +
|
||||
"AND (? = '' " +
|
||||
"OR (length(?) >= 3 AND rowid IN (SELECT rowid FROM album_search " +
|
||||
"WHERE album_search MATCH '\"' || replace(?, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(?) < 3 AND (instr(lower(name), lower(?)) > 0 " +
|
||||
"OR instr(lower(albumArtist), lower(?)) > 0 " +
|
||||
"OR instr(lower(sortName), lower(?)) > 0 " +
|
||||
"OR instr(lower(albumArtistSort), lower(?)) > 0))) "
|
||||
// The default filters never mention song_downloads, so the paging sources used without the
|
||||
// Downloaded filter are not invalidated by download writes (including progress updates). The
|
||||
// downloaded variants are the same statements the hand-written queries used.
|
||||
internal const val ALBUMS_FILTER = """
|
||||
FROM albums WHERE sourceId = :sourceId
|
||||
AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL))
|
||||
AND (:search = ''
|
||||
OR (length(:search) >= $SEARCH_MIN_LENGTH AND rowid IN (SELECT rowid FROM album_search
|
||||
WHERE album_search MATCH '"' || replace(:search, '"', '""') || '"'))
|
||||
OR (length(:search) < $SEARCH_MIN_LENGTH AND (instr(lower(name), lower(:search)) > 0
|
||||
OR instr(lower(albumArtist), lower(:search)) > 0
|
||||
OR instr(lower(sortName), lower(:search)) > 0
|
||||
OR instr(lower(albumArtistSort), lower(:search)) > 0)))
|
||||
"""
|
||||
|
||||
internal const val ARTISTS_FILTER_BASE =
|
||||
"FROM artists WHERE sourceId = ? " +
|
||||
"AND (? = 0 OR (? = 1 AND starred IS NOT NULL) OR (? = 2 AND starred IS NULL)) " +
|
||||
"AND $ARTIST_CREDITED " +
|
||||
"AND (? = '' " +
|
||||
"OR (length(?) >= 3 AND rowid IN (SELECT rowid FROM artist_search " +
|
||||
"WHERE artist_search MATCH '\"' || replace(?, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(?) < 3 AND (instr(lower(name), lower(?)) > 0 " +
|
||||
"OR instr(lower(sortName), lower(?)) > 0))) "
|
||||
internal const val ALBUMS_FILTER_DOWNLOADED = """
|
||||
FROM albums WHERE sourceId = :sourceId
|
||||
AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL))
|
||||
AND (:downloadedFilter = 0 OR EXISTS (SELECT 1 FROM songs
|
||||
JOIN song_downloads sd ON sd.sourceId = songs.sourceId AND sd.songId = songs.id
|
||||
WHERE songs.sourceId = albums.sourceId AND songs.albumId = albums.id AND sd.status = 'Completed'))
|
||||
AND (:search = ''
|
||||
OR (length(:search) >= $SEARCH_MIN_LENGTH AND rowid IN (SELECT rowid FROM album_search
|
||||
WHERE album_search MATCH '"' || replace(:search, '"', '""') || '"'))
|
||||
OR (length(:search) < $SEARCH_MIN_LENGTH AND (instr(lower(name), lower(:search)) > 0
|
||||
OR instr(lower(albumArtist), lower(:search)) > 0
|
||||
OR instr(lower(sortName), lower(:search)) > 0
|
||||
OR instr(lower(albumArtistSort), lower(:search)) > 0)))
|
||||
"""
|
||||
|
||||
internal const val PLAYLISTS_FILTER_BASE =
|
||||
"FROM playlists WHERE sourceId = ? " +
|
||||
"AND (? = '' " +
|
||||
"OR (length(?) >= 3 AND rowid IN (SELECT rowid FROM playlist_search " +
|
||||
"WHERE playlist_search MATCH '\"' || replace(?, '\"', '\"\"') || '\"')) " +
|
||||
"OR (length(?) < 3 AND instr(lower(name), lower(?)) > 0)) "
|
||||
internal const val ARTISTS_FILTER = """
|
||||
FROM artists WHERE sourceId = :sourceId
|
||||
AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL))
|
||||
AND $ARTIST_CREDITED
|
||||
AND (:search = ''
|
||||
OR (length(:search) >= $SEARCH_MIN_LENGTH AND rowid IN (SELECT rowid FROM artist_search
|
||||
WHERE artist_search MATCH '"' || replace(:search, '"', '""') || '"'))
|
||||
OR (length(:search) < $SEARCH_MIN_LENGTH AND (instr(lower(name), lower(:search)) > 0
|
||||
OR instr(lower(sortName), lower(:search)) > 0)))
|
||||
"""
|
||||
|
||||
internal fun albumsDefaultQuery(
|
||||
internal const val ARTISTS_FILTER_DOWNLOADED = """
|
||||
FROM artists WHERE sourceId = :sourceId
|
||||
AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL))
|
||||
AND $ARTIST_CREDITED
|
||||
AND (:downloadedFilter = 0 OR EXISTS (SELECT 1 FROM ($ARTIST_DOWNLOAD_ROWS) dl
|
||||
WHERE dl.id = artists.id AND dl.status = 'Completed'))
|
||||
AND (:search = ''
|
||||
OR (length(:search) >= $SEARCH_MIN_LENGTH AND rowid IN (SELECT rowid FROM artist_search
|
||||
WHERE artist_search MATCH '"' || replace(:search, '"', '""') || '"'))
|
||||
OR (length(:search) < $SEARCH_MIN_LENGTH AND (instr(lower(name), lower(:search)) > 0
|
||||
OR instr(lower(sortName), lower(:search)) > 0)))
|
||||
"""
|
||||
|
||||
// With the Downloaded filter on, count the albums that actually have a download so the number under
|
||||
// an artist matches the albums its detail screen lists.
|
||||
internal const val ARTIST_COLUMNS_DOWNLOADED = """
|
||||
artists.sourceId, artists.id, artists.name,
|
||||
CASE WHEN :downloadedFilter = 1 THEN (SELECT COUNT(*) FROM ($DOWNLOADED_ARTIST_ALBUMS)) ELSE artists.albumCount END AS albumCount,
|
||||
$ARTIST_COLUMNS_TAIL
|
||||
"""
|
||||
|
||||
internal const val PLAYLISTS_FILTER = """
|
||||
FROM playlists WHERE sourceId = :sourceId
|
||||
AND (:search = ''
|
||||
OR (length(:search) >= $SEARCH_MIN_LENGTH AND rowid IN (SELECT rowid FROM playlist_search
|
||||
WHERE playlist_search MATCH '"' || replace(:search, '"', '""') || '"'))
|
||||
OR (length(:search) < $SEARCH_MIN_LENGTH AND instr(lower(name), lower(:search)) > 0))
|
||||
"""
|
||||
|
||||
internal const val PLAYLISTS_FILTER_DOWNLOADED = """
|
||||
FROM playlists WHERE sourceId = :sourceId
|
||||
AND (:downloadedFilter = 0 OR EXISTS (SELECT 1 FROM playlist_songs ps
|
||||
JOIN song_downloads sd ON sd.sourceId = ps.sourceId AND sd.songId = ps.songId
|
||||
WHERE ps.sourceId = playlists.sourceId AND ps.playlistId = playlists.id AND sd.status = 'Completed'))
|
||||
AND (:search = ''
|
||||
OR (length(:search) >= $SEARCH_MIN_LENGTH AND rowid IN (SELECT rowid FROM playlist_search
|
||||
WHERE playlist_search MATCH '"' || replace(:search, '"', '""') || '"'))
|
||||
OR (length(:search) < $SEARCH_MIN_LENGTH AND instr(lower(name), lower(:search)) > 0))
|
||||
"""
|
||||
|
||||
// With the Downloaded filter on, count the songs that actually have a download so the number under
|
||||
// a playlist matches the songs its detail screen lists.
|
||||
internal const val PLAYLISTS_COLUMNS_DOWNLOADED = """
|
||||
playlists.sourceId, playlists.id, playlists.name, playlists.comment, playlists.coverArt,
|
||||
CASE WHEN :downloadedFilter = 1 THEN (SELECT COUNT(DISTINCT ps.songId)
|
||||
FROM playlist_songs ps
|
||||
JOIN song_downloads sd ON sd.sourceId = ps.sourceId AND sd.songId = ps.songId AND sd.status = 'Completed'
|
||||
WHERE ps.sourceId = playlists.sourceId AND ps.playlistId = playlists.id
|
||||
) ELSE playlists.songCount END AS songCount,
|
||||
playlists.created, playlists.changed, playlists.duration, playlists.owner, playlists.shared
|
||||
"""
|
||||
|
||||
internal fun albumsPageQuery(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
sort: AlbumSort,
|
||||
descending: Boolean,
|
||||
downloaded: Boolean,
|
||||
sortNameMode: SortNameMode = SortNameMode.SortName,
|
||||
): RoomRawQuery {
|
||||
val order = albumOrder(sort, descending, sortNameMode)
|
||||
return RoomRawQuery("SELECT * $ALBUMS_FILTER_BASE ORDER BY $order") { stmt ->
|
||||
stmt.bindAlbumFilters(sourceId, starredFilter, search)
|
||||
}
|
||||
}
|
||||
): RoomRawQuery =
|
||||
rawQuery(
|
||||
sql = "SELECT * ${if (downloaded) ALBUMS_FILTER_DOWNLOADED else ALBUMS_FILTER} ORDER BY ${albumOrder(sort, descending, sortNameMode)}",
|
||||
bindings =
|
||||
mapOf(
|
||||
"sourceId" to sourceId,
|
||||
"starredFilter" to starredFilter,
|
||||
"downloadedFilter" to if (downloaded) 1 else 0,
|
||||
"search" to search,
|
||||
),
|
||||
)
|
||||
|
||||
internal fun artistsPageQuery(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
sort: ArtistSort,
|
||||
descending: Boolean,
|
||||
downloaded: Boolean,
|
||||
sortNameMode: SortNameMode = SortNameMode.SortName,
|
||||
): RoomRawQuery =
|
||||
rawQuery(
|
||||
sql =
|
||||
"SELECT ${if (downloaded) ARTIST_COLUMNS_DOWNLOADED else ARTIST_COLUMNS} " +
|
||||
"${if (downloaded) ARTISTS_FILTER_DOWNLOADED else ARTISTS_FILTER} " +
|
||||
"ORDER BY ${artistOrder(sort, descending, sortNameMode)}",
|
||||
bindings =
|
||||
mapOf(
|
||||
"sourceId" to sourceId,
|
||||
"starredFilter" to starredFilter,
|
||||
"downloadedFilter" to if (downloaded) 1 else 0,
|
||||
"search" to search,
|
||||
),
|
||||
)
|
||||
|
||||
internal fun playlistsPageQuery(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
sort: PlaylistSort,
|
||||
descending: Boolean,
|
||||
downloaded: Boolean,
|
||||
): RoomRawQuery =
|
||||
rawQuery(
|
||||
sql =
|
||||
"SELECT ${if (downloaded) PLAYLISTS_COLUMNS_DOWNLOADED else "*"} " +
|
||||
"${if (downloaded) PLAYLISTS_FILTER_DOWNLOADED else PLAYLISTS_FILTER} " +
|
||||
"ORDER BY ${playlistOrder(sort, descending)}",
|
||||
bindings =
|
||||
mapOf(
|
||||
"sourceId" to sourceId,
|
||||
"downloadedFilter" to if (downloaded) 1 else 0,
|
||||
"search" to search,
|
||||
),
|
||||
)
|
||||
|
||||
internal fun rediscoverAlbumsQuery(
|
||||
sourceId: Long,
|
||||
@@ -57,70 +169,71 @@ internal fun rediscoverAlbumsQuery(
|
||||
search: String,
|
||||
cutoff: Long,
|
||||
): RoomRawQuery =
|
||||
RoomRawQuery(
|
||||
"SELECT * $ALBUMS_FILTER_BASE AND played IS NOT NULL AND played < ? " +
|
||||
"ORDER BY played ASC, sortName COLLATE NOCASE, id",
|
||||
) { stmt ->
|
||||
stmt.bindAlbumFilters(sourceId, starredFilter, search)
|
||||
stmt.bindLong(13, cutoff)
|
||||
}
|
||||
rawQuery(
|
||||
sql =
|
||||
"SELECT * $ALBUMS_FILTER AND played IS NOT NULL AND played < :cutoff " +
|
||||
"ORDER BY played ASC, sortName COLLATE NOCASE, id",
|
||||
bindings =
|
||||
mapOf(
|
||||
"sourceId" to sourceId,
|
||||
"starredFilter" to starredFilter,
|
||||
"search" to search,
|
||||
"cutoff" to cutoff,
|
||||
),
|
||||
)
|
||||
|
||||
private fun SQLiteStatement.bindAlbumFilters(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
// RoomRawQuery binds by position, so the named fragments are rewritten once here instead of
|
||||
// every caller carrying an index for each repeated :sourceId.
|
||||
internal fun rawQuery(
|
||||
sql: String,
|
||||
bindings: Map<String, Any?>,
|
||||
): RoomRawQuery {
|
||||
val names = mutableListOf<String>()
|
||||
val positional =
|
||||
buildString(sql.length) {
|
||||
var index = 0
|
||||
var quote: Char? = null
|
||||
while (index < sql.length) {
|
||||
val char = sql[index]
|
||||
if (quote != null) {
|
||||
append(char)
|
||||
if (char == quote) quote = null
|
||||
index++
|
||||
continue
|
||||
}
|
||||
if (char == '\'' || char == '"') {
|
||||
quote = char
|
||||
append(char)
|
||||
index++
|
||||
continue
|
||||
}
|
||||
if (char == ':' && sql.getOrNull(index + 1).let { it != null && (it.isLetter() || it == '_') }) {
|
||||
var end = index + 1
|
||||
while (end < sql.length && (sql[end].isLetterOrDigit() || sql[end] == '_')) end++
|
||||
names += sql.substring(index + 1, end)
|
||||
append('?')
|
||||
index = end
|
||||
continue
|
||||
}
|
||||
append(char)
|
||||
index++
|
||||
}
|
||||
}
|
||||
return RoomRawQuery(positional) { statement ->
|
||||
names.forEachIndexed { index, name -> statement.bind(index + 1, bindings.getValue(name)) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun SQLiteStatement.bind(
|
||||
index: Int,
|
||||
value: Any?,
|
||||
) {
|
||||
bindLong(1, sourceId)
|
||||
bindInt(2, starredFilter)
|
||||
bindInt(3, starredFilter)
|
||||
bindInt(4, starredFilter)
|
||||
bindText(5, search)
|
||||
bindText(6, search)
|
||||
bindText(7, search)
|
||||
bindText(8, search)
|
||||
bindText(9, search)
|
||||
bindText(10, search)
|
||||
bindText(11, search)
|
||||
bindText(12, search)
|
||||
}
|
||||
|
||||
internal fun artistsDefaultQuery(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
sort: ArtistSort,
|
||||
descending: Boolean,
|
||||
sortNameMode: SortNameMode = SortNameMode.SortName,
|
||||
): RoomRawQuery {
|
||||
val order = artistOrder(sort, descending, sortNameMode)
|
||||
return RoomRawQuery("SELECT $ARTIST_COLUMNS $ARTISTS_FILTER_BASE ORDER BY $order") { stmt ->
|
||||
stmt.bindLong(1, sourceId)
|
||||
stmt.bindInt(2, starredFilter)
|
||||
stmt.bindInt(3, starredFilter)
|
||||
stmt.bindInt(4, starredFilter)
|
||||
stmt.bindText(5, search)
|
||||
stmt.bindText(6, search)
|
||||
stmt.bindText(7, search)
|
||||
stmt.bindText(8, search)
|
||||
stmt.bindText(9, search)
|
||||
stmt.bindText(10, search)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun playlistsDefaultQuery(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
sort: PlaylistSort,
|
||||
descending: Boolean,
|
||||
): RoomRawQuery {
|
||||
val order = playlistOrder(sort, descending)
|
||||
return RoomRawQuery("SELECT * $PLAYLISTS_FILTER_BASE ORDER BY $order") { stmt ->
|
||||
stmt.bindLong(1, sourceId)
|
||||
stmt.bindText(2, search)
|
||||
stmt.bindText(3, search)
|
||||
stmt.bindText(4, search)
|
||||
stmt.bindText(5, search)
|
||||
stmt.bindText(6, search)
|
||||
when (value) {
|
||||
null -> bindNull(index)
|
||||
is Int -> bindLong(index, value.toLong())
|
||||
is Long -> bindLong(index, value)
|
||||
is String -> bindText(index, value)
|
||||
else -> error("Unsupported SQL parameter: ${value::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import androidx.paging.PagingSource
|
||||
import com.subtracks.R
|
||||
import com.subtracks.UiMessage
|
||||
import com.subtracks.data.db.SubtracksDatabase
|
||||
import com.subtracks.data.db.albumsDefaultQuery
|
||||
import com.subtracks.data.db.artistsDefaultQuery
|
||||
import com.subtracks.data.db.playlistsDefaultQuery
|
||||
import com.subtracks.data.db.albumsPageQuery
|
||||
import com.subtracks.data.db.artistsPageQuery
|
||||
import com.subtracks.data.db.playlistsPageQuery
|
||||
import com.subtracks.data.db.rediscoverAlbumsQuery
|
||||
import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.AlbumSongItem
|
||||
@@ -195,68 +195,8 @@ class LibraryRepository(
|
||||
userPreferences.sortNameMode().flatMapLatest { mode ->
|
||||
pager(40, enablePlaceholders = true) {
|
||||
val dao = db.libraryDao()
|
||||
if (!downloaded) {
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, starred.ordinal, search, sort, descending, mode))
|
||||
} else {
|
||||
val downloadedFilter = 1
|
||||
when (sort) {
|
||||
AlbumSort.Name -> {
|
||||
if (descending) {
|
||||
dao.albumsByNameReversed(sourceId, starred.ordinal, search, downloadedFilter, mode.name)
|
||||
} else {
|
||||
dao.albumsByName(sourceId, starred.ordinal, search, downloadedFilter, mode.name)
|
||||
}
|
||||
}
|
||||
|
||||
AlbumSort.Artist -> {
|
||||
if (descending) {
|
||||
dao.albumsByArtistReversed(sourceId, starred.ordinal, search, downloadedFilter, mode.name)
|
||||
} else {
|
||||
dao.albumsByArtist(sourceId, starred.ordinal, search, downloadedFilter, mode.name)
|
||||
}
|
||||
}
|
||||
|
||||
AlbumSort.Year -> {
|
||||
if (descending) {
|
||||
dao.albumsByYearReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.albumsByYear(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
AlbumSort.Added -> {
|
||||
if (descending) {
|
||||
dao.albumsByRecentlyAddedReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.albumsByRecentlyAdded(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
AlbumSort.Starred -> {
|
||||
if (descending) {
|
||||
dao.albumsByStarredReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.albumsByStarred(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
AlbumSort.Frequent -> {
|
||||
if (descending) {
|
||||
dao.albumsByFrequentReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.albumsByFrequent(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
AlbumSort.Recent -> {
|
||||
if (descending) {
|
||||
dao.albumsByRecentReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.albumsByRecent(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val query = albumsPageQuery(sourceId, starred.ordinal, search, sort, descending, downloaded, mode)
|
||||
if (downloaded) dao.downloadedAlbumsPaging(query) else dao.albumsPaging(query)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,52 +211,8 @@ class LibraryRepository(
|
||||
userPreferences.sortNameMode().flatMapLatest { mode ->
|
||||
pager(60) {
|
||||
val dao = db.libraryDao()
|
||||
if (!downloaded) {
|
||||
dao.artistsPaging(artistsDefaultQuery(sourceId, starred.ordinal, search, sort, descending, mode))
|
||||
} else {
|
||||
val downloadedFilter = 1
|
||||
when (sort) {
|
||||
ArtistSort.Name -> {
|
||||
if (descending) {
|
||||
dao.artistsByNameReversed(sourceId, starred.ordinal, search, downloadedFilter, mode.name)
|
||||
} else {
|
||||
dao.artistsByName(sourceId, starred.ordinal, search, downloadedFilter, mode.name)
|
||||
}
|
||||
}
|
||||
|
||||
ArtistSort.AlbumCount -> {
|
||||
if (descending) {
|
||||
dao.artistsByAlbumCountReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.artistsByAlbumCount(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
ArtistSort.Starred -> {
|
||||
if (descending) {
|
||||
dao.artistsByStarredReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.artistsByStarred(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
ArtistSort.Frequent -> {
|
||||
if (descending) {
|
||||
dao.artistsByFrequentReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.artistsByFrequent(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
ArtistSort.Recent -> {
|
||||
if (descending) {
|
||||
dao.artistsByRecentReversed(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
} else {
|
||||
dao.artistsByRecent(sourceId, starred.ordinal, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val query = artistsPageQuery(sourceId, starred.ordinal, search, sort, descending, downloaded, mode)
|
||||
if (downloaded) dao.downloadedArtistsPaging(query) else dao.artistsPaging(query)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,36 +225,8 @@ class LibraryRepository(
|
||||
): Flow<PagingData<Playlist>> =
|
||||
pager(40) {
|
||||
val dao = db.libraryDao()
|
||||
if (!downloaded) {
|
||||
dao.playlistsPaging(playlistsDefaultQuery(sourceId, search, sort, descending))
|
||||
} else {
|
||||
val downloadedFilter = 1
|
||||
when (sort) {
|
||||
PlaylistSort.Name -> {
|
||||
if (descending) {
|
||||
dao.playlistsByNameReversed(sourceId, search, downloadedFilter)
|
||||
} else {
|
||||
dao.playlistsByName(sourceId, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
PlaylistSort.Added -> {
|
||||
if (descending) {
|
||||
dao.playlistsByAddedReversed(sourceId, search, downloadedFilter)
|
||||
} else {
|
||||
dao.playlistsByAdded(sourceId, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
|
||||
PlaylistSort.Updated -> {
|
||||
if (descending) {
|
||||
dao.playlistsByUpdatedReversed(sourceId, search, downloadedFilter)
|
||||
} else {
|
||||
dao.playlistsByUpdated(sourceId, search, downloadedFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val query = playlistsPageQuery(sourceId, search, sort, descending, downloaded)
|
||||
if (downloaded) dao.downloadedPlaylistsPaging(query) else dao.playlistsPaging(query)
|
||||
}
|
||||
|
||||
fun album(
|
||||
|
||||
@@ -67,17 +67,17 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta", "Gamma"),
|
||||
dao.albumsByName(sourceId, starredFilter = 0, search = "").page().map { it.name },
|
||||
dao.albumPages(sourceId, starredFilter = 0, search = "").page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Gamma", "Beta", "Alpha"),
|
||||
dao.albumsByNameReversed(sourceId, starredFilter = 0, search = "").page().map { it.name },
|
||||
dao.albumPages(sourceId, starredFilter = 0, search = "", descending = true).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta", "Gamma"),
|
||||
dao.albumsByYear(sourceId, starredFilter = 0, search = "").page().map { it.name },
|
||||
dao.albumPages(sourceId, starredFilter = 0, search = "", sort = AlbumSort.Year).page().map { it.name },
|
||||
)
|
||||
assertEquals(listOf("Alpha"), dao.albumsByName(sourceId, starredFilter = 1, search = "").page().map { it.name })
|
||||
assertEquals(listOf("Alpha"), dao.albumPages(sourceId, starredFilter = 1, search = "").page().map { it.name })
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,14 +95,14 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("Beta", "Gamma", "Alpha"),
|
||||
dao.albumsByRecentlyAdded(sourceId, starredFilter = 0, search = "").page().map { it.name },
|
||||
dao.albumPages(sourceId, starredFilter = 0, search = "", sort = AlbumSort.Added).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha", "Gamma", "Beta"),
|
||||
dao.albumsByStarred(sourceId, starredFilter = 0, search = "").page().map { it.name },
|
||||
dao.albumPages(sourceId, starredFilter = 0, search = "", sort = AlbumSort.Starred).page().map { it.name },
|
||||
)
|
||||
assertEquals(listOf("Gamma"), dao.albumsByName(sourceId, starredFilter = 0, search = "gam").page().map { it.name })
|
||||
assertEquals(listOf("Beta"), dao.albumsByName(sourceId, starredFilter = 2, search = "").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumPages(sourceId, starredFilter = 0, search = "gam").page().map { it.name })
|
||||
assertEquals(listOf("Beta"), dao.albumPages(sourceId, starredFilter = 2, search = "").page().map { it.name })
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -148,19 +148,19 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("Beta", "Alpha", "Delta", "Gamma"),
|
||||
dao.albumsByStarred(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Starred).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta", "Gamma", "Delta"),
|
||||
dao.albumsByStarredReversed(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Starred, descending = true).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Beta", "Alpha", "Delta", "Gamma"),
|
||||
dao.artistsByStarred(sourceId, 0, "").page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Starred).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta", "Gamma", "Delta"),
|
||||
dao.artistsByStarredReversed(sourceId, 0, "").page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Starred, descending = true).page().map { it.name },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -206,19 +206,19 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("Two", "One", "Three"),
|
||||
dao.albumsByFrequent(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Frequent).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Two", "One", "Three"),
|
||||
dao.albumsByRecent(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Recent).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Many", "Few"),
|
||||
dao.artistsByFrequent(sourceId, 0, "").page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Frequent).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Many", "Few"),
|
||||
dao.artistsByRecent(sourceId, 0, "").page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Recent).page().map { it.name },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -268,12 +268,17 @@ class LibraryDaoTest {
|
||||
|
||||
val pairs =
|
||||
listOf(
|
||||
dao.albumsByName(sourceId, 0, "") to dao.albumsByNameReversed(sourceId, 0, ""),
|
||||
dao.albumsByArtist(sourceId, 0, "") to dao.albumsByArtistReversed(sourceId, 0, ""),
|
||||
dao.albumsByYear(sourceId, 0, "") to dao.albumsByYearReversed(sourceId, 0, ""),
|
||||
dao.albumsByRecentlyAdded(sourceId, 0, "") to dao.albumsByRecentlyAddedReversed(sourceId, 0, ""),
|
||||
dao.albumsByFrequent(sourceId, 0, "") to dao.albumsByFrequentReversed(sourceId, 0, ""),
|
||||
dao.albumsByRecent(sourceId, 0, "") to dao.albumsByRecentReversed(sourceId, 0, ""),
|
||||
dao.albumPages(sourceId, 0, "") to dao.albumPages(sourceId, 0, "", descending = true),
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Artist) to
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Artist, descending = true),
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Year) to
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Year, descending = true),
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Added) to
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Added, descending = true),
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Frequent) to
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Frequent, descending = true),
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Recent) to
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Recent, descending = true),
|
||||
)
|
||||
for ((base, reversed) in pairs) {
|
||||
val ids = base.page().map { it.id }
|
||||
@@ -303,23 +308,23 @@ class LibraryDaoTest {
|
||||
|
||||
val artistPairs =
|
||||
listOf(
|
||||
dao.artistsByName(sourceId, 0, "").page().map { it.id } to
|
||||
dao.artistsByNameReversed(sourceId, 0, "").page().map { it.id },
|
||||
dao.artistsByAlbumCount(sourceId, 0, "").page().map { it.id } to
|
||||
dao.artistsByAlbumCountReversed(sourceId, 0, "").page().map { it.id },
|
||||
dao.artistsByFrequent(sourceId, 0, "").page().map { it.id } to
|
||||
dao.artistsByFrequentReversed(sourceId, 0, "").page().map { it.id },
|
||||
dao.artistsByRecent(sourceId, 0, "").page().map { it.id } to
|
||||
dao.artistsByRecentReversed(sourceId, 0, "").page().map { it.id },
|
||||
dao.artistPages(sourceId, 0, "").page().map { it.id } to
|
||||
dao.artistPages(sourceId, 0, "", descending = true).page().map { it.id },
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.AlbumCount).page().map { it.id } to
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.AlbumCount, descending = true).page().map { it.id },
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Frequent).page().map { it.id } to
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Frequent, descending = true).page().map { it.id },
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Recent).page().map { it.id } to
|
||||
dao.artistPages(sourceId, 0, "", sort = ArtistSort.Recent, descending = true).page().map { it.id },
|
||||
)
|
||||
val playlistPairs =
|
||||
listOf(
|
||||
dao.playlistsByName(sourceId, "").page().map { it.id } to
|
||||
dao.playlistsByNameReversed(sourceId, "").page().map { it.id },
|
||||
dao.playlistsByAdded(sourceId, "").page().map { it.id } to
|
||||
dao.playlistsByAddedReversed(sourceId, "").page().map { it.id },
|
||||
dao.playlistsByUpdated(sourceId, "").page().map { it.id } to
|
||||
dao.playlistsByUpdatedReversed(sourceId, "").page().map { it.id },
|
||||
dao.playlistPages(sourceId, "").page().map { it.id } to
|
||||
dao.playlistPages(sourceId, "", descending = true).page().map { it.id },
|
||||
dao.playlistPages(sourceId, "", sort = PlaylistSort.Added).page().map { it.id } to
|
||||
dao.playlistPages(sourceId, "", sort = PlaylistSort.Added, descending = true).page().map { it.id },
|
||||
dao.playlistPages(sourceId, "", sort = PlaylistSort.Updated).page().map { it.id } to
|
||||
dao.playlistPages(sourceId, "", sort = PlaylistSort.Updated, descending = true).page().map { it.id },
|
||||
)
|
||||
for ((base, reversed) in artistPairs + playlistPairs) {
|
||||
assertEquals(base.reversed(), reversed)
|
||||
@@ -357,9 +362,11 @@ class LibraryDaoTest {
|
||||
ALBUM_ORDER_BY_RECENT_REVERSED to "index_albums_recent",
|
||||
)
|
||||
for ((order, index) in orders) {
|
||||
val plan = plan("SELECT * $ALBUMS_FILTER ORDER BY $order LIMIT 20 OFFSET 0")
|
||||
assertTrue(plan, plan.contains("USING INDEX $index"))
|
||||
assertFalse(plan, plan.contains("TEMP B-TREE"))
|
||||
for (filter in listOf(ALBUMS_FILTER, ALBUMS_FILTER_DOWNLOADED)) {
|
||||
val plan = plan("SELECT * $filter ORDER BY $order LIMIT 20 OFFSET 0")
|
||||
assertTrue(plan, plan.contains("USING INDEX $index"))
|
||||
assertFalse(plan, plan.contains("TEMP B-TREE"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,9 +389,11 @@ class LibraryDaoTest {
|
||||
ARTIST_ORDER_BY_RECENT_REVERSED to "index_artists_recent",
|
||||
)
|
||||
for ((order, index) in orders) {
|
||||
val plan = plan("SELECT * $ARTISTS_FILTER ORDER BY $order LIMIT 20 OFFSET 0")
|
||||
assertTrue(plan, plan.contains("USING INDEX $index"))
|
||||
assertFalse(plan, plan.contains("TEMP B-TREE"))
|
||||
for (filter in listOf(ARTISTS_FILTER, ARTISTS_FILTER_DOWNLOADED)) {
|
||||
val plan = plan("SELECT * $filter ORDER BY $order LIMIT 20 OFFSET 0")
|
||||
assertTrue(plan, plan.contains("USING INDEX $index"))
|
||||
assertFalse(plan, plan.contains("TEMP B-TREE"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,9 +410,11 @@ class LibraryDaoTest {
|
||||
PLAYLIST_ORDER_BY_UPDATED_REVERSED to "index_playlists_updated",
|
||||
)
|
||||
for ((order, index) in orders) {
|
||||
val plan = plan("SELECT * $PLAYLISTS_FILTER ORDER BY $order LIMIT 20 OFFSET 0")
|
||||
assertTrue(plan, plan.contains("USING INDEX $index"))
|
||||
assertFalse(plan, plan.contains("TEMP B-TREE"))
|
||||
for (filter in listOf(PLAYLISTS_FILTER, PLAYLISTS_FILTER_DOWNLOADED)) {
|
||||
val plan = plan("SELECT * $filter ORDER BY $order LIMIT 20 OFFSET 0")
|
||||
assertTrue(plan, plan.contains("USING INDEX $index"))
|
||||
assertFalse(plan, plan.contains("TEMP B-TREE"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,17 +467,17 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("Downloaded"),
|
||||
dao.albumsByName(sourceId, 0, "", downloadedFilter = 1).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", downloaded = true).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("ar-1"),
|
||||
dao.artistsByName(sourceId, 0, "", downloadedFilter = 1).page().map { it.id },
|
||||
dao.artistPages(sourceId, 0, "", downloaded = true).page().map { it.id },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("pl-1"),
|
||||
dao.playlistsByName(sourceId, "", downloadedFilter = 1).page().map { it.id },
|
||||
dao.playlistPages(sourceId, "", downloaded = true).page().map { it.id },
|
||||
)
|
||||
assertEquals(3, dao.albumsByName(sourceId, 0, "").page().size)
|
||||
assertEquals(3, dao.albumPages(sourceId, 0, "").page().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -628,7 +639,7 @@ class LibraryDaoTest {
|
||||
|
||||
dao.recomputeArtistArt(sourceId)
|
||||
|
||||
val artists = dao.artistsByName(sourceId, 0, "").page().associateBy { it.id }
|
||||
val artists = dao.artistPages(sourceId, 0, "").page().associateBy { it.id }
|
||||
|
||||
assertEquals("own-art", artists.getValue("ar-own").coverArt)
|
||||
assertNull(artists.getValue("ar-album").coverArt)
|
||||
@@ -648,7 +659,7 @@ class LibraryDaoTest {
|
||||
assertEquals(
|
||||
listOf("album-ref-art"),
|
||||
dao
|
||||
.artistsPaging(artistsDefaultQuery(sourceId, 0, "", ArtistSort.Name, false))
|
||||
.artistPages(sourceId, 0, "", ArtistSort.Name, false)
|
||||
.page()
|
||||
.first { it.id == "ar-album-ref" }
|
||||
.coverArts,
|
||||
@@ -904,7 +915,7 @@ class LibraryDaoTest {
|
||||
db.downloadDao().upsert(SongDownload(sourceId, "s1", DownloadStatus.Completed))
|
||||
assertEquals(
|
||||
listOf("Album Artist"),
|
||||
dao.artistsByName(sourceId, 0, "", downloadedFilter = 1).page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", downloaded = true).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Album Artist"),
|
||||
@@ -913,7 +924,7 @@ class LibraryDaoTest {
|
||||
|
||||
db.downloadDao().upsert(SongDownload(sourceId, "s2", DownloadStatus.Completed))
|
||||
|
||||
val filtered = dao.artistsByName(sourceId, 0, "", downloadedFilter = 1).page()
|
||||
val filtered = dao.artistPages(sourceId, 0, "", downloaded = true).page()
|
||||
assertEquals(listOf("Album Artist", "Guest"), filtered.map { it.name })
|
||||
assertEquals(listOf(1L, 1L), filtered.map { it.albumCount })
|
||||
|
||||
@@ -961,14 +972,14 @@ class LibraryDaoTest {
|
||||
)
|
||||
db.downloadDao().upsert(SongDownload(sourceId, "s1", DownloadStatus.Completed))
|
||||
|
||||
val filtered = dao.artistsByName(sourceId, 0, "", downloadedFilter = 1).page()
|
||||
val filtered = dao.artistPages(sourceId, 0, "", downloaded = true).page()
|
||||
assertEquals(1, filtered.size)
|
||||
assertEquals(1L, filtered.first().albumCount)
|
||||
|
||||
assertEquals(
|
||||
5L,
|
||||
dao
|
||||
.artistsByName(sourceId, 0, "")
|
||||
.artistPages(sourceId, 0, "")
|
||||
.page()
|
||||
.first { it.id == "ar-1" }
|
||||
.albumCount,
|
||||
@@ -1006,7 +1017,7 @@ class LibraryDaoTest {
|
||||
|
||||
// ar-1 has two downloaded albums, ar-2 one, so the downloaded order is ar-1 first even
|
||||
// though the synced counts would put ar-2 first.
|
||||
val filtered = dao.artistsByAlbumCount(sourceId, 0, "", downloadedFilter = 1).page()
|
||||
val filtered = dao.artistPages(sourceId, 0, "", downloaded = true, sort = ArtistSort.AlbumCount).page()
|
||||
assertEquals(listOf("ar-1", "ar-2"), filtered.map { it.id })
|
||||
assertEquals(listOf(2L, 1L), filtered.map { it.albumCount })
|
||||
}
|
||||
@@ -1036,7 +1047,7 @@ class LibraryDaoTest {
|
||||
)
|
||||
db.downloadDao().upsert(SongDownload(sourceId, "s1", DownloadStatus.Completed))
|
||||
|
||||
val filtered = dao.playlistsByName(sourceId, "", downloadedFilter = 1).page()
|
||||
val filtered = dao.playlistPages(sourceId, "", downloaded = true).page()
|
||||
assertEquals(1, filtered.size)
|
||||
assertEquals(1L, filtered.first().songCount)
|
||||
assertEquals("austin", filtered.first().owner)
|
||||
@@ -1045,7 +1056,7 @@ class LibraryDaoTest {
|
||||
assertEquals(
|
||||
5L,
|
||||
dao
|
||||
.playlistsByName(sourceId, "")
|
||||
.playlistPages(sourceId, "")
|
||||
.page()
|
||||
.first { it.id == "pl-1" }
|
||||
.songCount,
|
||||
@@ -1064,11 +1075,11 @@ class LibraryDaoTest {
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(listOf("Gamma"), dao.albumsByName(sourceId, 0, "amm").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumsByName(sourceId, 0, "GAM").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumsByName(sourceId, 0, "ga").page().map { it.name })
|
||||
assertEquals(listOf("Alpha"), dao.albumsByName(sourceId, 0, "Else").page().map { it.name })
|
||||
assertTrue(dao.albumsByName(sourceId, 0, "zzz").page().isEmpty())
|
||||
assertEquals(listOf("Gamma"), dao.albumPages(sourceId, 0, "amm").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumPages(sourceId, 0, "GAM").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumPages(sourceId, 0, "ga").page().map { it.name })
|
||||
assertEquals(listOf("Alpha"), dao.albumPages(sourceId, 0, "Else").page().map { it.name })
|
||||
assertTrue(dao.albumPages(sourceId, 0, "zzz").page().isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1077,17 +1088,17 @@ class LibraryDaoTest {
|
||||
val sourceId = source()
|
||||
val dao = db.libraryDao()
|
||||
dao.upsertAlbums(listOf(album(sourceId, "a", "Gamma", year = null, starred = null)))
|
||||
assertEquals(listOf("Gamma"), dao.albumsByName(sourceId, 0, "gam").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumPages(sourceId, 0, "gam").page().map { it.name })
|
||||
|
||||
dao.setAlbumStar(sourceId, "a", 7)
|
||||
assertEquals(listOf("Gamma"), dao.albumsByName(sourceId, 0, "gam").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumPages(sourceId, 0, "gam").page().map { it.name })
|
||||
|
||||
dao.upsertAlbums(listOf(album(sourceId, "a", "Delta", year = null, starred = null)))
|
||||
assertTrue(dao.albumsByName(sourceId, 0, "gam").page().isEmpty())
|
||||
assertEquals(listOf("Delta"), dao.albumsByName(sourceId, 0, "elt").page().map { it.name })
|
||||
assertTrue(dao.albumPages(sourceId, 0, "gam").page().isEmpty())
|
||||
assertEquals(listOf("Delta"), dao.albumPages(sourceId, 0, "elt").page().map { it.name })
|
||||
|
||||
dao.deleteAlbums(sourceId, listOf("a"))
|
||||
assertTrue(dao.albumsByName(sourceId, 0, "elt").page().isEmpty())
|
||||
assertTrue(dao.albumPages(sourceId, 0, "elt").page().isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1101,8 +1112,8 @@ class LibraryDaoTest {
|
||||
val second = source()
|
||||
dao.upsertAlbums(listOf(album(second, "a", "Beta", year = null, starred = null)))
|
||||
|
||||
assertEquals(listOf("Beta"), dao.albumsByName(second, 0, "eta").page().map { it.name })
|
||||
assertTrue(dao.albumsByName(second, 0, "gam").page().isEmpty())
|
||||
assertEquals(listOf("Beta"), dao.albumPages(second, 0, "eta").page().map { it.name })
|
||||
assertTrue(dao.albumPages(second, 0, "gam").page().isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1113,10 +1124,10 @@ class LibraryDaoTest {
|
||||
dao.upsertArtists(listOf(artist(sourceId, "r1", "The Beatles", albumCount = 1)))
|
||||
dao.upsertPlaylists(listOf(playlist(sourceId, "l1", "Road Trip", created = 0, changed = 0)))
|
||||
|
||||
assertEquals(listOf("r1"), dao.artistsByName(sourceId, 0, "eat").page().map { it.id })
|
||||
assertEquals(listOf("l1"), dao.playlistsByName(sourceId, "rip").page().map { it.id })
|
||||
assertTrue(dao.artistsByName(sourceId, 0, "rip").page().isEmpty())
|
||||
assertTrue(dao.playlistsByName(sourceId, "eat").page().isEmpty())
|
||||
assertEquals(listOf("r1"), dao.artistPages(sourceId, 0, "eat").page().map { it.id })
|
||||
assertEquals(listOf("l1"), dao.playlistPages(sourceId, "rip").page().map { it.id })
|
||||
assertTrue(dao.artistPages(sourceId, 0, "rip").page().isEmpty())
|
||||
assertTrue(dao.playlistPages(sourceId, "eat").page().isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1131,10 +1142,10 @@ class LibraryDaoTest {
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(listOf("Say \"Hello\""), dao.albumsByName(sourceId, 0, "\"Hel").page().map { it.name })
|
||||
assertEquals(listOf("Say \"Hello\""), dao.albumPages(sourceId, 0, "\"Hel").page().map { it.name })
|
||||
assertEquals(
|
||||
listOf("Say \"Hello\""),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "\"Hel", AlbumSort.Name, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "\"Hel", AlbumSort.Name, false).page().map { it.name },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1145,7 +1156,7 @@ class LibraryDaoTest {
|
||||
val dao = db.libraryDao()
|
||||
dao.upsertAlbums(listOf(album(sourceId, "a", "Gamma", year = null, starred = null).copy(albumArtist = null)))
|
||||
|
||||
assertEquals(listOf("Gamma"), dao.albumsByName(sourceId, 0, "amm").page().map { it.name })
|
||||
assertEquals(listOf("Gamma"), dao.albumPages(sourceId, 0, "amm").page().map { it.name })
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1274,35 +1285,35 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta", "Gamma"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "", AlbumSort.Name, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", AlbumSort.Name, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Gamma", "Beta", "Alpha"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "", AlbumSort.Name, true)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", AlbumSort.Name, true).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta", "Gamma"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "", AlbumSort.Year, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", AlbumSort.Year, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Gamma", "Beta", "Alpha"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "", AlbumSort.Artist, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", AlbumSort.Artist, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "alp", AlbumSort.Name, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "alp", AlbumSort.Name, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Gamma"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "am", AlbumSort.Name, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "am", AlbumSort.Name, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 1, "", AlbumSort.Name, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 1, "", AlbumSort.Name, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Beta", "Gamma"),
|
||||
dao.albumsPaging(albumsDefaultQuery(sourceId, 2, "", AlbumSort.Name, false)).page().map { it.name },
|
||||
dao.albumPages(sourceId, 2, "", AlbumSort.Name, false).page().map { it.name },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1326,23 +1337,23 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta"),
|
||||
dao.artistsPaging(artistsDefaultQuery(sourceId, 0, "a", ArtistSort.Name, false)).page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "a", ArtistSort.Name, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Beta", "Alpha"),
|
||||
dao.artistsPaging(artistsDefaultQuery(sourceId, 0, "", ArtistSort.AlbumCount, false)).page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", ArtistSort.AlbumCount, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta"),
|
||||
dao.playlistsPaging(playlistsDefaultQuery(sourceId, "a", PlaylistSort.Name, false)).page().map { it.name },
|
||||
dao.playlistPages(sourceId, "a", PlaylistSort.Name, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Alpha", "Beta"),
|
||||
dao.playlistsPaging(playlistsDefaultQuery(sourceId, "", PlaylistSort.Added, false)).page().map { it.name },
|
||||
dao.playlistPages(sourceId, "", PlaylistSort.Added, false).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Beta", "Alpha"),
|
||||
dao.playlistsPaging(playlistsDefaultQuery(sourceId, "", PlaylistSort.Updated, false)).page().map { it.name },
|
||||
dao.playlistPages(sourceId, "", PlaylistSort.Updated, false).page().map { it.name },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1355,12 +1366,12 @@ class LibraryDaoTest {
|
||||
dao.upsertSongs(listOf(song(sourceId, "s1", "One", starred = null).copy(albumId = "a")))
|
||||
|
||||
val defaultInvalidated = AtomicBoolean(false)
|
||||
val default = dao.albumsPaging(albumsDefaultQuery(sourceId, 0, "", AlbumSort.Name, false))
|
||||
val default = dao.albumPages(sourceId, 0, "", AlbumSort.Name, false)
|
||||
default.registerInvalidatedCallback { defaultInvalidated.set(true) }
|
||||
default.page()
|
||||
|
||||
val downloadedInvalidated = AtomicBoolean(false)
|
||||
val downloaded = dao.albumsByName(sourceId, 0, "", downloadedFilter = 1)
|
||||
val downloaded = dao.albumPages(sourceId, 0, "", downloaded = true)
|
||||
downloaded.registerInvalidatedCallback { downloadedInvalidated.set(true) }
|
||||
downloaded.page()
|
||||
|
||||
@@ -1395,27 +1406,27 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("宇多田ヒカル", "あいみょん"),
|
||||
dao.artistsByName(sourceId, 0, "").page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "").page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("あいみょん", "宇多田ヒカル"),
|
||||
dao.artistsByNameReversed(sourceId, 0, "").page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", descending = true).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Zzz", "Aaa"),
|
||||
dao.albumsByName(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "").page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Aaa", "Zzz"),
|
||||
dao.albumsByNameReversed(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", descending = true).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Aaa", "Zzz"),
|
||||
dao.albumsByArtist(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Artist).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Zzz", "Aaa"),
|
||||
dao.albumsByArtistReversed(sourceId, 0, "").page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", sort = AlbumSort.Artist, descending = true).page().map { it.name },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1445,40 +1456,48 @@ class LibraryDaoTest {
|
||||
|
||||
assertEquals(
|
||||
listOf("宇多田ヒカル", "Zebra", "Beatles", "あいみょん"),
|
||||
dao.artistsByName(sourceId, 0, "", sortMode = SortNameMode.SortName.name).page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", sortNameMode = SortNameMode.SortName).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Beatles", "Zebra", "あいみょん", "宇多田ヒカル"),
|
||||
dao.artistsByName(sourceId, 0, "", sortMode = SortNameMode.Name.name).page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", sortNameMode = SortNameMode.Name).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("宇多田ヒカル", "あいみょん", "Zebra", "Beatles"),
|
||||
dao.artistsByNameReversed(sourceId, 0, "", sortMode = SortNameMode.Name.name).page().map { it.name },
|
||||
dao
|
||||
.artistPages(sourceId, 0, "", descending = true, sortNameMode = SortNameMode.Name)
|
||||
.page()
|
||||
.map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("宇多田ヒカル", "Beatles", "Zebra", "あいみょん"),
|
||||
dao.artistsByName(sourceId, 0, "", sortMode = SortNameMode.NonLatin.name).page().map { it.name },
|
||||
dao.artistPages(sourceId, 0, "", sortNameMode = SortNameMode.NonLatin).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Aaa", "Beatles", "Zzz"),
|
||||
dao.albumsByName(sourceId, 0, "", sortMode = SortNameMode.Name.name).page().map { it.name },
|
||||
dao.albumPages(sourceId, 0, "", sortNameMode = SortNameMode.Name).page().map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Aaa", "Zzz", "Beatles"),
|
||||
dao.albumsByArtist(sourceId, 0, "", sortMode = SortNameMode.Name.name).page().map { it.name },
|
||||
dao
|
||||
.albumPages(sourceId, 0, "", sort = AlbumSort.Artist, sortNameMode = SortNameMode.Name)
|
||||
.page()
|
||||
.map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Beatles", "Zebra", "あいみょん", "宇多田ヒカル"),
|
||||
dao
|
||||
.artistsPaging(artistsDefaultQuery(sourceId, 0, "", ArtistSort.Name, false, SortNameMode.Name))
|
||||
.page()
|
||||
.artistsPaging(
|
||||
artistsPageQuery(sourceId, 0, "", ArtistSort.Name, false, false, SortNameMode.Name),
|
||||
).page()
|
||||
.map { it.name },
|
||||
)
|
||||
assertEquals(
|
||||
listOf("Aaa", "Beatles", "Zzz"),
|
||||
dao
|
||||
.albumsPaging(albumsDefaultQuery(sourceId, 0, "", AlbumSort.Name, false, SortNameMode.Name))
|
||||
.page()
|
||||
.albumsPaging(
|
||||
albumsPageQuery(sourceId, 0, "", AlbumSort.Name, false, false, SortNameMode.Name),
|
||||
).page()
|
||||
.map { it.name },
|
||||
)
|
||||
}
|
||||
@@ -1507,11 +1526,11 @@ class LibraryDaoTest {
|
||||
),
|
||||
)
|
||||
|
||||
assertEquals(listOf("宇多田ヒカル"), dao.artistsByName(sourceId, 0, "utada").page().map { it.name })
|
||||
assertEquals(listOf("宇多田ヒカル"), dao.artistsByName(sourceId, 0, "ut").page().map { it.name })
|
||||
assertEquals(listOf("宇多田ヒカル"), dao.artistPages(sourceId, 0, "utada").page().map { it.name })
|
||||
assertEquals(listOf("宇多田ヒカル"), dao.artistPages(sourceId, 0, "ut").page().map { it.name })
|
||||
assertEquals(listOf("宇多田ヒカル"), dao.searchArtists(sourceId, "utada", 10).first().map { it.name })
|
||||
assertEquals(listOf("First Love"), dao.albumsByName(sourceId, 0, "first").page().map { it.name })
|
||||
assertEquals(listOf("First Love"), dao.albumsByName(sourceId, 0, "fi").page().map { it.name })
|
||||
assertEquals(listOf("First Love"), dao.albumPages(sourceId, 0, "first").page().map { it.name })
|
||||
assertEquals(listOf("First Love"), dao.albumPages(sourceId, 0, "fi").page().map { it.name })
|
||||
assertEquals(listOf("First Love"), dao.searchAlbums(sourceId, "first", 10).first().map { it.name })
|
||||
assertEquals(listOf("Automatic"), dao.searchSongs(sourceId, "utada", 10).first().map { it.song.title })
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.subtracks.data.db
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.data.prefs.AlbumSort
|
||||
import com.subtracks.data.prefs.ArtistSort
|
||||
import com.subtracks.data.prefs.PlaylistSort
|
||||
import com.subtracks.data.prefs.SortNameMode
|
||||
|
||||
internal fun LibraryDao.albumPages(
|
||||
sourceId: Long,
|
||||
starredFilter: Int = 0,
|
||||
search: String = "",
|
||||
sort: AlbumSort = AlbumSort.Name,
|
||||
descending: Boolean = false,
|
||||
downloaded: Boolean = false,
|
||||
sortNameMode: SortNameMode = SortNameMode.SortName,
|
||||
): PagingSource<Int, Album> =
|
||||
if (downloaded) {
|
||||
downloadedAlbumsPaging(albumsPageQuery(sourceId, starredFilter, search, sort, descending, true, sortNameMode))
|
||||
} else {
|
||||
albumsPaging(albumsPageQuery(sourceId, starredFilter, search, sort, descending, false, sortNameMode))
|
||||
}
|
||||
|
||||
internal fun LibraryDao.artistPages(
|
||||
sourceId: Long,
|
||||
starredFilter: Int = 0,
|
||||
search: String = "",
|
||||
sort: ArtistSort = ArtistSort.Name,
|
||||
descending: Boolean = false,
|
||||
downloaded: Boolean = false,
|
||||
sortNameMode: SortNameMode = SortNameMode.SortName,
|
||||
): PagingSource<Int, Artist> =
|
||||
if (downloaded) {
|
||||
downloadedArtistsPaging(artistsPageQuery(sourceId, starredFilter, search, sort, descending, true, sortNameMode))
|
||||
} else {
|
||||
artistsPaging(artistsPageQuery(sourceId, starredFilter, search, sort, descending, false, sortNameMode))
|
||||
}
|
||||
|
||||
internal fun LibraryDao.playlistPages(
|
||||
sourceId: Long,
|
||||
search: String = "",
|
||||
sort: PlaylistSort = PlaylistSort.Name,
|
||||
descending: Boolean = false,
|
||||
downloaded: Boolean = false,
|
||||
): PagingSource<Int, Playlist> =
|
||||
if (downloaded) {
|
||||
downloadedPlaylistsPaging(playlistsPageQuery(sourceId, search, sort, descending, true))
|
||||
} else {
|
||||
playlistsPaging(playlistsPageQuery(sourceId, search, sort, descending, false))
|
||||
}
|
||||
@@ -14,6 +14,9 @@ import com.subtracks.data.model.Playlist
|
||||
import com.subtracks.data.model.PlaylistSong
|
||||
import com.subtracks.data.model.Song
|
||||
import com.subtracks.data.model.Source
|
||||
import com.subtracks.data.prefs.AlbumSort
|
||||
import com.subtracks.data.prefs.ArtistSort
|
||||
import com.subtracks.data.prefs.PlaylistSort
|
||||
import com.subtracks.data.source.MusicSource
|
||||
import com.subtracks.data.source.StarType
|
||||
import com.subtracks.data.sync.SyncService
|
||||
@@ -110,28 +113,31 @@ class QueryTimingMeasurementTest {
|
||||
|
||||
private suspend fun measureReads() {
|
||||
val dao = db.libraryDao()
|
||||
timed("albums first page (name)") { dao.albumsByName(1, 0, "").firstPage() }
|
||||
timed("albums first page (artist)") { dao.albumsByArtist(1, 0, "").firstPage() }
|
||||
timed("albums first page (year)") { dao.albumsByYear(1, 0, "").firstPage() }
|
||||
timed("albums first page (added)") { dao.albumsByRecentlyAdded(1, 0, "").firstPage() }
|
||||
timed("albums first page (starred)") { dao.albumsByStarred(1, 0, "").firstPage() }
|
||||
timed("albums first page (frequent)") { dao.albumsByFrequent(1, 0, "").firstPage() }
|
||||
timed("albums first page (recent)") { dao.albumsByRecent(1, 0, "").firstPage() }
|
||||
timed("artists first page (name)") { dao.artistsByName(1, 0, "").firstPage() }
|
||||
timed("artists first page (frequent)") { dao.artistsByFrequent(1, 0, "").firstPage() }
|
||||
timed("albums first page (name)") { dao.albumPages(1, 0, "", sort = AlbumSort.Name, downloaded = true).firstPage() }
|
||||
timed("albums first page (name, default)") { dao.albumPages(1, 0, "", sort = AlbumSort.Name).firstPage() }
|
||||
timed("albums first page (artist)") { dao.albumPages(1, 0, "", sort = AlbumSort.Artist, downloaded = true).firstPage() }
|
||||
timed("albums first page (year)") { dao.albumPages(1, 0, "", sort = AlbumSort.Year, downloaded = true).firstPage() }
|
||||
timed("albums first page (added)") { dao.albumPages(1, 0, "", sort = AlbumSort.Added, downloaded = true).firstPage() }
|
||||
timed("albums first page (starred)") { dao.albumPages(1, 0, "", sort = AlbumSort.Starred, downloaded = true).firstPage() }
|
||||
timed("albums first page (frequent)") { dao.albumPages(1, 0, "", sort = AlbumSort.Frequent, downloaded = true).firstPage() }
|
||||
timed("albums first page (recent)") { dao.albumPages(1, 0, "", sort = AlbumSort.Recent, downloaded = true).firstPage() }
|
||||
timed("artists first page (name)") { dao.artistPages(1, 0, "", sort = ArtistSort.Name, downloaded = true).firstPage() }
|
||||
timed("artists first page (name, default)") { dao.artistPages(1, 0, "", sort = ArtistSort.Name).firstPage() }
|
||||
timed("artists first page (frequent)") { dao.artistPages(1, 0, "", sort = ArtistSort.Frequent, downloaded = true).firstPage() }
|
||||
timed("artist albums") { dao.albumsForArtist(1, "ar0").first() }
|
||||
timed("artist name") { dao.artistName(1, "ar0").first() }
|
||||
timed("artist songs") { db.queueDao().artistSongs(1, "ar0", 0, 100) }
|
||||
timed("artist length") { db.queueDao().artistLength(1, "ar0") }
|
||||
timed("artist song ids") { db.queueDao().artistSongIds(1, "ar0") }
|
||||
timed("downloaded artists") { dao.downloadedArtists(1).firstPage() }
|
||||
timed("artists downloaded filter") { dao.artistsByName(1, 0, "", downloadedFilter = 1).firstPage() }
|
||||
timed("artists downloaded filter") { dao.artistPages(1, 0, "", downloaded = true).firstPage() }
|
||||
timed("artist statuses") { db.downloadDao().artistStatuses(1).first() }
|
||||
timed("artist status") { db.downloadDao().artistStatus(1, "ar0").first() }
|
||||
timed("playlists first page (name)") { dao.playlistsByName(1, "").firstPage() }
|
||||
timed("albums deep page") { dao.albumsByName(1, 0, "").deepPage(1000) }
|
||||
timed("albums search FTS") { dao.albumsByName(1, 0, "Album 1").firstPage() }
|
||||
timed("albums search short") { dao.albumsByName(1, 0, "al").firstPage() }
|
||||
timed("playlists first page (name)") { dao.playlistPages(1, "", sort = PlaylistSort.Name, downloaded = true).firstPage() }
|
||||
timed("playlists first page (name, default)") { dao.playlistPages(1, "", sort = PlaylistSort.Name).firstPage() }
|
||||
timed("albums deep page") { dao.albumPages(1, 0, "", sort = AlbumSort.Name, downloaded = true).deepPage(1000) }
|
||||
timed("albums search FTS") { dao.albumPages(1, 0, "Album 1", sort = AlbumSort.Name, downloaded = true).firstPage() }
|
||||
timed("albums search short") { dao.albumPages(1, 0, "al", sort = AlbumSort.Name, downloaded = true).firstPage() }
|
||||
timed("songs search FTS") { dao.searchSongs(1, "Song", 50).first() }
|
||||
timed("home recently played") { dao.recentlyPlayedAlbums(1, 20).first() }
|
||||
timed("home most played") { dao.mostPlayedAlbums(1, 20).first() }
|
||||
|
||||
@@ -10,7 +10,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.subtracks.data.db.LoggingSQLiteDriver
|
||||
import com.subtracks.data.db.SqlExecution
|
||||
import com.subtracks.data.db.SubtracksDatabase
|
||||
import com.subtracks.data.db.artistsDefaultQuery
|
||||
import com.subtracks.data.db.artistPages
|
||||
import com.subtracks.data.db.artistsPageQuery
|
||||
import com.subtracks.data.model.Album
|
||||
import com.subtracks.data.model.Artist
|
||||
import com.subtracks.data.model.ArtistRef
|
||||
@@ -75,7 +76,7 @@ class SyncServiceTest {
|
||||
2,
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.size,
|
||||
)
|
||||
@@ -98,7 +99,7 @@ class SyncServiceTest {
|
||||
listOf("a1"),
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.map { it.id },
|
||||
)
|
||||
@@ -172,7 +173,7 @@ class SyncServiceTest {
|
||||
"Old",
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.single()
|
||||
.name,
|
||||
@@ -185,7 +186,7 @@ class SyncServiceTest {
|
||||
"New",
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.single()
|
||||
.name,
|
||||
@@ -1107,16 +1108,16 @@ class SyncServiceTest {
|
||||
listOf("a1"),
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.map { it.id },
|
||||
)
|
||||
val query = artistsDefaultQuery(1, 0, "alpha", ArtistSort.Name, false)
|
||||
val query = artistsPageQuery(1, 0, "alpha", ArtistSort.Name, false, false)
|
||||
assertEquals(
|
||||
listOf("a1"),
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "alpha")
|
||||
.artistPages(1, 0, "alpha")
|
||||
.allRows()
|
||||
.map { it.id },
|
||||
)
|
||||
@@ -1203,7 +1204,7 @@ class SyncServiceTest {
|
||||
listOf("a1", "combo"),
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.map { it.id },
|
||||
)
|
||||
@@ -1216,7 +1217,7 @@ class SyncServiceTest {
|
||||
listOf("a1"),
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.map { it.id },
|
||||
)
|
||||
@@ -1434,7 +1435,7 @@ class SyncServiceTest {
|
||||
SyncService(db, source).sync()
|
||||
db.downloadDao().upsert(SongDownload(1, "s1", DownloadStatus.Completed))
|
||||
|
||||
val filtered = db.libraryDao().artistsByName(1, 0, "", downloadedFilter = 1).allRows()
|
||||
val filtered = db.libraryDao().artistPages(1, 0, "", downloaded = true).allRows()
|
||||
assertEquals(listOf("A", "B"), filtered.map { it.name })
|
||||
assertEquals(listOf(1L, 1L), filtered.map { it.albumCount })
|
||||
assertEquals(ListDownloadStatus(total = 1, downloaded = 1), db.downloadDao().artistStatus(1, "a2").first())
|
||||
@@ -1538,7 +1539,7 @@ class SyncServiceTest {
|
||||
albums.size.toLong(),
|
||||
db
|
||||
.libraryDao()
|
||||
.artistsByName(1, 0, "")
|
||||
.artistPages(1, 0, "")
|
||||
.allRows()
|
||||
.first { it.id == "a2" }
|
||||
.albumCount,
|
||||
@@ -1780,7 +1781,7 @@ class SyncServiceTest {
|
||||
assertEquals("$artistId downloaded", downloaded.toLong(), status.downloaded)
|
||||
}
|
||||
|
||||
val downloadedArtists = db.libraryDao().artistsByName(1, 0, "", downloadedFilter = 1).allRows()
|
||||
val downloadedArtists = db.libraryDao().artistPages(1, 0, "", downloaded = true).allRows()
|
||||
for (artist in downloadedArtists) {
|
||||
assertEquals(
|
||||
"${artist.id} downloaded albums",
|
||||
|
||||
Reference in New Issue
Block a user