Kill @Rewrite support in queries These had been significantly pared down since almost all queries of consequence are sent as-is to the secondary index subsystem. The remaining queries just existed to simplify some arbitrary subtrees into slightly less complicated subtrees. This required almost a thousand lines of magical supporting code for something with no remaining performance benefit. Let it die a graceful death. Change-Id: I99ee92549b6619e7aa7529875149073f55c85c69
diff --git a/gerrit-antlr/src/main/antlr3/com/google/gerrit/server/query/Query.g b/gerrit-antlr/src/main/antlr3/com/google/gerrit/server/query/Query.g index 98f1af9..d0b5875 100644 --- a/gerrit-antlr/src/main/antlr3/com/google/gerrit/server/query/Query.g +++ b/gerrit-antlr/src/main/antlr3/com/google/gerrit/server/query/Query.g
@@ -116,7 +116,6 @@ conditionNot : '-' conditionBase -> ^(NOT conditionBase) | NOT^ conditionBase - | VARIABLE_ASSIGN^ conditionOr ')'! | conditionBase ; conditionBase @@ -143,13 +142,6 @@ : ('a'..'z' | '_')+ ; -VARIABLE_ASSIGN - : ('A'..'Z') ('A'..'Z' | 'a'..'Z')* '=' '(' { - String s = $text; - setText(s.substring(0, s.length() - 2)); - } - ; - EXACT_PHRASE : '"' ( ~('"') )* '"' { String s = $text;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexModule.java index 0cfc659..28f7f7e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexModule.java
@@ -22,7 +22,6 @@ import com.google.gerrit.lifecycle.LifecycleModule; import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.git.WorkQueue; -import com.google.gerrit.server.query.change.BasicChangeRewrites; import com.google.gerrit.server.query.change.ChangeQueryRewriter; import com.google.inject.Injector; import com.google.inject.Key; @@ -69,7 +68,6 @@ @Override protected void configure() { bind(ChangeQueryRewriter.class).to(IndexRewriteImpl.class); - bind(BasicChangeRewrites.class); bind(IndexCollection.class); listener().to(IndexCollection.class); factory(ChangeIndexer.Factory.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexRewriteImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexRewriteImpl.java index 7fbddfb..f551a7e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexRewriteImpl.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/IndexRewriteImpl.java
@@ -26,7 +26,6 @@ import com.google.gerrit.server.query.Predicate; import com.google.gerrit.server.query.QueryParseException; import com.google.gerrit.server.query.change.AndSource; -import com.google.gerrit.server.query.change.BasicChangeRewrites; import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeQueryRewriter; import com.google.gerrit.server.query.change.ChangeStatusPredicate; @@ -118,13 +117,10 @@ } private final IndexCollection indexes; - private final BasicChangeRewrites basicRewrites; @Inject - IndexRewriteImpl(IndexCollection indexes, - BasicChangeRewrites basicRewrites) { + IndexRewriteImpl(IndexCollection indexes) { this.indexes = indexes; - this.basicRewrites = basicRewrites; } @Override @@ -132,7 +128,6 @@ int limit) throws QueryParseException { checkArgument(limit > 0, "limit must be positive: %s", limit); ChangeIndex index = indexes.getSearchIndex(); - in = basicRewrites.rewrite(in); // Increase the limit rather than skipping, since we don't know how many // skipped results would have been filtered out by the enclosing AndSource. limit += start;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java index b3c6aeb..2a53e6d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java
@@ -24,7 +24,6 @@ import static com.google.gerrit.server.query.QueryParser.NOT; import static com.google.gerrit.server.query.QueryParser.OR; import static com.google.gerrit.server.query.QueryParser.SINGLE_WORD; -import static com.google.gerrit.server.query.QueryParser.VARIABLE_ASSIGN; import org.antlr.runtime.tree.Tree; @@ -222,20 +221,6 @@ case FIELD_NAME: return operator(r.getText(), onlyChildOf(r)); - case VARIABLE_ASSIGN: { - final String var = r.getText(); - final Tree opTree = onlyChildOf(r); - if (opTree.getType() == FIELD_NAME) { - final Tree val = onlyChildOf(opTree); - if (val.getType() == SINGLE_WORD && "*".equals(val.getText())) { - final String op = opTree.getText(); - final WildPatternPredicate<T> pat = new WildPatternPredicate<>(op); - return new VariablePredicate<>(var, pat); - } - } - return new VariablePredicate<>(var, toPredicate(opTree)); - } - default: throw error("Unsupported operator: " + r); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryRewriter.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryRewriter.java deleted file mode 100644 index 6173fb6..0000000 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryRewriter.java +++ /dev/null
@@ -1,505 +0,0 @@ -// Copyright (C) 2009 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.gerrit.server.query; - -import com.google.common.collect.Lists; -import com.google.inject.name.Named; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * Rewrites a Predicate tree by applying rewrite rules. - * <p> - * Subclasses may document their rewrite rules by declaring public methods with - * {@link Rewrite} annotations, such as: - * - * <pre> - * @Rewrite("A=(owner:*) B=(status:*)") - * public Predicate r1_ownerStatus(@Named("A") OperatorPredicate owner, - * @Named("B") OperatorPredicate status) { - * } - * </pre> - * <p> - * Rewrite methods are applied in order by declared name, so naming methods with - * a numeric prefix to ensure a specific ordering (if required) is suggested. - * - * @param <T> type of object the predicate can evaluate in memory. - */ -public abstract class QueryRewriter<T> { - /** - * Defines the rewrite rules known by a QueryRewriter. - * - * This class is thread-safe and may be reused or cached. - * - * @param <T> type of object the predicates can evaluate in memory. - * @param <R> type of the rewriter subclass. - */ - public static class Definition<T, R extends QueryRewriter<T>> { - private final List<RewriteRule<T>> rewriteRules; - - public Definition(Class<R> clazz, QueryBuilder<T> qb) { - rewriteRules = Lists.newArrayList(); - - Class<?> c = clazz; - while (c != QueryRewriter.class) { - Method[] declared = c.getDeclaredMethods(); - for (Method m : declared) { - Rewrite rp = m.getAnnotation(Rewrite.class); - if ((m.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT - && (m.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC - && rp != null) { - rewriteRules.add(new MethodRewrite<>(qb, rp.value(), m)); - } - } - c = c.getSuperclass(); - } - Collections.sort(rewriteRules); - } - } - - private final List<RewriteRule<T>> rewriteRules; - - protected QueryRewriter(final Definition<T, ? extends QueryRewriter<T>> def) { - this.rewriteRules = def.rewriteRules; - } - - /** Combine the passed predicates into a single AND node. */ - public Predicate<T> and(Collection<? extends Predicate<T>> that) { - return Predicate.and(that); - } - - /** Combine the passed predicates into a single AND node. */ - public Predicate<T> and(@SuppressWarnings("unchecked") Predicate<T>... that) { - return and(Arrays.asList(that)); - } - - /** Combine the passed predicates into a single OR node. */ - public Predicate<T> or(Collection<? extends Predicate<T>> that) { - return Predicate.or(that); - } - - /** Combine the passed predicates into a single OR node. */ - public Predicate<T> or(@SuppressWarnings("unchecked") Predicate<T>... that) { - return or(Arrays.asList(that)); - } - - /** Invert the passed node. */ - public Predicate<T> not(Predicate<T> that) { - return Predicate.not(that); - } - - protected Predicate<T> preRewrite(Predicate<T> in) { - return in; - } - - /** - * Apply rewrites to a graph until it stops changing. - * - * @param in the graph to rewrite. - * @return the rewritten graph. - */ - public final Predicate<T> rewrite(Predicate<T> in) { - in = preRewrite(in); - return rewriteImpl(in); - } - - private Predicate<T> rewriteImpl(Predicate<T> in) { - Predicate<T> old; - do { - old = in; - in = rewriteOne(in); - - if (old.equals(in) && in.getChildCount() > 0) { - List<Predicate<T>> n = new ArrayList<>(in.getChildCount()); - for (Predicate<T> p : in.getChildren()) { - n.add(rewriteImpl(p)); - } - n = removeDuplicates(n); - if (n.size() == 1 && (isAND(in) || isOR(in))) { - in = n.get(0); - } else { - in = in.copy(n); - } - } - - } while (!old.equals(in)); - return replaceGenericNodes(in); - } - - protected Predicate<T> replaceGenericNodes(final Predicate<T> in) { - if (in instanceof NotPredicate) { - return not(replaceGenericNodes(in.getChild(0))); - - } else if (in instanceof AndPredicate) { - List<Predicate<T>> n = new ArrayList<>(in.getChildCount()); - for (Predicate<T> c : in.getChildren()) { - n.add(replaceGenericNodes(c)); - } - return and(n); - - } else if (in instanceof OrPredicate) { - List<Predicate<T>> n = new ArrayList<>(in.getChildCount()); - for (Predicate<T> c : in.getChildren()) { - n.add(replaceGenericNodes(c)); - } - return or(n); - - } else { - return in; - } - } - - private Predicate<T> rewriteOne(Predicate<T> input) { - Predicate<T> best = null; - for (RewriteRule<T> r : rewriteRules) { - Predicate<T> n = r.rewrite(this, input); - if (n == null) { - continue; - } - - if (!r.useBestCost()) { - return n; - } - - if (best == null || n.getCost() < best.getCost()) { - best = n; - continue; - } - } - return best != null ? best : input; - } - - private static class MatchResult<T> { - private static final MatchResult<?> FAIL = new MatchResult<>(null); - private static final MatchResult<?> OK = new MatchResult<>(null); - - @SuppressWarnings("unchecked") - static <T> MatchResult<T> fail() { - return (MatchResult<T>) FAIL; - } - - @SuppressWarnings("unchecked") - static <T> MatchResult<T> ok() { - return (MatchResult<T>) OK; - } - - final Predicate<T> extra; - - MatchResult(Predicate<T> extra) { - this.extra = extra; - } - - boolean success() { - return this != FAIL; - } - } - - private MatchResult<T> match(final Map<String, Predicate<T>> outVars, - final Predicate<T> pattern, final Predicate<T> actual) { - if (pattern instanceof VariablePredicate) { - final VariablePredicate<T> v = (VariablePredicate<T>) pattern; - final MatchResult<T> r = match(outVars, v.getChild(0), actual); - if (r.success()) { - Predicate<T> old = outVars.get(v.getName()); - if (old == null) { - outVars.put(v.getName(), actual); - return r; - } else if (old.equals(actual)) { - return r; - } else { - return MatchResult.fail(); - } - } else { - return MatchResult.fail(); - } - } - - if ((isAND(pattern) && isAND(actual)) // - || (isOR(pattern) && isOR(actual)) // - || (isNOT(pattern) && isNOT(actual)) // - ) { - // Order doesn't actually matter here. That does make our logic quite - // a bit more complex as we need to consult each child at most once, - // but in any order. - // - final LinkedList<Predicate<T>> have = dup(actual); - final LinkedList<Predicate<T>> extra = new LinkedList<>(); - for (final Predicate<T> pat : pattern.getChildren()) { - boolean found = false; - for (final Iterator<Predicate<T>> i = have.iterator(); i.hasNext();) { - final MatchResult<T> r = match(outVars, pat, i.next()); - if (r.success()) { - found = true; - i.remove(); - if (r.extra != null) { - extra.add(r.extra); - } - break; - } - } - if (!found) { - return MatchResult.fail(); - } - } - have.addAll(extra); - switch (have.size()) { - case 0: - return MatchResult.ok(); - case 1: - if (isNOT(actual)) { - return new MatchResult<>(actual.copy(have)); - } - return new MatchResult<>(have.get(0)); - default: - return new MatchResult<>(actual.copy(have)); - } - - } else if (pattern.equals(actual)) { - return MatchResult.ok(); - - } else if (pattern instanceof WildPatternPredicate - && actual instanceof OperatorPredicate - && ((OperatorPredicate<T>) pattern).getOperator().equals( - ((OperatorPredicate<T>) actual).getOperator())) { - return MatchResult.ok(); - - } else { - return MatchResult.fail(); - } - } - - private static <T> LinkedList<Predicate<T>> dup(final Predicate<T> actual) { - return new LinkedList<>(actual.getChildren()); - } - - /** - * Denotes a method which wants to replace a predicate expression. - * <p> - * This annotation must be applied to a public method which returns - * {@link Predicate}. The arguments of the method should {@link Predicate}, or - * any subclass of it. The annotation value is a query language string which - * describes the subtree this rewrite applies to. Method arguments should be - * named with a {@link Named} annotation, and the same names should be used in - * the query. - * <p> - * For example: - * - * <pre> - * @Rewrite("A=(owner:*) B=(status:*)") - * public Predicate ownerStatus(@Named("A") OperatorPredicate owner, - * @Named("B") OperatorPredicate status) { - * } - * </pre> - * - * matches an AND Predicate with at least two children, one being an operator - * predicate called "owner" and the other being an operator predicate called - * "status". The variables in the query are matched by name against the - * parameters. - */ - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) - protected @interface Rewrite { - String value(); - } - - @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.METHOD) - protected @interface NoCostComputation { - } - - /** Applies a rewrite rule to a Predicate. */ - protected interface RewriteRule<T> extends Comparable<RewriteRule<T>> { - /** - * Apply a rewrite rule to the Predicate. - * - * @param input the input predicate to be tested, and possibly rewritten. - * @return a rewritten form of the predicate if this rule matches with the - * tree {@code input} and has a rewrite for it; {@code null} if this - * rule does not want this predicate. - */ - Predicate<T> rewrite(QueryRewriter<T> rewriter, Predicate<T> input); - - /** @return true if the best cost should be selected. */ - boolean useBestCost(); - } - - /** Implements the magic behind {@link Rewrite} annotations. */ - private static class MethodRewrite<T> implements RewriteRule<T> { - private final Method method; - private final Predicate<T> pattern; - private final String[] argNames; - private final Class<? extends Predicate<T>>[] argTypes; - private final boolean useBestCost; - - @SuppressWarnings("unchecked") - MethodRewrite(QueryBuilder<T> queryBuilder, String patternText, Method m) { - method = m; - useBestCost = m.getAnnotation(NoCostComputation.class) == null; - - Predicate<T> p; - try { - p = queryBuilder.parse(patternText); - } catch (QueryParseException e) { - throw new RuntimeException("Bad @Rewrite(\"" + patternText + "\")" - + " on " + m.toGenericString() + " in " + m.getDeclaringClass() - + ": " + e.getMessage(), e); - } - if (!Predicate.class.isAssignableFrom(m.getReturnType())) { - throw new RuntimeException(m.toGenericString() + " in " - + m.getDeclaringClass() + " must return " + Predicate.class); - } - - pattern = p; - argNames = new String[method.getParameterTypes().length]; - argTypes = new Class[argNames.length]; - for (int i = 0; i < argNames.length; i++) { - Named name = null; - for (Annotation a : method.getParameterAnnotations()[i]) { - if (a instanceof Named) { - name = (Named) a; - break; - } - } - if (name == null) { - throw new RuntimeException("Argument " + (i + 1) + " of " - + m.toGenericString() + " in " + m.getDeclaringClass() - + " has no @Named annotation"); - } - if (!Predicate.class.isAssignableFrom(method.getParameterTypes()[i])) { - throw new RuntimeException("Argument " + (i + 1) + " of " - + m.toGenericString() + " in " + m.getDeclaringClass() - + " must be of type " + Predicate.class); - } - argNames[i] = name.value(); - argTypes[i] = (Class<Predicate<T>>) method.getParameterTypes()[i]; - } - } - - @Override - public boolean useBestCost() { - return useBestCost; - } - - @SuppressWarnings("unchecked") - @Override - public Predicate<T> rewrite(QueryRewriter<T> rewriter, - final Predicate<T> input) { - final HashMap<String, Predicate<T>> args = new HashMap<>(); - final MatchResult<T> res = rewriter.match(args, pattern, input); - if (!res.success()) { - return null; - } - - final Predicate<T>[] argList = new Predicate[argNames.length]; - for (int i = 0; i < argList.length; i++) { - argList[i] = args.get(argNames[i]); - if (argList[i] == null) { - final String a = "@Named(\"" + argNames[i] + "\")"; - throw error(new IllegalStateException("No value bound for " + a)); - } - if (!argTypes[i].isInstance(argList[i])) { - return null; - } - } - - final Predicate<T> rep; - try { - rep = (Predicate<T>) method.invoke(rewriter, (Object[]) argList); - } catch (IllegalArgumentException e) { - throw error(e); - } catch (IllegalAccessException e) { - throw error(e); - } catch (InvocationTargetException e) { - throw error(e.getCause()); - } - - if (rep instanceof RewritePredicate) { - ((RewritePredicate<T>) rep).init(method.getName(), argList); - } - - if (res.extra == null) { - return rep; - } - - Predicate<T> extra = removeDuplicates(res.extra); - Predicate<T>[] newArgs = new Predicate[] {extra, rep}; - return input.copy(Arrays.asList(newArgs)); - } - - private IllegalArgumentException error(Throwable e) { - final String msg = "Cannot apply " + method.getName(); - return new IllegalArgumentException(msg, e); - } - - @Override - public int compareTo(RewriteRule<T> in) { - if (in instanceof MethodRewrite) { - return method.getName().compareTo( - ((MethodRewrite<T>) in).method.getName()); - } - return 1; - } - } - - private static <T> Predicate<T> removeDuplicates(Predicate<T> in) { - if (in.getChildCount() > 0) { - List<Predicate<T>> n = removeDuplicates(in.getChildren()); - if (n.size() == 1 && (isAND(in) || isOR(in))) { - in = n.get(0); - } else { - in = in.copy(n); - } - } - return in; - } - - private static <T> List<Predicate<T>> removeDuplicates(List<Predicate<T>> n) { - List<Predicate<T>> r = new ArrayList<>(); - for (Predicate<T> p : n) { - if (!r.contains(p)) { - r.add(p); - } - } - return r; - } - - private static <T> boolean isAND(final Predicate<T> p) { - return p instanceof AndPredicate; - } - - private static <T> boolean isOR(final Predicate<T> p) { - return p instanceof OrPredicate; - } - - private static <T> boolean isNOT(final Predicate<T> p) { - return p instanceof NotPredicate; - } -}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/RewritePredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/RewritePredicate.java deleted file mode 100644 index f4a2111..0000000 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/RewritePredicate.java +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright (C) 2010 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.gerrit.server.query; - -import com.google.common.collect.ImmutableList; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public abstract class RewritePredicate<T> extends Predicate<T> { - private boolean init; - private String name = getClass().getSimpleName(); - private List<Predicate<T>> children = Collections.emptyList(); - - protected void init(String name, @SuppressWarnings("unchecked") Predicate<T>... args) { - this.init = true; - this.name = name; - this.children = ImmutableList.copyOf(args); - } - - @Override - public Predicate<T> copy(Collection<? extends Predicate<T>> children) { - return this; - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object other) { - if (other instanceof RewritePredicate) { - RewritePredicate<T> that = (RewritePredicate<T>) other; - if (this.init && that.init) { - return this.getClass() == that.getClass() - && this.name.equals(that.name) - && this.children.equals(that.children); - } - } - return this == other; - } - - @Override - public int hashCode() { - int h = getClass().hashCode(); - if (!children.isEmpty()) { - h *= 31; - h += children.get(0).hashCode(); - } - return h; - } - - @Override - public final String toString() { - final StringBuilder r = new StringBuilder(); - r.append(name); - if (!children.isEmpty()) { - r.append("("); - for (int i = 0; i < children.size(); i++) { - if (i != 0) { - r.append(" "); - } - r.append(children.get(i)); - } - r.append(")"); - } - return r.toString(); - } -}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/VariablePredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/VariablePredicate.java deleted file mode 100644 index e298e5f..0000000 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/VariablePredicate.java +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright (C) 2009 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.gerrit.server.query; - -import com.google.gwtorm.server.OrmException; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Holds another predicate in a named variable. - * - * @see QueryRewriter - */ -public class VariablePredicate<T> extends Predicate<T> { - private final String name; - private final Predicate<T> that; - - protected VariablePredicate(final String name, final Predicate<T> that) { - this.name = name; - this.that = that; - } - - public String getName() { - return name; - } - - @Override - public final List<Predicate<T>> getChildren() { - return Collections.singletonList(that); - } - - @Override - public final int getChildCount() { - return 1; - } - - @Override - public final Predicate<T> getChild(final int i) { - if (i != 0) { - throw new ArrayIndexOutOfBoundsException(i); - } - return that; - } - - @Override - public Predicate<T> copy(final Collection<? extends Predicate<T>> children) { - if (children.size() != 1) { - throw new IllegalArgumentException("Expected exactly one child"); - } - return new VariablePredicate<>(getName(), children.iterator().next()); - } - - @Override - public boolean match(final T object) throws OrmException { - return that.match(object); - } - - @Override - public int getCost() { - return that.getCost(); - } - - @Override - public int hashCode() { - return getName().hashCode() * 31 + that.hashCode(); - } - - @Override - public boolean equals(final Object other) { - if (other == null) { - return false; - } - if (getClass() == other.getClass()) { - final VariablePredicate<?> v = (VariablePredicate<?>) other; - return getName().equals(v.getName()) - && getChildren().equals(v.getChildren()); - } - return false; - } - - @Override - public final String toString() { - return getName() + "=(" + that.toString() + ")"; - } -}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/WildPatternPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/WildPatternPredicate.java deleted file mode 100644 index 981051b..0000000 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/WildPatternPredicate.java +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright (C) 2009 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.gerrit.server.query; - -/** - * Predicate only for use in rewrite rule patterns. - * <p> - * May <b>only</b> be used when nested immediately within a - * {@link VariablePredicate}. Within the QueryRewriter this predicate matches - * any other operator whose name matches this predicate's operator name. - * - * @see QueryRewriter - */ -public final class WildPatternPredicate<T> extends OperatorPredicate<T> { - public WildPatternPredicate(final String name) { - super(name, "*"); - } - - @Override - public boolean match(final T object) { - throw new UnsupportedOperationException("Cannot match " + toString()); - } - - @Override - public int getCost() { - return 0; - } - - @Override - public int hashCode() { - return getOperator().hashCode() * 31; - } - - @Override - public boolean equals(final Object other) { - if (other == null) { - return false; - } - if (getClass() == other.getClass()) { - final WildPatternPredicate<?> p = (WildPatternPredicate<?>) other; - return getOperator().equals(p.getOperator()); - } - return false; - } - - @Override - public String toString() { - return getOperator() + ":" + getValue(); - } -}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/BasicChangeRewrites.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/BasicChangeRewrites.java deleted file mode 100644 index d167860..0000000 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/BasicChangeRewrites.java +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright (C) 2013 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.gerrit.server.query.change; - -import com.google.gerrit.reviewdb.client.Change; -import com.google.gerrit.reviewdb.server.ReviewDb; -import com.google.gerrit.server.query.Predicate; -import com.google.gerrit.server.query.QueryRewriter; -import com.google.inject.Inject; -import com.google.inject.OutOfScopeException; -import com.google.inject.Provider; - -public class BasicChangeRewrites extends QueryRewriter<ChangeData> { - private static final ChangeQueryBuilder BUILDER = new ChangeQueryBuilder( - new ChangeQueryBuilder.Arguments( - new InvalidProvider<ReviewDb>(), - new InvalidProvider<InternalChangeQuery>(), - new InvalidProvider<ChangeQueryRewriter>(), - null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, null, null, null, null, null)); - - private static final QueryRewriter.Definition<ChangeData, BasicChangeRewrites> mydef = - new QueryRewriter.Definition<>(BasicChangeRewrites.class, BUILDER); - - @Inject - public BasicChangeRewrites() { - super(mydef); - } - - @Rewrite("-status:open") - @NoCostComputation - public Predicate<ChangeData> r00_notOpen() { - return ChangeStatusPredicate.closed(); - } - - @Rewrite("-status:closed") - @NoCostComputation - public Predicate<ChangeData> r00_notClosed() { - return ChangeStatusPredicate.open(); - } - - @SuppressWarnings("unchecked") - @NoCostComputation - @Rewrite("-status:merged") - public Predicate<ChangeData> r00_notMerged() { - return or(ChangeStatusPredicate.open(), - new ChangeStatusPredicate(Change.Status.ABANDONED)); - } - - @SuppressWarnings("unchecked") - @NoCostComputation - @Rewrite("-status:abandoned") - public Predicate<ChangeData> r00_notAbandoned() { - return or(ChangeStatusPredicate.open(), - new ChangeStatusPredicate(Change.Status.MERGED)); - } - - private static final class InvalidProvider<T> implements Provider<T> { - @Override - public T get() { - throw new OutOfScopeException("Not available at init"); - } - } -}
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriteTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriteTest.java index 042459b..8d7866d 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriteTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/index/IndexRewriteTest.java
@@ -30,7 +30,6 @@ import com.google.gerrit.server.query.Predicate; import com.google.gerrit.server.query.QueryParseException; import com.google.gerrit.server.query.change.AndSource; -import com.google.gerrit.server.query.change.BasicChangeRewrites; import com.google.gerrit.server.query.change.ChangeData; import com.google.gerrit.server.query.change.ChangeQueryBuilder; import com.google.gerrit.server.query.change.OrSource; @@ -54,7 +53,7 @@ indexes = new IndexCollection(); indexes.setSearchIndex(index); queryBuilder = new FakeQueryBuilder(indexes); - rewrite = new IndexRewriteImpl(indexes, new BasicChangeRewrites()); + rewrite = new IndexRewriteImpl(indexes); } @Test @@ -94,9 +93,9 @@ @Test public void testThreeLevelTreeWithAllIndexPredicates() throws Exception { Predicate<ChangeData> in = - parse("-status:abandoned (status:open OR status:merged)"); + parse("-status:abandoned (file:a OR file:b)"); assertEquals( - query(parse("status:new OR status:submitted OR status:draft OR status:merged")), + query(in), rewrite.rewrite(in, 0, DEFAULT_MAX_QUERY_LIMIT)); }