Tweak library query (#8214)
* Tweak library query Co-Authored-By: Quang Kieu <kieuq@wit.edu> * Update app/src/main/sqldelight/migrations/21.sqm * Update app/src/main/java/eu/kanade/domain/library/model/LibraryManga.kt * Update app/src/main/sqldelight/view/libraryView.sq * Update app/src/main/java/eu/kanade/data/manga/MangaMapper.kt * Update app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt * Update app/src/main/java/eu/kanade/data/manga/MangaMapper.kt * Bump version Co-authored-by: Quang Kieu <kieuq@wit.edu>
This commit is contained in:
parent
aea0cadbfb
commit
d6cbff2837
@ -27,7 +27,7 @@ android {
|
|||||||
applicationId = "eu.kanade.tachiyomi"
|
applicationId = "eu.kanade.tachiyomi"
|
||||||
minSdk = AndroidConfig.minSdk
|
minSdk = AndroidConfig.minSdk
|
||||||
targetSdk = AndroidConfig.targetSdk
|
targetSdk = AndroidConfig.targetSdk
|
||||||
versionCode = 86
|
versionCode = 87
|
||||||
versionName = "0.13.6"
|
versionName = "0.13.6"
|
||||||
|
|
||||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||||
|
@ -5,14 +5,14 @@ import eu.kanade.domain.manga.model.Manga
|
|||||||
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
|
|
||||||
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy) -> Manga =
|
val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy) -> Manga =
|
||||||
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, _, initialized, viewer, chapterFlags, coverLastModified, dateAdded, updateStrategy ->
|
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, _, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy ->
|
||||||
Manga(
|
Manga(
|
||||||
id = id,
|
id = id,
|
||||||
source = source,
|
source = source,
|
||||||
favorite = favorite,
|
favorite = favorite,
|
||||||
lastUpdate = lastUpdate ?: 0,
|
lastUpdate = lastUpdate ?: 0,
|
||||||
dateAdded = dateAdded,
|
dateAdded = dateAdded,
|
||||||
viewerFlags = viewer,
|
viewerFlags = viewerFlags,
|
||||||
chapterFlags = chapterFlags,
|
chapterFlags = chapterFlags,
|
||||||
coverLastModified = coverLastModified,
|
coverLastModified = coverLastModified,
|
||||||
url = url,
|
url = url,
|
||||||
@ -28,11 +28,11 @@ val mangaMapper: (Long, Long, String, String?, String?, String?, List<String>?,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long) -> LibraryManga =
|
val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?, String, Long, String?, Boolean, Long?, Long?, Boolean, Long, Long, Long, Long, UpdateStrategy, Long, Long, Long, Long, Long, Long) -> LibraryManga =
|
||||||
{ _id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, unreadCount, readCount, category ->
|
{ id, source, url, artist, author, description, genre, title, status, thumbnailUrl, favorite, lastUpdate, nextUpdate, initialized, viewerFlags, chapterFlags, coverLastModified, dateAdded, updateStrategy, unreadCount, readCount, latestUpload, chapterFetchedAt, lastRead, category ->
|
||||||
LibraryManga(
|
LibraryManga(
|
||||||
manga = mangaMapper(
|
manga = mangaMapper(
|
||||||
_id,
|
id,
|
||||||
source,
|
source,
|
||||||
url,
|
url,
|
||||||
artist,
|
artist,
|
||||||
@ -55,5 +55,8 @@ val libraryManga: (Long, Long, String, String?, String?, String?, List<String>?,
|
|||||||
category = category,
|
category = category,
|
||||||
unreadCount = unreadCount,
|
unreadCount = unreadCount,
|
||||||
readCount = readCount,
|
readCount = readCount,
|
||||||
|
latestUpload = latestUpload,
|
||||||
|
chapterFetchedAt = chapterFetchedAt,
|
||||||
|
lastRead = lastRead,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -37,11 +37,11 @@ class MangaRepositoryImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getLibraryManga(): List<LibraryManga> {
|
override suspend fun getLibraryManga(): List<LibraryManga> {
|
||||||
return handler.awaitList { mangasQueries.getLibrary(libraryManga) }
|
return handler.awaitList { libraryViewQueries.library(libraryManga) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>> {
|
override fun getLibraryMangaAsFlow(): Flow<List<LibraryManga>> {
|
||||||
return handler.subscribeToList { mangasQueries.getLibrary(libraryManga) }
|
return handler.subscribeToList { libraryViewQueries.library(libraryManga) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> {
|
override fun getFavoritesBySourceId(sourceId: Long): Flow<List<Manga>> {
|
||||||
|
@ -7,6 +7,9 @@ data class LibraryManga(
|
|||||||
val category: Long,
|
val category: Long,
|
||||||
val unreadCount: Long,
|
val unreadCount: Long,
|
||||||
val readCount: Long,
|
val readCount: Long,
|
||||||
|
val latestUpload: Long,
|
||||||
|
val chapterFetchedAt: Long,
|
||||||
|
val lastRead: Long,
|
||||||
) {
|
) {
|
||||||
val totalChapters
|
val totalChapters
|
||||||
get() = readCount + unreadCount
|
get() = readCount + unreadCount
|
||||||
|
@ -15,7 +15,6 @@ import eu.kanade.core.prefs.CheckboxState
|
|||||||
import eu.kanade.core.prefs.PreferenceMutableState
|
import eu.kanade.core.prefs.PreferenceMutableState
|
||||||
import eu.kanade.core.util.asFlow
|
import eu.kanade.core.util.asFlow
|
||||||
import eu.kanade.core.util.asObservable
|
import eu.kanade.core.util.asObservable
|
||||||
import eu.kanade.data.DatabaseHandler
|
|
||||||
import eu.kanade.domain.base.BasePreferences
|
import eu.kanade.domain.base.BasePreferences
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.SetMangaCategories
|
import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
@ -82,7 +81,6 @@ typealias LibraryMap = Map<Long, List<LibraryItem>>
|
|||||||
*/
|
*/
|
||||||
class LibraryPresenter(
|
class LibraryPresenter(
|
||||||
private val state: LibraryStateImpl = LibraryState() as LibraryStateImpl,
|
private val state: LibraryStateImpl = LibraryState() as LibraryStateImpl,
|
||||||
private val handler: DatabaseHandler = Injekt.get(),
|
|
||||||
private val getLibraryManga: GetLibraryManga = Injekt.get(),
|
private val getLibraryManga: GetLibraryManga = Injekt.get(),
|
||||||
private val getTracks: GetTracks = Injekt.get(),
|
private val getTracks: GetTracks = Injekt.get(),
|
||||||
private val getCategories: GetCategories = Injekt.get(),
|
private val getCategories: GetCategories = Injekt.get(),
|
||||||
@ -286,37 +284,7 @@ class LibraryPresenter(
|
|||||||
* @param map the map to sort.
|
* @param map the map to sort.
|
||||||
*/
|
*/
|
||||||
private fun applySort(categories: List<Category>, map: LibraryMap): LibraryMap {
|
private fun applySort(categories: List<Category>, map: LibraryMap): LibraryMap {
|
||||||
val lastReadManga by lazy {
|
val sortModes = categories.associate { it.id to it.sort }
|
||||||
var counter = 0
|
|
||||||
// TODO: Make [applySort] a suspended function
|
|
||||||
runBlocking {
|
|
||||||
handler.awaitList {
|
|
||||||
mangasQueries.getLastRead()
|
|
||||||
}.associate { it._id to counter++ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val latestChapterManga by lazy {
|
|
||||||
var counter = 0
|
|
||||||
// TODO: Make [applySort] a suspended function
|
|
||||||
runBlocking {
|
|
||||||
handler.awaitList {
|
|
||||||
mangasQueries.getLatestByChapterUploadDate()
|
|
||||||
}.associate { it._id to counter++ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val chapterFetchDateManga by lazy {
|
|
||||||
var counter = 0
|
|
||||||
// TODO: Make [applySort] a suspended function
|
|
||||||
runBlocking {
|
|
||||||
handler.awaitList {
|
|
||||||
mangasQueries.getLatestByChapterFetchDate()
|
|
||||||
}.associate { it._id to counter++ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val sortModes = categories.associate { category ->
|
|
||||||
category.id to category.sort
|
|
||||||
}
|
|
||||||
|
|
||||||
val locale = Locale.getDefault()
|
val locale = Locale.getDefault()
|
||||||
val collator = Collator.getInstance(locale).apply {
|
val collator = Collator.getInstance(locale).apply {
|
||||||
@ -329,9 +297,7 @@ class LibraryPresenter(
|
|||||||
collator.compare(i1.libraryManga.manga.title.lowercase(locale), i2.libraryManga.manga.title.lowercase(locale))
|
collator.compare(i1.libraryManga.manga.title.lowercase(locale), i2.libraryManga.manga.title.lowercase(locale))
|
||||||
}
|
}
|
||||||
LibrarySort.Type.LastRead -> {
|
LibrarySort.Type.LastRead -> {
|
||||||
val manga1LastRead = lastReadManga[i1.libraryManga.manga.id] ?: 0
|
i1.libraryManga.lastRead.compareTo(i2.libraryManga.lastRead)
|
||||||
val manga2LastRead = lastReadManga[i2.libraryManga.manga.id] ?: 0
|
|
||||||
manga1LastRead.compareTo(manga2LastRead)
|
|
||||||
}
|
}
|
||||||
LibrarySort.Type.LastUpdate -> {
|
LibrarySort.Type.LastUpdate -> {
|
||||||
i1.libraryManga.manga.lastUpdate.compareTo(i2.libraryManga.manga.lastUpdate)
|
i1.libraryManga.manga.lastUpdate.compareTo(i2.libraryManga.manga.lastUpdate)
|
||||||
@ -347,16 +313,10 @@ class LibraryPresenter(
|
|||||||
i1.libraryManga.totalChapters.compareTo(i2.libraryManga.totalChapters)
|
i1.libraryManga.totalChapters.compareTo(i2.libraryManga.totalChapters)
|
||||||
}
|
}
|
||||||
LibrarySort.Type.LatestChapter -> {
|
LibrarySort.Type.LatestChapter -> {
|
||||||
val manga1latestChapter = latestChapterManga[i1.libraryManga.manga.id]
|
i1.libraryManga.latestUpload.compareTo(i2.libraryManga.latestUpload)
|
||||||
?: latestChapterManga.size
|
|
||||||
val manga2latestChapter = latestChapterManga[i2.libraryManga.manga.id]
|
|
||||||
?: latestChapterManga.size
|
|
||||||
manga1latestChapter.compareTo(manga2latestChapter)
|
|
||||||
}
|
}
|
||||||
LibrarySort.Type.ChapterFetchDate -> {
|
LibrarySort.Type.ChapterFetchDate -> {
|
||||||
val manga1chapterFetchDate = chapterFetchDateManga[i1.libraryManga.manga.id] ?: 0
|
i1.libraryManga.chapterFetchedAt.compareTo(i2.libraryManga.chapterFetchedAt)
|
||||||
val manga2chapterFetchDate = chapterFetchDateManga[i2.libraryManga.manga.id] ?: 0
|
|
||||||
manga1chapterFetchDate.compareTo(manga2chapterFetchDate)
|
|
||||||
}
|
}
|
||||||
LibrarySort.Type.DateAdded -> {
|
LibrarySort.Type.DateAdded -> {
|
||||||
i1.libraryManga.manga.dateAdded.compareTo(i2.libraryManga.manga.dateAdded)
|
i1.libraryManga.manga.dateAdded.compareTo(i2.libraryManga.manga.dateAdded)
|
||||||
|
@ -74,62 +74,6 @@ FROM mangas
|
|||||||
WHERE favorite = 0
|
WHERE favorite = 0
|
||||||
GROUP BY source;
|
GROUP BY source;
|
||||||
|
|
||||||
getLibrary:
|
|
||||||
SELECT M.*, COALESCE(MC.category_id, 0) AS category
|
|
||||||
FROM (
|
|
||||||
SELECT mangas.*, COALESCE(UR.unreadCount, 0) AS unread_count, COALESCE(R.readCount, 0) AS read_count
|
|
||||||
FROM mangas
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT chapters.manga_id, COUNT(*) AS unreadCount
|
|
||||||
FROM chapters
|
|
||||||
WHERE chapters.read = 0
|
|
||||||
GROUP BY chapters.manga_id
|
|
||||||
) AS UR
|
|
||||||
ON mangas._id = UR.manga_id
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT chapters.manga_id, COUNT(*) AS readCount
|
|
||||||
FROM chapters
|
|
||||||
WHERE chapters.read = 1
|
|
||||||
GROUP BY chapters.manga_id
|
|
||||||
) AS R
|
|
||||||
ON mangas._id = R.manga_id
|
|
||||||
WHERE mangas.favorite = 1
|
|
||||||
GROUP BY mangas._id
|
|
||||||
ORDER BY mangas.title
|
|
||||||
) AS M
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT *
|
|
||||||
FROM mangas_categories
|
|
||||||
) AS MC
|
|
||||||
ON M._id = MC.manga_id;
|
|
||||||
|
|
||||||
getLastRead:
|
|
||||||
SELECT M.*, MAX(H.last_read) AS max
|
|
||||||
FROM mangas M
|
|
||||||
JOIN chapters C
|
|
||||||
ON M._id = C.manga_id
|
|
||||||
JOIN history H
|
|
||||||
ON C._id = H.chapter_id
|
|
||||||
WHERE M.favorite = 1
|
|
||||||
GROUP BY M._id
|
|
||||||
ORDER BY max ASC;
|
|
||||||
|
|
||||||
getLatestByChapterUploadDate:
|
|
||||||
SELECT M.*, MAX(C.date_upload) AS max
|
|
||||||
FROM mangas M
|
|
||||||
JOIN chapters C
|
|
||||||
ON M._id = C.manga_id
|
|
||||||
GROUP BY M._id
|
|
||||||
ORDER BY max ASC;
|
|
||||||
|
|
||||||
getLatestByChapterFetchDate:
|
|
||||||
SELECT M.*, MAX(C.date_fetch) AS max
|
|
||||||
FROM mangas M
|
|
||||||
JOIN chapters C
|
|
||||||
ON M._id = C.manga_id
|
|
||||||
GROUP BY M._id
|
|
||||||
ORDER BY max ASC;
|
|
||||||
|
|
||||||
deleteMangasNotInLibraryBySourceIds:
|
deleteMangasNotInLibraryBySourceIds:
|
||||||
DELETE FROM mangas
|
DELETE FROM mangas
|
||||||
WHERE favorite = 0 AND source IN :sourceIds;
|
WHERE favorite = 0 AND source IN :sourceIds;
|
||||||
|
27
app/src/main/sqldelight/migrations/21.sqm
Normal file
27
app/src/main/sqldelight/migrations/21.sqm
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
CREATE VIEW libraryView AS
|
||||||
|
SELECT
|
||||||
|
M.*,
|
||||||
|
coalesce(C.total - C.readCount, 0) AS unreadCount,
|
||||||
|
coalesce(C.readCount, 0) AS readCount,
|
||||||
|
coalesce(C.latestUpload, 0) AS latestUpload,
|
||||||
|
coalesce(C.fetchedAt, 0) AS chapterFetchedAt,
|
||||||
|
coalesce(C.lastRead, 0) AS lastRead,
|
||||||
|
COALESCE(MC.category_id, 0) AS category
|
||||||
|
FROM mangas M
|
||||||
|
LEFT JOIN mangas_categories AS MC
|
||||||
|
ON MC.manga_id = M._id
|
||||||
|
LEFT JOIN(
|
||||||
|
SELECT
|
||||||
|
chapters.manga_id,
|
||||||
|
count(*) AS total,
|
||||||
|
sum(read) AS readCount,
|
||||||
|
max(chapters.date_upload) AS latestUpload,
|
||||||
|
max(history.last_read) AS lastRead,
|
||||||
|
max(chapters.date_fetch) AS fetchedAt
|
||||||
|
FROM chapters
|
||||||
|
LEFT JOIN history
|
||||||
|
ON chapters._id = history.chapter_id
|
||||||
|
GROUP BY chapters.manga_id
|
||||||
|
) AS C
|
||||||
|
ON M._id = C.manga_id
|
||||||
|
WHERE M.favorite = 1;
|
31
app/src/main/sqldelight/view/libraryView.sq
Normal file
31
app/src/main/sqldelight/view/libraryView.sq
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
CREATE VIEW libraryView AS
|
||||||
|
SELECT
|
||||||
|
M.*,
|
||||||
|
coalesce(C.total - C.readCount, 0) AS unreadCount,
|
||||||
|
coalesce(C.readCount, 0) AS readCount,
|
||||||
|
coalesce(C.latestUpload, 0) AS latestUpload,
|
||||||
|
coalesce(C.fetchedAt, 0) AS chapterFetchedAt,
|
||||||
|
coalesce(C.lastRead, 0) AS lastRead,
|
||||||
|
COALESCE(MC.category_id, 0) AS category
|
||||||
|
FROM mangas M
|
||||||
|
LEFT JOIN mangas_categories AS MC
|
||||||
|
ON MC.manga_id = M._id
|
||||||
|
LEFT JOIN(
|
||||||
|
SELECT
|
||||||
|
chapters.manga_id,
|
||||||
|
count(*) AS total,
|
||||||
|
sum(read) AS readCount,
|
||||||
|
coalesce(max(chapters.date_upload), 0) AS latestUpload,
|
||||||
|
coalesce(max(history.last_read), 0) AS lastRead,
|
||||||
|
coalesce(max(chapters.date_fetch), 0) AS fetchedAt
|
||||||
|
FROM chapters
|
||||||
|
LEFT JOIN history
|
||||||
|
ON chapters._id = history.chapter_id
|
||||||
|
GROUP BY chapters.manga_id
|
||||||
|
) AS C
|
||||||
|
ON M._id = C.manga_id
|
||||||
|
WHERE M.favorite = 1;
|
||||||
|
|
||||||
|
library:
|
||||||
|
SELECT *
|
||||||
|
FROM libraryView;
|
Loading…
Reference in New Issue
Block a user