001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client;
019
020import static org.apache.hadoop.hbase.HBaseTestingUtil.countRows;
021import static org.junit.Assert.assertArrayEquals;
022import static org.junit.Assert.assertEquals;
023import static org.junit.Assert.assertNull;
024import static org.junit.Assert.assertSame;
025import static org.junit.Assert.assertTrue;
026import static org.junit.Assert.fail;
027
028import java.io.IOException;
029import java.util.ArrayList;
030import java.util.Arrays;
031import java.util.Collection;
032import java.util.Collections;
033import java.util.HashMap;
034import java.util.List;
035import java.util.Map;
036import org.apache.hadoop.conf.Configuration;
037import org.apache.hadoop.hbase.Cell;
038import org.apache.hadoop.hbase.CellUtil;
039import org.apache.hadoop.hbase.CompareOperator;
040import org.apache.hadoop.hbase.HBaseClassTestRule;
041import org.apache.hadoop.hbase.HBaseTestingUtil;
042import org.apache.hadoop.hbase.HConstants;
043import org.apache.hadoop.hbase.HRegionLocation;
044import org.apache.hadoop.hbase.KeepDeletedCells;
045import org.apache.hadoop.hbase.PrivateCellUtil;
046import org.apache.hadoop.hbase.TableName;
047import org.apache.hadoop.hbase.TableNameTestRule;
048import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint;
049import org.apache.hadoop.hbase.filter.Filter;
050import org.apache.hadoop.hbase.filter.KeyOnlyFilter;
051import org.apache.hadoop.hbase.filter.LongComparator;
052import org.apache.hadoop.hbase.filter.QualifierFilter;
053import org.apache.hadoop.hbase.filter.RegexStringComparator;
054import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
055import org.apache.hadoop.hbase.testclassification.ClientTests;
056import org.apache.hadoop.hbase.testclassification.LargeTests;
057import org.apache.hadoop.hbase.util.Bytes;
058import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
059import org.junit.AfterClass;
060import org.junit.ClassRule;
061import org.junit.Rule;
062import org.junit.Test;
063import org.junit.experimental.categories.Category;
064import org.junit.runner.RunWith;
065import org.junit.runners.Parameterized;
066import org.slf4j.Logger;
067import org.slf4j.LoggerFactory;
068
069/**
070 * Run tests that use the HBase clients; {@link Table}.
071 * Sets up the HBase mini cluster once at start and runs through all client tests.
072 * Each creates a table named for the method and does its stuff against that.
073 *
074 * Parameterized to run with different registry implementations.
075 *
076 * This class was split in three because it got too big when parameterized. Other classes
077 * are below.
078 *
079 * @see TestFromClientSide4
080 * @see TestFromClientSide5
081 */
082// NOTE: Increment tests were moved to their own class, TestIncrementsFromClientSide.
083@Category({LargeTests.class, ClientTests.class})
084@SuppressWarnings ("deprecation")
085@RunWith(Parameterized.class)
086public class TestFromClientSide extends FromClientSideBase {
087  private static final Logger LOG = LoggerFactory.getLogger(TestFromClientSide.class);
088
089  @ClassRule
090  public static final HBaseClassTestRule CLASS_RULE =
091    HBaseClassTestRule.forClass(TestFromClientSide.class);
092  @Rule
093  public TableNameTestRule name = new TableNameTestRule();
094
095  // To keep the child classes happy.
096  TestFromClientSide() {
097  }
098
099  public TestFromClientSide(Class registry, int numHedgedReqs) throws Exception {
100    initialize(registry, numHedgedReqs, MultiRowMutationEndpoint.class);
101  }
102
103  @Parameterized.Parameters public static Collection parameters() {
104    return Arrays.asList(new Object[][] { { MasterRegistry.class, 1 }, { MasterRegistry.class, 2 },
105      { ZKConnectionRegistry.class, 1 } });
106  }
107
108  @AfterClass public static void tearDownAfterClass() throws Exception {
109    afterClass();
110  }
111
112  /**
113   * Test append result when there are duplicate rpc request.
114   */
115  @Test
116  public void testDuplicateAppend() throws Exception {
117    TableDescriptorBuilder builder = TEST_UTIL
118      .createModifyableTableDescriptor(name.getTableName(),
119        ColumnFamilyDescriptorBuilder.DEFAULT_MIN_VERSIONS, 3, HConstants.FOREVER,
120        ColumnFamilyDescriptorBuilder.DEFAULT_KEEP_DELETED);
121    Map<String, String> kvs = new HashMap<>();
122    kvs.put(SleepAtFirstRpcCall.SLEEP_TIME_CONF_KEY, "2000");
123    builder.setCoprocessor(CoprocessorDescriptorBuilder
124      .newBuilder(SleepAtFirstRpcCall.class.getName())
125      .setPriority(1)
126      .setProperties(kvs)
127      .build());
128    TEST_UTIL.createTable(builder.build(), new byte[][] { ROW }).close();
129
130    Configuration c = new Configuration(TEST_UTIL.getConfiguration());
131    c.setInt(HConstants.HBASE_CLIENT_PAUSE, 50);
132    // Client will retry because rpc timeout is small than the sleep time of first rpc call
133    c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500);
134
135    try (Connection connection = ConnectionFactory.createConnection(c);
136      Table table = connection.getTableBuilder(name.getTableName(), null).
137        setOperationTimeout(3 * 1000).build()) {
138      Append append = new Append(ROW);
139      append.addColumn(HBaseTestingUtil.fam1, QUALIFIER, VALUE);
140      Result result = table.append(append);
141
142      // Verify expected result
143      Cell[] cells = result.rawCells();
144      assertEquals(1, cells.length);
145      assertKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, VALUE);
146
147      // Verify expected result again
148      Result readResult = table.get(new Get(ROW));
149      cells = readResult.rawCells();
150      assertEquals(1, cells.length);
151      assertKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, VALUE);
152    }
153  }
154
155  /**
156   * Test batch append result when there are duplicate rpc request.
157   */
158  @Test
159  public void testDuplicateBatchAppend() throws Exception {
160    TableDescriptorBuilder builder = TEST_UTIL
161      .createModifyableTableDescriptor(name.getTableName(),
162        ColumnFamilyDescriptorBuilder.DEFAULT_MIN_VERSIONS, 3, HConstants.FOREVER,
163        ColumnFamilyDescriptorBuilder.DEFAULT_KEEP_DELETED);
164    Map<String, String> kvs = new HashMap<>();
165    kvs.put(SleepAtFirstRpcCall.SLEEP_TIME_CONF_KEY, "2000");
166    builder.setCoprocessor(CoprocessorDescriptorBuilder
167      .newBuilder(SleepAtFirstRpcCall.class.getName())
168      .setPriority(1)
169      .setProperties(kvs)
170      .build());
171    TEST_UTIL.createTable(builder.build(), new byte[][] { ROW }).close();
172
173    Configuration c = new Configuration(TEST_UTIL.getConfiguration());
174    c.setInt(HConstants.HBASE_CLIENT_PAUSE, 50);
175    // Client will retry because rpc timeout is small than the sleep time of first rpc call
176    c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500);
177
178    try (Connection connection = ConnectionFactory.createConnection(c);
179      Table table = connection.getTableBuilder(name.getTableName(), null).
180        setOperationTimeout(3 * 1000).build()) {
181      Append append = new Append(ROW);
182      append.addColumn(HBaseTestingUtil.fam1, QUALIFIER, VALUE);
183
184      // Batch append
185      Object[] results = new Object[1];
186      table.batch(Collections.singletonList(append), results);
187
188      // Verify expected result
189      Cell[] cells = ((Result) results[0]).rawCells();
190      assertEquals(1, cells.length);
191      assertKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, VALUE);
192
193      // Verify expected result again
194      Result readResult = table.get(new Get(ROW));
195      cells = readResult.rawCells();
196      assertEquals(1, cells.length);
197      assertKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, VALUE);
198    }
199  }
200
201  /**
202   * Basic client side validation of HBASE-4536
203   */
204  @Test
205  public void testKeepDeletedCells() throws Exception {
206    final TableName tableName = name.getTableName();
207    final byte[] FAMILY = Bytes.toBytes("family");
208    final byte[] C0 = Bytes.toBytes("c0");
209
210    final byte[] T1 = Bytes.toBytes("T1");
211    final byte[] T2 = Bytes.toBytes("T2");
212    final byte[] T3 = Bytes.toBytes("T3");
213
214    TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(tableName)
215      .setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(FAMILY)
216        .setKeepDeletedCells(KeepDeletedCells.TRUE).setMaxVersions(3).build())
217      .build();
218    TEST_UTIL.getAdmin().createTable(tableDescriptor);
219    try (Table h = TEST_UTIL.getConnection().getTable(tableName)) {
220      long ts = EnvironmentEdgeManager.currentTime();
221      Put p = new Put(T1, ts);
222      p.addColumn(FAMILY, C0, T1);
223      h.put(p);
224      p = new Put(T1, ts + 2);
225      p.addColumn(FAMILY, C0, T2);
226      h.put(p);
227      p = new Put(T1, ts + 4);
228      p.addColumn(FAMILY, C0, T3);
229      h.put(p);
230
231      Delete d = new Delete(T1, ts + 3);
232      h.delete(d);
233
234      d = new Delete(T1, ts + 3);
235      d.addColumns(FAMILY, C0, ts + 3);
236      h.delete(d);
237
238      Get g = new Get(T1);
239      // does *not* include the delete
240      g.setTimeRange(0, ts + 3);
241      Result r = h.get(g);
242      assertArrayEquals(T2, r.getValue(FAMILY, C0));
243
244      Scan s = new Scan().withStartRow(T1);
245      s.setTimeRange(0, ts + 3);
246      s.readAllVersions();
247      ResultScanner scanner = h.getScanner(s);
248      Cell[] kvs = scanner.next().rawCells();
249      assertArrayEquals(T2, CellUtil.cloneValue(kvs[0]));
250      assertArrayEquals(T1, CellUtil.cloneValue(kvs[1]));
251      scanner.close();
252
253      s = new Scan().withStartRow(T1);
254      s.setRaw(true);
255      s.readAllVersions();
256      scanner = h.getScanner(s);
257      kvs = scanner.next().rawCells();
258      assertTrue(PrivateCellUtil.isDeleteFamily(kvs[0]));
259      assertArrayEquals(T3, CellUtil.cloneValue(kvs[1]));
260      assertTrue(CellUtil.isDelete(kvs[2]));
261      assertArrayEquals(T2, CellUtil.cloneValue(kvs[3]));
262      assertArrayEquals(T1, CellUtil.cloneValue(kvs[4]));
263      scanner.close();
264    }
265  }
266
267  /**
268   * Basic client side validation of HBASE-10118
269   */
270  @Test public void testPurgeFutureDeletes() throws Exception {
271    final TableName tableName = name.getTableName();
272    final byte[] ROW = Bytes.toBytes("row");
273    final byte[] FAMILY = Bytes.toBytes("family");
274    final byte[] COLUMN = Bytes.toBytes("column");
275    final byte[] VALUE = Bytes.toBytes("value");
276
277    try (Table table = TEST_UTIL.createTable(tableName, FAMILY)) {
278      // future timestamp
279      long ts = EnvironmentEdgeManager.currentTime() * 2;
280      Put put = new Put(ROW, ts);
281      put.addColumn(FAMILY, COLUMN, VALUE);
282      table.put(put);
283
284      Get get = new Get(ROW);
285      Result result = table.get(get);
286      assertArrayEquals(VALUE, result.getValue(FAMILY, COLUMN));
287
288      Delete del = new Delete(ROW);
289      del.addColumn(FAMILY, COLUMN, ts);
290      table.delete(del);
291
292      get = new Get(ROW);
293      result = table.get(get);
294      assertNull(result.getValue(FAMILY, COLUMN));
295
296      // major compaction, purged future deletes
297      TEST_UTIL.getAdmin().flush(tableName);
298      TEST_UTIL.getAdmin().majorCompact(tableName);
299
300      // waiting for the major compaction to complete
301      TEST_UTIL.waitFor(6000,
302        () -> TEST_UTIL.getAdmin().getCompactionState(tableName) == CompactionState.NONE);
303
304      put = new Put(ROW, ts);
305      put.addColumn(FAMILY, COLUMN, VALUE);
306      table.put(put);
307
308      get = new Get(ROW);
309      result = table.get(get);
310      assertArrayEquals(VALUE, result.getValue(FAMILY, COLUMN));
311    }
312  }
313
314  /**
315   * Verifies that getConfiguration returns the same Configuration object used
316   * to create the HTable instance.
317   */
318  @Test public void testGetConfiguration() throws Exception {
319    final TableName tableName = name.getTableName();
320    byte[][] FAMILIES = new byte[][] { Bytes.toBytes("foo") };
321    Configuration conf = TEST_UTIL.getConfiguration();
322    try (Table table = TEST_UTIL.createTable(tableName, FAMILIES)) {
323      assertSame(conf, table.getConfiguration());
324    }
325  }
326
327  /**
328   * Test from client side of an involved filter against a multi family that
329   * involves deletes.
330   */
331  @Test public void testWeirdCacheBehaviour() throws Exception {
332    final TableName tableName = name.getTableName();
333    byte[][] FAMILIES = new byte[][] {
334      Bytes.toBytes("trans-blob"),
335      Bytes.toBytes("trans-type"),
336      Bytes.toBytes("trans-date"),
337      Bytes.toBytes("trans-tags"),
338      Bytes.toBytes("trans-group")
339    };
340    try (Table ht = TEST_UTIL.createTable(tableName, FAMILIES)) {
341      String value = "this is the value";
342      String value2 = "this is some other value";
343      String keyPrefix1 = HBaseTestingUtil.getRandomUUID().toString();
344      String keyPrefix2 = HBaseTestingUtil.getRandomUUID().toString();
345      String keyPrefix3 = HBaseTestingUtil.getRandomUUID().toString();
346      putRows(ht, 3, value, keyPrefix1);
347      putRows(ht, 3, value, keyPrefix2);
348      putRows(ht, 3, value, keyPrefix3);
349      putRows(ht, 3, value2, keyPrefix1);
350      putRows(ht, 3, value2, keyPrefix2);
351      putRows(ht, 3, value2, keyPrefix3);
352      try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {
353        System.out.println("Checking values for key: " + keyPrefix1);
354        assertEquals("Got back incorrect number of rows from scan", 3,
355          getNumberOfRows(keyPrefix1, value2, table));
356        System.out.println("Checking values for key: " + keyPrefix2);
357        assertEquals("Got back incorrect number of rows from scan", 3,
358          getNumberOfRows(keyPrefix2, value2, table));
359        System.out.println("Checking values for key: " + keyPrefix3);
360        assertEquals("Got back incorrect number of rows from scan", 3,
361          getNumberOfRows(keyPrefix3, value2, table));
362        deleteColumns(ht, value2, keyPrefix1);
363        deleteColumns(ht, value2, keyPrefix2);
364        deleteColumns(ht, value2, keyPrefix3);
365        System.out.println("Starting important checks.....");
366        assertEquals("Got back incorrect number of rows from scan: " + keyPrefix1, 0,
367          getNumberOfRows(keyPrefix1, value2, table));
368        assertEquals("Got back incorrect number of rows from scan: " + keyPrefix2, 0,
369          getNumberOfRows(keyPrefix2, value2, table));
370        assertEquals("Got back incorrect number of rows from scan: " + keyPrefix3, 0,
371          getNumberOfRows(keyPrefix3, value2, table));
372      }
373    }
374  }
375
376  /**
377   * Test filters when multiple regions.  It does counts.  Needs eye-balling of
378   * logs to ensure that we're not scanning more regions that we're supposed to.
379   * Related to the TestFilterAcrossRegions over in the o.a.h.h.filter package.
380   */
381  @Test public void testFilterAcrossMultipleRegions() throws IOException {
382    final TableName tableName = name.getTableName();
383    try (Table t = TEST_UTIL.createTable(tableName, FAMILY)) {
384      int rowCount = TEST_UTIL.loadTable(t, FAMILY, false);
385      assertRowCount(t, rowCount);
386      // Split the table.  Should split on a reasonable key; 'lqj'
387      List<HRegionLocation> regions = splitTable(t);
388      assertRowCount(t, rowCount);
389      // Get end key of first region.
390      byte[] endKey = regions.get(0).getRegion().getEndKey();
391      // Count rows with a filter that stops us before passed 'endKey'.
392      // Should be count of rows in first region.
393      int endKeyCount = countRows(t, createScanWithRowFilter(endKey));
394      assertTrue(endKeyCount < rowCount);
395
396      // How do I know I did not got to second region?  Thats tough.  Can't really
397      // do that in client-side region test.  I verified by tracing in debugger.
398      // I changed the messages that come out when set to DEBUG so should see
399      // when scanner is done. Says "Finished with scanning..." with region name.
400      // Check that its finished in right region.
401
402      // New test.  Make it so scan goes into next region by one and then two.
403      // Make sure count comes out right.
404      byte[] key = new byte[] { endKey[0], endKey[1], (byte) (endKey[2] + 1) };
405      int plusOneCount = countRows(t, createScanWithRowFilter(key));
406      assertEquals(endKeyCount + 1, plusOneCount);
407      key = new byte[] { endKey[0], endKey[1], (byte) (endKey[2] + 2) };
408      int plusTwoCount = countRows(t, createScanWithRowFilter(key));
409      assertEquals(endKeyCount + 2, plusTwoCount);
410
411      // New test.  Make it so I scan one less than endkey.
412      key = new byte[] { endKey[0], endKey[1], (byte) (endKey[2] - 1) };
413      int minusOneCount = countRows(t, createScanWithRowFilter(key));
414      assertEquals(endKeyCount - 1, minusOneCount);
415      // For above test... study logs.  Make sure we do "Finished with scanning.."
416      // in first region and that we do not fall into the next region.
417
418      key = new byte[] { 'a', 'a', 'a' };
419      int countBBB = countRows(t, createScanWithRowFilter(key, null, CompareOperator.EQUAL));
420      assertEquals(1, countBBB);
421
422      int countGreater =
423        countRows(t, createScanWithRowFilter(endKey, null, CompareOperator.GREATER_OR_EQUAL));
424      // Because started at start of table.
425      assertEquals(0, countGreater);
426      countGreater =
427        countRows(t, createScanWithRowFilter(endKey, endKey, CompareOperator.GREATER_OR_EQUAL));
428      assertEquals(rowCount - endKeyCount, countGreater);
429    }
430  }
431
432  @Test public void testSuperSimple() throws Exception {
433    final TableName tableName = name.getTableName();
434    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
435      Put put = new Put(ROW);
436      put.addColumn(FAMILY, QUALIFIER, VALUE);
437      ht.put(put);
438      Scan scan = new Scan();
439      scan.addColumn(FAMILY, tableName.toBytes());
440      ResultScanner scanner = ht.getScanner(scan);
441      Result result = scanner.next();
442      assertNull("Expected null result", result);
443      scanner.close();
444    }
445  }
446
447  @Test public void testMaxKeyValueSize() throws Exception {
448    final TableName tableName = name.getTableName();
449    Configuration conf = TEST_UTIL.getConfiguration();
450    String oldMaxSize = conf.get(ConnectionConfiguration.MAX_KEYVALUE_SIZE_KEY);
451    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
452      byte[] value = new byte[4 * 1024 * 1024];
453      Put put = new Put(ROW);
454      put.addColumn(FAMILY, QUALIFIER, value);
455      ht.put(put);
456
457      try {
458        TEST_UTIL.getConfiguration().setInt(ConnectionConfiguration.MAX_KEYVALUE_SIZE_KEY,
459          2 * 1024 * 1024);
460        // Create new table so we pick up the change in Configuration.
461        try (Connection connection =
462            ConnectionFactory.createConnection(TEST_UTIL.getConfiguration())) {
463          try (Table t = connection.getTable(TableName.valueOf(FAMILY))) {
464            put = new Put(ROW);
465            put.addColumn(FAMILY, QUALIFIER, value);
466            t.put(put);
467          }
468        }
469        fail("Inserting a too large KeyValue worked, should throw exception");
470      } catch (Exception ignored) {
471      }
472    }
473    conf.set(ConnectionConfiguration.MAX_KEYVALUE_SIZE_KEY, oldMaxSize);
474  }
475
476  @Test public void testFilters() throws Exception {
477    final TableName tableName = name.getTableName();
478    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
479      byte[][] ROWS = makeN(ROW, 10);
480      byte[][] QUALIFIERS =
481        { Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
482          Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
483          Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
484          Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
485          Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>") };
486      for (int i = 0; i < 10; i++) {
487        Put put = new Put(ROWS[i]);
488        put.setDurability(Durability.SKIP_WAL);
489        put.addColumn(FAMILY, QUALIFIERS[i], VALUE);
490        ht.put(put);
491      }
492      Scan scan = new Scan();
493      scan.addFamily(FAMILY);
494      Filter filter = new QualifierFilter(CompareOperator.EQUAL,
495        new RegexStringComparator("col[1-5]"));
496      scan.setFilter(filter);
497      try (ResultScanner scanner = ht.getScanner(scan)) {
498        int expectedIndex = 1;
499        for (Result result : scanner) {
500          assertEquals(1, result.size());
501          assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[expectedIndex]));
502          assertTrue(Bytes.equals(CellUtil.cloneQualifier(result.rawCells()[0]),
503            QUALIFIERS[expectedIndex]));
504          expectedIndex++;
505        }
506        assertEquals(6, expectedIndex);
507      }
508    }
509  }
510
511  @Test public void testFilterWithLongCompartor() throws Exception {
512    final TableName tableName = name.getTableName();
513    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
514      byte[][] ROWS = makeN(ROW, 10);
515      byte[][] values = new byte[10][];
516      for (int i = 0; i < 10; i++) {
517        values[i] = Bytes.toBytes(100L * i);
518      }
519      for (int i = 0; i < 10; i++) {
520        Put put = new Put(ROWS[i]);
521        put.setDurability(Durability.SKIP_WAL);
522        put.addColumn(FAMILY, QUALIFIER, values[i]);
523        ht.put(put);
524      }
525      Scan scan = new Scan();
526      scan.addFamily(FAMILY);
527      Filter filter = new SingleColumnValueFilter(FAMILY, QUALIFIER, CompareOperator.GREATER,
528        new LongComparator(500));
529      scan.setFilter(filter);
530      try (ResultScanner scanner = ht.getScanner(scan)) {
531        int expectedIndex = 0;
532        for (Result result : scanner) {
533          assertEquals(1, result.size());
534          assertTrue(Bytes.toLong(result.getValue(FAMILY, QUALIFIER)) > 500);
535          expectedIndex++;
536        }
537        assertEquals(4, expectedIndex);
538      }
539    }
540  }
541
542  @Test public void testKeyOnlyFilter() throws Exception {
543    final TableName tableName = name.getTableName();
544    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
545      byte[][] ROWS = makeN(ROW, 10);
546      byte[][] QUALIFIERS =
547        { Bytes.toBytes("col0-<d2v1>-<d3v2>"), Bytes.toBytes("col1-<d2v1>-<d3v2>"),
548          Bytes.toBytes("col2-<d2v1>-<d3v2>"), Bytes.toBytes("col3-<d2v1>-<d3v2>"),
549          Bytes.toBytes("col4-<d2v1>-<d3v2>"), Bytes.toBytes("col5-<d2v1>-<d3v2>"),
550          Bytes.toBytes("col6-<d2v1>-<d3v2>"), Bytes.toBytes("col7-<d2v1>-<d3v2>"),
551          Bytes.toBytes("col8-<d2v1>-<d3v2>"), Bytes.toBytes("col9-<d2v1>-<d3v2>") };
552      for (int i = 0; i < 10; i++) {
553        Put put = new Put(ROWS[i]);
554        put.setDurability(Durability.SKIP_WAL);
555        put.addColumn(FAMILY, QUALIFIERS[i], VALUE);
556        ht.put(put);
557      }
558      Scan scan = new Scan();
559      scan.addFamily(FAMILY);
560      Filter filter = new KeyOnlyFilter(true);
561      scan.setFilter(filter);
562      try (ResultScanner scanner = ht.getScanner(scan)) {
563        int count = 0;
564        for (Result result : scanner) {
565          assertEquals(1, result.size());
566          assertEquals(Bytes.SIZEOF_INT, result.rawCells()[0].getValueLength());
567          assertEquals(VALUE.length, Bytes.toInt(CellUtil.cloneValue(result.rawCells()[0])));
568          count++;
569        }
570        assertEquals(10, count);
571      }
572    }
573  }
574
575  /**
576   * Test simple table and non-existent row cases.
577   */
578  @Test public void testSimpleMissing() throws Exception {
579    final TableName tableName = name.getTableName();
580    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
581      byte[][] ROWS = makeN(ROW, 4);
582
583      // Try to get a row on an empty table
584      Get get = new Get(ROWS[0]);
585      Result result = ht.get(get);
586      assertEmptyResult(result);
587
588      get = new Get(ROWS[0]);
589      get.addFamily(FAMILY);
590      result = ht.get(get);
591      assertEmptyResult(result);
592
593      get = new Get(ROWS[0]);
594      get.addColumn(FAMILY, QUALIFIER);
595      result = ht.get(get);
596      assertEmptyResult(result);
597
598      Scan scan = new Scan();
599      result = getSingleScanResult(ht, scan);
600      assertNullResult(result);
601
602      scan = new Scan().withStartRow(ROWS[0]);
603      result = getSingleScanResult(ht, scan);
604      assertNullResult(result);
605
606      scan = new Scan().withStartRow(ROWS[0]).withStopRow(ROWS[1]);
607      result = getSingleScanResult(ht, scan);
608      assertNullResult(result);
609
610      scan = new Scan();
611      scan.addFamily(FAMILY);
612      result = getSingleScanResult(ht, scan);
613      assertNullResult(result);
614
615      scan = new Scan();
616      scan.addColumn(FAMILY, QUALIFIER);
617      result = getSingleScanResult(ht, scan);
618      assertNullResult(result);
619
620      // Insert a row
621
622      Put put = new Put(ROWS[2]);
623      put.addColumn(FAMILY, QUALIFIER, VALUE);
624      ht.put(put);
625
626      // Try to get empty rows around it
627
628      get = new Get(ROWS[1]);
629      result = ht.get(get);
630      assertEmptyResult(result);
631
632      get = new Get(ROWS[0]);
633      get.addFamily(FAMILY);
634      result = ht.get(get);
635      assertEmptyResult(result);
636
637      get = new Get(ROWS[3]);
638      get.addColumn(FAMILY, QUALIFIER);
639      result = ht.get(get);
640      assertEmptyResult(result);
641
642      // Try to scan empty rows around it
643
644      scan = new Scan().withStartRow(ROWS[3]);
645      result = getSingleScanResult(ht, scan);
646      assertNullResult(result);
647
648      scan = new Scan().withStartRow(ROWS[0]).withStopRow(ROWS[2]);
649      result = getSingleScanResult(ht, scan);
650      assertNullResult(result);
651
652      // Make sure we can actually get the row
653
654      get = new Get(ROWS[2]);
655      result = ht.get(get);
656      assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
657
658      get = new Get(ROWS[2]);
659      get.addFamily(FAMILY);
660      result = ht.get(get);
661      assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
662
663      get = new Get(ROWS[2]);
664      get.addColumn(FAMILY, QUALIFIER);
665      result = ht.get(get);
666      assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
667
668      // Make sure we can scan the row
669
670      scan = new Scan();
671      result = getSingleScanResult(ht, scan);
672      assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
673
674      scan = new Scan().withStartRow(ROWS[0]).withStopRow(ROWS[3]);
675      result = getSingleScanResult(ht, scan);
676      assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
677
678      scan = new Scan().withStartRow(ROWS[2]).withStopRow(ROWS[3]);
679      result = getSingleScanResult(ht, scan);
680      assertSingleResult(result, ROWS[2], FAMILY, QUALIFIER, VALUE);
681    }
682  }
683
684  /**
685   * Test basic puts, gets, scans, and deletes for a single row
686   * in a multiple family table.
687   */
688  @SuppressWarnings("checkstyle:MethodLength")
689  @Test
690  public void testSingleRowMultipleFamily() throws Exception {
691    final TableName tableName = name.getTableName();
692    byte[][] ROWS = makeN(ROW, 3);
693    byte[][] FAMILIES = makeNAscii(FAMILY, 10);
694    byte[][] QUALIFIERS = makeN(QUALIFIER, 10);
695    byte[][] VALUES = makeN(VALUE, 10);
696
697    try (Table ht = TEST_UTIL.createTable(tableName, FAMILIES)) {
698      ////////////////////////////////////////////////////////////////////////////
699      // Insert one column to one family
700      ////////////////////////////////////////////////////////////////////////////
701
702      Put put = new Put(ROWS[0]);
703      put.addColumn(FAMILIES[4], QUALIFIERS[0], VALUES[0]);
704      ht.put(put);
705
706      // Get the single column
707      getVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
708
709      // Scan the single column
710      scanVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
711
712      // Get empty results around inserted column
713      getVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
714
715      // Scan empty results around inserted column
716      scanVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
717
718      ////////////////////////////////////////////////////////////////////////////
719      // Flush memstore and run same tests from storefiles
720      ////////////////////////////////////////////////////////////////////////////
721
722      TEST_UTIL.flush();
723
724      // Redo get and scan tests from storefile
725      getVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
726      scanVerifySingleColumn(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0, VALUES, 0);
727      getVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
728      scanVerifySingleEmpty(ht, ROWS, 0, FAMILIES, 4, QUALIFIERS, 0);
729
730      ////////////////////////////////////////////////////////////////////////////
731      // Now, Test reading from memstore and storefiles at once
732      ////////////////////////////////////////////////////////////////////////////
733
734      // Insert multiple columns to two other families
735      put = new Put(ROWS[0]);
736      put.addColumn(FAMILIES[2], QUALIFIERS[2], VALUES[2]);
737      put.addColumn(FAMILIES[2], QUALIFIERS[4], VALUES[4]);
738      put.addColumn(FAMILIES[4], QUALIFIERS[4], VALUES[4]);
739      put.addColumn(FAMILIES[6], QUALIFIERS[6], VALUES[6]);
740      put.addColumn(FAMILIES[6], QUALIFIERS[7], VALUES[7]);
741      put.addColumn(FAMILIES[7], QUALIFIERS[7], VALUES[7]);
742      put.addColumn(FAMILIES[9], QUALIFIERS[0], VALUES[0]);
743      ht.put(put);
744
745      // Get multiple columns across multiple families and get empties around it
746      singleRowGetTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
747
748      // Scan multiple columns across multiple families and scan empties around it
749      singleRowScanTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
750
751      ////////////////////////////////////////////////////////////////////////////
752      // Flush the table again
753      ////////////////////////////////////////////////////////////////////////////
754
755      TEST_UTIL.flush();
756
757      // Redo tests again
758      singleRowGetTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
759      singleRowScanTest(ht, ROWS, FAMILIES, QUALIFIERS, VALUES);
760
761      // Insert more data to memstore
762      put = new Put(ROWS[0]);
763      put.addColumn(FAMILIES[6], QUALIFIERS[5], VALUES[5]);
764      put.addColumn(FAMILIES[6], QUALIFIERS[8], VALUES[8]);
765      put.addColumn(FAMILIES[6], QUALIFIERS[9], VALUES[9]);
766      put.addColumn(FAMILIES[4], QUALIFIERS[3], VALUES[3]);
767      ht.put(put);
768
769      ////////////////////////////////////////////////////////////////////////////
770      // Delete a storefile column
771      ////////////////////////////////////////////////////////////////////////////
772      Delete delete = new Delete(ROWS[0]);
773      delete.addColumns(FAMILIES[6], QUALIFIERS[7]);
774      ht.delete(delete);
775
776      // Try to get deleted column
777      Get get = new Get(ROWS[0]);
778      get.addColumn(FAMILIES[6], QUALIFIERS[7]);
779      Result result = ht.get(get);
780      assertEmptyResult(result);
781
782      // Try to scan deleted column
783      Scan scan = new Scan();
784      scan.addColumn(FAMILIES[6], QUALIFIERS[7]);
785      result = getSingleScanResult(ht, scan);
786      assertNullResult(result);
787
788      // Make sure we can still get a column before it and after it
789      get = new Get(ROWS[0]);
790      get.addColumn(FAMILIES[6], QUALIFIERS[6]);
791      result = ht.get(get);
792      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
793
794      get = new Get(ROWS[0]);
795      get.addColumn(FAMILIES[6], QUALIFIERS[8]);
796      result = ht.get(get);
797      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[8], VALUES[8]);
798
799      // Make sure we can still scan a column before it and after it
800      scan = new Scan();
801      scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
802      result = getSingleScanResult(ht, scan);
803      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
804
805      scan = new Scan();
806      scan.addColumn(FAMILIES[6], QUALIFIERS[8]);
807      result = getSingleScanResult(ht, scan);
808      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[8], VALUES[8]);
809
810      ////////////////////////////////////////////////////////////////////////////
811      // Delete a memstore column
812      ////////////////////////////////////////////////////////////////////////////
813      delete = new Delete(ROWS[0]);
814      delete.addColumns(FAMILIES[6], QUALIFIERS[8]);
815      ht.delete(delete);
816
817      // Try to get deleted column
818      get = new Get(ROWS[0]);
819      get.addColumn(FAMILIES[6], QUALIFIERS[8]);
820      result = ht.get(get);
821      assertEmptyResult(result);
822
823      // Try to scan deleted column
824      scan = new Scan();
825      scan.addColumn(FAMILIES[6], QUALIFIERS[8]);
826      result = getSingleScanResult(ht, scan);
827      assertNullResult(result);
828
829      // Make sure we can still get a column before it and after it
830      get = new Get(ROWS[0]);
831      get.addColumn(FAMILIES[6], QUALIFIERS[6]);
832      result = ht.get(get);
833      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
834
835      get = new Get(ROWS[0]);
836      get.addColumn(FAMILIES[6], QUALIFIERS[9]);
837      result = ht.get(get);
838      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
839
840      // Make sure we can still scan a column before it and after it
841      scan = new Scan();
842      scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
843      result = getSingleScanResult(ht, scan);
844      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
845
846      scan = new Scan();
847      scan.addColumn(FAMILIES[6], QUALIFIERS[9]);
848      result = getSingleScanResult(ht, scan);
849      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
850
851      ////////////////////////////////////////////////////////////////////////////
852      // Delete joint storefile/memstore family
853      ////////////////////////////////////////////////////////////////////////////
854
855      delete = new Delete(ROWS[0]);
856      delete.addFamily(FAMILIES[4]);
857      ht.delete(delete);
858
859      // Try to get storefile column in deleted family
860      get = new Get(ROWS[0]);
861      get.addColumn(FAMILIES[4], QUALIFIERS[4]);
862      result = ht.get(get);
863      assertEmptyResult(result);
864
865      // Try to get memstore column in deleted family
866      get = new Get(ROWS[0]);
867      get.addColumn(FAMILIES[4], QUALIFIERS[3]);
868      result = ht.get(get);
869      assertEmptyResult(result);
870
871      // Try to get deleted family
872      get = new Get(ROWS[0]);
873      get.addFamily(FAMILIES[4]);
874      result = ht.get(get);
875      assertEmptyResult(result);
876
877      // Try to scan storefile column in deleted family
878      scan = new Scan();
879      scan.addColumn(FAMILIES[4], QUALIFIERS[4]);
880      result = getSingleScanResult(ht, scan);
881      assertNullResult(result);
882
883      // Try to scan memstore column in deleted family
884      scan = new Scan();
885      scan.addColumn(FAMILIES[4], QUALIFIERS[3]);
886      result = getSingleScanResult(ht, scan);
887      assertNullResult(result);
888
889      // Try to scan deleted family
890      scan = new Scan();
891      scan.addFamily(FAMILIES[4]);
892      result = getSingleScanResult(ht, scan);
893      assertNullResult(result);
894
895      // Make sure we can still get another family
896      get = new Get(ROWS[0]);
897      get.addColumn(FAMILIES[2], QUALIFIERS[2]);
898      result = ht.get(get);
899      assertSingleResult(result, ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
900
901      get = new Get(ROWS[0]);
902      get.addColumn(FAMILIES[6], QUALIFIERS[9]);
903      result = ht.get(get);
904      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
905
906      // Make sure we can still scan another family
907      scan = new Scan();
908      scan.addColumn(FAMILIES[6], QUALIFIERS[6]);
909      result = getSingleScanResult(ht, scan);
910      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
911
912      scan = new Scan();
913      scan.addColumn(FAMILIES[6], QUALIFIERS[9]);
914      result = getSingleScanResult(ht, scan);
915      assertSingleResult(result, ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
916
917      ////////////////////////////////////////////////////////////////////////////
918      // Flush everything and rerun delete tests
919      ////////////////////////////////////////////////////////////////////////////
920
921      TEST_UTIL.flush();
922
923      // Try to get storefile column in deleted family
924      assertEmptyResult(ht.get(new Get(ROWS[0]).addColumn(FAMILIES[4], QUALIFIERS[4])));
925
926      // Try to get memstore column in deleted family
927      assertEmptyResult(ht.get(new Get(ROWS[0]).addColumn(FAMILIES[4], QUALIFIERS[3])));
928
929      // Try to get deleted family
930      assertEmptyResult(ht.get(new Get(ROWS[0]).addFamily(FAMILIES[4])));
931
932      // Try to scan storefile column in deleted family
933      assertNullResult(getSingleScanResult(ht, new Scan().addColumn(FAMILIES[4], QUALIFIERS[4])));
934
935      // Try to scan memstore column in deleted family
936      assertNullResult(getSingleScanResult(ht, new Scan().addColumn(FAMILIES[4], QUALIFIERS[3])));
937
938      // Try to scan deleted family
939      assertNullResult(getSingleScanResult(ht, new Scan().addFamily(FAMILIES[4])));
940
941      // Make sure we can still get another family
942      assertSingleResult(ht.get(new Get(ROWS[0]).addColumn(FAMILIES[2], QUALIFIERS[2])),
943        ROWS[0], FAMILIES[2], QUALIFIERS[2], VALUES[2]);
944
945      assertSingleResult(ht.get(new Get(ROWS[0]).addColumn(FAMILIES[6], QUALIFIERS[9])),
946        ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
947
948      // Make sure we can still scan another family
949      assertSingleResult(getSingleScanResult(ht, new Scan().addColumn(FAMILIES[6], QUALIFIERS[6])),
950        ROWS[0], FAMILIES[6], QUALIFIERS[6], VALUES[6]);
951
952      assertSingleResult(getSingleScanResult(ht, new Scan().addColumn(FAMILIES[6], QUALIFIERS[9])),
953        ROWS[0], FAMILIES[6], QUALIFIERS[9], VALUES[9]);
954    }
955  }
956
957  @Test(expected = NullPointerException.class) public void testNullTableName() throws IOException {
958    // Null table name (should NOT work)
959    TEST_UTIL.createTable(null, FAMILY);
960    fail("Creating a table with null name passed, should have failed");
961  }
962
963  @Test(expected = IllegalArgumentException.class) public void testNullFamilyName()
964    throws IOException {
965    final TableName tableName = name.getTableName();
966
967    // Null family (should NOT work)
968    TEST_UTIL.createTable(tableName, new byte[][] { null });
969    fail("Creating a table with a null family passed, should fail");
970  }
971
972  @Test public void testNullRowAndQualifier() throws Exception {
973    final TableName tableName = name.getTableName();
974
975    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
976
977      // Null row (should NOT work)
978      try {
979        Put put = new Put((byte[]) null);
980        put.addColumn(FAMILY, QUALIFIER, VALUE);
981        ht.put(put);
982        fail("Inserting a null row worked, should throw exception");
983      } catch (Exception ignored) {
984      }
985
986      // Null qualifier (should work)
987      {
988        Put put = new Put(ROW);
989        put.addColumn(FAMILY, null, VALUE);
990        ht.put(put);
991
992        getTestNull(ht, ROW, FAMILY, VALUE);
993
994        scanTestNull(ht, ROW, FAMILY, VALUE);
995
996        Delete delete = new Delete(ROW);
997        delete.addColumns(FAMILY, null);
998        ht.delete(delete);
999
1000        Get get = new Get(ROW);
1001        Result result = ht.get(get);
1002        assertEmptyResult(result);
1003      }
1004    }
1005  }
1006
1007  @Test public void testNullEmptyQualifier() throws Exception {
1008    final TableName tableName = name.getTableName();
1009
1010    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
1011
1012      // Empty qualifier, byte[0] instead of null (should work)
1013      try {
1014        Put put = new Put(ROW);
1015        put.addColumn(FAMILY, HConstants.EMPTY_BYTE_ARRAY, VALUE);
1016        ht.put(put);
1017
1018        getTestNull(ht, ROW, FAMILY, VALUE);
1019
1020        scanTestNull(ht, ROW, FAMILY, VALUE);
1021
1022        // Flush and try again
1023
1024        TEST_UTIL.flush();
1025
1026        getTestNull(ht, ROW, FAMILY, VALUE);
1027
1028        scanTestNull(ht, ROW, FAMILY, VALUE);
1029
1030        Delete delete = new Delete(ROW);
1031        delete.addColumns(FAMILY, HConstants.EMPTY_BYTE_ARRAY);
1032        ht.delete(delete);
1033
1034        Get get = new Get(ROW);
1035        Result result = ht.get(get);
1036        assertEmptyResult(result);
1037
1038      } catch (Exception e) {
1039        throw new IOException("Using a row with null qualifier should not throw exception");
1040      }
1041    }
1042  }
1043
1044  @Test public void testNullValue() throws IOException {
1045    final TableName tableName = name.getTableName();
1046
1047    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY)) {
1048      // Null value
1049      try {
1050        Put put = new Put(ROW);
1051        put.addColumn(FAMILY, QUALIFIER, null);
1052        ht.put(put);
1053
1054        Get get = new Get(ROW);
1055        get.addColumn(FAMILY, QUALIFIER);
1056        Result result = ht.get(get);
1057        assertSingleResult(result, ROW, FAMILY, QUALIFIER, null);
1058
1059        Scan scan = new Scan();
1060        scan.addColumn(FAMILY, QUALIFIER);
1061        result = getSingleScanResult(ht, scan);
1062        assertSingleResult(result, ROW, FAMILY, QUALIFIER, null);
1063
1064        Delete delete = new Delete(ROW);
1065        delete.addColumns(FAMILY, QUALIFIER);
1066        ht.delete(delete);
1067
1068        get = new Get(ROW);
1069        result = ht.get(get);
1070        assertEmptyResult(result);
1071
1072      } catch (Exception e) {
1073        throw new IOException("Null values should be allowed, but threw exception");
1074      }
1075    }
1076  }
1077
1078  @Test public void testNullQualifier() throws Exception {
1079    final TableName tableName = name.getTableName();
1080    try (Table table = TEST_UTIL.createTable(tableName, FAMILY)) {
1081
1082      // Work for Put
1083      Put put = new Put(ROW);
1084      put.addColumn(FAMILY, null, VALUE);
1085      table.put(put);
1086
1087      // Work for Get, Scan
1088      getTestNull(table, ROW, FAMILY, VALUE);
1089      scanTestNull(table, ROW, FAMILY, VALUE);
1090
1091      // Work for Delete
1092      Delete delete = new Delete(ROW);
1093      delete.addColumns(FAMILY, null);
1094      table.delete(delete);
1095
1096      Get get = new Get(ROW);
1097      Result result = table.get(get);
1098      assertEmptyResult(result);
1099
1100      // Work for Increment/Append
1101      Increment increment = new Increment(ROW);
1102      increment.addColumn(FAMILY, null, 1L);
1103      table.increment(increment);
1104      getTestNull(table, ROW, FAMILY, 1L);
1105
1106      table.incrementColumnValue(ROW, FAMILY, null, 1L);
1107      getTestNull(table, ROW, FAMILY, 2L);
1108
1109      delete = new Delete(ROW);
1110      delete.addColumns(FAMILY, null);
1111      table.delete(delete);
1112
1113      Append append = new Append(ROW);
1114      append.addColumn(FAMILY, null, VALUE);
1115      table.append(append);
1116      getTestNull(table, ROW, FAMILY, VALUE);
1117
1118      // Work for checkAndMutate using thenPut, thenMutate and thenDelete
1119      put = new Put(ROW);
1120      put.addColumn(FAMILY, null, Bytes.toBytes("checkAndPut"));
1121      table.put(put);
1122      table.checkAndMutate(ROW, FAMILY).ifEquals(VALUE).thenPut(put);
1123
1124      RowMutations mutate = new RowMutations(ROW);
1125      mutate.add(new Put(ROW).addColumn(FAMILY, null, Bytes.toBytes("checkAndMutate")));
1126      table.checkAndMutate(ROW, FAMILY).ifEquals(Bytes.toBytes("checkAndPut")).thenMutate(mutate);
1127
1128      delete = new Delete(ROW);
1129      delete.addColumns(FAMILY, null);
1130      table.checkAndMutate(ROW, FAMILY).
1131        ifEquals(Bytes.toBytes("checkAndMutate")).thenDelete(delete);
1132    }
1133  }
1134
1135  @Test
1136  @SuppressWarnings("checkstyle:MethodLength")
1137  public void testVersions() throws Exception {
1138    final TableName tableName = name.getTableName();
1139
1140    long[] STAMPS = makeStamps(20);
1141    byte[][] VALUES = makeNAscii(VALUE, 20);
1142
1143    try (Table ht = TEST_UTIL.createTable(tableName, FAMILY, 10)) {
1144
1145      // Insert 4 versions of same column
1146      Put put = new Put(ROW);
1147      put.addColumn(FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1148      put.addColumn(FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1149      put.addColumn(FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1150      put.addColumn(FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1151      ht.put(put);
1152
1153      // Verify we can get each one properly
1154      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1155      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1156      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1157      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1158      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1159      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1160      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1161      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1162
1163      // Verify we don't accidentally get others
1164      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1165      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1166      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1167      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1168      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1169      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1170
1171      // Ensure maxVersions in query is respected
1172      Get get = new Get(ROW);
1173      get.addColumn(FAMILY, QUALIFIER);
1174      get.readVersions(2);
1175      Result result = ht.get(get);
1176      assertNResult(result, ROW, FAMILY, QUALIFIER, new long[] { STAMPS[4], STAMPS[5] },
1177        new byte[][] { VALUES[4], VALUES[5] }, 0, 1);
1178
1179      Scan scan = new Scan().withStartRow(ROW);
1180      scan.addColumn(FAMILY, QUALIFIER);
1181      scan.readVersions(2);
1182      result = getSingleScanResult(ht, scan);
1183      assertNResult(result, ROW, FAMILY, QUALIFIER, new long[] { STAMPS[4], STAMPS[5] },
1184        new byte[][] { VALUES[4], VALUES[5] }, 0, 1);
1185
1186      // Flush and redo
1187
1188      TEST_UTIL.flush();
1189
1190      // Verify we can get each one properly
1191      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1192      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1193      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1194      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1195      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1196      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1197      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1198      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[5], VALUES[5]);
1199
1200      // Verify we don't accidentally get others
1201      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1202      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1203      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1204      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1205      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[3]);
1206      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[6]);
1207
1208      // Ensure maxVersions in query is respected
1209      get = new Get(ROW);
1210      get.addColumn(FAMILY, QUALIFIER);
1211      get.readVersions(2);
1212      result = ht.get(get);
1213      assertNResult(result, ROW, FAMILY, QUALIFIER, new long[] { STAMPS[4], STAMPS[5] },
1214        new byte[][] { VALUES[4], VALUES[5] }, 0, 1);
1215
1216      scan = new Scan().withStartRow(ROW);
1217      scan.addColumn(FAMILY, QUALIFIER);
1218      scan.readVersions(2);
1219      result = getSingleScanResult(ht, scan);
1220      assertNResult(result, ROW, FAMILY, QUALIFIER, new long[] { STAMPS[4], STAMPS[5] },
1221        new byte[][] { VALUES[4], VALUES[5] }, 0, 1);
1222
1223      // Add some memstore and retest
1224
1225      // Insert 4 more versions of same column and a dupe
1226      put = new Put(ROW);
1227      put.addColumn(FAMILY, QUALIFIER, STAMPS[3], VALUES[3]);
1228      put.addColumn(FAMILY, QUALIFIER, STAMPS[6], VALUES[6]);
1229      put.addColumn(FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
1230      put.addColumn(FAMILY, QUALIFIER, STAMPS[8], VALUES[8]);
1231      ht.put(put);
1232
1233      // Ensure maxVersions in query is respected
1234      get = new Get(ROW);
1235      get.addColumn(FAMILY, QUALIFIER);
1236      get.readAllVersions();
1237      result = ht.get(get);
1238      assertNResult(result, ROW, FAMILY, QUALIFIER,
1239        new long[] { STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7],
1240          STAMPS[8] },
1241        new byte[][] { VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7],
1242          VALUES[8] }, 0, 7);
1243
1244      scan = new Scan().withStartRow(ROW);
1245      scan.addColumn(FAMILY, QUALIFIER);
1246      scan.readAllVersions();
1247      result = getSingleScanResult(ht, scan);
1248      assertNResult(result, ROW, FAMILY, QUALIFIER,
1249        new long[] { STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7],
1250          STAMPS[8] },
1251        new byte[][] { VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7],
1252          VALUES[8] }, 0, 7);
1253
1254      get = new Get(ROW);
1255      get.readAllVersions();
1256      result = ht.get(get);
1257      assertNResult(result, ROW, FAMILY, QUALIFIER,
1258        new long[] { STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7],
1259          STAMPS[8] },
1260        new byte[][] { VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7],
1261          VALUES[8] }, 0, 7);
1262
1263      scan = new Scan().withStartRow(ROW);
1264      scan.readAllVersions();
1265      result = getSingleScanResult(ht, scan);
1266      assertNResult(result, ROW, FAMILY, QUALIFIER,
1267        new long[] { STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7],
1268          STAMPS[8] },
1269        new byte[][] { VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7],
1270          VALUES[8] }, 0, 7);
1271
1272      // Verify we can get each one properly
1273      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1274      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1275      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1276      getVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
1277      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[1], VALUES[1]);
1278      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[2], VALUES[2]);
1279      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[4], VALUES[4]);
1280      scanVersionAndVerify(ht, ROW, FAMILY, QUALIFIER, STAMPS[7], VALUES[7]);
1281
1282      // Verify we don't accidentally get others
1283      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1284      getVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[9]);
1285      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[0]);
1286      scanVersionAndVerifyMissing(ht, ROW, FAMILY, QUALIFIER, STAMPS[9]);
1287
1288      // Ensure maxVersions of table is respected
1289
1290      TEST_UTIL.flush();
1291
1292      // Insert 4 more versions of same column and a dupe
1293      put = new Put(ROW);
1294      put.addColumn(FAMILY, QUALIFIER, STAMPS[9], VALUES[9]);
1295      put.addColumn(FAMILY, QUALIFIER, STAMPS[11], VALUES[11]);
1296      put.addColumn(FAMILY, QUALIFIER, STAMPS[13], VALUES[13]);
1297      put.addColumn(FAMILY, QUALIFIER, STAMPS[15], VALUES[15]);
1298      ht.put(put);
1299
1300      get = new Get(ROW);
1301      get.addColumn(FAMILY, QUALIFIER);
1302      get.readVersions(Integer.MAX_VALUE);
1303      result = ht.get(get);
1304      assertNResult(result, ROW, FAMILY, QUALIFIER,
1305        new long[] { STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8], STAMPS[9],
1306          STAMPS[11], STAMPS[13], STAMPS[15] },
1307        new byte[][] { VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8], VALUES[9],
1308          VALUES[11], VALUES[13], VALUES[15] }, 0, 9);
1309
1310      scan = new Scan().withStartRow(ROW);
1311      scan.addColumn(FAMILY, QUALIFIER);
1312      scan.readVersions(Integer.MAX_VALUE);
1313      result = getSingleScanResult(ht, scan);
1314      assertNResult(result, ROW, FAMILY, QUALIFIER,
1315        new long[] { STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[7], STAMPS[8], STAMPS[9],
1316          STAMPS[11], STAMPS[13], STAMPS[15] },
1317        new byte[][] { VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[7], VALUES[8], VALUES[9],
1318          VALUES[11], VALUES[13], VALUES[15] }, 0, 9);
1319
1320      // Delete a version in the memstore and a version in a storefile
1321      Delete delete = new Delete(ROW);
1322      delete.addColumn(FAMILY, QUALIFIER, STAMPS[11]);
1323      delete.addColumn(FAMILY, QUALIFIER, STAMPS[7]);
1324      ht.delete(delete);
1325
1326      // Test that it's gone
1327      get = new Get(ROW);
1328      get.addColumn(FAMILY, QUALIFIER);
1329      get.readVersions(Integer.MAX_VALUE);
1330      result = ht.get(get);
1331      assertNResult(result, ROW, FAMILY, QUALIFIER,
1332        new long[] { STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[8],
1333          STAMPS[9], STAMPS[13], STAMPS[15] },
1334        new byte[][] { VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[8],
1335          VALUES[9], VALUES[13], VALUES[15] }, 0, 9);
1336
1337      scan = new Scan().withStartRow(ROW);
1338      scan.addColumn(FAMILY, QUALIFIER);
1339      scan.readVersions(Integer.MAX_VALUE);
1340      result = getSingleScanResult(ht, scan);
1341      assertNResult(result, ROW, FAMILY, QUALIFIER,
1342        new long[] { STAMPS[1], STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6], STAMPS[8],
1343          STAMPS[9], STAMPS[13], STAMPS[15] },
1344        new byte[][] { VALUES[1], VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6], VALUES[8],
1345          VALUES[9], VALUES[13], VALUES[15] }, 0, 9);
1346    }
1347  }
1348
1349  @Test @SuppressWarnings("checkstyle:MethodLength") public void testVersionLimits()
1350    throws Exception {
1351    final TableName tableName = name.getTableName();
1352    byte[][] FAMILIES = makeNAscii(FAMILY, 3);
1353    int[] LIMITS = { 1, 3, 5 };
1354    long[] STAMPS = makeStamps(10);
1355    byte[][] VALUES = makeNAscii(VALUE, 10);
1356    try (Table ht = TEST_UTIL.createTable(tableName, FAMILIES, LIMITS)) {
1357
1358      // Insert limit + 1 on each family
1359      Put put = new Put(ROW);
1360      put.addColumn(FAMILIES[0], QUALIFIER, STAMPS[0], VALUES[0]);
1361      put.addColumn(FAMILIES[0], QUALIFIER, STAMPS[1], VALUES[1]);
1362      put.addColumn(FAMILIES[1], QUALIFIER, STAMPS[0], VALUES[0]);
1363      put.addColumn(FAMILIES[1], QUALIFIER, STAMPS[1], VALUES[1]);
1364      put.addColumn(FAMILIES[1], QUALIFIER, STAMPS[2], VALUES[2]);
1365      put.addColumn(FAMILIES[1], QUALIFIER, STAMPS[3], VALUES[3]);
1366      put.addColumn(FAMILIES[2], QUALIFIER, STAMPS[0], VALUES[0]);
1367      put.addColumn(FAMILIES[2], QUALIFIER, STAMPS[1], VALUES[1]);
1368      put.addColumn(FAMILIES[2], QUALIFIER, STAMPS[2], VALUES[2]);
1369      put.addColumn(FAMILIES[2], QUALIFIER, STAMPS[3], VALUES[3]);
1370      put.addColumn(FAMILIES[2], QUALIFIER, STAMPS[4], VALUES[4]);
1371      put.addColumn(FAMILIES[2], QUALIFIER, STAMPS[5], VALUES[5]);
1372      put.addColumn(FAMILIES[2], QUALIFIER, STAMPS[6], VALUES[6]);
1373      ht.put(put);
1374
1375      // Verify we only get the right number out of each
1376
1377      // Family0
1378
1379      Get get = new Get(ROW);
1380      get.addColumn(FAMILIES[0], QUALIFIER);
1381      get.readVersions(Integer.MAX_VALUE);
1382      Result result = ht.get(get);
1383      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { STAMPS[1] },
1384        new byte[][] { VALUES[1] }, 0, 0);
1385
1386      get = new Get(ROW);
1387      get.addFamily(FAMILIES[0]);
1388      get.readVersions(Integer.MAX_VALUE);
1389      result = ht.get(get);
1390      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { STAMPS[1] },
1391        new byte[][] { VALUES[1] }, 0, 0);
1392
1393      Scan scan = new Scan().withStartRow(ROW);
1394      scan.addColumn(FAMILIES[0], QUALIFIER);
1395      scan.readVersions(Integer.MAX_VALUE);
1396      result = getSingleScanResult(ht, scan);
1397      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { STAMPS[1] },
1398        new byte[][] { VALUES[1] }, 0, 0);
1399
1400      scan = new Scan().withStartRow(ROW);
1401      scan.addFamily(FAMILIES[0]);
1402      scan.readVersions(Integer.MAX_VALUE);
1403      result = getSingleScanResult(ht, scan);
1404      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { STAMPS[1] },
1405        new byte[][] { VALUES[1] }, 0, 0);
1406
1407      // Family1
1408
1409      get = new Get(ROW);
1410      get.addColumn(FAMILIES[1], QUALIFIER);
1411      get.readVersions(Integer.MAX_VALUE);
1412      result = ht.get(get);
1413      assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1414        new long[] { STAMPS[1], STAMPS[2], STAMPS[3] },
1415        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1416
1417      get = new Get(ROW);
1418      get.addFamily(FAMILIES[1]);
1419      get.readVersions(Integer.MAX_VALUE);
1420      result = ht.get(get);
1421      assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1422        new long[] { STAMPS[1], STAMPS[2], STAMPS[3] },
1423        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1424
1425      scan = new Scan().withStartRow(ROW);
1426      scan.addColumn(FAMILIES[1], QUALIFIER);
1427      scan.readVersions(Integer.MAX_VALUE);
1428      result = getSingleScanResult(ht, scan);
1429      assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1430        new long[] { STAMPS[1], STAMPS[2], STAMPS[3] },
1431        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1432
1433      scan = new Scan().withStartRow(ROW);
1434      scan.addFamily(FAMILIES[1]);
1435      scan.readVersions(Integer.MAX_VALUE);
1436      result = getSingleScanResult(ht, scan);
1437      assertNResult(result, ROW, FAMILIES[1], QUALIFIER,
1438        new long[] { STAMPS[1], STAMPS[2], STAMPS[3] },
1439        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1440
1441      // Family2
1442
1443      get = new Get(ROW);
1444      get.addColumn(FAMILIES[2], QUALIFIER);
1445      get.readVersions(Integer.MAX_VALUE);
1446      result = ht.get(get);
1447      assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1448        new long[] { STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6] },
1449        new byte[][] { VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6] }, 0, 4);
1450
1451      get = new Get(ROW);
1452      get.addFamily(FAMILIES[2]);
1453      get.readVersions(Integer.MAX_VALUE);
1454      result = ht.get(get);
1455      assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1456        new long[] { STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6] },
1457        new byte[][] { VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6] }, 0, 4);
1458
1459      scan = new Scan().withStartRow(ROW);
1460      scan.addColumn(FAMILIES[2], QUALIFIER);
1461      scan.readVersions(Integer.MAX_VALUE);
1462      result = getSingleScanResult(ht, scan);
1463      assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1464        new long[] { STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6] },
1465        new byte[][] { VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6] }, 0, 4);
1466
1467      scan = new Scan().withStartRow(ROW);
1468      scan.addFamily(FAMILIES[2]);
1469      scan.readVersions(Integer.MAX_VALUE);
1470      result = getSingleScanResult(ht, scan);
1471      assertNResult(result, ROW, FAMILIES[2], QUALIFIER,
1472        new long[] { STAMPS[2], STAMPS[3], STAMPS[4], STAMPS[5], STAMPS[6] },
1473        new byte[][] { VALUES[2], VALUES[3], VALUES[4], VALUES[5], VALUES[6] }, 0, 4);
1474
1475      // Try all families
1476
1477      get = new Get(ROW);
1478      get.readVersions(Integer.MAX_VALUE);
1479      result = ht.get(get);
1480      assertEquals("Expected 9 keys but received " + result.size(), 9, result.size());
1481
1482      get = new Get(ROW);
1483      get.addFamily(FAMILIES[0]);
1484      get.addFamily(FAMILIES[1]);
1485      get.addFamily(FAMILIES[2]);
1486      get.readVersions(Integer.MAX_VALUE);
1487      result = ht.get(get);
1488      assertEquals("Expected 9 keys but received " + result.size(), 9, result.size());
1489
1490      get = new Get(ROW);
1491      get.addColumn(FAMILIES[0], QUALIFIER);
1492      get.addColumn(FAMILIES[1], QUALIFIER);
1493      get.addColumn(FAMILIES[2], QUALIFIER);
1494      get.readVersions(Integer.MAX_VALUE);
1495      result = ht.get(get);
1496      assertEquals("Expected 9 keys but received " + result.size(), 9, result.size());
1497
1498      scan = new Scan().withStartRow(ROW);
1499      scan.readVersions(Integer.MAX_VALUE);
1500      result = getSingleScanResult(ht, scan);
1501      assertEquals("Expected 9 keys but received " + result.size(), 9, result.size());
1502
1503      scan = new Scan().withStartRow(ROW);
1504      scan.readVersions(Integer.MAX_VALUE);
1505      scan.addFamily(FAMILIES[0]);
1506      scan.addFamily(FAMILIES[1]);
1507      scan.addFamily(FAMILIES[2]);
1508      result = getSingleScanResult(ht, scan);
1509      assertEquals("Expected 9 keys but received " + result.size(), 9, result.size());
1510
1511      scan = new Scan().withStartRow(ROW);
1512      scan.readVersions(Integer.MAX_VALUE);
1513      scan.addColumn(FAMILIES[0], QUALIFIER);
1514      scan.addColumn(FAMILIES[1], QUALIFIER);
1515      scan.addColumn(FAMILIES[2], QUALIFIER);
1516      result = getSingleScanResult(ht, scan);
1517      assertEquals("Expected 9 keys but received " + result.size(), 9, result.size());
1518    }
1519  }
1520
1521  @Test public void testDeleteFamilyVersion() throws Exception {
1522    try (Admin admin = TEST_UTIL.getAdmin()) {
1523      final TableName tableName = name.getTableName();
1524
1525      byte[][] QUALIFIERS = makeNAscii(QUALIFIER, 1);
1526      byte[][] VALUES = makeN(VALUE, 5);
1527      long[] ts = { 1000, 2000, 3000, 4000, 5000 };
1528
1529      try (Table ht = TEST_UTIL.createTable(tableName, FAMILY, 5)) {
1530
1531        Put put = new Put(ROW);
1532        for (int q = 0; q < 1; q++) {
1533          for (int t = 0; t < 5; t++) {
1534            put.addColumn(FAMILY, QUALIFIERS[q], ts[t], VALUES[t]);
1535          }
1536        }
1537        ht.put(put);
1538        admin.flush(tableName);
1539
1540        Delete delete = new Delete(ROW);
1541        delete.addFamilyVersion(FAMILY, ts[1]);  // delete version '2000'
1542        delete.addFamilyVersion(FAMILY, ts[3]);  // delete version '4000'
1543        ht.delete(delete);
1544        admin.flush(tableName);
1545
1546        for (int i = 0; i < 1; i++) {
1547          Get get = new Get(ROW);
1548          get.addColumn(FAMILY, QUALIFIERS[i]);
1549          get.readVersions(Integer.MAX_VALUE);
1550          Result result = ht.get(get);
1551          // verify version '1000'/'3000'/'5000' remains for all columns
1552          assertNResult(result, ROW, FAMILY, QUALIFIERS[i], new long[] { ts[0], ts[2], ts[4] },
1553            new byte[][] { VALUES[0], VALUES[2], VALUES[4] }, 0, 2);
1554        }
1555      }
1556    }
1557  }
1558
1559  @Test public void testDeleteFamilyVersionWithOtherDeletes() throws Exception {
1560    final TableName tableName = name.getTableName();
1561
1562    byte[][] QUALIFIERS = makeNAscii(QUALIFIER, 5);
1563    byte[][] VALUES = makeN(VALUE, 5);
1564    long[] ts = { 1000, 2000, 3000, 4000, 5000 };
1565
1566    try (Admin admin = TEST_UTIL.getAdmin(); Table ht = TEST_UTIL.createTable(tableName, FAMILY,
1567      5)) {
1568      Put put;
1569      Result result;
1570      Get get;
1571      Delete delete = null;
1572
1573      // 1. put on ROW
1574      put = new Put(ROW);
1575      for (int q = 0; q < 5; q++) {
1576        for (int t = 0; t < 5; t++) {
1577          put.addColumn(FAMILY, QUALIFIERS[q], ts[t], VALUES[t]);
1578        }
1579      }
1580      ht.put(put);
1581      admin.flush(tableName);
1582
1583      // 2. put on ROWS[0]
1584      byte[] ROW2 = Bytes.toBytes("myRowForTest");
1585      put = new Put(ROW2);
1586      for (int q = 0; q < 5; q++) {
1587        for (int t = 0; t < 5; t++) {
1588          put.addColumn(FAMILY, QUALIFIERS[q], ts[t], VALUES[t]);
1589        }
1590      }
1591      ht.put(put);
1592      admin.flush(tableName);
1593
1594      // 3. delete on ROW
1595      delete = new Delete(ROW);
1596      // delete version <= 2000 of all columns
1597      // note: addFamily must be the first since it will mask
1598      // the subsequent other type deletes!
1599      delete.addFamily(FAMILY, ts[1]);
1600      // delete version '4000' of all columns
1601      delete.addFamilyVersion(FAMILY, ts[3]);
1602      // delete version <= 3000 of column 0
1603      delete.addColumns(FAMILY, QUALIFIERS[0], ts[2]);
1604      // delete version <= 5000 of column 2
1605      delete.addColumns(FAMILY, QUALIFIERS[2], ts[4]);
1606      // delete version 5000 of column 4
1607      delete.addColumn(FAMILY, QUALIFIERS[4], ts[4]);
1608      ht.delete(delete);
1609      admin.flush(tableName);
1610
1611      // 4. delete on ROWS[0]
1612      delete = new Delete(ROW2);
1613      delete.addFamilyVersion(FAMILY, ts[1]);  // delete version '2000'
1614      delete.addFamilyVersion(FAMILY, ts[3]);  // delete version '4000'
1615      ht.delete(delete);
1616      admin.flush(tableName);
1617
1618      // 5. check ROW
1619      get = new Get(ROW);
1620      get.addColumn(FAMILY, QUALIFIERS[0]);
1621      get.readVersions(Integer.MAX_VALUE);
1622      result = ht.get(get);
1623      assertNResult(result, ROW, FAMILY, QUALIFIERS[0], new long[] { ts[4] },
1624        new byte[][] { VALUES[4] }, 0, 0);
1625
1626      get = new Get(ROW);
1627      get.addColumn(FAMILY, QUALIFIERS[1]);
1628      get.readVersions(Integer.MAX_VALUE);
1629      result = ht.get(get);
1630      assertNResult(result, ROW, FAMILY, QUALIFIERS[1], new long[] { ts[2], ts[4] },
1631        new byte[][] { VALUES[2], VALUES[4] }, 0, 1);
1632
1633      get = new Get(ROW);
1634      get.addColumn(FAMILY, QUALIFIERS[2]);
1635      get.readVersions(Integer.MAX_VALUE);
1636      result = ht.get(get);
1637      assertEquals(0, result.size());
1638
1639      get = new Get(ROW);
1640      get.addColumn(FAMILY, QUALIFIERS[3]);
1641      get.readVersions(Integer.MAX_VALUE);
1642      result = ht.get(get);
1643      assertNResult(result, ROW, FAMILY, QUALIFIERS[3], new long[] { ts[2], ts[4] },
1644        new byte[][] { VALUES[2], VALUES[4] }, 0, 1);
1645
1646      get = new Get(ROW);
1647      get.addColumn(FAMILY, QUALIFIERS[4]);
1648      get.readVersions(Integer.MAX_VALUE);
1649      result = ht.get(get);
1650      assertNResult(result, ROW, FAMILY, QUALIFIERS[4], new long[] { ts[2] },
1651        new byte[][] { VALUES[2] }, 0, 0);
1652
1653      // 6. check ROWS[0]
1654      for (int i = 0; i < 5; i++) {
1655        get = new Get(ROW2);
1656        get.addColumn(FAMILY, QUALIFIERS[i]);
1657        get.readVersions(Integer.MAX_VALUE);
1658        result = ht.get(get);
1659        // verify version '1000'/'3000'/'5000' remains for all columns
1660        assertNResult(result, ROW2, FAMILY, QUALIFIERS[i], new long[] { ts[0], ts[2], ts[4] },
1661          new byte[][] { VALUES[0], VALUES[2], VALUES[4] }, 0, 2);
1662      }
1663    }
1664  }
1665
1666  @Test public void testDeleteWithFailed() throws Exception {
1667    final TableName tableName = name.getTableName();
1668
1669    byte[][] FAMILIES = makeNAscii(FAMILY, 3);
1670    byte[][] VALUES = makeN(VALUE, 5);
1671    long[] ts = { 1000, 2000, 3000, 4000, 5000 };
1672
1673    try (Table ht = TEST_UTIL.createTable(tableName, FAMILIES, 3)) {
1674      Put put = new Put(ROW);
1675      put.addColumn(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
1676      ht.put(put);
1677
1678      // delete wrong family
1679      Delete delete = new Delete(ROW);
1680      delete.addFamily(FAMILIES[1], ts[0]);
1681      ht.delete(delete);
1682
1683      Get get = new Get(ROW);
1684      get.addFamily(FAMILIES[0]);
1685      get.readAllVersions();
1686      Result result = ht.get(get);
1687      assertTrue(Bytes.equals(result.getValue(FAMILIES[0], QUALIFIER), VALUES[0]));
1688    }
1689  }
1690
1691  @Test
1692  @SuppressWarnings("checkstyle:MethodLength")
1693  public void testDeletes() throws Exception {
1694    final TableName tableName = name.getTableName();
1695
1696    byte[][] ROWS = makeNAscii(ROW, 6);
1697    byte[][] FAMILIES = makeNAscii(FAMILY, 3);
1698    byte[][] VALUES = makeN(VALUE, 5);
1699    long[] ts = { 1000, 2000, 3000, 4000, 5000 };
1700
1701    try (Table ht = TEST_UTIL.createTable(tableName, FAMILIES, 3)) {
1702
1703      Put put = new Put(ROW);
1704      put.addColumn(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]);
1705      put.addColumn(FAMILIES[0], QUALIFIER, ts[1], VALUES[1]);
1706      ht.put(put);
1707
1708      Delete delete = new Delete(ROW);
1709      delete.addFamily(FAMILIES[0], ts[0]);
1710      ht.delete(delete);
1711
1712      Get get = new Get(ROW);
1713      get.addFamily(FAMILIES[0]);
1714      get.readVersions(Integer.MAX_VALUE);
1715      Result result = ht.get(get);
1716      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1] },
1717        new byte[][] { VALUES[1] }, 0, 0);
1718
1719      Scan scan = new Scan().withStartRow(ROW);
1720      scan.addFamily(FAMILIES[0]);
1721      scan.readVersions(Integer.MAX_VALUE);
1722      result = getSingleScanResult(ht, scan);
1723      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1] },
1724        new byte[][] { VALUES[1] }, 0, 0);
1725
1726      // Test delete latest version
1727      put = new Put(ROW);
1728      put.addColumn(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]);
1729      put.addColumn(FAMILIES[0], QUALIFIER, ts[2], VALUES[2]);
1730      put.addColumn(FAMILIES[0], QUALIFIER, ts[3], VALUES[3]);
1731      put.addColumn(FAMILIES[0], null, ts[4], VALUES[4]);
1732      put.addColumn(FAMILIES[0], null, ts[2], VALUES[2]);
1733      put.addColumn(FAMILIES[0], null, ts[3], VALUES[3]);
1734      ht.put(put);
1735
1736      delete = new Delete(ROW);
1737      delete.addColumn(FAMILIES[0], QUALIFIER); // ts[4]
1738      ht.delete(delete);
1739
1740      get = new Get(ROW);
1741      get.addColumn(FAMILIES[0], QUALIFIER);
1742      get.readVersions(Integer.MAX_VALUE);
1743      result = ht.get(get);
1744      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
1745        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1746
1747      scan = new Scan().withStartRow(ROW);
1748      scan.addColumn(FAMILIES[0], QUALIFIER);
1749      scan.readVersions(Integer.MAX_VALUE);
1750      result = getSingleScanResult(ht, scan);
1751      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
1752        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1753
1754      // Test for HBASE-1847
1755      delete = new Delete(ROW);
1756      delete.addColumn(FAMILIES[0], null);
1757      ht.delete(delete);
1758
1759      // Cleanup null qualifier
1760      delete = new Delete(ROW);
1761      delete.addColumns(FAMILIES[0], null);
1762      ht.delete(delete);
1763
1764      // Expected client behavior might be that you can re-put deleted values
1765      // But alas, this is not to be.  We can't put them back in either case.
1766
1767      put = new Put(ROW);
1768      put.addColumn(FAMILIES[0], QUALIFIER, ts[0], VALUES[0]); // 1000
1769      put.addColumn(FAMILIES[0], QUALIFIER, ts[4], VALUES[4]); // 5000
1770      ht.put(put);
1771
1772      // It used to be due to the internal implementation of Get, that
1773      // the Get() call would return ts[4] UNLIKE the Scan below. With
1774      // the switch to using Scan for Get this is no longer the case.
1775      get = new Get(ROW);
1776      get.addFamily(FAMILIES[0]);
1777      get.readVersions(Integer.MAX_VALUE);
1778      result = ht.get(get);
1779      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
1780        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1781
1782      // The Scanner returns the previous values, the expected-naive-unexpected behavior
1783
1784      scan = new Scan().withStartRow(ROW);
1785      scan.addFamily(FAMILIES[0]);
1786      scan.readVersions(Integer.MAX_VALUE);
1787      result = getSingleScanResult(ht, scan);
1788      assertNResult(result, ROW, FAMILIES[0], QUALIFIER, new long[] { ts[1], ts[2], ts[3] },
1789        new byte[][] { VALUES[1], VALUES[2], VALUES[3] }, 0, 2);
1790
1791      // Test deleting an entire family from one row but not the other various ways
1792
1793      put = new Put(ROWS[0]);
1794      put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
1795      put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
1796      put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
1797      put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
1798      ht.put(put);
1799
1800      put = new Put(ROWS[1]);
1801      put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
1802      put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
1803      put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
1804      put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
1805      ht.put(put);
1806
1807      put = new Put(ROWS[2]);
1808      put.addColumn(FAMILIES[1], QUALIFIER, ts[0], VALUES[0]);
1809      put.addColumn(FAMILIES[1], QUALIFIER, ts[1], VALUES[1]);
1810      put.addColumn(FAMILIES[2], QUALIFIER, ts[2], VALUES[2]);
1811      put.addColumn(FAMILIES[2], QUALIFIER, ts[3], VALUES[3]);
1812      ht.put(put);
1813
1814      // Assert that above went in.
1815      get = new Get(ROWS[2]);
1816      get.addFamily(FAMILIES[1]);
1817      get.addFamily(FAMILIES[2]);
1818      get.readVersions(Integer.MAX_VALUE);
1819      result = ht.get(get);
1820      assertEquals("Expected 4 key but received " + result.size() + ": " + result, 4,
1821        result.size());
1822
1823      delete = new Delete(ROWS[0]);
1824      delete.addFamily(FAMILIES[2]);
1825      ht.delete(delete);
1826
1827      delete = new Delete(ROWS[1]);
1828      delete.addColumns(FAMILIES[1], QUALIFIER);
1829      ht.delete(delete);
1830
1831      delete = new Delete(ROWS[2]);
1832      delete.addColumn(FAMILIES[1], QUALIFIER);
1833      delete.addColumn(FAMILIES[1], QUALIFIER);
1834      delete.addColumn(FAMILIES[2], QUALIFIER);
1835      ht.delete(delete);
1836
1837      get = new Get(ROWS[0]);
1838      get.addFamily(FAMILIES[1]);
1839      get.addFamily(FAMILIES[2]);
1840      get.readVersions(Integer.MAX_VALUE);
1841      result = ht.get(get);
1842      assertEquals("Expected 2 keys but received " + result.size(), 2, result.size());
1843      assertNResult(result, ROWS[0], FAMILIES[1], QUALIFIER, new long[] { ts[0], ts[1] },
1844        new byte[][] { VALUES[0], VALUES[1] }, 0, 1);
1845
1846      scan = new Scan().withStartRow(ROWS[0]);
1847      scan.addFamily(FAMILIES[1]);
1848      scan.addFamily(FAMILIES[2]);
1849      scan.readVersions(Integer.MAX_VALUE);
1850      result = getSingleScanResult(ht, scan);
1851      assertEquals("Expected 2 keys but received " + result.size(), 2, result.size());
1852      assertNResult(result, ROWS[0], FAMILIES[1], QUALIFIER, new long[] { ts[0], ts[1] },
1853        new byte[][] { VALUES[0], VALUES[1] }, 0, 1);
1854
1855      get = new Get(ROWS[1]);
1856      get.addFamily(FAMILIES[1]);
1857      get.addFamily(FAMILIES[2]);
1858      get.readVersions(Integer.MAX_VALUE);
1859      result = ht.get(get);
1860      assertEquals("Expected 2 keys but received " + result.size(), 2, result.size());
1861
1862      scan = new Scan().withStartRow(ROWS[1]);
1863      scan.addFamily(FAMILIES[1]);
1864      scan.addFamily(FAMILIES[2]);
1865      scan.readVersions(Integer.MAX_VALUE);
1866      result = getSingleScanResult(ht, scan);
1867      assertEquals("Expected 2 keys but received " + result.size(), 2, result.size());
1868
1869      get = new Get(ROWS[2]);
1870      get.addFamily(FAMILIES[1]);
1871      get.addFamily(FAMILIES[2]);
1872      get.readVersions(Integer.MAX_VALUE);
1873      result = ht.get(get);
1874      assertEquals(1, result.size());
1875      assertNResult(result, ROWS[2], FAMILIES[2], QUALIFIER, new long[] { ts[2] },
1876        new byte[][] { VALUES[2] }, 0, 0);
1877
1878      scan = new Scan().withStartRow(ROWS[2]);
1879      scan.addFamily(FAMILIES[1]);
1880      scan.addFamily(FAMILIES[2]);
1881      scan.readVersions(Integer.MAX_VALUE);
1882      result = getSingleScanResult(ht, scan);
1883      assertEquals(1, result.size());
1884      assertNResult(result, ROWS[2], FAMILIES[2], QUALIFIER, new long[] { ts[2] },
1885        new byte[][] { VALUES[2] }, 0, 0);
1886
1887      // Test if we delete the family first in one row (HBASE-1541)
1888
1889      delete = new Delete(ROWS[3]);
1890      delete.addFamily(FAMILIES[1]);
1891      ht.delete(delete);
1892
1893      put = new Put(ROWS[3]);
1894      put.addColumn(FAMILIES[2], QUALIFIER, VALUES[0]);
1895      ht.put(put);
1896
1897      put = new Put(ROWS[4]);
1898      put.addColumn(FAMILIES[1], QUALIFIER, VALUES[1]);
1899      put.addColumn(FAMILIES[2], QUALIFIER, VALUES[2]);
1900      ht.put(put);
1901
1902      get = new Get(ROWS[3]);
1903      get.addFamily(FAMILIES[1]);
1904      get.addFamily(FAMILIES[2]);
1905      get.readVersions(Integer.MAX_VALUE);
1906      result = ht.get(get);
1907      assertEquals("Expected 1 key but received " + result.size(), 1, result.size());
1908
1909      get = new Get(ROWS[4]);
1910      get.addFamily(FAMILIES[1]);
1911      get.addFamily(FAMILIES[2]);
1912      get.readVersions(Integer.MAX_VALUE);
1913      result = ht.get(get);
1914      assertEquals("Expected 2 keys but received " + result.size(), 2, result.size());
1915
1916      scan = new Scan().withStartRow(ROWS[3]);
1917      scan.addFamily(FAMILIES[1]);
1918      scan.addFamily(FAMILIES[2]);
1919      scan.readVersions(Integer.MAX_VALUE);
1920      ResultScanner scanner = ht.getScanner(scan);
1921      result = scanner.next();
1922      assertEquals("Expected 1 key but received " + result.size(), 1, result.size());
1923      assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[3]));
1924      assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[0]));
1925      result = scanner.next();
1926      assertEquals("Expected 2 keys but received " + result.size(), 2, result.size());
1927      assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[0]), ROWS[4]));
1928      assertTrue(Bytes.equals(CellUtil.cloneRow(result.rawCells()[1]), ROWS[4]));
1929      assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[0]), VALUES[1]));
1930      assertTrue(Bytes.equals(CellUtil.cloneValue(result.rawCells()[1]), VALUES[2]));
1931      scanner.close();
1932
1933      // Add test of bulk deleting.
1934      for (int i = 0; i < 10; i++) {
1935        byte[] bytes = Bytes.toBytes(i);
1936        put = new Put(bytes);
1937        put.setDurability(Durability.SKIP_WAL);
1938        put.addColumn(FAMILIES[0], QUALIFIER, bytes);
1939        ht.put(put);
1940      }
1941      for (int i = 0; i < 10; i++) {
1942        byte[] bytes = Bytes.toBytes(i);
1943        get = new Get(bytes);
1944        get.addFamily(FAMILIES[0]);
1945        result = ht.get(get);
1946        assertEquals(1, result.size());
1947      }
1948      ArrayList<Delete> deletes = new ArrayList<>();
1949      for (int i = 0; i < 10; i++) {
1950        byte[] bytes = Bytes.toBytes(i);
1951        delete = new Delete(bytes);
1952        delete.addFamily(FAMILIES[0]);
1953        deletes.add(delete);
1954      }
1955      ht.delete(deletes);
1956      for (int i = 0; i < 10; i++) {
1957        byte[] bytes = Bytes.toBytes(i);
1958        get = new Get(bytes);
1959        get.addFamily(FAMILIES[0]);
1960        result = ht.get(get);
1961        assertTrue(result.isEmpty());
1962      }
1963    }
1964  }
1965}