Make InDependsOnOperator like a ChangeDataSource To make InDependsOnOperator behave like a ChangesDataSource, make it return an ORed list of ChangeIndexPredicates which will be processed as a ChangeDataSource. Although ORing together a bunch of ChangeIndexPredicates results in slower match()s then the previous implementation, this is negligible with only a few changes (likely unmeasurable in real life), as a ChangeDataSource it will not have to get ANDed with status predicates when unqualifed, and even better, it will get selected when ANDed with status sources as the source. Change-Id: I0d4487ceef47e8b8416ea8403072d331de4d9d88
diff --git a/src/main/java/com/googlesource/gerrit/plugins/depends/on/InDependsOnOperator.java b/src/main/java/com/googlesource/gerrit/plugins/depends/on/InDependsOnOperator.java index 35fde51..df52117 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/depends/on/InDependsOnOperator.java +++ b/src/main/java/com/googlesource/gerrit/plugins/depends/on/InDependsOnOperator.java
@@ -15,18 +15,17 @@ package com.googlesource.gerrit.plugins.depends.on; import com.google.gerrit.entities.Change; -import com.google.gerrit.exceptions.StorageException; -import com.google.gerrit.index.query.PostFilterPredicate; import com.google.gerrit.index.query.Predicate; import com.google.gerrit.index.query.QueryParseException; import com.google.gerrit.server.query.change.ChangeData; +import com.google.gerrit.server.query.change.ChangeIndexPredicate; +import com.google.gerrit.server.query.change.ChangePredicates; import com.google.gerrit.server.query.change.ChangeQueryBuilder; import com.google.gerrit.server.query.change.ChangeQueryBuilder.ChangeOperatorFactory; import com.google.inject.Inject; import com.google.inject.Singleton; -import java.util.Collections; +import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,33 +34,8 @@ public class InDependsOnOperator implements ChangeOperatorFactory { private static final Logger log = LoggerFactory.getLogger(InDependsOnOperator.class); - public class InDependsOnPredicate extends PostFilterPredicate<ChangeData> { - protected final Set<Change.Id> dependentChanges; - - public InDependsOnPredicate(String value) { - super(InDependsOnOperator.FIELD, value); - Optional<Change.Id> changeId = Change.Id.tryParse(value); - dependentChanges = - changeId.isPresent() - ? changeMessageStore.load(changeId.get()).stream() - .filter(DependsOn::isResolved) - .map(d -> d.id()) - .collect(Collectors.toSet()) - : Collections.emptySet(); - } - - @Override - public int getCost() { - return 1; - } - - @Override - public boolean match(ChangeData changeData) throws StorageException { - return dependentChanges.contains(changeData.getId()); - } - } - public static final String FIELD = "in"; + protected final ChangeMessageStore changeMessageStore; @Inject @@ -72,14 +46,17 @@ @Override public Predicate<ChangeData> create(ChangeQueryBuilder builder, String value) throws QueryParseException { - try { - return new InDependsOnPredicate(value); - } catch (NumberFormatException ex) { - throw new QueryParseException("Error in operator " + FIELD + ":" + value, ex); - } catch (StorageException ex) { - String message = "Error in operator " + FIELD + ":" + value; - log.error(message, ex); - throw new QueryParseException(message, ex); + Optional<Change.Id> changeId = Change.Id.tryParse(value); + if (changeId.isPresent()) { + List<Predicate<ChangeData>> predicates = + changeMessageStore.load(changeId.get()).stream() + .filter(DependsOn::isResolved) + .map(d -> ChangePredicates.idStr(d.id())) + .collect(Collectors.toList()); + if (!predicates.isEmpty()) { + return Predicate.or(predicates); + } } + return ChangeIndexPredicate.none(); } }