001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.filter; 019 020import java.io.IOException; 021import java.util.ArrayList; 022import java.util.Objects; 023import org.apache.hadoop.hbase.Cell; 024import org.apache.hadoop.hbase.CompareOperator; 025import org.apache.hadoop.hbase.PrivateCellUtil; 026import org.apache.hadoop.hbase.util.Bytes; 027import org.apache.yetus.audience.InterfaceAudience; 028 029import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; 030 031import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 032import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 033import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 034import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.CompareType; 035 036/** 037 * This is a generic filter to be used to filter by comparison. It takes an operator (equal, 038 * greater, not equal, etc) and a byte [] comparator. 039 * <p> 040 * To filter by row key, use {@link RowFilter}. 041 * <p> 042 * To filter by column family, use {@link FamilyFilter}. 043 * <p> 044 * To filter by column qualifier, use {@link QualifierFilter}. 045 * <p> 046 * To filter by value, use {@link ValueFilter}. 047 * <p> 048 * These filters can be wrapped with {@link SkipFilter} and {@link WhileMatchFilter} to add more 049 * control. 050 * <p> 051 * Multiple filters can be combined using {@link FilterList}. 052 */ 053@InterfaceAudience.Public 054public abstract class CompareFilter extends FilterBase { 055 /** 056 * Comparison operators. For filters only! Use {@link CompareOperator} otherwise. It 057 * (intentionally) has at least the below enums with same names. 058 * @deprecated since 2.0.0. Will be removed in 3.0.0. Use {@link CompareOperator} instead. 059 */ 060 @Deprecated 061 @InterfaceAudience.Public 062 public enum CompareOp { 063 /** less than */ 064 LESS, 065 /** less than or equal to */ 066 LESS_OR_EQUAL, 067 /** equals */ 068 EQUAL, 069 /** not equal */ 070 NOT_EQUAL, 071 /** greater than or equal to */ 072 GREATER_OR_EQUAL, 073 /** greater than */ 074 GREATER, 075 /** no operation */ 076 NO_OP, 077 } 078 079 protected CompareOperator op; 080 protected ByteArrayComparable comparator; 081 082 /** 083 * Constructor. 084 * @param compareOp the compare op for row matching 085 * @param comparator the comparator for row matching 086 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use other constructor. 087 */ 088 @Deprecated 089 public CompareFilter(final CompareOp compareOp, final ByteArrayComparable comparator) { 090 this(CompareOperator.valueOf(compareOp.name()), comparator); 091 } 092 093 /** 094 * Constructor. 095 * @param op the compare op for row matching 096 * @param comparator the comparator for row matching 097 */ 098 public CompareFilter(final CompareOperator op, final ByteArrayComparable comparator) { 099 this.op = op; 100 this.comparator = comparator; 101 } 102 103 /** 104 * n * @deprecated since 2.0.0. Will be removed in 3.0.0. Use {@link #getCompareOperator()} 105 * instead. 106 */ 107 @Deprecated 108 public CompareOp getOperator() { 109 return CompareOp.valueOf(op.name()); 110 } 111 112 public CompareOperator getCompareOperator() { 113 return op; 114 } 115 116 /** Returns the comparator */ 117 public ByteArrayComparable getComparator() { 118 return comparator; 119 } 120 121 @Override 122 public boolean filterRowKey(Cell cell) throws IOException { 123 // Impl in FilterBase might do unnecessary copy for Off heap backed Cells. 124 return false; 125 } 126 127 /** 128 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 129 * {@link #compareRow(CompareOperator, ByteArrayComparable, Cell)} 130 */ 131 @Deprecated 132 protected boolean compareRow(final CompareOp compareOp, final ByteArrayComparable comparator, 133 final Cell cell) { 134 if (compareOp == CompareOp.NO_OP) { 135 return true; 136 } 137 int compareResult = PrivateCellUtil.compareRow(cell, comparator); 138 return compare(compareOp, compareResult); 139 } 140 141 protected boolean compareRow(final CompareOperator op, final ByteArrayComparable comparator, 142 final Cell cell) { 143 if (op == CompareOperator.NO_OP) { 144 return true; 145 } 146 int compareResult = PrivateCellUtil.compareRow(cell, comparator); 147 return compare(op, compareResult); 148 } 149 150 /** 151 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 152 * {@link #compareFamily(CompareOperator, ByteArrayComparable, Cell)} 153 */ 154 @Deprecated 155 protected boolean compareFamily(final CompareOp compareOp, final ByteArrayComparable comparator, 156 final Cell cell) { 157 if (compareOp == CompareOp.NO_OP) { 158 return true; 159 } 160 int compareResult = PrivateCellUtil.compareFamily(cell, comparator); 161 return compare(compareOp, compareResult); 162 } 163 164 protected boolean compareFamily(final CompareOperator op, final ByteArrayComparable comparator, 165 final Cell cell) { 166 if (op == CompareOperator.NO_OP) { 167 return true; 168 } 169 int compareResult = PrivateCellUtil.compareFamily(cell, comparator); 170 return compare(op, compareResult); 171 } 172 173 /** 174 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 175 * {@link #compareQualifier(CompareOperator, ByteArrayComparable, Cell)} 176 */ 177 @Deprecated 178 protected boolean compareQualifier(final CompareOp compareOp, 179 final ByteArrayComparable comparator, final Cell cell) { 180 // We do not call through to the non-deprecated method for perf reasons. 181 if (compareOp == CompareOp.NO_OP) { 182 return true; 183 } 184 int compareResult = PrivateCellUtil.compareQualifier(cell, comparator); 185 return compare(compareOp, compareResult); 186 } 187 188 protected boolean compareQualifier(final CompareOperator op, final ByteArrayComparable comparator, 189 final Cell cell) { 190 // We do not call through to the non-deprecated method for perf reasons. 191 if (op == CompareOperator.NO_OP) { 192 return true; 193 } 194 int compareResult = PrivateCellUtil.compareQualifier(cell, comparator); 195 return compare(op, compareResult); 196 } 197 198 /** 199 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 200 * {@link #compareValue(CompareOperator, ByteArrayComparable, Cell)} 201 */ 202 @Deprecated 203 protected boolean compareValue(final CompareOp compareOp, final ByteArrayComparable comparator, 204 final Cell cell) { 205 // We do not call through to the non-deprecated method for perf reasons. 206 if (compareOp == CompareOp.NO_OP) { 207 return true; 208 } 209 int compareResult = PrivateCellUtil.compareValue(cell, comparator); 210 return compare(compareOp, compareResult); 211 } 212 213 protected boolean compareValue(final CompareOperator op, final ByteArrayComparable comparator, 214 final Cell cell) { 215 if (op == CompareOperator.NO_OP) { 216 return true; 217 } 218 int compareResult = PrivateCellUtil.compareValue(cell, comparator); 219 return compare(op, compareResult); 220 } 221 222 static boolean compare(final CompareOp op, int compareResult) { 223 switch (op) { 224 case LESS: 225 return compareResult <= 0; 226 case LESS_OR_EQUAL: 227 return compareResult < 0; 228 case EQUAL: 229 return compareResult != 0; 230 case NOT_EQUAL: 231 return compareResult == 0; 232 case GREATER_OR_EQUAL: 233 return compareResult > 0; 234 case GREATER: 235 return compareResult >= 0; 236 default: 237 throw new RuntimeException("Unknown Compare op " + op.name()); 238 } 239 } 240 241 static boolean compare(final CompareOperator op, int compareResult) { 242 switch (op) { 243 case LESS: 244 return compareResult <= 0; 245 case LESS_OR_EQUAL: 246 return compareResult < 0; 247 case EQUAL: 248 return compareResult != 0; 249 case NOT_EQUAL: 250 return compareResult == 0; 251 case GREATER_OR_EQUAL: 252 return compareResult > 0; 253 case GREATER: 254 return compareResult >= 0; 255 default: 256 throw new RuntimeException("Unknown Compare op " + op.name()); 257 } 258 } 259 260 /** Returns an array of heterogeneous objects */ 261 public static ArrayList<Object> extractArguments(ArrayList<byte[]> filterArguments) { 262 Preconditions.checkArgument(filterArguments.size() == 2, "Expected 2 but got: %s", 263 filterArguments.size()); 264 CompareOperator op = ParseFilter.createCompareOperator(filterArguments.get(0)); 265 ByteArrayComparable comparator = 266 ParseFilter.createComparator(ParseFilter.removeQuotesFromByteArray(filterArguments.get(1))); 267 268 if (comparator instanceof RegexStringComparator || comparator instanceof SubstringComparator) { 269 if (op != CompareOperator.EQUAL && op != CompareOperator.NOT_EQUAL) { 270 throw new IllegalArgumentException("A regexstring comparator and substring comparator" 271 + " can only be used with EQUAL and NOT_EQUAL"); 272 } 273 } 274 ArrayList<Object> arguments = new ArrayList<>(2); 275 arguments.add(op); 276 arguments.add(comparator); 277 return arguments; 278 } 279 280 /** Returns A pb instance to represent this instance. */ 281 FilterProtos.CompareFilter convert() { 282 FilterProtos.CompareFilter.Builder builder = FilterProtos.CompareFilter.newBuilder(); 283 HBaseProtos.CompareType compareOp = CompareType.valueOf(this.op.name()); 284 builder.setCompareOp(compareOp); 285 if (this.comparator != null) builder.setComparator(ProtobufUtil.toComparator(this.comparator)); 286 return builder.build(); 287 } 288 289 /** 290 * Returns true if and only if the fields of the filter that are serialized are equal to the 291 * corresponding fields in other. Used for testing. 292 */ 293 @Override 294 boolean areSerializedFieldsEqual(Filter o) { 295 if (o == this) { 296 return true; 297 } 298 if (!(o instanceof CompareFilter)) { 299 return false; 300 } 301 CompareFilter other = (CompareFilter) o; 302 return this.getCompareOperator().equals(other.getCompareOperator()) 303 && (this.getComparator() == other.getComparator() 304 || this.getComparator().areSerializedFieldsEqual(other.getComparator())); 305 } 306 307 @Override 308 public String toString() { 309 return String.format("%s (%s, %s)", this.getClass().getSimpleName(), this.op.name(), 310 Bytes.toStringBinary(this.comparator.getValue())); 311 } 312 313 @Override 314 public boolean equals(Object obj) { 315 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 316 } 317 318 @Override 319 public int hashCode() { 320 return Objects.hash(this.getComparator(), this.getCompareOperator()); 321 } 322}