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