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