1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.regionserver;
21
22 import static org.apache.hadoop.hbase.regionserver.ScanQueryMatcher.MatchCode.INCLUDE;
23 import static org.apache.hadoop.hbase.regionserver.ScanQueryMatcher.MatchCode.SKIP;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.NavigableSet;
31
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.Cell;
34 import org.apache.hadoop.hbase.HBaseConfiguration;
35 import org.apache.hadoop.hbase.HConstants;
36 import org.apache.hadoop.hbase.KeepDeletedCells;
37 import org.apache.hadoop.hbase.KeyValue;
38 import org.apache.hadoop.hbase.KeyValue.KVComparator;
39 import org.apache.hadoop.hbase.KeyValue.Type;
40 import org.apache.hadoop.hbase.KeyValueUtil;
41 import org.apache.hadoop.hbase.client.Get;
42 import org.apache.hadoop.hbase.client.Scan;
43 import org.apache.hadoop.hbase.regionserver.ScanQueryMatcher.MatchCode;
44 import org.apache.hadoop.hbase.testclassification.SmallTests;
45 import org.apache.hadoop.hbase.util.Bytes;
46 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.experimental.categories.Category;
50
51 @Category(SmallTests.class)
52 public class TestQueryMatcher {
53 private static final boolean PRINT = false;
54 private Configuration conf;
55
56 private byte[] row1;
57 private byte[] row2;
58 private byte[] row3;
59 private byte[] fam1;
60 private byte[] fam2;
61 private byte[] col1;
62 private byte[] col2;
63 private byte[] col3;
64 private byte[] col4;
65 private byte[] col5;
66
67 private byte[] data;
68
69 private Get get;
70
71 long ttl = Long.MAX_VALUE;
72 KVComparator rowComparator;
73 private Scan scan;
74
75 @Before
76 public void setUp() throws Exception {
77 this.conf = HBaseConfiguration.create();
78 row1 = Bytes.toBytes("row1");
79 row2 = Bytes.toBytes("row2");
80 row3 = Bytes.toBytes("row3");
81 fam1 = Bytes.toBytes("fam1");
82 fam2 = Bytes.toBytes("fam2");
83 col1 = Bytes.toBytes("col1");
84 col2 = Bytes.toBytes("col2");
85 col3 = Bytes.toBytes("col3");
86 col4 = Bytes.toBytes("col4");
87 col5 = Bytes.toBytes("col5");
88
89 data = Bytes.toBytes("data");
90
91
92 get = new Get(row1);
93 get.addFamily(fam1);
94 get.addColumn(fam2, col2);
95 get.addColumn(fam2, col4);
96 get.addColumn(fam2, col5);
97 this.scan = new Scan(get);
98
99 rowComparator = KeyValue.COMPARATOR;
100 }
101
102
103
104
105
106
107 @Test
108 public void testNeverIncludeFakeCell() throws IOException {
109 long now = EnvironmentEdgeManager.currentTime();
110
111 ScanQueryMatcher qm = new ScanQueryMatcher(scan,
112 new ScanInfo(this.conf, fam2, 10, 1, ttl, KeepDeletedCells.FALSE, 0, rowComparator),
113 get.getFamilyMap().get(fam2), now - ttl, now);
114 Cell kv = new KeyValue(row1, fam2, col2, 1, data);
115 Cell cell = KeyValueUtil.createLastOnRowCol(kv);
116 qm.setRow(kv.getRowArray(), kv.getRowOffset(), kv.getRowLength());
117 MatchCode code = qm.match(cell);
118 assertFalse(code.compareTo(MatchCode.SEEK_NEXT_COL) != 0);
119 }
120
121 private void _testMatch_ExplicitColumns(Scan scan, List<MatchCode> expected) throws IOException {
122 long now = EnvironmentEdgeManager.currentTime();
123
124 ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(this.conf, fam2,
125 0, 1, ttl, KeepDeletedCells.FALSE, 0, rowComparator), get.getFamilyMap().get(fam2),
126 now - ttl, now);
127
128 List<KeyValue> memstore = new ArrayList<KeyValue>();
129 memstore.add(new KeyValue(row1, fam2, col1, 1, data));
130 memstore.add(new KeyValue(row1, fam2, col2, 1, data));
131 memstore.add(new KeyValue(row1, fam2, col3, 1, data));
132 memstore.add(new KeyValue(row1, fam2, col4, 1, data));
133 memstore.add(new KeyValue(row1, fam2, col5, 1, data));
134
135 memstore.add(new KeyValue(row2, fam1, col1, data));
136
137 List<ScanQueryMatcher.MatchCode> actual = new ArrayList<ScanQueryMatcher.MatchCode>();
138 KeyValue k = memstore.get(0);
139 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
140
141 for (KeyValue kv : memstore){
142 actual.add(qm.match(kv));
143 }
144
145 assertEquals(expected.size(), actual.size());
146 for(int i=0; i< expected.size(); i++){
147 assertEquals(expected.get(i), actual.get(i));
148 if(PRINT){
149 System.out.println("expected "+expected.get(i)+
150 ", actual " +actual.get(i));
151 }
152 }
153 }
154
155 @Test
156 public void testMatch_ExplicitColumns()
157 throws IOException {
158
159
160
161
162 List<MatchCode> expected = new ArrayList<ScanQueryMatcher.MatchCode>();
163 expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
164 expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL);
165 expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
166 expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL);
167 expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW);
168 expected.add(ScanQueryMatcher.MatchCode.DONE);
169
170 _testMatch_ExplicitColumns(scan, expected);
171 }
172
173 @Test
174 public void testMatch_Wildcard()
175 throws IOException {
176
177
178
179
180 List<MatchCode> expected = new ArrayList<ScanQueryMatcher.MatchCode>();
181 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
182 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
183 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
184 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
185 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
186 expected.add(ScanQueryMatcher.MatchCode.DONE);
187
188 long now = EnvironmentEdgeManager.currentTime();
189 ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(this.conf, fam2,
190 0, 1, ttl, KeepDeletedCells.FALSE, 0, rowComparator), null,
191 now - ttl, now);
192
193 List<KeyValue> memstore = new ArrayList<KeyValue>();
194 memstore.add(new KeyValue(row1, fam2, col1, 1, data));
195 memstore.add(new KeyValue(row1, fam2, col2, 1, data));
196 memstore.add(new KeyValue(row1, fam2, col3, 1, data));
197 memstore.add(new KeyValue(row1, fam2, col4, 1, data));
198 memstore.add(new KeyValue(row1, fam2, col5, 1, data));
199 memstore.add(new KeyValue(row2, fam1, col1, 1, data));
200
201 List<ScanQueryMatcher.MatchCode> actual = new ArrayList<ScanQueryMatcher.MatchCode>();
202
203 KeyValue k = memstore.get(0);
204 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
205
206 for(KeyValue kv : memstore) {
207 actual.add(qm.match(kv));
208 }
209
210 assertEquals(expected.size(), actual.size());
211 for(int i=0; i< expected.size(); i++){
212 assertEquals(expected.get(i), actual.get(i));
213 if(PRINT){
214 System.out.println("expected "+expected.get(i)+
215 ", actual " +actual.get(i));
216 }
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229 @Test
230 public void testMatch_ExpiredExplicit()
231 throws IOException {
232
233 long testTTL = 1000;
234 MatchCode [] expected = new MatchCode[] {
235 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
236 ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL,
237 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
238 ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL,
239 ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW,
240 ScanQueryMatcher.MatchCode.DONE
241 };
242
243 long now = EnvironmentEdgeManager.currentTime();
244 ScanQueryMatcher qm =
245 new ScanQueryMatcher(scan,
246 new ScanInfo(this.conf, fam2, 0, 1, testTTL, KeepDeletedCells.FALSE, 0,
247 rowComparator), get.getFamilyMap().get(fam2), now - testTTL, now);
248
249 KeyValue [] kvs = new KeyValue[] {
250 new KeyValue(row1, fam2, col1, now-100, data),
251 new KeyValue(row1, fam2, col2, now-50, data),
252 new KeyValue(row1, fam2, col3, now-5000, data),
253 new KeyValue(row1, fam2, col4, now-500, data),
254 new KeyValue(row1, fam2, col5, now-10000, data),
255 new KeyValue(row2, fam1, col1, now-10, data)
256 };
257
258 KeyValue k = kvs[0];
259 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
260
261 List<MatchCode> actual = new ArrayList<MatchCode>(kvs.length);
262 for (KeyValue kv : kvs) {
263 actual.add( qm.match(kv) );
264 }
265
266 assertEquals(expected.length, actual.size());
267 for (int i=0; i<expected.length; i++) {
268 if(PRINT){
269 System.out.println("expected "+expected[i]+
270 ", actual " +actual.get(i));
271 }
272 assertEquals(expected[i], actual.get(i));
273 }
274 }
275
276
277
278
279
280
281
282
283
284 @Test
285 public void testMatch_ExpiredWildcard()
286 throws IOException {
287
288 long testTTL = 1000;
289 MatchCode [] expected = new MatchCode[] {
290 ScanQueryMatcher.MatchCode.INCLUDE,
291 ScanQueryMatcher.MatchCode.INCLUDE,
292 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
293 ScanQueryMatcher.MatchCode.INCLUDE,
294 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
295 ScanQueryMatcher.MatchCode.DONE
296 };
297
298 long now = EnvironmentEdgeManager.currentTime();
299 ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(this.conf, fam2,
300 0, 1, testTTL, KeepDeletedCells.FALSE, 0, rowComparator), null,
301 now - testTTL, now);
302
303 KeyValue [] kvs = new KeyValue[] {
304 new KeyValue(row1, fam2, col1, now-100, data),
305 new KeyValue(row1, fam2, col2, now-50, data),
306 new KeyValue(row1, fam2, col3, now-5000, data),
307 new KeyValue(row1, fam2, col4, now-500, data),
308 new KeyValue(row1, fam2, col5, now-10000, data),
309 new KeyValue(row2, fam1, col1, now-10, data)
310 };
311 KeyValue k = kvs[0];
312 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
313
314 List<ScanQueryMatcher.MatchCode> actual =
315 new ArrayList<ScanQueryMatcher.MatchCode>(kvs.length);
316 for (KeyValue kv : kvs) {
317 actual.add( qm.match(kv) );
318 }
319
320 assertEquals(expected.length, actual.size());
321 for (int i=0; i<expected.length; i++) {
322 if(PRINT){
323 System.out.println("expected "+expected[i]+
324 ", actual " +actual.get(i));
325 }
326 assertEquals(expected[i], actual.get(i));
327 }
328 }
329
330 @Test
331 public void testMatch_PartialRangeDropDeletes() throws Exception {
332
333 testDropDeletes(
334 row2, row3, new byte[][] { row1, row2, row2, row3 }, INCLUDE, SKIP, SKIP, INCLUDE);
335 testDropDeletes(row2, row3, new byte[][] { row1, row1, row2 }, INCLUDE, INCLUDE, SKIP);
336 testDropDeletes(row2, row3, new byte[][] { row2, row3, row3 }, SKIP, INCLUDE, INCLUDE);
337 testDropDeletes(row1, row3, new byte[][] { row1, row2, row3 }, SKIP, SKIP, INCLUDE);
338
339 testDropDeletes(HConstants.EMPTY_START_ROW, row3,
340 new byte[][] { row1, row2, row3 }, SKIP, SKIP, INCLUDE);
341 testDropDeletes(row2, HConstants.EMPTY_END_ROW,
342 new byte[][] { row1, row2, row3 }, INCLUDE, SKIP, SKIP);
343 testDropDeletes(HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW,
344 new byte[][] { row1, row2, row3, row3 }, SKIP, SKIP, SKIP, SKIP);
345
346
347 testDropDeletes(row2, row3, new byte[][] { row1, row1, row3 }, INCLUDE, INCLUDE, INCLUDE);
348 testDropDeletes(row2, row3, new byte[][] { row3, row3 }, INCLUDE, INCLUDE);
349 testDropDeletes(row2, row3, new byte[][] { row1, row1 }, INCLUDE, INCLUDE);
350 }
351
352 private void testDropDeletes(
353 byte[] from, byte[] to, byte[][] rows, MatchCode... expected) throws IOException {
354 long now = EnvironmentEdgeManager.currentTime();
355
356 ScanInfo scanInfo =
357 new ScanInfo(this.conf, fam2, 0, 1, ttl, KeepDeletedCells.FALSE, -1L, rowComparator);
358 NavigableSet<byte[]> cols = get.getFamilyMap().get(fam2);
359
360 ScanQueryMatcher qm = new ScanQueryMatcher(scan, scanInfo, cols, Long.MAX_VALUE,
361 HConstants.OLDEST_TIMESTAMP, HConstants.OLDEST_TIMESTAMP, now, from, to, null);
362 List<ScanQueryMatcher.MatchCode> actual =
363 new ArrayList<ScanQueryMatcher.MatchCode>(rows.length);
364 byte[] prevRow = null;
365 for (byte[] row : rows) {
366 if (prevRow == null || !Bytes.equals(prevRow, row)) {
367 qm.setRow(row, 0, (short)row.length);
368 prevRow = row;
369 }
370 actual.add(qm.match(new KeyValue(row, fam2, null, now, Type.Delete)));
371 }
372
373 assertEquals(expected.length, actual.size());
374 for (int i = 0; i < expected.length; i++) {
375 if (PRINT) System.out.println("expected " + expected[i] + ", actual " + actual.get(i));
376 assertEquals(expected[i], actual.get(i));
377 }
378 }
379 }