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