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 static org.junit.Assert.assertFalse;
021import static org.junit.Assert.assertTrue;
022
023import java.io.IOException;
024import java.nio.ByteBuffer;
025import java.util.regex.Pattern;
026import org.apache.hadoop.hbase.ByteBufferKeyValue;
027import org.apache.hadoop.hbase.Cell;
028import org.apache.hadoop.hbase.CompareOperator;
029import org.apache.hadoop.hbase.HBaseClassTestRule;
030import org.apache.hadoop.hbase.KeyValue;
031import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
032import org.apache.hadoop.hbase.testclassification.FilterTests;
033import org.apache.hadoop.hbase.testclassification.SmallTests;
034import org.apache.hadoop.hbase.util.Bytes;
035import org.junit.Before;
036import org.junit.ClassRule;
037import org.junit.Test;
038import org.junit.experimental.categories.Category;
039
040/**
041 * Tests the value filter
042 */
043@Category({FilterTests.class, SmallTests.class})
044public class TestSingleColumnValueFilter {
045
046  @ClassRule
047  public static final HBaseClassTestRule CLASS_RULE =
048      HBaseClassTestRule.forClass(TestSingleColumnValueFilter.class);
049
050  private static final byte[] ROW = Bytes.toBytes("test");
051  private static final byte[] COLUMN_FAMILY = Bytes.toBytes("test");
052  private static final byte [] COLUMN_QUALIFIER = Bytes.toBytes("foo");
053  private static final byte[] VAL_1 = Bytes.toBytes("a");
054  private static final byte[] VAL_2 = Bytes.toBytes("ab");
055  private static final byte[] VAL_3 = Bytes.toBytes("abc");
056  private static final byte[] VAL_4 = Bytes.toBytes("abcd");
057  private static final byte[] FULLSTRING_1 =
058    Bytes.toBytes("The quick brown fox jumps over the lazy dog.");
059  private static final byte[] FULLSTRING_2 =
060    Bytes.toBytes("The slow grey fox trips over the lazy dog.");
061  private static final String QUICK_SUBSTR = "quick";
062  private static final String QUICK_REGEX = ".+quick.+";
063  private static final Pattern QUICK_PATTERN = Pattern.compile("QuIcK", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
064
065  Filter basicFilter;
066  Filter nullFilter;
067  Filter substrFilter;
068  Filter regexFilter;
069  Filter regexPatternFilter;
070
071  @Before
072  public void setUp() throws Exception {
073    basicFilter = basicFilterNew();
074    nullFilter = nullFilterNew();
075    substrFilter = substrFilterNew();
076    regexFilter = regexFilterNew();
077    regexPatternFilter = regexFilterNew(QUICK_PATTERN);
078  }
079
080  private Filter basicFilterNew() {
081    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
082    CompareOperator.GREATER_OR_EQUAL, VAL_2);
083  }
084
085  private Filter nullFilterNew() {
086    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER, CompareOperator.NOT_EQUAL,
087        new NullComparator());
088  }
089
090  private Filter substrFilterNew() {
091    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
092    CompareOperator.EQUAL,
093      new SubstringComparator(QUICK_SUBSTR));
094  }
095
096  private Filter regexFilterNew() {
097    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
098    CompareOperator.EQUAL,
099      new RegexStringComparator(QUICK_REGEX));
100  }
101
102  private Filter regexFilterNew(Pattern pattern) {
103    return new SingleColumnValueFilter(COLUMN_FAMILY, COLUMN_QUALIFIER,
104    CompareOperator.EQUAL,
105        new RegexStringComparator(pattern.pattern(), pattern.flags()));
106  }
107
108  @Test
109  public void testLongComparator() throws IOException {
110    Filter filter = new SingleColumnValueFilter(COLUMN_FAMILY,
111        COLUMN_QUALIFIER, CompareOperator.GREATER, new LongComparator(100L));
112    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
113      Bytes.toBytes(1L));
114    assertTrue("less than", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
115    filter.reset();
116    byte[] buffer = cell.getBuffer();
117    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
118    assertTrue("less than", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
119    filter.reset();
120
121    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
122      Bytes.toBytes(100L));
123    assertTrue("Equals 100", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
124    filter.reset();
125    buffer = cell.getBuffer();
126    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
127    assertTrue("Equals 100", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
128    filter.reset();
129
130    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
131      Bytes.toBytes(120L));
132    assertTrue("include 120", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
133    filter.reset();
134    buffer = cell.getBuffer();
135    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
136    assertTrue("include 120", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
137  }
138
139  private void basicFilterTests(SingleColumnValueFilter filter)
140      throws Exception {
141    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2);
142    assertTrue("basicFilter1", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
143    byte[] buffer = cell.getBuffer();
144    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
145    assertTrue("basicFilter1", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
146    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_3);
147    assertTrue("basicFilter2", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
148    buffer = cell.getBuffer();
149    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
150    assertTrue("basicFilter2", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
151    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_4);
152    assertTrue("basicFilter3", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
153    buffer = cell.getBuffer();
154    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
155    assertTrue("basicFilter3", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
156    assertFalse("basicFilterNotNull", filter.filterRow());
157    filter.reset();
158    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_1);
159    assertTrue("basicFilter4", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
160    buffer = cell.getBuffer();
161    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
162    assertTrue("basicFilter4", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
163    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2);
164    assertTrue("basicFilter4", filter.filterCell(cell) == Filter.ReturnCode.NEXT_ROW);
165    buffer = cell.getBuffer();
166    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
167    assertTrue("basicFilter4", filter.filterCell(c) == Filter.ReturnCode.NEXT_ROW);
168    assertFalse("basicFilterAllRemaining", filter.filterAllRemaining());
169    assertTrue("basicFilterNotNull", filter.filterRow());
170    filter.reset();
171    filter.setLatestVersionOnly(false);
172    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_1);
173    assertTrue("basicFilter5", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
174    buffer = cell.getBuffer();
175    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
176    assertTrue("basicFilter5", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
177    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, VAL_2);
178    assertTrue("basicFilter5", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
179    buffer = cell.getBuffer();
180    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
181    assertTrue("basicFilter5", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
182    assertFalse("basicFilterNotNull", filter.filterRow());
183  }
184
185  private void nullFilterTests(Filter filter) throws Exception {
186    ((SingleColumnValueFilter) filter).setFilterIfMissing(true);
187    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER, FULLSTRING_1);
188    assertTrue("null1", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
189    byte[] buffer = cell.getBuffer();
190    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
191    assertTrue("null1", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
192    assertFalse("null1FilterRow", filter.filterRow());
193    filter.reset();
194    cell = new KeyValue(ROW, COLUMN_FAMILY, Bytes.toBytes("qual2"), FULLSTRING_2);
195    assertTrue("null2", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
196    buffer = cell.getBuffer();
197    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
198    assertTrue("null2", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
199    assertTrue("null2FilterRow", filter.filterRow());
200  }
201
202  private void substrFilterTests(Filter filter)
203      throws Exception {
204    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
205      FULLSTRING_1);
206    assertTrue("substrTrue",
207      filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
208    byte[] buffer = cell.getBuffer();
209    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
210    assertTrue("substrTrue", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
211    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
212      FULLSTRING_2);
213    assertTrue("substrFalse", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
214    buffer = cell.getBuffer();
215    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
216    assertTrue("substrFalse", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
217    assertFalse("substrFilterAllRemaining", filter.filterAllRemaining());
218    assertFalse("substrFilterNotNull", filter.filterRow());
219  }
220
221  private void regexFilterTests(Filter filter)
222      throws Exception {
223    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
224      FULLSTRING_1);
225    assertTrue("regexTrue",
226      filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
227    byte[] buffer = cell.getBuffer();
228    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
229    assertTrue("regexTrue", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
230    cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
231      FULLSTRING_2);
232    assertTrue("regexFalse", filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
233    buffer = cell.getBuffer();
234    c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
235    assertTrue("regexFalse", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
236    assertFalse("regexFilterAllRemaining", filter.filterAllRemaining());
237    assertFalse("regexFilterNotNull", filter.filterRow());
238  }
239
240  private void regexPatternFilterTests(Filter filter)
241      throws Exception {
242    KeyValue cell = new KeyValue(ROW, COLUMN_FAMILY, COLUMN_QUALIFIER,
243      FULLSTRING_1);
244    assertTrue("regexTrue",
245      filter.filterCell(cell) == Filter.ReturnCode.INCLUDE);
246    byte[] buffer = cell.getBuffer();
247    Cell c = new ByteBufferKeyValue(ByteBuffer.wrap(buffer), 0, buffer.length);
248    assertTrue("regexTrue", filter.filterCell(c) == Filter.ReturnCode.INCLUDE);
249    assertFalse("regexFilterAllRemaining", filter.filterAllRemaining());
250    assertFalse("regexFilterNotNull", filter.filterRow());
251  }
252
253  private Filter serializationTest(Filter filter)
254      throws Exception {
255    // Decompose filter to bytes.
256    byte[] buffer = filter.toByteArray();
257
258    // Recompose filter.
259    Filter newFilter = SingleColumnValueFilter.parseFrom(buffer);
260    return newFilter;
261  }
262
263  /**
264   * Tests identification of the stop row
265   * @throws Exception
266   */
267  @Test
268  public void testStop() throws Exception {
269    basicFilterTests((SingleColumnValueFilter) basicFilter);
270    nullFilterTests(nullFilter);
271    substrFilterTests(substrFilter);
272    regexFilterTests(regexFilter);
273    regexPatternFilterTests(regexPatternFilter);
274  }
275
276  /**
277   * Tests serialization
278   * @throws Exception
279   */
280  @Test
281  public void testSerialization() throws Exception {
282    Filter newFilter = serializationTest(basicFilter);
283    basicFilterTests((SingleColumnValueFilter)newFilter);
284    newFilter = serializationTest(nullFilter);
285    nullFilterTests(newFilter);
286    newFilter = serializationTest(substrFilter);
287    substrFilterTests(newFilter);
288    newFilter = serializationTest(regexFilter);
289    regexFilterTests(newFilter);
290    newFilter = serializationTest(regexPatternFilter);
291    regexPatternFilterTests(newFilter);
292  }
293
294}
295