View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.filter;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertTrue;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.List;
26  import org.apache.hadoop.hbase.Cell;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.HColumnDescriptor;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.HRegionInfo;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  import org.apache.hadoop.hbase.KeyValue;
33  import org.apache.hadoop.hbase.TableName;
34  import org.apache.hadoop.hbase.client.Durability;
35  import org.apache.hadoop.hbase.client.Put;
36  import org.apache.hadoop.hbase.client.Scan;
37  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
38  import org.apache.hadoop.hbase.regionserver.HRegion;
39  import org.apache.hadoop.hbase.regionserver.InternalScanner;
40  import org.apache.hadoop.hbase.testclassification.FilterTests;
41  import org.apache.hadoop.hbase.testclassification.SmallTests;
42  import org.apache.hadoop.hbase.util.Bytes;
43  import org.junit.After;
44  import org.junit.Before;
45  import org.junit.Rule;
46  import org.junit.Test;
47  import org.junit.experimental.categories.Category;
48  import org.junit.rules.TestName;
49  import org.slf4j.Logger;
50  import org.slf4j.LoggerFactory;
51  
52  /**
53   * Test qualifierFilter with empty qualifier column
54   */
55  @Category({FilterTests.class, SmallTests.class})
56  public class TestQualifierFilterWithEmptyQualifier {
57    private final static Logger LOG
58        = LoggerFactory.getLogger(TestQualifierFilterWithEmptyQualifier.class);
59    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
60    private HRegion region;
61  
62    @Rule
63    public TestName name = new TestName();
64  
65    private static final byte[][] ROWS =
66      { Bytes.toBytes("testRowOne-0"), Bytes.toBytes("testRowOne-1"),
67            Bytes.toBytes("testRowOne-2"), Bytes.toBytes("testRowOne-3") };
68    private static final byte[] FAMILY = Bytes.toBytes("testFamily");
69    private static final byte[][] QUALIFIERS = {HConstants.EMPTY_BYTE_ARRAY,
70        Bytes.toBytes("testQualifier")};
71    private static final byte[] VALUE = Bytes.toBytes("testValueOne");
72    private long numRows = (long) ROWS.length;
73  
74    @Before
75    public void setUp() throws Exception {
76      HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("TestQualifierFilter"));
77      htd.addFamily(new HColumnDescriptor(FAMILY));
78      HRegionInfo info = new HRegionInfo(htd.getTableName(), null, null, false);
79      this.region = HRegion.createHRegion(info, TEST_UTIL.getDataTestDir(),
80          TEST_UTIL.getConfiguration(), htd);
81  
82      // Insert data
83      for (byte[] ROW : ROWS) {
84        Put p = new Put(ROW);
85        p.setDurability(Durability.SKIP_WAL);
86        for (byte[] QUALIFIER : QUALIFIERS) {
87          p.addColumn(FAMILY, QUALIFIER, VALUE);
88        }
89        this.region.put(p);
90      }
91  
92      // Flush
93      this.region.flush(true);
94    }
95  
96    @After
97    public void tearDown() throws Exception {
98      HBaseTestingUtility.closeRegionAndWAL(region);
99    }
100 
101   @Test
102   public void testQualifierFilterWithEmptyColumn() throws IOException {
103     long colsPerRow = 2;
104     long expectedKeys = colsPerRow / 2;
105     Filter f = new QualifierFilter(CompareOp.EQUAL,
106         new BinaryComparator(QUALIFIERS[0]));
107     Scan s = new Scan();
108     s.setFilter(f);
109     verifyScanNoEarlyOut(s, this.numRows, expectedKeys);
110 
111     expectedKeys = colsPerRow / 2;
112     f = new QualifierFilter(CompareOp.EQUAL,
113         new BinaryComparator(QUALIFIERS[1]));
114     s = new Scan();
115     s.setFilter(f);
116     verifyScanNoEarlyOut(s, this.numRows, expectedKeys);
117 
118     expectedKeys = colsPerRow / 2;
119     f = new QualifierFilter(CompareOp.GREATER,
120         new BinaryComparator(QUALIFIERS[0]));
121     s = new Scan();
122     s.setFilter(f);
123     verifyScanNoEarlyOut(s, this.numRows, expectedKeys);
124 
125     expectedKeys = colsPerRow;
126     f = new QualifierFilter(CompareOp.GREATER_OR_EQUAL,
127         new BinaryComparator(QUALIFIERS[0]));
128     s = new Scan();
129     s.setFilter(f);
130     verifyScanNoEarlyOut(s, this.numRows, expectedKeys);
131   }
132 
133   private void verifyScanNoEarlyOut(Scan s, long expectedRows,
134       long expectedKeys)
135       throws IOException {
136     InternalScanner scanner = this.region.getScanner(s);
137     List<Cell> results = new ArrayList<>();
138     int i = 0;
139     for (boolean done = true; done; i++) {
140       done = scanner.next(results);
141       Arrays.sort(results.toArray(new KeyValue[results.size()]),
142           KeyValue.COMPARATOR);
143       LOG.info("counter=" + i + ", " + results);
144       if(results.isEmpty()) {
145         break;
146       }
147       assertTrue("Scanned too many rows! Only expected " + expectedRows +
148           " total but already scanned " + (i+1), expectedRows > i);
149       assertEquals("Expected " + expectedKeys + " keys per row but " +
150           "returned " + results.size(), expectedKeys, results.size());
151       results.clear();
152     }
153     assertEquals("Expected " + expectedRows + " rows but scanned " + i +
154         " rows", expectedRows, i);
155   }
156 }