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