diff --git a/pkg/database/alertfilter.go b/pkg/database/alertfilter.go index 6d5987f848a..c2e460c17e4 100644 --- a/pkg/database/alertfilter.go +++ b/pkg/database/alertfilter.go @@ -220,9 +220,9 @@ func alertPredicatesFromFilter(filter map[string][]string) ([]predicate.Alert, e return nil, err } case "decision_type": - predicates = append(predicates, alert.HasDecisionsWith(decision.TypeEQ(value[0]))) + predicates = append(predicates, alert.HasDecisionsMatching(decision.TypeEQ(value[0]))) case "origin": - predicates = append(predicates, alert.HasDecisionsWith(decision.OriginEQ(value[0]))) + predicates = append(predicates, alert.HasDecisionsMatching(decision.OriginEQ(value[0]))) case "include_capi": // allows to exclude one or more specific origins if err = handleIncludeCapiFilter(value[0], &predicates); err != nil { return nil, err @@ -233,7 +233,7 @@ func alertPredicatesFromFilter(filter map[string][]string) ([]predicate.Alert, e } if hasActiveDecision { - predicates = append(predicates, alert.HasDecisionsWith(decision.UntilGTE(time.Now().UTC()))) + predicates = append(predicates, alert.HasDecisionsMatching(decision.UntilGTE(time.Now().UTC()))) } else { predicates = append(predicates, alert.Not(alert.HasDecisions())) } diff --git a/pkg/database/ent/alert/decision_predicates.go b/pkg/database/ent/alert/decision_predicates.go new file mode 100644 index 00000000000..a963e4c8891 --- /dev/null +++ b/pkg/database/ent/alert/decision_predicates.go @@ -0,0 +1,19 @@ +package alert + +import ( + "entgo.io/ent/dialect/sql" + + "github.com/crowdsecurity/crowdsec/pkg/database/ent/predicate" +) + +// HasDecisionsMatching keeps independent decision filters as independent subqueries, +// but avoids correlated EXISTS plans that are expensive for SQLite on large decision sets. +func HasDecisionsMatching(preds ...predicate.Decision) predicate.Alert { + return predicate.Alert(func(selector *sql.Selector) { + decisions := sql.Select(DecisionsColumn).From(sql.Table(DecisionsTable)) + for _, pred := range preds { + pred(decisions) + } + selector.Where(sql.In(selector.C(FieldID), decisions)) + }) +}