Line data Source code
1 : // Copyright (C) 2016 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.index.query; 16 : 17 : import com.google.common.base.MoreObjects; 18 : import com.google.common.collect.ImmutableList; 19 : import com.google.gerrit.exceptions.StorageException; 20 : import com.google.gerrit.index.Index; 21 : import com.google.gerrit.index.QueryOptions; 22 : import java.util.Collection; 23 : import java.util.List; 24 : 25 : /** 26 : * Wrapper combining an {@link IndexPredicate} together with a {@link DataSource} that returns 27 : * matching results from the index. 28 : * 29 : * <p>Appropriate to return as the rootmost predicate that can be processed using the secondary 30 : * index; such predicates must also implement {@link DataSource} to be chosen by the query 31 : * processor. 32 : * 33 : * @param <I> The type of the IDs by which the entities are stored in the index. 34 : * @param <T> The type of the entities that are stored in the index. 35 : */ 36 : public class IndexedQuery<I, T> extends Predicate<T> implements DataSource<T>, Paginated<T> { 37 : protected final Index<I, T> index; 38 : 39 : private QueryOptions opts; 40 : private final Predicate<T> pred; 41 : protected DataSource<T> source; 42 : 43 : public IndexedQuery(Index<I, T> index, Predicate<T> pred, QueryOptions opts) 44 151 : throws QueryParseException { 45 151 : this.index = index; 46 151 : this.opts = opts; 47 151 : this.pred = pred; 48 151 : this.source = index.getSource(pred, this.opts); 49 151 : } 50 : 51 : @Override 52 : public int getChildCount() { 53 0 : return 1; 54 : } 55 : 56 : @Override 57 : public Predicate<T> getChild(int i) { 58 151 : if (i == 0) { 59 151 : return pred; 60 : } 61 0 : throw new ArrayIndexOutOfBoundsException(i); 62 : } 63 : 64 : @Override 65 : public List<Predicate<T>> getChildren() { 66 0 : return ImmutableList.of(pred); 67 : } 68 : 69 : @Override 70 : public QueryOptions getOptions() { 71 106 : return opts; 72 : } 73 : 74 : @Override 75 : public int getCardinality() { 76 120 : return source != null ? source.getCardinality() : opts.limit(); 77 : } 78 : 79 : @Override 80 : public ResultSet<T> read() { 81 151 : return source.read(); 82 : } 83 : 84 : @Override 85 : public ResultSet<FieldBundle> readRaw() { 86 0 : return source.readRaw(); 87 : } 88 : 89 : @Override 90 : public ResultSet<T> restart(int start, int pageSize) { 91 6 : opts = opts.withStart(start).withPageSize(pageSize); 92 6 : return search(); 93 : } 94 : 95 : @Override 96 : public ResultSet<T> restart(Object searchAfter, int pageSize) { 97 4 : opts = opts.withSearchAfter(searchAfter).withPageSize(pageSize); 98 4 : return search(); 99 : } 100 : 101 : @Override 102 : public Predicate<T> copy(Collection<? extends Predicate<T>> children) { 103 0 : return this; 104 : } 105 : 106 : @Override 107 : public int hashCode() { 108 0 : return pred.hashCode(); 109 : } 110 : 111 : // Suppress the EqualsGetClass warning as this is legacy code. 112 : @SuppressWarnings("EqualsGetClass") 113 : @Override 114 : public boolean equals(Object other) { 115 1 : if (other == null || getClass() != other.getClass()) { 116 0 : return false; 117 : } 118 1 : IndexedQuery<?, ?> o = (IndexedQuery<?, ?>) other; 119 1 : return pred.equals(o.pred) && opts.equals(o.opts); 120 : } 121 : 122 : @Override 123 : public String toString() { 124 14 : return MoreObjects.toStringHelper("index").add("p", pred).add("opts", opts).toString(); 125 : } 126 : 127 : private ResultSet<T> search() { 128 : try { 129 6 : source = index.getSource(pred, opts); 130 0 : } catch (QueryParseException e) { 131 : // Don't need to show this exception to the user; the only thing that 132 : // changed about pred was its start, and any other QPEs that might happen 133 : // should have already thrown from the constructor. 134 0 : throw new StorageException(e); 135 6 : } 136 : // Don't convert start to a limit, since the caller of this method (see 137 : // AndSource) has calculated the actual number to skip. 138 6 : return read(); 139 : } 140 : }