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 34c1edde47..4e50098fef 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/MangaQuery.kt @@ -28,6 +28,7 @@ import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompare import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareEntity import suwayomi.tachidesk.graphql.queries.filter.andFilterWithCompareString import suwayomi.tachidesk.graphql.queries.filter.applyOps +import suwayomi.tachidesk.graphql.queries.util.distinctOn import suwayomi.tachidesk.graphql.server.primitives.Cursor import suwayomi.tachidesk.graphql.server.primitives.OrderBy import suwayomi.tachidesk.graphql.server.primitives.PageInfo @@ -217,7 +218,12 @@ class MangaQuery { ): MangaNodeList { val queryResults = transaction { - val res = MangaTable.leftJoin(CategoryMangaTable).selectAll() + val res = + MangaTable.leftJoin(CategoryMangaTable).slice( + distinctOn(MangaTable.id), + *(MangaTable.columns).toTypedArray(), + *(CategoryMangaTable.columns).toTypedArray(), + ).selectAll() res.applyOps(condition, filter) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/util/CustomDistinctOn.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/util/CustomDistinctOn.kt new file mode 100644 index 0000000000..b91122b509 --- /dev/null +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/util/CustomDistinctOn.kt @@ -0,0 +1,31 @@ +package suwayomi.tachidesk.graphql.queries.util + +import org.jetbrains.exposed.sql.BooleanColumnType +import org.jetbrains.exposed.sql.CustomFunction +import org.jetbrains.exposed.sql.Expression +import org.jetbrains.exposed.sql.QueryBuilder + +/** + * src: https://github.com/JetBrains/Exposed/issues/500#issuecomment-543574151 (2024-04-02 02:20) + */ + +fun distinctOn(vararg expressions: Expression<*>): CustomFunction = + customBooleanFunction( + functionName = "DISTINCT ON", + postfix = " TRUE", + params = expressions, + ) + +fun customBooleanFunction( + functionName: String, + postfix: String = "", + vararg params: Expression<*>, +): CustomFunction = + object : CustomFunction(functionName, BooleanColumnType(), *params) { + override fun toQueryBuilder(queryBuilder: QueryBuilder) { + super.toQueryBuilder(queryBuilder) + if (postfix.isNotEmpty()) { + queryBuilder.append(postfix) + } + } + }