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 * @deprecated since 2.0.0. Will be removed in 3.0.0. Use {@link #getCompareOperator()} instead. 105 */ 106 @Deprecated 107 public CompareOp getOperator() { 108 return CompareOp.valueOf(op.name()); 109 } 110 111 public CompareOperator getCompareOperator() { 112 return op; 113 } 114 115 /** Returns the comparator */ 116 public ByteArrayComparable getComparator() { 117 return comparator; 118 } 119 120 @Override 121 public boolean filterRowKey(Cell cell) throws IOException { 122 // Impl in FilterBase might do unnecessary copy for Off heap backed Cells. 123 return false; 124 } 125 126 /** 127 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 128 * {@link #compareRow(CompareOperator, ByteArrayComparable, Cell)} 129 */ 130 @Deprecated 131 protected boolean compareRow(final CompareOp compareOp, final ByteArrayComparable comparator, 132 final Cell cell) { 133 if (compareOp == CompareOp.NO_OP) { 134 return true; 135 } 136 int compareResult = PrivateCellUtil.compareRow(cell, comparator); 137 return compare(compareOp, compareResult); 138 } 139 140 protected boolean compareRow(final CompareOperator op, final ByteArrayComparable comparator, 141 final Cell cell) { 142 if (op == CompareOperator.NO_OP) { 143 return true; 144 } 145 int compareResult = PrivateCellUtil.compareRow(cell, comparator); 146 return compare(op, compareResult); 147 } 148 149 /** 150 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 151 * {@link #compareFamily(CompareOperator, ByteArrayComparable, Cell)} 152 */ 153 @Deprecated 154 protected boolean compareFamily(final CompareOp compareOp, final ByteArrayComparable comparator, 155 final Cell cell) { 156 if (compareOp == CompareOp.NO_OP) { 157 return true; 158 } 159 int compareResult = PrivateCellUtil.compareFamily(cell, comparator); 160 return compare(compareOp, compareResult); 161 } 162 163 protected boolean compareFamily(final CompareOperator op, final ByteArrayComparable comparator, 164 final Cell cell) { 165 if (op == CompareOperator.NO_OP) { 166 return true; 167 } 168 int compareResult = PrivateCellUtil.compareFamily(cell, comparator); 169 return compare(op, compareResult); 170 } 171 172 /** 173 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 174 * {@link #compareQualifier(CompareOperator, ByteArrayComparable, Cell)} 175 */ 176 @Deprecated 177 protected boolean compareQualifier(final CompareOp compareOp, 178 final ByteArrayComparable comparator, final Cell cell) { 179 // We do not call through to the non-deprecated method for perf reasons. 180 if (compareOp == CompareOp.NO_OP) { 181 return true; 182 } 183 int compareResult = PrivateCellUtil.compareQualifier(cell, comparator); 184 return compare(compareOp, compareResult); 185 } 186 187 protected boolean compareQualifier(final CompareOperator op, final ByteArrayComparable comparator, 188 final Cell cell) { 189 // We do not call through to the non-deprecated method for perf reasons. 190 if (op == CompareOperator.NO_OP) { 191 return true; 192 } 193 int compareResult = PrivateCellUtil.compareQualifier(cell, comparator); 194 return compare(op, compareResult); 195 } 196 197 /** 198 * @deprecated Since 2.0.0. Will be removed in 3.0.0. Use 199 * {@link #compareValue(CompareOperator, ByteArrayComparable, Cell)} 200 */ 201 @Deprecated 202 protected boolean compareValue(final CompareOp compareOp, final ByteArrayComparable comparator, 203 final Cell cell) { 204 // We do not call through to the non-deprecated method for perf reasons. 205 if (compareOp == CompareOp.NO_OP) { 206 return true; 207 } 208 int compareResult = PrivateCellUtil.compareValue(cell, comparator); 209 return compare(compareOp, compareResult); 210 } 211 212 protected boolean compareValue(final CompareOperator op, final ByteArrayComparable comparator, 213 final Cell cell) { 214 if (op == CompareOperator.NO_OP) { 215 return true; 216 } 217 int compareResult = PrivateCellUtil.compareValue(cell, comparator); 218 return compare(op, compareResult); 219 } 220 221 static boolean compare(final CompareOp op, int compareResult) { 222 switch (op) { 223 case LESS: 224 return compareResult <= 0; 225 case LESS_OR_EQUAL: 226 return compareResult < 0; 227 case EQUAL: 228 return compareResult != 0; 229 case NOT_EQUAL: 230 return compareResult == 0; 231 case GREATER_OR_EQUAL: 232 return compareResult > 0; 233 case GREATER: 234 return compareResult >= 0; 235 default: 236 throw new RuntimeException("Unknown Compare op " + op.name()); 237 } 238 } 239 240 static boolean compare(final CompareOperator op, int compareResult) { 241 switch (op) { 242 case LESS: 243 return compareResult <= 0; 244 case LESS_OR_EQUAL: 245 return compareResult < 0; 246 case EQUAL: 247 return compareResult != 0; 248 case NOT_EQUAL: 249 return compareResult == 0; 250 case GREATER_OR_EQUAL: 251 return compareResult > 0; 252 case GREATER: 253 return compareResult >= 0; 254 default: 255 throw new RuntimeException("Unknown Compare op " + op.name()); 256 } 257 } 258 259 /** Returns an array of heterogeneous objects */ 260 public static ArrayList<Object> extractArguments(ArrayList<byte[]> filterArguments) { 261 Preconditions.checkArgument(filterArguments.size() == 2, "Expected 2 but got: %s", 262 filterArguments.size()); 263 CompareOperator op = ParseFilter.createCompareOperator(filterArguments.get(0)); 264 ByteArrayComparable comparator = 265 ParseFilter.createComparator(ParseFilter.removeQuotesFromByteArray(filterArguments.get(1))); 266 267 if (comparator instanceof RegexStringComparator || comparator instanceof SubstringComparator) { 268 if (op != CompareOperator.EQUAL && op != CompareOperator.NOT_EQUAL) { 269 throw new IllegalArgumentException("A regexstring comparator and substring comparator" 270 + " can only be used with EQUAL and NOT_EQUAL"); 271 } 272 } 273 ArrayList<Object> arguments = new ArrayList<>(2); 274 arguments.add(op); 275 arguments.add(comparator); 276 return arguments; 277 } 278 279 /** Returns A pb instance to represent this instance. */ 280 FilterProtos.CompareFilter convert() { 281 FilterProtos.CompareFilter.Builder builder = FilterProtos.CompareFilter.newBuilder(); 282 HBaseProtos.CompareType compareOp = CompareType.valueOf(this.op.name()); 283 builder.setCompareOp(compareOp); 284 if (this.comparator != null) builder.setComparator(ProtobufUtil.toComparator(this.comparator)); 285 return builder.build(); 286 } 287 288 /** 289 * Returns true if and only if the fields of the filter that are serialized are equal to the 290 * corresponding fields in other. Used for testing. 291 */ 292 @Override 293 boolean areSerializedFieldsEqual(Filter o) { 294 if (o == this) { 295 return true; 296 } 297 if (!(o instanceof CompareFilter)) { 298 return false; 299 } 300 CompareFilter other = (CompareFilter) o; 301 return this.getCompareOperator().equals(other.getCompareOperator()) 302 && (this.getComparator() == other.getComparator() 303 || this.getComparator().areSerializedFieldsEqual(other.getComparator())); 304 } 305 306 @Override 307 public String toString() { 308 return String.format("%s (%s, %s)", this.getClass().getSimpleName(), this.op.name(), 309 Bytes.toStringBinary(this.comparator.getValue())); 310 } 311 312 @Override 313 public boolean equals(Object obj) { 314 return obj instanceof Filter && areSerializedFieldsEqual((Filter) obj); 315 } 316 317 @Override 318 public int hashCode() { 319 return Objects.hash(this.getComparator(), this.getCompareOperator()); 320 } 321}