diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c17c85ec..c3f96d217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - (**Chapter**) Fix losing chapter data on failed chapter list update - (**Chapter**) Fix database error when fetching chapter updates - (**Manga/API**) Fix "mangas" graphql query with active sorting and using a postgresql database (QUERY "mangas") +- (**API**) Fix GraphQL `Filter` `notAll` and `notAny` being inversed - (**API**) Fix GraphQL `Filter` causing an UnsupportedOperationException when passing an empty list as a `Any` filter value ## [v2.2.2100] + [WebUI: v20260508.01] - 2026-05-08 diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt index ce9833f3d..74998b6c1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/filter/Filter.kt @@ -435,7 +435,7 @@ fun andFilterWithCompareString( opAnd.andWhere(filter.isNull) { if (it) column.isNull() else column.isNotNull() } opAnd.andWhere(filter.equalTo) { column eq it as S } - opAnd.andWhere(filter.notEqualTo, filter.notEqualToAll, filter.notEqualToAny) { column neq it as S } + opAnd.andNotWhere(filter.notEqualTo, filter.notEqualToAll, filter.notEqualToAny) { column neq it as S } opAnd.andWhere( filter.distinctFrom, filter.distinctFromAll, @@ -455,36 +455,36 @@ fun andFilterWithCompareString( opAnd.andWhere(filter.greaterThanOrEqualTo) { column greaterEq it } opAnd.andWhere(filter.includes, filter.includesAll, filter.includesAny) { column like "%$it%" } - opAnd.andWhere(filter.notIncludes, filter.notIncludesAll, filter.notIncludesAny) { column notLike "%$it%" } + opAnd.andNotWhere(filter.notIncludes, filter.notIncludesAll, filter.notIncludesAny) { column notLike "%$it%" } opAnd.andWhere(filter.includesInsensitive, filter.includesInsensitiveAll, filter.includesInsensitiveAny) { ILikeEscapeOp.iLike(column, "%$it%") } - opAnd.andWhere(filter.notIncludesInsensitive, filter.notIncludesInsensitiveAll, filter.notIncludesInsensitiveAny) { + opAnd.andNotWhere(filter.notIncludesInsensitive, filter.notIncludesInsensitiveAll, filter.notIncludesInsensitiveAny) { ILikeEscapeOp.iNotLike(column, "%$it%") } opAnd.andWhere(filter.startsWith, filter.startsWithAll, filter.startsWithAny) { column like "$it%" } - opAnd.andWhere(filter.notStartsWith, filter.notStartsWithAll, filter.notStartsWithAny) { column notLike "$it%" } + opAnd.andNotWhere(filter.notStartsWith, filter.notStartsWithAll, filter.notStartsWithAny) { column notLike "$it%" } opAnd.andWhere(filter.startsWithInsensitive, filter.startsWithInsensitiveAll, filter.startsWithInsensitiveAny) { ILikeEscapeOp.iLike(column, "$it%") } - opAnd.andWhere(filter.notStartsWithInsensitive, filter.notStartsWithInsensitiveAll, filter.notStartsWithInsensitiveAny) { + opAnd.andNotWhere(filter.notStartsWithInsensitive, filter.notStartsWithInsensitiveAll, filter.notStartsWithInsensitiveAny) { ILikeEscapeOp.iNotLike(column, "$it%") } opAnd.andWhere(filter.endsWith, filter.endsWithAll, filter.endsWithAny) { column like "%$it" } - opAnd.andWhere(filter.notEndsWith, filter.notEndsWithAll, filter.notEndsWithAny) { column notLike "%$it" } + opAnd.andNotWhere(filter.notEndsWith, filter.notEndsWithAll, filter.notEndsWithAny) { column notLike "%$it" } opAnd.andWhere(filter.endsWithInsensitive, filter.endsWithInsensitiveAll, filter.endsWithInsensitiveAny) { ILikeEscapeOp.iLike(column, "%$it") } - opAnd.andWhere(filter.notEndsWithInsensitive, filter.notEndsWithInsensitiveAll, filter.notEndsWithInsensitiveAny) { + opAnd.andNotWhere(filter.notEndsWithInsensitive, filter.notEndsWithInsensitiveAll, filter.notEndsWithInsensitiveAny) { ILikeEscapeOp.iNotLike(column, "%$it") } opAnd.andWhere(filter.like, filter.likeAll, filter.likeAny) { column like it } - opAnd.andWhere(filter.notLike, filter.notLikeAll, filter.notLikeAny) { column notLike it } + opAnd.andNotWhere(filter.notLike, filter.notLikeAll, filter.notLikeAny) { column notLike it } opAnd.andWhere(filter.likeInsensitive, filter.likeInsensitiveAll, filter.likeInsensitiveAny) { ILikeEscapeOp.iLike(column, it) } - opAnd.andWhere(filter.notLikeInsensitive, filter.notLikeInsensitiveAll, filter.notLikeInsensitiveAny) { + opAnd.andNotWhere(filter.notLikeInsensitive, filter.notLikeInsensitiveAll, filter.notLikeInsensitiveAny) { ILikeEscapeOp.iNotLike(column, it) } @@ -535,6 +535,17 @@ class OpAnd( andWhereAny(valueAny, expr) } + fun andNotWhere( + valueDefault: T?, + valueAll: List?, + valueAny: List?, + expr: (T) -> Op, + ) { + andWhere(valueDefault, expr) + andNotWhereAll(valueAll, expr) + andNotWhereAny(valueAny, expr) + } + fun andWhereAll( values: List?, andPart: (T) -> Op, @@ -542,6 +553,14 @@ class OpAnd( values?.map { andWhere(it, andPart) } } + fun andNotWhereAll( + values: List?, + andPart: (T) -> Op, + ) { + // Inversed all equals any + andWhereAny(values, andPart) + } + fun andWhereAny( values: List?, andPart: (T) -> Op, @@ -551,6 +570,14 @@ class OpAnd( op = if (op == null) expr else (op!! and expr) } + fun andNotWhereAny( + values: List?, + andPart: (T) -> Op, + ) { + // Inversed any equals all + andWhereAll(values, andPart) + } + fun eq( value: T?, column: Column, @@ -578,7 +605,7 @@ fun , S : T?> andFilterWithCompare( opAnd.andWhere(filter.isNull) { if (it) column.isNull() else column.isNotNull() } opAnd.andWhere(filter.equalTo) { column eq it as S } - opAnd.andWhere(filter.notEqualTo, filter.notEqualToAll, filter.notEqualToAny) { column neq it as S } + opAnd.andNotWhere(filter.notEqualTo, filter.notEqualToAll, filter.notEqualToAny) { column neq it as S } opAnd.andWhere(filter.distinctFrom, filter.distinctFromAll, filter.distinctFromAny) { DistinctFromOp.distinctFrom(column, it as S) } opAnd.andWhere(filter.notDistinctFrom) { DistinctFromOp.notDistinctFrom(column, it as S) } if (!filter.`in`.isNullOrEmpty()) { @@ -606,7 +633,7 @@ fun > andFilterWithCompareEntity( opAnd.andWhere(filter.isNull) { if (it) column.isNull() else column.isNotNull() } opAnd.andWhere(filter.equalTo) { column eq it } - opAnd.andWhere(filter.notEqualTo, filter.notEqualToAll, filter.notEqualToAny) { column neq it } + opAnd.andNotWhere(filter.notEqualTo, filter.notEqualToAll, filter.notEqualToAny) { column neq it } opAnd.andWhere(filter.distinctFrom, filter.distinctFromAll, filter.distinctFromAny) { DistinctFromOp.distinctFrom(column, it) } opAnd.andWhere(filter.notDistinctFrom) { DistinctFromOp.notDistinctFrom(column, it) } if (!filter.`in`.isNullOrEmpty()) {