@Test
public void testIndexGet() throws IOException {

  Result result = null;
  nextTsAndCreateTransaction();
  transaction.put(MAIN_TABLE, new ThemisPut(ROW).add(FAMILY, QUALIFIER, VALUE));
  mockTsAndCommitTransaction();
  
  nextTsAndCreateTransaction();
  
  // no-index scan
  ResultScanner scanner = transaction.getScanner(MAIN_TABLE,
    new ThemisScan().addColumn(FAMILY, QUALIFIER));
  Assert.assertFalse(scanner instanceof IndexScanner);
  checkReadResult(VALUE, COLUMN, scanner.next());
  scanner.close();
  
  // index get column
  IndexGet indexGet = new IndexGet(INDEX_COLUMN, VALUE,
      new DataGet().addColumn(FAMILY, QUALIFIER));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  Assert.assertTrue(scanner instanceof IndexScanner);
  checkReadResult(VALUE, COLUMN, scanner.next());
  checkAndCloseScanner(scanner);
  
  // write other qualifier and family
  nextTsAndCreateTransaction();
  transaction.delete(MAIN_TABLE, new ThemisDelete(ROW).deleteColumn(FAMILY, ANOTHER_QUALIFIER));
  transaction.put(MAIN_TABLE, new ThemisPut(ROW).add(ANOTHER_FAMILY, QUALIFIER, ANOTHER_VALUE));
  mockTsAndCommitTransaction();
  
  nextTsAndCreateTransaction();
  // index get family and column
  indexGet = new IndexGet(INDEX_COLUMN, VALUE,
    new DataGet().addColumn(FAMILY, QUALIFIER).addFamily(ANOTHER_FAMILY));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  checkReadResults(new byte[][] { VALUE, ANOTHER_VALUE }, new ColumnCoordinate[] { COLUMN,
      COLUMN_WITH_ANOTHER_FAMILY }, scanner.next());
  checkAndCloseScanner(scanner);
  
  // index get whole row
  indexGet = new IndexGet(INDEX_COLUMN, VALUE, new DataGet());
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  checkReadResults(new byte[][] { VALUE, ANOTHER_VALUE }, new ColumnCoordinate[] { COLUMN,
      COLUMN_WITH_ANOTHER_FAMILY }, scanner.next());
  checkAndCloseScanner(scanner);
  
  // write another value in index column
  transaction.put(MAIN_TABLE, new ThemisPut(ROW).add(FAMILY, QUALIFIER, ANOTHER_VALUE));
  mockTsAndCommitTransaction();
  
  // also get old value because timestamp is not updated
  indexGet = new IndexGet(INDEX_COLUMN, VALUE, new DataGet().addColumn(FAMILY, QUALIFIER));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  Assert.assertTrue(scanner instanceof IndexScanner);
  checkReadResult(VALUE, COLUMN, scanner.next());
  checkAndCloseScanner(scanner);
  
  // can not read the old value
  nextTransactionTs();
  createTransactionWithMock();
  indexGet = new IndexGet(INDEX_COLUMN, VALUE, new DataGet().addColumn(FAMILY, QUALIFIER));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  Assert.assertTrue(scanner instanceof IndexScanner);
  checkAndCloseScanner(scanner);
  
  // can read the new value
  nextTsAndCreateTransaction();
  indexGet = new IndexGet(INDEX_COLUMN, ANOTHER_VALUE, new DataGet().addColumn(FAMILY, QUALIFIER)
      .addFamily(ANOTHER_FAMILY));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  Assert.assertTrue(scanner instanceof IndexScanner);
  checkReadResults(new byte[][] { ANOTHER_VALUE, ANOTHER_VALUE }, new ColumnCoordinate[] { COLUMN,
      COLUMN_WITH_ANOTHER_FAMILY }, scanner.next());
  checkAndCloseScanner(scanner);
  
  // delete value
  // write another value in index column
  transaction.delete(MAIN_TABLE, new ThemisDelete(ROW).deleteColumn(FAMILY, QUALIFIER));
  mockTsAndCommitTransaction();
  
  // still read old value
  indexGet = new IndexGet(INDEX_COLUMN, ANOTHER_VALUE, new DataGet().addColumn(FAMILY, QUALIFIER));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  Assert.assertTrue(scanner instanceof IndexScanner);
  checkReadResult(ANOTHER_VALUE, COLUMN, scanner.next());
  checkAndCloseScanner(scanner);
  
  // can not read value after timestamp updated
  nextTsAndCreateTransaction();
  indexGet = new IndexGet(INDEX_COLUMN, ANOTHER_VALUE, new DataGet().addColumn(FAMILY, QUALIFIER));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  Assert.assertTrue(scanner instanceof IndexScanner);
  checkAndCloseScanner(scanner);
  
  // two rows with the same index column value
  nextTsAndCreateTransaction();
  transaction.put(MAIN_TABLE, new ThemisPut(ANOTHER_ROW).add(FAMILY, QUALIFIER, VALUE));
  transaction.put(MAIN_TABLE, new ThemisPut(ROW).add(FAMILY, QUALIFIER, VALUE));
  mockTsAndCommitTransaction();
  
  nextTsAndCreateTransaction();
  indexGet = new IndexGet(INDEX_COLUMN, VALUE, new DataGet().addColumn(FAMILY, QUALIFIER));
  scanner = transaction.getScanner(MAIN_TABLE, indexGet);
  Assert.assertTrue(scanner instanceof IndexScanner);
  result = scanner.next();
  Assert.assertArrayEquals(ANOTHER_ROW, result.getRow());
  checkReadResult(VALUE, COLUMN, result);
  result = scanner.next();
  Assert.assertArrayEquals(ROW, result.getRow());
  checkReadResult(VALUE, COLUMN, result);
  checkAndCloseScanner(scanner);
}