1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
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
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
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 }