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