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:
AntsyLich 2022-10-17 01:33:12 +06:00 committed by GitHub
parent aea0cadbfb
commit d6cbff2837
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 76 additions and 108 deletions

View file

@ -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()}\"")

View file

@ -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,
) )
} }

View file

@ -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>> {

View file

@ -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

View file

@ -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)

View file

@ -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;

View 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;

View 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;