Complete MetaQuery
This commit is contained in:
@@ -9,13 +9,31 @@ package suwayomi.tachidesk.graphql.queries
|
||||
|
||||
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
||||
import graphql.schema.DataFetchingEnvironment
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import org.jetbrains.exposed.sql.Op
|
||||
import org.jetbrains.exposed.sql.SortOrder
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
|
||||
import org.jetbrains.exposed.sql.andWhere
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.tachidesk.global.model.table.GlobalMetaTable
|
||||
import suwayomi.tachidesk.graphql.queries.filter.Filter
|
||||
import suwayomi.tachidesk.graphql.queries.filter.HasGetOp
|
||||
import suwayomi.tachidesk.graphql.queries.filter.OpAnd
|
||||
import suwayomi.tachidesk.graphql.queries.filter.StringFilter
|
||||
import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString
|
||||
import suwayomi.tachidesk.graphql.queries.filter.applyOps
|
||||
import suwayomi.tachidesk.graphql.server.primitives.Cursor
|
||||
import suwayomi.tachidesk.graphql.server.primitives.OrderBy
|
||||
import suwayomi.tachidesk.graphql.server.primitives.PageInfo
|
||||
import suwayomi.tachidesk.graphql.server.primitives.QueryResults
|
||||
import suwayomi.tachidesk.graphql.server.primitives.greaterNotUnique
|
||||
import suwayomi.tachidesk.graphql.server.primitives.lessNotUnique
|
||||
import suwayomi.tachidesk.graphql.server.primitives.maybeSwap
|
||||
import suwayomi.tachidesk.graphql.types.GlobalMetaItem
|
||||
import suwayomi.tachidesk.graphql.types.MetaItem
|
||||
import suwayomi.tachidesk.graphql.types.MetaNodeList
|
||||
import suwayomi.tachidesk.graphql.types.MetaNodeList.Companion.toNodeList
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
@@ -32,11 +50,145 @@ class MetaQuery {
|
||||
return dataFetchingEnvironment.getValueFromDataLoader<String, MetaItem?>("GlobalMetaDataLoader", key)
|
||||
}
|
||||
|
||||
fun metas(): MetaNodeList {
|
||||
val results = transaction {
|
||||
GlobalMetaTable.selectAll().toList()
|
||||
enum class MetaOrderBy(override val column: Column<out Comparable<*>>) : OrderBy<MetaItem> {
|
||||
KEY(GlobalMetaTable.key),
|
||||
VALUE(GlobalMetaTable.value);
|
||||
|
||||
override fun greater(cursor: Cursor): Op<Boolean> {
|
||||
return when (this) {
|
||||
KEY -> GlobalMetaTable.key greater cursor.value
|
||||
VALUE -> greaterNotUnique(GlobalMetaTable.value, GlobalMetaTable.key, cursor, String::toString)
|
||||
}
|
||||
}
|
||||
|
||||
return results.map { GlobalMetaItem(it) }.toNodeList()
|
||||
override fun less(cursor: Cursor): Op<Boolean> {
|
||||
return when (this) {
|
||||
KEY -> GlobalMetaTable.key less cursor.value
|
||||
VALUE -> lessNotUnique(GlobalMetaTable.value, GlobalMetaTable.key, cursor, String::toString)
|
||||
}
|
||||
}
|
||||
|
||||
override fun asCursor(type: MetaItem): Cursor {
|
||||
val value = when (this) {
|
||||
KEY -> type.key
|
||||
VALUE -> type.key + "-" + type.value
|
||||
}
|
||||
return Cursor(value)
|
||||
}
|
||||
}
|
||||
|
||||
data class MetaCondition(
|
||||
val key: String? = null,
|
||||
val value: String? = null
|
||||
) : HasGetOp {
|
||||
override fun getOp(): Op<Boolean>? {
|
||||
val opAnd = OpAnd()
|
||||
opAnd.eq(key, GlobalMetaTable.key)
|
||||
opAnd.eq(value, GlobalMetaTable.value)
|
||||
|
||||
return opAnd.op
|
||||
}
|
||||
}
|
||||
|
||||
data class MetaFilter(
|
||||
val key: StringFilter? = null,
|
||||
val value: StringFilter? = null,
|
||||
override val and: List<MetaFilter>? = null,
|
||||
override val or: List<MetaFilter>? = null,
|
||||
override val not: MetaFilter? = null
|
||||
) : Filter<MetaFilter> {
|
||||
override fun getOpList(): List<Op<Boolean>> {
|
||||
return listOfNotNull(
|
||||
andFilterWithCompareString(GlobalMetaTable.key, key),
|
||||
andFilterWithCompareString(GlobalMetaTable.value, value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun metas(
|
||||
condition: MetaCondition? = null,
|
||||
filter: MetaFilter? = null,
|
||||
orderBy: MetaOrderBy? = null,
|
||||
orderByType: SortOrder? = null,
|
||||
before: Cursor? = null,
|
||||
after: Cursor? = null,
|
||||
first: Int? = null,
|
||||
last: Int? = null,
|
||||
offset: Int? = null
|
||||
): MetaNodeList {
|
||||
val queryResults = transaction {
|
||||
val res = GlobalMetaTable.selectAll()
|
||||
|
||||
res.applyOps(condition, filter)
|
||||
|
||||
if (orderBy != null || (last != null || before != null)) {
|
||||
val orderByColumn = orderBy?.column ?: GlobalMetaTable.key
|
||||
val orderType = orderByType.maybeSwap(last ?: before)
|
||||
|
||||
if (orderBy == MetaOrderBy.KEY || orderBy == null) {
|
||||
res.orderBy(orderByColumn to orderType)
|
||||
} else {
|
||||
res.orderBy(
|
||||
orderByColumn to orderType,
|
||||
GlobalMetaTable.key to SortOrder.ASC
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val total = res.count()
|
||||
val firstResult = res.firstOrNull()?.get(GlobalMetaTable.key)
|
||||
val lastResult = res.lastOrNull()?.get(GlobalMetaTable.key)
|
||||
|
||||
if (after != null) {
|
||||
res.andWhere {
|
||||
(orderBy ?: MetaOrderBy.KEY).greater(after)
|
||||
}
|
||||
} else if (before != null) {
|
||||
res.andWhere {
|
||||
(orderBy ?: MetaOrderBy.KEY).less(before)
|
||||
}
|
||||
}
|
||||
|
||||
if (first != null) {
|
||||
res.limit(first, offset?.toLong() ?: 0)
|
||||
} else if (last != null) {
|
||||
res.limit(last)
|
||||
}
|
||||
|
||||
QueryResults(total, firstResult, lastResult, res.toList())
|
||||
}
|
||||
|
||||
val getAsCursor: (MetaItem) -> Cursor = (orderBy ?: MetaOrderBy.KEY)::asCursor
|
||||
|
||||
val resultsAsType = queryResults.results.map { GlobalMetaItem(it) }
|
||||
|
||||
return MetaNodeList(
|
||||
resultsAsType,
|
||||
if (resultsAsType.isEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
listOfNotNull(
|
||||
resultsAsType.firstOrNull()?.let {
|
||||
MetaNodeList.MetaEdge(
|
||||
getAsCursor(it),
|
||||
it
|
||||
)
|
||||
},
|
||||
resultsAsType.lastOrNull()?.let {
|
||||
MetaNodeList.MetaEdge(
|
||||
getAsCursor(it),
|
||||
it
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
pageInfo = PageInfo(
|
||||
hasNextPage = queryResults.lastKey != resultsAsType.lastOrNull()?.key,
|
||||
hasPreviousPage = queryResults.firstKey != resultsAsType.firstOrNull()?.key,
|
||||
startCursor = resultsAsType.firstOrNull()?.let { getAsCursor(it) },
|
||||
endCursor = resultsAsType.lastOrNull()?.let { getAsCursor(it) }
|
||||
),
|
||||
totalCount = queryResults.total.toInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,14 +36,38 @@ fun SortOrder?.maybeSwap(value: Any?): SortOrder {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T: Comparable<T>> greaterNotUnique(column: Column<T>, idColumn: Column<EntityID<Int>>, cursor: Cursor, toValue: (String) -> T): Op<Boolean> {
|
||||
fun <T : Comparable<T>> greaterNotUnique(column: Column<T>, idColumn: Column<EntityID<Int>>, cursor: Cursor, toValue: (String) -> T): Op<Boolean> {
|
||||
val id = cursor.value.substringBefore('-').toInt()
|
||||
val value = toValue(cursor.value.substringAfter('-'))
|
||||
return (column greater value) or ((column eq value) and (idColumn greater id))
|
||||
}
|
||||
|
||||
fun <T: Comparable<T>> lessNotUnique(column: Column<T>, idColumn: Column<EntityID<Int>>, cursor: Cursor, toValue: (String) -> T): Op<Boolean> {
|
||||
@JvmName("greaterNotUniqueStringKey")
|
||||
fun <T : Comparable<T>> greaterNotUnique(
|
||||
column: Column<T>,
|
||||
idColumn: Column<String>,
|
||||
cursor: Cursor,
|
||||
toValue: (String) -> T
|
||||
): Op<Boolean> {
|
||||
val id = cursor.value.substringBefore('-')
|
||||
val value = toValue(cursor.value.substringAfter('-'))
|
||||
return (column greater value) or ((column eq value) and (idColumn greater id))
|
||||
}
|
||||
|
||||
fun <T : Comparable<T>> lessNotUnique(column: Column<T>, idColumn: Column<EntityID<Int>>, cursor: Cursor, toValue: (String) -> T): Op<Boolean> {
|
||||
val id = cursor.value.substringBefore('-').toInt()
|
||||
val value = toValue(cursor.value.substringAfter('-'))
|
||||
return (column less value) or ((column eq value) and (idColumn less id))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("lessNotUniqueStringKey")
|
||||
fun <T : Comparable<T>> lessNotUnique(
|
||||
column: Column<T>,
|
||||
idColumn: Column<String>,
|
||||
cursor: Cursor,
|
||||
toValue: (String) -> T
|
||||
): Op<Boolean> {
|
||||
val id = cursor.value.substringBefore('-')
|
||||
val value = toValue(cursor.value.substringAfter('-'))
|
||||
return (column less value) or ((column eq value) and (idColumn less id))
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ class MangaType(
|
||||
val inLibrary: Boolean,
|
||||
val inLibraryAt: Long,
|
||||
val realUrl: String?,
|
||||
var lastFetchedAt: Long?, //todo
|
||||
var chaptersLastFetchedAt: Long? //todo
|
||||
var lastFetchedAt: Long?, // todo
|
||||
var chaptersLastFetchedAt: Long? // todo
|
||||
) : Node {
|
||||
constructor(row: ResultRow) : this(
|
||||
row[MangaTable.id].value,
|
||||
|
||||
Reference in New Issue
Block a user