gt:         testKeyToObject(tid, values.length, "c2");
context: /**
   * Copyright (C) 2009-2013 FoundationDB, LLC
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Affero General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Affero General Public License for more details.
   *
   * You should have received a copy of the GNU Affero General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package com.foundationdb.server.test.it.rowtests;
  
  import com.foundationdb.ais.model.Column;
  import com.foundationdb.ais.model.Index;
  import com.foundationdb.ais.model.IndexColumn;
  import com.foundationdb.ais.model.Table;
  import com.foundationdb.qp.row.Row;
  import com.foundationdb.server.PersistitKeyValueSource;
  import com.foundationdb.server.error.UnsupportedIndexDataTypeException;
  import com.foundationdb.server.service.transaction.TransactionService.CloseableTransaction;
  import com.foundationdb.server.store.IndexVisitor;
  import com.foundationdb.server.test.it.ITBase;
  import com.foundationdb.server.types.value.ValueSources;
  import com.foundationdb.util.WrappingByteSource;
  import com.persistit.Key;
  import com.persistit.Value;
  import org.junit.Assert;
  import org.junit.Test;
  
  import java.math.BigDecimal;
  import java.nio.ByteBuffer;
  import java.util.Iterator;
  import java.util.List;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertNotNull;
  
  public class KeyToObjectIT extends ITBase {
      private final String SCHEMA = "test";
      private final String TABLE = "t";
      private final boolean IS_PK = false;
      private final boolean INDEXES = true;
  
       private void testKeyToObject(int tableId, int expectedRowCount, String indexName) throws Exception {
          try(CloseableTransaction txn = txnService().beginCloseableTransaction(session())) {
              testKeyToObjectInternal(tableId, expectedRowCount, indexName);
              txn.commit();
          }
      }
  
      /**
       * Internal helper for comparing all indexed values in an index tree to their values in the row after
       * going through Encoder.toObject(RowData) and Encoder.toObject(Key), respectively.
       * <p><b>Note:</b> For test simplicity, the values in the row must be in index order.</p>
       * @param tableId Table to scan.
       * @param expectedRowCount Rows expected from a full table scan.
       * @param indexName Name of index to compare to.
       * @throws Exception On error.
       */
      private void testKeyToObjectInternal(int tableId, int expectedRowCount, String indexName) throws Exception {
          final Table table = getTable(tableId);
          final Index index = table.getIndex(indexName);
          assertNotNull("expected index named: "+indexName, index);
          
          final List<Row> allRows = scanAll(tableId);
          assertEquals("rows scanned", expectedRowCount, allRows.size());
  
          final Iterator<Row> rowIt = allRows.iterator();
  
          store().traverse(session(), index, new IndexVisitor<Key,Value>() {
              private int rowCounter = 0;
  
              @Override
              protected void visit(Key key, Value value) {
                  if(!rowIt.hasNext()) {
                      Assert.fail("More index entries than rows: rows("+allRows+") index("+index+")");
                  }
  
                  final Row row = rowIt.next();
                  key.indexTo(0);
  
                 
                  for(IndexColumn indexColumn : index.getKeyColumns()) {
                      Column column = indexColumn.getColumn();
                      int colPos = column.getPosition();
                      Object objFromRow = ValueSources.toObject(row.value(colPos));
                      PersistitKeyValueSource valueSource = new PersistitKeyValueSource(indexColumn.getColumn().getType());
                      valueSource.attach(key, indexColumn);
                      
                      final Object lastConvertedValue;
                      try {
                          lastConvertedValue = ValueSources.toObject(valueSource);
                      } catch (Exception e) {
                          throw new RuntimeException("with type" + column.getTypeDescription(), e);
                      }
  
                      // Work around for dropping of 0 value sigfigs from key.decode()    
                      int compareValue = 1;
                      if(objFromRow instanceof BigDecimal && lastConvertedValue instanceof BigDecimal) {
                          compareValue = ((BigDecimal)objFromRow).compareTo(((BigDecimal)lastConvertedValue));
                      }
                      if(compareValue != 0) {
                          if (objFromRow instanceof ByteBuffer) {
                              objFromRow = WrappingByteSource.fromByteBuffer((ByteBuffer)objFromRow);
                          }
                      }
                      ++rowCounter;
                  }
              }
          }, -1, 0);
  
          if(rowIt.hasNext()) {
              Assert.fail("More rows than index entries: rows("+allRows+") index("+index+")");
          }
      }
  
      void createAndWriteRows(int tableId, Object[] singleColumnValue) {
          int i = 0;
          for(Object o : singleColumnValue) {
              writeRow(tableId, i++, o);
          }
      }
  
  
      @Test
      public void intField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ int");
          Integer values[] = {null, -89573, -10, 0, 1, 42, 1337, 29348291};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void intUnsignedField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ int unsigned");
          Integer values[] = {null, 0, 1, 255, 400, 674532, 16777215, 2147483647};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void bigintUnsignedField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ bigint unsigned");
          Long values[] = {null, 0L, 1L, 255L, 400L, 674532L, 16777215L, 2147483647L, 9223372036854775806L};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
      
      @Test
      public void floatField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ float");
          Float values[] = {null, -Float.MAX_VALUE, -1337.4356f, -10f, -Float.MIN_VALUE,
                            0f, Float.MIN_VALUE, 1f, 432.235f, 829483.3125f, Float.MAX_VALUE};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void floatUnsignedField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ float unsigned");
          Float values[] = {null, 0f, Float.MIN_VALUE, 1f, 42.24f, 829483.3125f, 1234567f, Float.MAX_VALUE};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void doubleField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ double");
          Double values[] = {null, -Double.MAX_VALUE, -849284.284, -5d, -Double.MIN_VALUE,
                             0d, Double.MIN_VALUE, 1d, 100d, 9128472947.284729, Double.MAX_VALUE};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void doubleUnsignedField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ double unsigned");
          Double values[] = {null, 0d, Double.MIN_VALUE, 1d, 8587d, 123456.789d, 9879679567.284729, Double.MAX_VALUE};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void decimalField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, new SimpleColumn("c2", "MCOMPAT_ decimal", 5L, 2L));
          BigDecimal values[] = {null, BigDecimal.valueOf(-99999, 2), BigDecimal.valueOf(-999),
                                 BigDecimal.valueOf(-1234, 1), BigDecimal.valueOf(0), BigDecimal.valueOf(1),
                                 BigDecimal.valueOf(426), BigDecimal.valueOf(5678, 1), BigDecimal.valueOf(99999, 2)};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void decimalUnsignedField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, new SimpleColumn("c2", "MCOMPAT_ decimal unsigned", 5L, 2L));
          BigDecimal values[] = {null, BigDecimal.valueOf(0), BigDecimal.valueOf(1), BigDecimal.valueOf(4242, 2),
                                 BigDecimal.valueOf(5678, 1), BigDecimal.valueOf(99999, 2)};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void charField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, new SimpleColumn("c2", "MCOMPAT_ char", 10L, null));
          String values[] = {null, "", "0123456789", "zebra"};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test
      public void varcharField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, new SimpleColumn("c2", "MCOMPAT_ varchar", 26L, null));
          String values[] = {null, "", "abcdefghijklmnopqrstuvwxyz", "see spot run"};
          createAndWriteRows(tid, values);
          testKeyToObject(tid, values.length, "c2");
      }
  
      @Test(expected=UnsupportedIndexDataTypeException.class)
      public void blobField() throws Exception {
          createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "AKSQL_ blob");
      }
  
      @Test(expected=UnsupportedIndexDataTypeException.class)
      public void textField() throws Exception {
          createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ text");
      }
  
      @Test
      public void binaryField() throws Exception {
          final int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, new SimpleColumn("c2", "MCOMPAT_ binary", 10L, null));
          byte[][] values = {null, {}, {1,2,3,4,5}, {-24, 8, -98, 45, 67, 127, 34, -42, 9, 10}};
          createAndWriteRows(tid, values);
  