Remake the merged database, has support for future features

This commit is contained in:
Jobobby04 2020-08-26 21:57:33 -04:00
parent 444d346874
commit d21a652944
11 changed files with 408 additions and 63 deletions

View File

@ -21,6 +21,9 @@ import eu.kanade.tachiyomi.data.database.queries.HistoryQueries
import eu.kanade.tachiyomi.data.database.queries.MangaCategoryQueries
import eu.kanade.tachiyomi.data.database.queries.MangaQueries
import eu.kanade.tachiyomi.data.database.queries.TrackQueries
import exh.merged.sql.mappers.MergedMangaTypeMapping
import exh.merged.sql.models.MergedMangaReference
import exh.merged.sql.queries.MergedQueries
import exh.metadata.sql.mappers.SearchMetadataTypeMapping
import exh.metadata.sql.mappers.SearchTagTypeMapping
import exh.metadata.sql.mappers.SearchTitleTypeMapping
@ -36,7 +39,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
* This class provides operations to manage the database through its interfaces.
*/
open class DatabaseHelper(context: Context) :
MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries /* EXH --> */, SearchMetadataQueries, SearchTagQueries, SearchTitleQueries /* EXH <-- */ {
MangaQueries, ChapterQueries, TrackQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries /* SY --> */, SearchMetadataQueries, SearchTagQueries, SearchTitleQueries, MergedQueries /* SY <-- */ {
private val configuration = SupportSQLiteOpenHelper.Configuration.builder(context)
.name(DbOpenCallback.DATABASE_NAME)
@ -51,11 +54,12 @@ open class DatabaseHelper(context: Context) :
.addTypeMapping(Category::class.java, CategoryTypeMapping())
.addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping())
.addTypeMapping(History::class.java, HistoryTypeMapping())
// EXH -->
// SY -->
.addTypeMapping(SearchMetadata::class.java, SearchMetadataTypeMapping())
.addTypeMapping(SearchTag::class.java, SearchTagTypeMapping())
.addTypeMapping(SearchTitle::class.java, SearchTitleTypeMapping())
// EXH <--
.addTypeMapping(MergedMangaReference::class.java, MergedMangaTypeMapping())
// SY <--
.build()
inline fun inTransaction(block: () -> Unit) = db.inTransaction(block)

View File

@ -7,8 +7,8 @@ import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.data.database.tables.HistoryTable
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import eu.kanade.tachiyomi.data.database.tables.MergedTable
import eu.kanade.tachiyomi.data.database.tables.TrackTable
import exh.merged.sql.tables.MergedTable
import exh.metadata.sql.tables.SearchMetadataTable
import exh.metadata.sql.tables.SearchTagTable
import exh.metadata.sql.tables.SearchTitleTable
@ -24,7 +24,7 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
/**
* Version of the database.
*/
const val DATABASE_VERSION = /* SY --> */ 3 /* SY <-- */
const val DATABASE_VERSION = /* SY --> */ 4 /* SY <-- */
}
override fun onCreate(db: SupportSQLiteDatabase) = with(db) {
@ -34,14 +34,12 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
execSQL(CategoryTable.createTableQuery)
execSQL(MangaCategoryTable.createTableQuery)
execSQL(HistoryTable.createTableQuery)
// EXH -->
// SY -->
execSQL(SearchMetadataTable.createTableQuery)
execSQL(SearchTagTable.createTableQuery)
execSQL(SearchTitleTable.createTableQuery)
// EXH <--
// AZ -->
execSQL(MergedTable.createTableQuery)
// AZ <--
// SY <--
// DB indexes
execSQL(MangaTable.createUrlIndexQuery)
@ -49,17 +47,15 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
execSQL(ChapterTable.createMangaIdIndexQuery)
execSQL(ChapterTable.createUnreadChaptersIndexQuery)
execSQL(HistoryTable.createChapterIdIndexQuery)
// EXH -->
db.execSQL(SearchMetadataTable.createUploaderIndexQuery)
db.execSQL(SearchMetadataTable.createIndexedExtraIndexQuery)
db.execSQL(SearchTagTable.createMangaIdIndexQuery)
db.execSQL(SearchTagTable.createNamespaceNameIndexQuery)
db.execSQL(SearchTitleTable.createMangaIdIndexQuery)
db.execSQL(SearchTitleTable.createTitleIndexQuery)
// EXH <--
// AZ -->
// SY -->
execSQL(SearchMetadataTable.createUploaderIndexQuery)
execSQL(SearchMetadataTable.createIndexedExtraIndexQuery)
execSQL(SearchTagTable.createMangaIdIndexQuery)
execSQL(SearchTagTable.createNamespaceNameIndexQuery)
execSQL(SearchTitleTable.createMangaIdIndexQuery)
execSQL(SearchTitleTable.createTitleIndexQuery)
execSQL(MergedTable.createIndexQuery)
// AZ <--
// SY <--
}
override fun onUpgrade(db: SupportSQLiteDatabase, oldVersion: Int, newVersion: Int) {
@ -70,6 +66,11 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
db.execSQL(MangaTable.addDateAdded)
db.execSQL(MangaTable.backfillDateAdded)
}
if (oldVersion < 4) {
db.execSQL(MergedTable.dropTableQuery)
db.execSQL(MergedTable.createTableQuery)
db.execSQL(MergedTable.createIndexQuery)
}
}
override fun onConfigure(db: SupportSQLiteDatabase) {

View File

@ -27,15 +27,6 @@ interface ChapterQueries : DbProvider {
.build()
)
.prepare()
fun getChaptersByMergedMangaId(mangaId: Long) = db.get()
.listOfObjects(Chapter::class.java)
.withQuery(
RawQuery.builder()
.query(getMergedChaptersQuery(mangaId))
.build()
)
.prepare()
// SY <--
fun getRecentChapters(date: Date) = db.get()

View File

@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.data.database.tables.CategoryTable
import eu.kanade.tachiyomi.data.database.tables.ChapterTable
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable
import eu.kanade.tachiyomi.data.database.tables.MangaTable
import exh.merged.sql.tables.MergedTable
import exh.metadata.sql.tables.SearchMetadataTable
interface MangaQueries : DbProvider {
@ -77,15 +78,6 @@ interface MangaQueries : DbProvider {
.prepare()
// SY -->
fun getMergedMangas(id: Long) = db.get()
.listOfObjects(Manga::class.java)
.withQuery(
RawQuery.builder()
.query(getMergedMangaQuery(id))
.build()
)
.prepare()
fun updateMangaInfo(manga: Manga) = db.put()
.`object`(manga)
.withPutResolver(MangaInfoPutResolver())
@ -139,7 +131,7 @@ interface MangaQueries : DbProvider {
.byQuery(
DeleteQuery.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_FAVORITE} = ?")
.where("${MangaTable.COL_FAVORITE} = ? AND ${MangaTable.COL_ID} NOT IN (SELECT ${MergedTable.COL_MANGA_ID} FROM ${MergedTable.TABLE})")
.whereArgs(0)
.build()
)

View File

@ -5,17 +5,40 @@ import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
import eu.kanade.tachiyomi.data.database.tables.HistoryTable as History
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
import eu.kanade.tachiyomi.data.database.tables.MergedTable as Merged
import exh.merged.sql.tables.MergedTable as Merged
// SY -->
/**
* Query to get the manga merged into a merged manga
*/
fun getMergedMangaQuery(id: Long) =
fun getMergedMangaQuery() =
"""
SELECT ${Manga.TABLE}.*
FROM (
SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE $(Merged.COL_MERGE_ID} = $id
SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE ${Merged.COL_MERGE_ID} = ?
) AS M
JOIN ${Manga.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = M.${Merged.COL_MANGA_ID}
"""
fun getAllMergedMangaQuery() =
"""
SELECT ${Manga.TABLE}.*
FROM (
SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE}
) AS M
JOIN ${Manga.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = M.${Merged.COL_MANGA_ID}
"""
/**
* Query to get the manga merged into a merged manga using the Url
*/
fun getMergedMangaFromUrlQuery() =
"""
SELECT ${Manga.TABLE}.*
FROM (
SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE ${Merged.COL_MERGE_URL} = ?
) AS M
JOIN ${Manga.TABLE}
ON ${Manga.TABLE}.${Manga.COL_ID} = M.${Merged.COL_MANGA_ID}
@ -24,11 +47,11 @@ fun getMergedMangaQuery(id: Long) =
/**
* Query to get the chapters of all manga in a merged manga
*/
fun getMergedChaptersQuery(id: Long) =
fun getMergedChaptersQuery() =
"""
SELECT ${Chapter.TABLE}.*
FROM (
SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE $(Merged.COL_MERGE_ID} = $id
SELECT ${Merged.COL_MANGA_ID} FROM ${Merged.TABLE} WHERE ${Merged.COL_MERGE_ID} = ?
) AS M
JOIN ${Chapter.TABLE}
ON ${Chapter.TABLE}.${Chapter.COL_MANGA_ID} = M.${Merged.COL_MANGA_ID}

View File

@ -1,20 +0,0 @@
package eu.kanade.tachiyomi.data.database.tables
object MergedTable {
const val TABLE = "merged"
const val COL_MERGE_ID = "mergeID"
const val COL_MANGA_ID = "mangaID"
val createTableQuery: String
get() =
"""CREATE TABLE $TABLE(
$COL_MERGE_ID INTEGER NOT NULL,
$COL_MANGA_ID INTEGER NOT NULL
)"""
val createIndexQuery: String
get() = "CREATE INDEX ${TABLE}_${COL_MERGE_ID}_index ON $TABLE($COL_MERGE_ID)"
}

View File

@ -0,0 +1,84 @@
package exh.merged.sql.mappers
import android.content.ContentValues
import android.database.Cursor
import androidx.core.database.getLongOrNull
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
import com.pushtorefresh.storio.sqlite.queries.InsertQuery
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import exh.merged.sql.models.MergedMangaReference
import exh.merged.sql.tables.MergedTable.COL_CHAPTER_PRIORITY
import exh.merged.sql.tables.MergedTable.COL_CHAPTER_SORT_MODE
import exh.merged.sql.tables.MergedTable.COL_DOWNLOAD_CHAPTERS
import exh.merged.sql.tables.MergedTable.COL_GET_CHAPTER_UPDATES
import exh.merged.sql.tables.MergedTable.COL_ID
import exh.merged.sql.tables.MergedTable.COL_IS_INFO_MANGA
import exh.merged.sql.tables.MergedTable.COL_MANGA_ID
import exh.merged.sql.tables.MergedTable.COL_MANGA_SOURCE
import exh.merged.sql.tables.MergedTable.COL_MANGA_URL
import exh.merged.sql.tables.MergedTable.COL_MERGE_ID
import exh.merged.sql.tables.MergedTable.COL_MERGE_URL
import exh.merged.sql.tables.MergedTable.TABLE
class MergedMangaTypeMapping : SQLiteTypeMapping<MergedMangaReference>(
MergedMangaPutResolver(),
MergedMangaGetResolver(),
MergedMangaDeleteResolver()
)
class MergedMangaPutResolver : DefaultPutResolver<MergedMangaReference>() {
override fun mapToInsertQuery(obj: MergedMangaReference) = InsertQuery.builder()
.table(TABLE)
.build()
override fun mapToUpdateQuery(obj: MergedMangaReference) = UpdateQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
override fun mapToContentValues(obj: MergedMangaReference) = ContentValues(5).apply {
put(COL_ID, obj.id)
put(COL_IS_INFO_MANGA, obj.isInfoManga)
put(COL_GET_CHAPTER_UPDATES, obj.getChapterUpdates)
put(COL_CHAPTER_SORT_MODE, obj.chapterSortMode)
put(COL_CHAPTER_PRIORITY, obj.chapterPriority)
put(COL_DOWNLOAD_CHAPTERS, obj.downloadChapters)
put(COL_MERGE_ID, obj.mergeId)
put(COL_MERGE_URL, obj.mergeUrl)
put(COL_MANGA_ID, obj.mangaId)
put(COL_MANGA_URL, obj.mangaUrl)
put(COL_MANGA_SOURCE, obj.mangaSourceId)
}
}
class MergedMangaGetResolver : DefaultGetResolver<MergedMangaReference>() {
override fun mapFromCursor(cursor: Cursor): MergedMangaReference = MergedMangaReference(
id = cursor.getLong(cursor.getColumnIndex(COL_ID)),
isInfoManga = cursor.getInt(cursor.getColumnIndex(COL_IS_INFO_MANGA)) == 1,
getChapterUpdates = cursor.getInt(cursor.getColumnIndex(COL_GET_CHAPTER_UPDATES)) == 1,
chapterSortMode = cursor.getInt(cursor.getColumnIndex(COL_CHAPTER_SORT_MODE)),
chapterPriority = cursor.getInt(cursor.getColumnIndex(COL_CHAPTER_PRIORITY)),
downloadChapters = cursor.getInt(cursor.getColumnIndex(COL_DOWNLOAD_CHAPTERS)) == 1,
mergeId = cursor.getLong(cursor.getColumnIndex(COL_MERGE_ID)),
mergeUrl = cursor.getString(cursor.getColumnIndex(COL_MERGE_URL)),
mangaId = cursor.getLongOrNull(cursor.getColumnIndex(COL_MANGA_ID)),
mangaUrl = cursor.getString(cursor.getColumnIndex(COL_MANGA_URL)),
mangaSourceId = cursor.getLong(cursor.getColumnIndex(COL_MANGA_SOURCE))
)
}
class MergedMangaDeleteResolver : DefaultDeleteResolver<MergedMangaReference>() {
override fun mapToDeleteQuery(obj: MergedMangaReference) = DeleteQuery.builder()
.table(TABLE)
.where("$COL_ID = ?")
.whereArgs(obj.id)
.build()
}

View File

@ -0,0 +1,44 @@
package exh.merged.sql.models
data class MergedMangaReference(
// Tag identifier, unique
var id: Long?,
// The manga where it grabs the updated manga info
var isInfoManga: Boolean,
// If false the manga will not grab chapter updates
var getChapterUpdates: Boolean,
// The mode in which the chapters are handeled, only set in the main merge reference
var chapterSortMode: Int,
// chapter priority the deduplication uses
var chapterPriority: Int,
// Set if you want it to download new chapters
var downloadChapters: Boolean,
// merged manga this reference is attached to
var mergeId: Long?,
// merged manga url this reference is attached to
val mergeUrl: String,
// manga id included in the merge this reference is attached to
var mangaId: Long?,
// manga url included in the merge this reference is attached to
val mangaUrl: String,
// source of the manga that is merged into this merge
val mangaSourceId: Long
) {
companion object {
const val CHAPTER_SORT_NONE = 0
const val CHAPTER_SORT_NO_DEDUPE = 1
const val CHAPTER_SORT_PRIORITY = 2
const val CHAPTER_SORT_MOST_CHAPTERS = 3
const val CHAPTER_SORT_HIGHEST_CHAPTER_NUMBER = 4
}
}

View File

@ -0,0 +1,139 @@
package exh.merged.sql.queries
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
import com.pushtorefresh.storio.sqlite.queries.Query
import com.pushtorefresh.storio.sqlite.queries.RawQuery
import eu.kanade.tachiyomi.data.database.DbProvider
import eu.kanade.tachiyomi.data.database.inTransaction
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.queries.getAllMergedMangaQuery
import eu.kanade.tachiyomi.data.database.queries.getMergedChaptersQuery
import eu.kanade.tachiyomi.data.database.queries.getMergedMangaFromUrlQuery
import eu.kanade.tachiyomi.data.database.queries.getMergedMangaQuery
import exh.merged.sql.models.MergedMangaReference
import exh.merged.sql.resolvers.MergeMangaSettingsPutResolver
import exh.merged.sql.resolvers.MergedMangaIdPutResolver
import exh.merged.sql.resolvers.MergedMangaSettingsPutResolver
import exh.merged.sql.tables.MergedTable
interface MergedQueries : DbProvider {
fun getMergedMangaReferences(mergedMangaId: Long) = db.get()
.listOfObjects(MergedMangaReference::class.java)
.withQuery(
Query.builder()
.table(MergedTable.TABLE)
.where("${MergedTable.COL_MERGE_ID} = ?")
.whereArgs(mergedMangaId)
.build()
)
.prepare()
fun getMergedMangaReferences(mergedMangaUrl: String) = db.get()
.listOfObjects(MergedMangaReference::class.java)
.withQuery(
Query.builder()
.table(MergedTable.TABLE)
.where("${MergedTable.COL_MERGE_URL} = ?")
.whereArgs(mergedMangaUrl)
.build()
)
.prepare()
fun deleteMangaForMergedManga(mergedMangaId: Long) = db.delete()
.byQuery(
DeleteQuery.builder()
.table(MergedTable.TABLE)
.where("${MergedTable.COL_MERGE_ID} = ?")
.whereArgs(mergedMangaId)
.build()
)
.prepare()
fun getMergedMangas(mergedMangaId: Long) = db.get()
.listOfObjects(Manga::class.java)
.withQuery(
RawQuery.builder()
.query(getMergedMangaQuery())
.args(mergedMangaId)
.build()
)
.prepare()
fun getMergedMangas(mergedMangaUrl: String) = db.get()
.listOfObjects(Manga::class.java)
.withQuery(
RawQuery.builder()
.query(getMergedMangaFromUrlQuery())
.args(mergedMangaUrl)
.build()
)
.prepare()
fun getMergedMangas() = db.get()
.listOfObjects(Manga::class.java)
.withQuery(
RawQuery.builder()
.query(getAllMergedMangaQuery())
.build()
)
.prepare()
fun deleteMangaForMergedManga(mergedMangaUrl: String) = db.delete()
.byQuery(
DeleteQuery.builder()
.table(MergedTable.TABLE)
.where("${MergedTable.COL_MERGE_URL} = ?")
.whereArgs(mergedMangaUrl)
.build()
)
.prepare()
fun getMergedMangaReferences() = db.get()
.listOfObjects(MergedMangaReference::class.java)
.withQuery(
Query.builder()
.table(MergedTable.TABLE)
.orderBy(MergedTable.COL_ID)
.build()
)
.prepare()
fun getChaptersByMergedMangaId(mergedMangaId: Long) = db.get()
.listOfObjects(Chapter::class.java)
.withQuery(
RawQuery.builder()
.query(getMergedChaptersQuery())
.args(mergedMangaId)
.build()
)
.prepare()
fun insertMergedManga(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).prepare()
fun insertNewMergedMangaId(mergedManga: MergedMangaReference) = db.put().`object`(mergedManga).withPutResolver(MergedMangaIdPutResolver()).prepare()
fun insertMergedMangas(mergedManga: List<MergedMangaReference>) = db.put().objects(mergedManga).prepare()
fun updateMergedMangaSettings(mergedManga: List<MergedMangaReference>) = db.put().objects(mergedManga).withPutResolver(MergedMangaSettingsPutResolver()).prepare()
fun updateMergeMangaSettings(mergeManga: MergedMangaReference) = db.put().`object`(mergeManga).withPutResolver(MergeMangaSettingsPutResolver()).prepare()
fun deleteMergedManga(mergedManga: MergedMangaReference) = db.delete().`object`(mergedManga).prepare()
fun deleteAllMergedManga() = db.delete().byQuery(
DeleteQuery.builder()
.table(MergedTable.TABLE)
.build()
)
.prepare()
fun setMangasForMergedManga(mergedMangaId: Long, mergedMangas: List<MergedMangaReference>) {
db.inTransaction {
deleteMangaForMergedManga(mergedMangaId).executeAsBlocking()
mergedMangas.chunked(100) { chunk ->
insertMergedMangas(chunk).executeAsBlocking()
}
}
}
}

View File

@ -0,0 +1,31 @@
package exh.merged.sql.resolvers
import android.content.ContentValues
import com.pushtorefresh.storio.sqlite.StorIOSQLite
import com.pushtorefresh.storio.sqlite.operations.put.PutResolver
import com.pushtorefresh.storio.sqlite.operations.put.PutResult
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
import eu.kanade.tachiyomi.data.database.inTransactionReturn
import exh.merged.sql.models.MergedMangaReference
import exh.merged.sql.tables.MergedTable
class MergedMangaIdPutResolver : PutResolver<MergedMangaReference>() {
override fun performPut(db: StorIOSQLite, mergedMangaReference: MergedMangaReference) = db.inTransactionReturn {
val updateQuery = mapToUpdateQuery(mergedMangaReference)
val contentValues = mapToContentValues(mergedMangaReference)
val numberOfRowsUpdated = db.lowLevel().update(updateQuery, contentValues)
PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table())
}
fun mapToUpdateQuery(mergedMangaReference: MergedMangaReference) = UpdateQuery.builder()
.table(MergedTable.TABLE)
.where("${MergedTable.COL_ID} = ?")
.whereArgs(mergedMangaReference.id)
.build()
fun mapToContentValues(mergedMangaReference: MergedMangaReference) = ContentValues(1).apply {
put(MergedTable.COL_MANGA_ID, mergedMangaReference.mangaId)
}
}

View File

@ -0,0 +1,56 @@
package exh.merged.sql.tables
import eu.kanade.tachiyomi.data.database.tables.MangaTable
object MergedTable {
const val TABLE = "merged"
const val COL_ID = "_id"
const val COL_IS_INFO_MANGA = "info_manga"
const val COL_GET_CHAPTER_UPDATES = "get_chapter_updates"
const val COL_CHAPTER_SORT_MODE = "chapter_sort_mode"
const val COL_CHAPTER_PRIORITY = "chapter_priority"
const val COL_DOWNLOAD_CHAPTERS = "download_chapters"
const val COL_MERGE_ID = "merge_id"
const val COL_MERGE_URL = "merge_url"
const val COL_MANGA_ID = "manga_id"
const val COL_MANGA_URL = "manga_url"
const val COL_MANGA_SOURCE = "manga_source"
val createTableQuery: String
get() =
"""CREATE TABLE $TABLE(
$COL_ID INTEGER NOT NULL PRIMARY KEY,
$COL_IS_INFO_MANGA BOOLEAN NOT NULL,
$COL_GET_CHAPTER_UPDATES BOOLEAN NOT NULL,
$COL_CHAPTER_SORT_MODE INTEGER NOT NULL,
$COL_CHAPTER_PRIORITY INTEGER NOT NULL,
$COL_DOWNLOAD_CHAPTERS BOOLEAN NOT NULL,
$COL_MERGE_ID INTEGER NOT NULL,
$COL_MERGE_URL TEXT NOT NULL,
$COL_MANGA_ID INTEGER,
$COL_MANGA_URL TEXT NOT NULL,
$COL_MANGA_SOURCE INTEGER NOT NULL,
FOREIGN KEY($COL_MANGA_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID})
ON DELETE SET NULL,
FOREIGN KEY($COL_MERGE_ID) REFERENCES ${MangaTable.TABLE} (${MangaTable.COL_ID})
ON DELETE CASCADE
)"""
val dropTableQuery: String
get() = "DROP TABLE $TABLE"
val createIndexQuery: String
get() = "CREATE INDEX ${TABLE}_${COL_MERGE_ID}_index ON $TABLE($COL_MERGE_ID)"
}