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