diff --git a/pkg/sqlite/criterion_handlers.go b/pkg/sqlite/criterion_handlers.go index c848f1a8b..6fe9c7ce9 100644 --- a/pkg/sqlite/criterion_handlers.go +++ b/pkg/sqlite/criterion_handlers.go @@ -1012,27 +1012,33 @@ func (h *stashIDCriterionHandler) handle(ctx context.Context, f *filterBuilder) return } - var stashIDs []*string + // ideally, this handler should just convert to stashIDsCriterionHandler + // but there are some differences in how the existing handler works compared + // to the new code, specifically because this code uses the stringCriterionHandler. + // To minimise potential regressions, we'll keep the existing logic for now. + + stashIDRepo := h.stashIDRepository + t := stashIDRepo.tableName + if h.stashIDTableAs != "" { + t = h.stashIDTableAs + } + + joinClause := fmt.Sprintf("%s.%s = %s", t, stashIDRepo.idColumn, h.parentIDCol) + if h.c.Endpoint != nil && *h.c.Endpoint != "" { + joinClause += fmt.Sprintf(" AND %s.endpoint = '%s'", t, *h.c.Endpoint) + } + + f.addLeftJoin(stashIDRepo.tableName, h.stashIDTableAs, joinClause) + + v := "" if h.c.StashID != nil { - stashIDs = []*string{h.c.StashID} - } else { - stashIDs = nil + v = *h.c.StashID } - convertedInput := &models.StashIDsCriterionInput{ - Endpoint: h.c.Endpoint, - StashIDs: stashIDs, + stringCriterionHandler(&models.StringCriterionInput{ + Value: v, Modifier: h.c.Modifier, - } - - convertedHandler := stashIDsCriterionHandler{ - c: convertedInput, - stashIDRepository: h.stashIDRepository, - stashIDTableAs: h.stashIDTableAs, - parentIDCol: h.parentIDCol, - } - - convertedHandler.handle(ctx, f) + }, t+".stash_id")(ctx, f) } type stashIDsCriterionHandler struct { @@ -1060,32 +1066,25 @@ func (h *stashIDsCriterionHandler) handle(ctx context.Context, f *filterBuilder) f.addLeftJoin(stashIDRepo.tableName, h.stashIDTableAs, joinClause) - if len(h.c.StashIDs) == 0 { - stringCriterionHandler(&models.StringCriterionInput{ - Value: "", - Modifier: h.c.Modifier, - }, t+".stash_id")(ctx, f) - } else { - b := f - for _, n := range h.c.StashIDs { - query := &filterBuilder{} - v := "" - if n != nil { - v = *n - } - - stringCriterionHandler(&models.StringCriterionInput{ - Value: v, - Modifier: h.c.Modifier, - }, t+".stash_id")(ctx, query) - - if h.c.Modifier == models.CriterionModifierNotEquals { - b.and(query) - } else { - b.or(query) - } - b = query + switch h.c.Modifier { + case models.CriterionModifierIsNull: + f.addWhere(fmt.Sprintf("%s.stash_id IS NULL", t)) + case models.CriterionModifierNotNull: + f.addWhere(fmt.Sprintf("%s.stash_id IS NOT NULL", t)) + case models.CriterionModifierEquals: + var clauses []sqlClause + for _, id := range h.c.StashIDs { + clauses = append(clauses, makeClause(fmt.Sprintf("%s.stash_id = ?", t), id)) } + f.whereClauses = append(f.whereClauses, orClauses(clauses...)) + case models.CriterionModifierNotEquals: + var clauses []sqlClause + for _, id := range h.c.StashIDs { + clauses = append(clauses, makeClause(fmt.Sprintf("%s.stash_id != ?", t), id)) + } + f.whereClauses = append(f.whereClauses, andClauses(clauses...)) + default: + f.setError(fmt.Errorf("invalid modifier %s for stash IDs criterion", h.c.Modifier)) } } diff --git a/pkg/sqlite/sql.go b/pkg/sqlite/sql.go index 2d5922555..0b55af8db 100644 --- a/pkg/sqlite/sql.go +++ b/pkg/sqlite/sql.go @@ -137,6 +137,8 @@ func getCountSort(primaryTable, joinTable, primaryFK, direction string) string { return fmt.Sprintf(" ORDER BY (SELECT COUNT(*) FROM %s AS sort WHERE sort.%s = %s.id) %s", joinTable, primaryFK, primaryTable, getSortDirection(direction)) } +// getStringSearchClause returns a sqlClause for searching strings in the provided columns. +// It is used for includes and excludes string criteria. func getStringSearchClause(columns []string, q string, not bool) sqlClause { var likeClauses []string var args []interface{}