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