From be2628875f2e966156b5073733ced1806c832bdc Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Mon, 2 Oct 2023 23:46:26 +0200 Subject: [PATCH] Correctly select results using cursors while sorting (#696) When using cursors for pagination while sorting, the sort order was inverted (desc -> asc, asc -> desc). However, this was then not considered when selecting results based on the cursor. For before/after results where always selected via greater/less. Due to inverting the sort order, this also needs to be inverted depending on the sort order (desc or asc). --- .../tachidesk/graphql/queries/CategoryQuery.kt | 16 ++++++++++++++-- .../tachidesk/graphql/queries/ChapterQuery.kt | 17 +++++++++++++++-- .../tachidesk/graphql/queries/ExtensionQuery.kt | 16 ++++++++++++++-- .../tachidesk/graphql/queries/MangaQuery.kt | 16 ++++++++++++++-- .../tachidesk/graphql/queries/MetaQuery.kt | 16 ++++++++++++++-- .../tachidesk/graphql/queries/SourceQuery.kt | 16 ++++++++++++++-- 6 files changed, 85 insertions(+), 12 deletions(-) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt index 3c5603e1..61d5521e 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/CategoryQuery.kt @@ -12,6 +12,12 @@ 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.SortOrder.ASC +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_LAST +import org.jetbrains.exposed.sql.SortOrder.DESC +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_LAST import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.andWhere @@ -147,11 +153,17 @@ class CategoryQuery { if (after != null) { res.andWhere { - (orderBy ?: CategoryOrderBy.ID).greater(after) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: CategoryOrderBy.ID).less(after) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: CategoryOrderBy.ID).greater(after) + } } } else if (before != null) { res.andWhere { - (orderBy ?: CategoryOrderBy.ID).less(before) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: CategoryOrderBy.ID).greater(before) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: CategoryOrderBy.ID).less(before) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt index cc0e931f..b2cc0d46 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ChapterQuery.kt @@ -12,11 +12,18 @@ 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.SortOrder.ASC +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_LAST +import org.jetbrains.exposed.sql.SortOrder.DESC +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_LAST 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.graphql.queries.ChapterQuery.ChapterOrderBy.ID import suwayomi.tachidesk.graphql.queries.filter.BooleanFilter import suwayomi.tachidesk.graphql.queries.filter.Filter import suwayomi.tachidesk.graphql.queries.filter.FloatFilter @@ -230,11 +237,17 @@ class ChapterQuery { if (after != null) { res.andWhere { - (orderBy ?: ChapterOrderBy.ID).greater(after) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: ID).less(after) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: ID).greater(after) + } } } else if (before != null) { res.andWhere { - (orderBy ?: ChapterOrderBy.ID).less(before) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: ID).greater(before) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: ID).less(before) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt index 27812546..58beae5d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt @@ -13,6 +13,12 @@ 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.SortOrder.ASC +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_LAST +import org.jetbrains.exposed.sql.SortOrder.DESC +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_LAST import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.neq @@ -177,11 +183,17 @@ class ExtensionQuery { if (after != null) { res.andWhere { - (orderBy ?: ExtensionOrderBy.PKG_NAME).greater(after) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: ExtensionOrderBy.PKG_NAME).less(after) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: ExtensionOrderBy.PKG_NAME).greater(after) + } } } else if (before != null) { res.andWhere { - (orderBy ?: ExtensionOrderBy.PKG_NAME).less(before) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: ExtensionOrderBy.PKG_NAME).greater(before) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: ExtensionOrderBy.PKG_NAME).less(before) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt index d4a7a11b..1fcbb71a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt @@ -12,6 +12,12 @@ 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.SortOrder.ASC +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_LAST +import org.jetbrains.exposed.sql.SortOrder.DESC +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_LAST import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.andWhere @@ -229,11 +235,17 @@ class MangaQuery { if (after != null) { res.andWhere { - (orderBy ?: MangaOrderBy.ID).greater(after) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: MangaOrderBy.ID).less(after) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: MangaOrderBy.ID).greater(after) + } } } else if (before != null) { res.andWhere { - (orderBy ?: MangaOrderBy.ID).less(before) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: MangaOrderBy.ID).greater(before) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: MangaOrderBy.ID).less(before) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt index 6204e44d..7566c4e5 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MetaQuery.kt @@ -12,6 +12,12 @@ 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.SortOrder.ASC +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_LAST +import org.jetbrains.exposed.sql.SortOrder.DESC +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_LAST import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.andWhere @@ -131,11 +137,17 @@ class MetaQuery { if (after != null) { res.andWhere { - (orderBy ?: MetaOrderBy.KEY).greater(after) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: MetaOrderBy.KEY).less(after) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: MetaOrderBy.KEY).greater(after) + } } } else if (before != null) { res.andWhere { - (orderBy ?: MetaOrderBy.KEY).less(before) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: MetaOrderBy.KEY).greater(before) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: MetaOrderBy.KEY).less(before) + } } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt index eaa688e6..aad508ec 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/SourceQuery.kt @@ -12,6 +12,12 @@ 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.SortOrder.ASC +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.ASC_NULLS_LAST +import org.jetbrains.exposed.sql.SortOrder.DESC +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_FIRST +import org.jetbrains.exposed.sql.SortOrder.DESC_NULLS_LAST import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.andWhere @@ -147,11 +153,17 @@ class SourceQuery { if (after != null) { res.andWhere { - (orderBy ?: SourceOrderBy.ID).greater(after) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: SourceOrderBy.ID).less(after) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: SourceOrderBy.ID).greater(after) + } } } else if (before != null) { res.andWhere { - (orderBy ?: SourceOrderBy.ID).less(before) + when (orderByType) { + DESC, DESC_NULLS_FIRST, DESC_NULLS_LAST -> (orderBy ?: SourceOrderBy.ID).greater(before) + null, ASC, ASC_NULLS_FIRST, ASC_NULLS_LAST -> (orderBy ?: SourceOrderBy.ID).less(before) + } } }