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.testclassification.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 long now = EnvironmentEdgeManager.currentTime();
96
97 ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(fam2,
98 0, 1, ttl, KeepDeletedCells.FALSE, 0, rowComparator), get.getFamilyMap().get(fam2),
99 now - ttl, now);
100
101 List<KeyValue> memstore = new ArrayList<KeyValue>();
102 memstore.add(new KeyValue(row1, fam2, col1, 1, data));
103 memstore.add(new KeyValue(row1, fam2, col2, 1, data));
104 memstore.add(new KeyValue(row1, fam2, col3, 1, data));
105 memstore.add(new KeyValue(row1, fam2, col4, 1, data));
106 memstore.add(new KeyValue(row1, fam2, col5, 1, data));
107
108 memstore.add(new KeyValue(row2, fam1, col1, data));
109
110 List<ScanQueryMatcher.MatchCode> actual = new ArrayList<ScanQueryMatcher.MatchCode>();
111 KeyValue k = memstore.get(0);
112 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
113
114 for (KeyValue kv : memstore){
115 actual.add(qm.match(kv));
116 }
117
118 assertEquals(expected.size(), actual.size());
119 for(int i=0; i< expected.size(); i++){
120 assertEquals(expected.get(i), actual.get(i));
121 if(PRINT){
122 System.out.println("expected "+expected.get(i)+
123 ", actual " +actual.get(i));
124 }
125 }
126 }
127
128 public void testMatch_ExplicitColumns()
129 throws IOException {
130
131
132
133
134 List<MatchCode> expected = new ArrayList<ScanQueryMatcher.MatchCode>();
135 expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
136 expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL);
137 expected.add(ScanQueryMatcher.MatchCode.SEEK_NEXT_COL);
138 expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL);
139 expected.add(ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_ROW);
140 expected.add(ScanQueryMatcher.MatchCode.DONE);
141
142 _testMatch_ExplicitColumns(scan, expected);
143 }
144
145 public void testMatch_Wildcard()
146 throws IOException {
147
148
149
150
151 List<MatchCode> expected = new ArrayList<ScanQueryMatcher.MatchCode>();
152 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
153 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
154 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
155 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
156 expected.add(ScanQueryMatcher.MatchCode.INCLUDE);
157 expected.add(ScanQueryMatcher.MatchCode.DONE);
158
159 long now = EnvironmentEdgeManager.currentTime();
160 ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(fam2,
161 0, 1, ttl, KeepDeletedCells.FALSE, 0, rowComparator), null,
162 now - ttl, now);
163
164 List<KeyValue> memstore = new ArrayList<KeyValue>();
165 memstore.add(new KeyValue(row1, fam2, col1, 1, data));
166 memstore.add(new KeyValue(row1, fam2, col2, 1, data));
167 memstore.add(new KeyValue(row1, fam2, col3, 1, data));
168 memstore.add(new KeyValue(row1, fam2, col4, 1, data));
169 memstore.add(new KeyValue(row1, fam2, col5, 1, data));
170 memstore.add(new KeyValue(row2, fam1, col1, 1, data));
171
172 List<ScanQueryMatcher.MatchCode> actual = new ArrayList<ScanQueryMatcher.MatchCode>();
173
174 KeyValue k = memstore.get(0);
175 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
176
177 for(KeyValue kv : memstore) {
178 actual.add(qm.match(kv));
179 }
180
181 assertEquals(expected.size(), actual.size());
182 for(int i=0; i< expected.size(); i++){
183 assertEquals(expected.get(i), actual.get(i));
184 if(PRINT){
185 System.out.println("expected "+expected.get(i)+
186 ", actual " +actual.get(i));
187 }
188 }
189 }
190
191
192
193
194
195
196
197
198
199
200 public void testMatch_ExpiredExplicit()
201 throws IOException {
202
203 long testTTL = 1000;
204 MatchCode [] expected = new MatchCode[] {
205 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
206 ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL,
207 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
208 ScanQueryMatcher.MatchCode.INCLUDE_AND_SEEK_NEXT_COL,
209 ScanQueryMatcher.MatchCode.SEEK_NEXT_ROW,
210 ScanQueryMatcher.MatchCode.DONE
211 };
212
213 long now = EnvironmentEdgeManager.currentTime();
214 ScanQueryMatcher qm =
215 new ScanQueryMatcher(scan, new ScanInfo(fam2, 0, 1, testTTL, KeepDeletedCells.FALSE, 0,
216 rowComparator), get.getFamilyMap().get(fam2), now - testTTL, now);
217
218 KeyValue [] kvs = new KeyValue[] {
219 new KeyValue(row1, fam2, col1, now-100, data),
220 new KeyValue(row1, fam2, col2, now-50, data),
221 new KeyValue(row1, fam2, col3, now-5000, data),
222 new KeyValue(row1, fam2, col4, now-500, data),
223 new KeyValue(row1, fam2, col5, now-10000, data),
224 new KeyValue(row2, fam1, col1, now-10, data)
225 };
226
227 KeyValue k = kvs[0];
228 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
229
230 List<MatchCode> actual = new ArrayList<MatchCode>(kvs.length);
231 for (KeyValue kv : kvs) {
232 actual.add( qm.match(kv) );
233 }
234
235 assertEquals(expected.length, actual.size());
236 for (int i=0; i<expected.length; i++) {
237 if(PRINT){
238 System.out.println("expected "+expected[i]+
239 ", actual " +actual.get(i));
240 }
241 assertEquals(expected[i], actual.get(i));
242 }
243 }
244
245
246
247
248
249
250
251
252
253
254 public void testMatch_ExpiredWildcard()
255 throws IOException {
256
257 long testTTL = 1000;
258 MatchCode [] expected = new MatchCode[] {
259 ScanQueryMatcher.MatchCode.INCLUDE,
260 ScanQueryMatcher.MatchCode.INCLUDE,
261 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
262 ScanQueryMatcher.MatchCode.INCLUDE,
263 ScanQueryMatcher.MatchCode.SEEK_NEXT_COL,
264 ScanQueryMatcher.MatchCode.DONE
265 };
266
267 long now = EnvironmentEdgeManager.currentTime();
268 ScanQueryMatcher qm = new ScanQueryMatcher(scan, new ScanInfo(fam2,
269 0, 1, testTTL, KeepDeletedCells.FALSE, 0, rowComparator), null,
270 now - testTTL, now);
271
272 KeyValue [] kvs = new KeyValue[] {
273 new KeyValue(row1, fam2, col1, now-100, data),
274 new KeyValue(row1, fam2, col2, now-50, data),
275 new KeyValue(row1, fam2, col3, now-5000, data),
276 new KeyValue(row1, fam2, col4, now-500, data),
277 new KeyValue(row1, fam2, col5, now-10000, data),
278 new KeyValue(row2, fam1, col1, now-10, data)
279 };
280 KeyValue k = kvs[0];
281 qm.setRow(k.getRowArray(), k.getRowOffset(), k.getRowLength());
282
283 List<ScanQueryMatcher.MatchCode> actual =
284 new ArrayList<ScanQueryMatcher.MatchCode>(kvs.length);
285 for (KeyValue kv : kvs) {
286 actual.add( qm.match(kv) );
287 }
288
289 assertEquals(expected.length, actual.size());
290 for (int i=0; i<expected.length; i++) {
291 if(PRINT){
292 System.out.println("expected "+expected[i]+
293 ", actual " +actual.get(i));
294 }
295 assertEquals(expected[i], actual.get(i));
296 }
297 }
298
299 public void testMatch_PartialRangeDropDeletes() throws Exception {
300
301 testDropDeletes(
302 row2, row3, new byte[][] { row1, row2, row2, row3 }, INCLUDE, SKIP, SKIP, INCLUDE);
303 testDropDeletes(row2, row3, new byte[][] { row1, row1, row2 }, INCLUDE, INCLUDE, SKIP);
304 testDropDeletes(row2, row3, new byte[][] { row2, row3, row3 }, SKIP, INCLUDE, INCLUDE);
305 testDropDeletes(row1, row3, new byte[][] { row1, row2, row3 }, SKIP, SKIP, INCLUDE);
306
307 testDropDeletes(HConstants.EMPTY_START_ROW, row3,
308 new byte[][] { row1, row2, row3 }, SKIP, SKIP, INCLUDE);
309 testDropDeletes(row2, HConstants.EMPTY_END_ROW,
310 new byte[][] { row1, row2, row3 }, INCLUDE, SKIP, SKIP);
311 testDropDeletes(HConstants.EMPTY_START_ROW, HConstants.EMPTY_END_ROW,
312 new byte[][] { row1, row2, row3, row3 }, SKIP, SKIP, SKIP, SKIP);
313
314
315 testDropDeletes(row2, row3, new byte[][] { row1, row1, row3 }, INCLUDE, INCLUDE, INCLUDE);
316 testDropDeletes(row2, row3, new byte[][] { row3, row3 }, INCLUDE, INCLUDE);
317 testDropDeletes(row2, row3, new byte[][] { row1, row1 }, INCLUDE, INCLUDE);
318 }
319
320 private void testDropDeletes(
321 byte[] from, byte[] to, byte[][] rows, MatchCode... expected) throws IOException {
322 long now = EnvironmentEdgeManager.currentTime();
323
324 ScanInfo scanInfo = new ScanInfo(fam2, 0, 1, ttl, KeepDeletedCells.FALSE, -1L, rowComparator);
325 NavigableSet<byte[]> cols = get.getFamilyMap().get(fam2);
326
327 ScanQueryMatcher qm = new ScanQueryMatcher(scan, scanInfo, cols, Long.MAX_VALUE,
328 HConstants.OLDEST_TIMESTAMP, HConstants.OLDEST_TIMESTAMP, now, from, to, null);
329 List<ScanQueryMatcher.MatchCode> actual =
330 new ArrayList<ScanQueryMatcher.MatchCode>(rows.length);
331 byte[] prevRow = null;
332 for (byte[] row : rows) {
333 if (prevRow == null || !Bytes.equals(prevRow, row)) {
334 qm.setRow(row, 0, (short)row.length);
335 prevRow = row;
336 }
337 actual.add(qm.match(new KeyValue(row, fam2, null, now, Type.Delete)));
338 }
339
340 assertEquals(expected.length, actual.size());
341 for (int i = 0; i < expected.length; i++) {
342 if (PRINT) System.out.println("expected " + expected[i] + ", actual " + actual.get(i));
343 assertEquals(expected[i], actual.get(i));
344 }
345 }
346 }
347