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