mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 23:21:59 +01:00
index the album, artist and playlist list sorts
This commit is contained in:
@@ -23,6 +23,48 @@ internal const val PLAYLIST_SONGS_SQL =
|
||||
"WHERE playlist_songs.sourceId = :sourceId AND playlist_songs.playlistId = :playlistId " +
|
||||
"ORDER BY playlist_songs.position"
|
||||
|
||||
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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) "
|
||||
|
||||
internal const val ALBUM_ORDER_BY_NAME = "name COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_NAME_REVERSED = "name COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ALBUM_ORDER_BY_ARTIST = "albumArtist COLLATE NOCASE, year, name COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_ARTIST_REVERSED = "albumArtist COLLATE NOCASE DESC, year DESC, name COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ALBUM_ORDER_BY_YEAR = "year DESC, name COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_YEAR_REVERSED = "year ASC, name COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ALBUM_ORDER_BY_ADDED = "created DESC, name COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_ADDED_REVERSED = "created ASC, name COLLATE NOCASE DESC, id DESC"
|
||||
|
||||
// Starred orders keep unstarred rows last in both directions, matching the list grouping, so the
|
||||
// reversed order is not a literal mirror of the base order.
|
||||
internal const val ALBUM_ORDER_BY_STARRED = "starred DESC NULLS LAST, name COLLATE NOCASE, id"
|
||||
internal const val ALBUM_ORDER_BY_STARRED_REVERSED = "starred ASC NULLS LAST, name COLLATE NOCASE DESC, id DESC"
|
||||
|
||||
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 (:search = '' OR instr(lower(name), lower(:search)) > 0) "
|
||||
|
||||
internal const val ARTIST_ORDER_BY_NAME = "name COLLATE NOCASE, id"
|
||||
internal const val ARTIST_ORDER_BY_NAME_REVERSED = "name COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ARTIST_ORDER_BY_ALBUM_COUNT = "albumCount DESC, name COLLATE NOCASE, id"
|
||||
internal const val ARTIST_ORDER_BY_ALBUM_COUNT_REVERSED = "albumCount ASC, name COLLATE NOCASE DESC, id DESC"
|
||||
internal const val ARTIST_ORDER_BY_STARRED = "starred DESC NULLS LAST, name COLLATE NOCASE, id"
|
||||
internal const val ARTIST_ORDER_BY_STARRED_REVERSED = "starred ASC NULLS LAST, name COLLATE NOCASE DESC, id DESC"
|
||||
|
||||
internal const val PLAYLISTS_FILTER =
|
||||
"FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) "
|
||||
|
||||
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"
|
||||
internal const val PLAYLIST_ORDER_BY_ADDED_REVERSED = "created ASC, name COLLATE NOCASE DESC, id DESC"
|
||||
internal const val PLAYLIST_ORDER_BY_UPDATED = "changed DESC, name COLLATE NOCASE, id"
|
||||
internal const val PLAYLIST_ORDER_BY_UPDATED_REVERSED = "changed ASC, name COLLATE NOCASE DESC, id DESC"
|
||||
|
||||
@Dao
|
||||
@DaoReturnTypeConverters(PagingSourceDaoReturnTypeConverter::class)
|
||||
interface LibraryDao {
|
||||
@@ -155,253 +197,149 @@ interface LibraryDao {
|
||||
)
|
||||
suspend fun deleteOrphanPlaylistSongs(sourceId: Long)
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_NAME")
|
||||
fun albumsByName(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY name COLLATE NOCASE DESC, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_NAME_REVERSED")
|
||||
fun albumsByNameReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY albumArtist COLLATE NOCASE, year, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ARTIST")
|
||||
fun albumsByArtist(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY albumArtist COLLATE NOCASE DESC, year DESC, name COLLATE NOCASE DESC, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ARTIST_REVERSED")
|
||||
fun albumsByArtistReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY year DESC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_YEAR")
|
||||
fun albumsByYear(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY year ASC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_YEAR_REVERSED")
|
||||
fun albumsByYearReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY created DESC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ADDED")
|
||||
fun albumsByRecentlyAdded(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY created ASC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_ADDED_REVERSED")
|
||||
fun albumsByRecentlyAddedReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY starred IS NULL, starred DESC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_STARRED")
|
||||
fun albumsByStarred(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * 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 instr(lower(name), lower(:search)) > 0 OR instr(lower(albumArtist), lower(:search)) > 0) " +
|
||||
"ORDER BY starred IS NULL, starred ASC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ALBUMS_FILTER ORDER BY $ALBUM_ORDER_BY_STARRED_REVERSED")
|
||||
fun albumsByStarredReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Album>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM artists WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_NAME")
|
||||
fun artistsByName(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM artists WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY name COLLATE NOCASE DESC, id",
|
||||
)
|
||||
@Query("SELECT * $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_NAME_REVERSED")
|
||||
fun artistsByNameReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM artists WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY albumCount DESC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_ALBUM_COUNT")
|
||||
fun artistsByAlbumCount(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM artists WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY albumCount ASC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_ALBUM_COUNT_REVERSED")
|
||||
fun artistsByAlbumCountReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM artists WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY starred IS NULL, starred DESC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_STARRED")
|
||||
fun artistsByStarred(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM artists WHERE sourceId = :sourceId " +
|
||||
"AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY starred IS NULL, starred ASC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $ARTISTS_FILTER ORDER BY $ARTIST_ORDER_BY_STARRED_REVERSED")
|
||||
fun artistsByStarredReversed(
|
||||
sourceId: Long,
|
||||
starredFilter: Int,
|
||||
search: String,
|
||||
): PagingSource<Int, Artist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_NAME")
|
||||
fun playlistsByName(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY name COLLATE NOCASE DESC, id",
|
||||
)
|
||||
@Query("SELECT * $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_NAME_REVERSED")
|
||||
fun playlistsByNameReversed(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY created DESC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_ADDED")
|
||||
fun playlistsByAdded(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY created ASC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_ADDED_REVERSED")
|
||||
fun playlistsByAddedReversed(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY changed DESC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_UPDATED")
|
||||
fun playlistsByUpdated(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
): PagingSource<Int, Playlist>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM playlists WHERE sourceId = :sourceId " +
|
||||
"AND (:search = '' OR instr(lower(name), lower(:search)) > 0) " +
|
||||
"ORDER BY changed ASC, name COLLATE NOCASE, id",
|
||||
)
|
||||
@Query("SELECT * $PLAYLISTS_FILTER ORDER BY $PLAYLIST_ORDER_BY_UPDATED_REVERSED")
|
||||
fun playlistsByUpdatedReversed(
|
||||
sourceId: Long,
|
||||
search: String,
|
||||
|
||||
@@ -135,6 +135,87 @@ val MIGRATION_13_14 =
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_14_15 =
|
||||
object : Migration(14, 15) {
|
||||
override suspend fun migrate(connection: SQLiteConnection) {
|
||||
rebuildTable(connection, "albums", ALBUMS_V14, ALBUMS_V14_COPY, ALBUMS_V14_INDICES)
|
||||
rebuildTable(connection, "artists", ARTISTS_V14, ARTISTS_V14_COPY, ARTISTS_V14_INDICES)
|
||||
rebuildTable(connection, "playlists", PLAYLISTS_V14, PLAYLISTS_V14_COPY, PLAYLISTS_V14_INDICES)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun rebuildTable(
|
||||
connection: SQLiteConnection,
|
||||
table: String,
|
||||
createSql: String,
|
||||
copySql: String,
|
||||
indices: List<String>,
|
||||
) {
|
||||
val temp = "${table}_new"
|
||||
connection.execSQL(createSql.replace("\${TABLE_NAME}", temp))
|
||||
connection.execSQL(copySql.replace("\${TABLE_NAME}", temp))
|
||||
connection.execSQL("DROP TABLE `$table`")
|
||||
connection.execSQL("ALTER TABLE `$temp` RENAME TO `$table`")
|
||||
indices.forEach { connection.execSQL(it.replace("\${TABLE_NAME}", table)) }
|
||||
}
|
||||
|
||||
private const val ALBUMS_V14 =
|
||||
"CREATE TABLE IF NOT EXISTS `\${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, `artistId` TEXT, " +
|
||||
"`name` TEXT NOT NULL COLLATE NOCASE, `albumArtist` TEXT COLLATE NOCASE, `created` INTEGER NOT NULL, " +
|
||||
"`coverArt` TEXT, `genre` TEXT, `year` INTEGER, `starred` INTEGER, `songCount` INTEGER NOT NULL, " +
|
||||
"PRIMARY KEY(`sourceId`, `id`), " +
|
||||
"FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"
|
||||
|
||||
private const val ALBUMS_V14_COPY =
|
||||
"INSERT INTO `\${TABLE_NAME}` (sourceId, id, artistId, name, albumArtist, created, coverArt, genre, year, starred, songCount) " +
|
||||
"SELECT sourceId, id, artistId, name, albumArtist, created, coverArt, genre, year, starred, songCount FROM `albums`"
|
||||
|
||||
private val ALBUMS_V14_INDICES =
|
||||
listOf(
|
||||
"CREATE INDEX IF NOT EXISTS `index_albums_sourceId` ON `\${TABLE_NAME}` (`sourceId`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_albums_sourceId_artistId` ON `\${TABLE_NAME}` (`sourceId`, `artistId`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_albums_name` ON `\${TABLE_NAME}` (`sourceId`, `name`, `id`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_albums_artist` ON `\${TABLE_NAME}` (`sourceId`, `albumArtist`, `year`, `name`, `id`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_albums_year` ON `\${TABLE_NAME}` (`sourceId` ASC, `year` DESC, `name` ASC, `id` ASC)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_albums_added` ON `\${TABLE_NAME}` (`sourceId` ASC, `created` DESC, `name` ASC, `id` ASC)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_albums_starred` ON `\${TABLE_NAME}` (`sourceId` ASC, `starred` DESC, `name` ASC, `id` ASC)",
|
||||
)
|
||||
|
||||
private const val ARTISTS_V14 =
|
||||
"CREATE TABLE IF NOT EXISTS `\${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, " +
|
||||
"`name` TEXT NOT NULL COLLATE NOCASE, `albumCount` INTEGER NOT NULL, `starred` INTEGER, `coverArt` TEXT, " +
|
||||
"PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"
|
||||
|
||||
private const val ARTISTS_V14_COPY =
|
||||
"INSERT INTO `\${TABLE_NAME}` (sourceId, id, name, albumCount, starred, coverArt) " +
|
||||
"SELECT sourceId, id, name, albumCount, starred, coverArt FROM `artists`"
|
||||
|
||||
private val ARTISTS_V14_INDICES =
|
||||
listOf(
|
||||
"CREATE INDEX IF NOT EXISTS `index_artists_sourceId` ON `\${TABLE_NAME}` (`sourceId`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_artists_name` ON `\${TABLE_NAME}` (`sourceId`, `name`, `id`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_artists_albumCount` ON `\${TABLE_NAME}` (`sourceId` ASC, `albumCount` DESC, `name` ASC, `id` ASC)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_artists_starred` ON `\${TABLE_NAME}` (`sourceId` ASC, `starred` DESC, `name` ASC, `id` ASC)",
|
||||
)
|
||||
|
||||
private const val PLAYLISTS_V14 =
|
||||
"CREATE TABLE IF NOT EXISTS `\${TABLE_NAME}` (`sourceId` INTEGER NOT NULL, `id` TEXT NOT NULL, " +
|
||||
"`name` TEXT NOT NULL COLLATE NOCASE, `comment` TEXT, `coverArt` TEXT, `songCount` INTEGER NOT NULL, " +
|
||||
"`created` INTEGER NOT NULL, `changed` INTEGER NOT NULL DEFAULT 0, `duration` INTEGER NOT NULL DEFAULT 0, " +
|
||||
"PRIMARY KEY(`sourceId`, `id`), FOREIGN KEY(`sourceId`) REFERENCES `sources`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )"
|
||||
|
||||
private const val PLAYLISTS_V14_COPY =
|
||||
"INSERT INTO `\${TABLE_NAME}` (sourceId, id, name, comment, coverArt, songCount, created, changed, duration) " +
|
||||
"SELECT sourceId, id, name, comment, coverArt, songCount, created, changed, duration FROM `playlists`"
|
||||
|
||||
private val PLAYLISTS_V14_INDICES =
|
||||
listOf(
|
||||
"CREATE INDEX IF NOT EXISTS `index_playlists_sourceId` ON `\${TABLE_NAME}` (`sourceId`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_playlists_name` ON `\${TABLE_NAME}` (`sourceId`, `name`, `id`)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_playlists_added` ON `\${TABLE_NAME}` (`sourceId` ASC, `created` DESC, `name` ASC, `id` ASC)",
|
||||
"CREATE INDEX IF NOT EXISTS `index_playlists_updated` ON `\${TABLE_NAME}` (`sourceId` ASC, `changed` DESC, `name` ASC, `id` ASC)",
|
||||
)
|
||||
|
||||
val MIGRATIONS: Array<Migration> =
|
||||
arrayOf(
|
||||
MIGRATION_1_2,
|
||||
@@ -150,4 +231,5 @@ val MIGRATIONS: Array<Migration> =
|
||||
MIGRATION_11_12,
|
||||
MIGRATION_12_13,
|
||||
MIGRATION_13_14,
|
||||
MIGRATION_14_15,
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.subtracks.data.model.SubsonicSource
|
||||
ShuffleOrder::class,
|
||||
ArtworkSeed::class,
|
||||
],
|
||||
version = 14,
|
||||
version = 15,
|
||||
exportSchema = true,
|
||||
)
|
||||
@ColumnTypeConverters(QueueKindConverter::class)
|
||||
|
||||
@@ -48,12 +48,25 @@ data class SubsonicSource(
|
||||
onDelete = ForeignKey.CASCADE,
|
||||
),
|
||||
],
|
||||
indices = [Index("sourceId")],
|
||||
indices = [
|
||||
Index("sourceId"),
|
||||
Index(name = "index_artists_name", value = ["sourceId", "name", "id"]),
|
||||
Index(
|
||||
name = "index_artists_albumCount",
|
||||
value = ["sourceId", "albumCount", "name", "id"],
|
||||
orders = [Index.Order.ASC, Index.Order.DESC, Index.Order.ASC, Index.Order.ASC],
|
||||
),
|
||||
Index(
|
||||
name = "index_artists_starred",
|
||||
value = ["sourceId", "starred", "name", "id"],
|
||||
orders = [Index.Order.ASC, Index.Order.DESC, Index.Order.ASC, Index.Order.ASC],
|
||||
),
|
||||
],
|
||||
)
|
||||
data class Artist(
|
||||
val sourceId: Long,
|
||||
val id: String,
|
||||
val name: String,
|
||||
@ColumnInfo(collate = ColumnInfo.NOCASE) val name: String,
|
||||
val albumCount: Long,
|
||||
val starred: Long?,
|
||||
val coverArt: String? = null,
|
||||
@@ -70,14 +83,34 @@ data class Artist(
|
||||
onDelete = ForeignKey.CASCADE,
|
||||
),
|
||||
],
|
||||
indices = [Index("sourceId"), Index("sourceId", "artistId")],
|
||||
indices = [
|
||||
Index("sourceId"),
|
||||
Index("sourceId", "artistId"),
|
||||
Index(name = "index_albums_name", value = ["sourceId", "name", "id"]),
|
||||
Index(name = "index_albums_artist", value = ["sourceId", "albumArtist", "year", "name", "id"]),
|
||||
Index(
|
||||
name = "index_albums_year",
|
||||
value = ["sourceId", "year", "name", "id"],
|
||||
orders = [Index.Order.ASC, Index.Order.DESC, Index.Order.ASC, Index.Order.ASC],
|
||||
),
|
||||
Index(
|
||||
name = "index_albums_added",
|
||||
value = ["sourceId", "created", "name", "id"],
|
||||
orders = [Index.Order.ASC, Index.Order.DESC, Index.Order.ASC, Index.Order.ASC],
|
||||
),
|
||||
Index(
|
||||
name = "index_albums_starred",
|
||||
value = ["sourceId", "starred", "name", "id"],
|
||||
orders = [Index.Order.ASC, Index.Order.DESC, Index.Order.ASC, Index.Order.ASC],
|
||||
),
|
||||
],
|
||||
)
|
||||
data class Album(
|
||||
val sourceId: Long,
|
||||
val id: String,
|
||||
val artistId: String?,
|
||||
val name: String,
|
||||
val albumArtist: String?,
|
||||
@ColumnInfo(collate = ColumnInfo.NOCASE) val name: String,
|
||||
@ColumnInfo(collate = ColumnInfo.NOCASE) val albumArtist: String?,
|
||||
val created: Long,
|
||||
val coverArt: String?,
|
||||
val genre: String?,
|
||||
@@ -118,12 +151,25 @@ data class Disc(
|
||||
onDelete = ForeignKey.CASCADE,
|
||||
),
|
||||
],
|
||||
indices = [Index("sourceId")],
|
||||
indices = [
|
||||
Index("sourceId"),
|
||||
Index(name = "index_playlists_name", value = ["sourceId", "name", "id"]),
|
||||
Index(
|
||||
name = "index_playlists_added",
|
||||
value = ["sourceId", "created", "name", "id"],
|
||||
orders = [Index.Order.ASC, Index.Order.DESC, Index.Order.ASC, Index.Order.ASC],
|
||||
),
|
||||
Index(
|
||||
name = "index_playlists_updated",
|
||||
value = ["sourceId", "changed", "name", "id"],
|
||||
orders = [Index.Order.ASC, Index.Order.DESC, Index.Order.ASC, Index.Order.ASC],
|
||||
),
|
||||
],
|
||||
)
|
||||
data class Playlist(
|
||||
val sourceId: Long,
|
||||
val id: String,
|
||||
val name: String,
|
||||
@ColumnInfo(collate = ColumnInfo.NOCASE) val name: String,
|
||||
val comment: String?,
|
||||
val coverArt: String?,
|
||||
val songCount: Long,
|
||||
|
||||
@@ -285,7 +285,7 @@ private suspend fun <T> PooledConnection.upsertChanged(
|
||||
"ON CONFLICT(${key.joinToString()}) DO UPDATE SET " +
|
||||
updates.joinToString { "$it = excluded.$it" } +
|
||||
" WHERE " +
|
||||
updates.joinToString(" OR ") { "$table.$it IS NOT excluded.$it" }
|
||||
updates.joinToString(" OR ") { "$table.$it COLLATE BINARY IS NOT excluded.$it" }
|
||||
usePrepared(sql) { statement ->
|
||||
rows.forEach { row ->
|
||||
values(row).forEachIndexed { index, value -> statement.bind(index + 1, value) }
|
||||
|
||||
Reference in New Issue
Block a user