Quick filter request refactor
parent
d06b396aec
commit
9e49b28ac3
@ -0,0 +1,109 @@
|
|||||||
|
package org.koitharu.kotatsu.core.db
|
||||||
|
|
||||||
|
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||||
|
import org.koitharu.kotatsu.list.domain.ListFilterOption
|
||||||
|
import java.util.LinkedList
|
||||||
|
|
||||||
|
class MangaQueryBuilder(
|
||||||
|
private val table: String,
|
||||||
|
private val conditionCallback: ConditionCallback
|
||||||
|
) {
|
||||||
|
|
||||||
|
private var filterOptions: Collection<ListFilterOption> = emptyList()
|
||||||
|
private var whereConditions = LinkedList<String>()
|
||||||
|
private var orderBy: String? = null
|
||||||
|
private var groupBy: String? = null
|
||||||
|
private var extraJoins: String? = null
|
||||||
|
private var limit: Int = 0
|
||||||
|
|
||||||
|
fun filters(options: Collection<ListFilterOption>) = apply {
|
||||||
|
filterOptions = options
|
||||||
|
}
|
||||||
|
|
||||||
|
fun where(condition: String) = apply {
|
||||||
|
whereConditions.add(condition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun orderBy(orderBy: String?) = apply {
|
||||||
|
this@MangaQueryBuilder.orderBy = orderBy
|
||||||
|
}
|
||||||
|
|
||||||
|
fun groupBy(groupBy: String?) = apply {
|
||||||
|
this@MangaQueryBuilder.groupBy = groupBy
|
||||||
|
}
|
||||||
|
|
||||||
|
fun limit(limit: Int) = apply {
|
||||||
|
this@MangaQueryBuilder.limit = limit
|
||||||
|
}
|
||||||
|
|
||||||
|
fun join(join: String?) = apply {
|
||||||
|
extraJoins = join
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build() = buildString {
|
||||||
|
append("SELECT * FROM ")
|
||||||
|
append(table)
|
||||||
|
extraJoins?.let {
|
||||||
|
append(' ')
|
||||||
|
append(it)
|
||||||
|
}
|
||||||
|
if (whereConditions.isNotEmpty()) {
|
||||||
|
whereConditions.joinTo(
|
||||||
|
buffer = this,
|
||||||
|
prefix = " WHERE ",
|
||||||
|
separator = " AND ",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (filterOptions.isNotEmpty()) {
|
||||||
|
if (whereConditions.isEmpty()) {
|
||||||
|
append(" WHERE")
|
||||||
|
}
|
||||||
|
var isFirst = true
|
||||||
|
val groupedOptions = filterOptions.groupBy { it.groupKey }
|
||||||
|
for ((_, group) in groupedOptions) {
|
||||||
|
if (group.isEmpty()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (isFirst) {
|
||||||
|
isFirst = false
|
||||||
|
append(' ')
|
||||||
|
} else {
|
||||||
|
append(" AND ")
|
||||||
|
}
|
||||||
|
if (group.size > 1) {
|
||||||
|
group.joinTo(
|
||||||
|
buffer = this,
|
||||||
|
separator = " OR ",
|
||||||
|
prefix = "(",
|
||||||
|
postfix = ")",
|
||||||
|
transform = ::getConditionOrThrow,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
append(getConditionOrThrow(group.single()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupBy?.let {
|
||||||
|
append(" GROUP BY ")
|
||||||
|
append(it)
|
||||||
|
}
|
||||||
|
orderBy?.let {
|
||||||
|
append(" ORDER BY ")
|
||||||
|
append(it)
|
||||||
|
}
|
||||||
|
if (limit > 0) {
|
||||||
|
append(" LIMIT ")
|
||||||
|
append(limit)
|
||||||
|
}
|
||||||
|
}.let { SimpleSQLiteQuery(it) }
|
||||||
|
|
||||||
|
private fun getConditionOrThrow(option: ListFilterOption): String =
|
||||||
|
requireNotNull(conditionCallback.getCondition(option)) {
|
||||||
|
"Unsupported filter option $option"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface ConditionCallback {
|
||||||
|
|
||||||
|
fun getCondition(option: ListFilterOption): String?
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue