mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-04 03:14:40 -05:00
Complete MetaQuery
This commit is contained in:
@@ -9,13 +9,31 @@ package suwayomi.tachidesk.graphql.queries
|
|||||||
|
|
||||||
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
||||||
import graphql.schema.DataFetchingEnvironment
|
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.selectAll
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
import suwayomi.tachidesk.global.model.table.GlobalMetaTable
|
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.GlobalMetaItem
|
||||||
import suwayomi.tachidesk.graphql.types.MetaItem
|
import suwayomi.tachidesk.graphql.types.MetaItem
|
||||||
import suwayomi.tachidesk.graphql.types.MetaNodeList
|
import suwayomi.tachidesk.graphql.types.MetaNodeList
|
||||||
import suwayomi.tachidesk.graphql.types.MetaNodeList.Companion.toNodeList
|
|
||||||
import java.util.concurrent.CompletableFuture
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,11 +50,145 @@ class MetaQuery {
|
|||||||
return dataFetchingEnvironment.getValueFromDataLoader<String, MetaItem?>("GlobalMetaDataLoader", key)
|
return dataFetchingEnvironment.getValueFromDataLoader<String, MetaItem?>("GlobalMetaDataLoader", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun metas(): MetaNodeList {
|
enum class MetaOrderBy(override val column: Column<out Comparable<*>>) : OrderBy<MetaItem> {
|
||||||
val results = transaction {
|
KEY(GlobalMetaTable.key),
|
||||||
GlobalMetaTable.selectAll().toList()
|
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()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,8 +42,32 @@ fun <T: Comparable<T>> greaterNotUnique(column: Column<T>, idColumn: Column<Enti
|
|||||||
return (column greater value) or ((column eq value) and (idColumn greater id))
|
return (column greater value) or ((column eq value) and (idColumn greater id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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> {
|
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 id = cursor.value.substringBefore('-').toInt()
|
||||||
val value = toValue(cursor.value.substringAfter('-'))
|
val value = toValue(cursor.value.substringAfter('-'))
|
||||||
return (column less value) or ((column eq value) and (idColumn less id))
|
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))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user