Simplify keyset pagination

This commit is contained in:
Syer10
2023-04-08 15:27:18 -04:00
parent 58a623d44d
commit 891fb0b479
4 changed files with 34 additions and 58 deletions

View File

@@ -12,12 +12,9 @@ import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.Column import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.Op import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.andWhere
import org.jetbrains.exposed.sql.or
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.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter
@@ -34,6 +31,8 @@ import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
import suwayomi.tachidesk.graphql.server.primitives.PageInfo import suwayomi.tachidesk.graphql.server.primitives.PageInfo
import suwayomi.tachidesk.graphql.server.primitives.QueryResults 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.server.primitives.maybeSwap
import suwayomi.tachidesk.graphql.types.CategoryNodeList import suwayomi.tachidesk.graphql.types.CategoryNodeList
import suwayomi.tachidesk.graphql.types.CategoryType import suwayomi.tachidesk.graphql.types.CategoryType
@@ -65,32 +64,16 @@ class CategoryQuery {
override fun greater(cursor: Cursor): Op<Boolean> { override fun greater(cursor: Cursor): Op<Boolean> {
return when (this) { return when (this) {
ID -> CategoryTable.id greater cursor.value.toInt() ID -> CategoryTable.id greater cursor.value.toInt()
NAME -> { NAME -> greaterNotUnique(CategoryTable.name, CategoryTable.id, cursor, String::toString)
val id = cursor.value.substringBefore('-').toInt() ORDER -> greaterNotUnique(CategoryTable.order, CategoryTable.id, cursor, String::toInt)
val value = cursor.value.substringAfter('-')
(CategoryTable.name greater value) or ((CategoryTable.name eq value) and (CategoryTable.id greater id))
}
ORDER -> {
val id = cursor.value.substringBefore('-').toInt()
val value = cursor.value.substringAfter('-').toInt()
(CategoryTable.order greater value) or ((CategoryTable.order eq value) and (CategoryTable.id greater id))
}
} }
} }
override fun less(cursor: Cursor): Op<Boolean> { override fun less(cursor: Cursor): Op<Boolean> {
return when (this) { return when (this) {
ID -> CategoryTable.id less cursor.value.toInt() ID -> CategoryTable.id less cursor.value.toInt()
NAME -> { NAME -> lessNotUnique(CategoryTable.name, CategoryTable.id, cursor, String::toString)
val id = cursor.value.substringBefore('-').toInt() ORDER -> lessNotUnique(CategoryTable.order, CategoryTable.id, cursor, String::toInt)
val value = cursor.value.substringAfter('-')
(CategoryTable.name less value) or ((CategoryTable.name eq value) and (CategoryTable.id less id))
}
ORDER -> {
val id = cursor.value.substringBefore('-').toInt()
val value = cursor.value.substringAfter('-').toInt()
(CategoryTable.order less value) or ((CategoryTable.order eq value) and (CategoryTable.id less id))
}
} }
} }

View File

@@ -12,12 +12,9 @@ import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.Column import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.Op import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.andWhere
import org.jetbrains.exposed.sql.or
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
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
@@ -37,6 +34,8 @@ import suwayomi.tachidesk.graphql.server.primitives.Cursor
import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.OrderBy
import suwayomi.tachidesk.graphql.server.primitives.PageInfo import suwayomi.tachidesk.graphql.server.primitives.PageInfo
import suwayomi.tachidesk.graphql.server.primitives.QueryResults 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.server.primitives.maybeSwap
import suwayomi.tachidesk.graphql.types.MangaNodeList import suwayomi.tachidesk.graphql.types.MangaNodeList
import suwayomi.tachidesk.graphql.types.MangaType import suwayomi.tachidesk.graphql.types.MangaType
@@ -73,42 +72,18 @@ class MangaQuery {
override fun greater(cursor: Cursor): Op<Boolean> { override fun greater(cursor: Cursor): Op<Boolean> {
return when (this) { return when (this) {
ID -> MangaTable.id greater cursor.value.toInt() ID -> MangaTable.id greater cursor.value.toInt()
TITLE -> { TITLE -> greaterNotUnique(MangaTable.title, MangaTable.id, cursor, String::toString)
val id = cursor.value.substringBefore('-').toInt() IN_LIBRARY_AT -> greaterNotUnique(MangaTable.inLibraryAt, MangaTable.id, cursor, String::toLong)
val value = cursor.value.substringAfter('-') LAST_FETCHED_AT -> greaterNotUnique(MangaTable.lastFetchedAt, MangaTable.id, cursor, String::toLong)
(MangaTable.title greater value) or ((MangaTable.title eq value) and (MangaTable.id greater id))
}
IN_LIBRARY_AT -> {
val id = cursor.value.substringBefore('-').toInt()
val value = cursor.value.substringAfter('-').toLong()
(MangaTable.inLibraryAt greater value) or ((MangaTable.inLibraryAt eq value) and (MangaTable.id greater id))
}
LAST_FETCHED_AT -> {
val id = cursor.value.substringBefore('-').toInt()
val value = cursor.value.substringAfter('-').toLong()
(MangaTable.lastFetchedAt greater value) or ((MangaTable.lastFetchedAt eq value) and (MangaTable.id greater id))
}
} }
} }
override fun less(cursor: Cursor): Op<Boolean> { override fun less(cursor: Cursor): Op<Boolean> {
return when (this) { return when (this) {
ID -> MangaTable.id less cursor.value.toInt() ID -> MangaTable.id less cursor.value.toInt()
TITLE -> { TITLE -> lessNotUnique(MangaTable.title, MangaTable.id, cursor, String::toString)
val id = cursor.value.substringBefore('-').toInt() IN_LIBRARY_AT -> lessNotUnique(MangaTable.inLibraryAt, MangaTable.id, cursor, String::toLong)
val value = cursor.value.substringAfter('-') LAST_FETCHED_AT -> lessNotUnique(MangaTable.lastFetchedAt, MangaTable.id, cursor, String::toLong)
(MangaTable.title less value) or ((MangaTable.title eq value) and (MangaTable.id less id))
}
IN_LIBRARY_AT -> {
val id = cursor.value.substringBefore('-').toInt()
val value = cursor.value.substringAfter('-').toLong()
(MangaTable.inLibraryAt less value) or ((MangaTable.inLibraryAt eq value) and (MangaTable.id less id))
}
LAST_FETCHED_AT -> {
val id = cursor.value.substringBefore('-').toInt()
val value = cursor.value.substringAfter('-').toLong()
(MangaTable.lastFetchedAt less value) or ((MangaTable.lastFetchedAt eq value) and (MangaTable.id less id))
}
} }
} }

View File

@@ -1,8 +1,14 @@
package suwayomi.tachidesk.graphql.server.primitives package suwayomi.tachidesk.graphql.server.primitives
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.Column import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.Op import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.or
interface OrderBy<T> { interface OrderBy<T> {
val column: Column<out Comparable<*>> val column: Column<out Comparable<*>>
@@ -29,3 +35,15 @@ fun SortOrder?.maybeSwap(value: Any?): SortOrder {
this ?: SortOrder.ASC this ?: SortOrder.ASC
} }
} }
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> {
val id = cursor.value.substringBefore('-').toInt()
val value = toValue(cursor.value.substringAfter('-'))
return (column less value) or ((column eq value) and (idColumn less id))
}

View File

@@ -37,8 +37,8 @@ class MangaType(
val inLibrary: Boolean, val inLibrary: Boolean,
val inLibraryAt: Long, val inLibraryAt: Long,
val realUrl: String?, val realUrl: String?,
var lastFetchedAt: Long?, var lastFetchedAt: Long?, //todo
var chaptersLastFetchedAt: Long? var chaptersLastFetchedAt: Long? //todo
) : Node { ) : Node {
constructor(row: ResultRow) : this( constructor(row: ResultRow) : this(
row[MangaTable.id].value, row[MangaTable.id].value,