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