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