/** * 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.qp.row.Row; import com.foundationdb.server.api.dml.scan.NewRow; import com.foundationdb.server.test.it.ITBase; import com.foundationdb.server.types.value.ValueSources; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Arrays; import java.util.Iterator; import java.util.List; import static org.junit.Assert.assertEquals; public class UnsignedFieldsIT extends ITBase { private final String SCHEMA = "test"; private final String TABLE = "t"; private final boolean IS_PK = false; private final boolean INDEXES = false; private void writeRows(int tableId, Object... values) { long id = 0; for(Object o : values) { writeRow(tableId, id++, o); } } private void compareRows(int tableId, Object... values) { List<Row> rows = scanAll(tableId); assertEquals("column count", 2, getTable(tableId).getColumns().size()); Iterator<Row> rowIt = rows.iterator(); Iterator<Object> expectedIt = Arrays.asList(values).iterator(); while(rowIt.hasNext() && expectedIt.hasNext()) { Row row = rowIt.next(); Number actual = (Number)ValueSources.toObject(row.value(1)); if (actual instanceof Short) { actual = actual.longValue(); } else if (actual instanceof Integer) { actual = actual.longValue(); } Number expected = (Number)expectedIt.next(); if (actual instanceof Long && expected instanceof BigInteger) { actual = BigInteger.valueOf(actual.longValue()); } assertEquals("row id " + ValueSources.toObject(row.value(0)), expected, actual); } String extra = ""; while(rowIt.hasNext()) { extra += rowIt.next() + ","; } if(!extra.isEmpty()) { Assert.fail("Extra rows from scan: " + extra); } while(expectedIt.hasNext()) { extra += expectedIt.next() + ","; } if(!extra.isEmpty()) { Assert.fail("Expected more rows from scan: " + extra); } } private void writeRowsAndCompareValues(int tableId, Object... values) { writeRows(tableId, values); compareRows(tableId, values); } private Object[] getTestValues(int bitCount) { long signedMax = (1L << (bitCount - 1)) - 1; return array(0L, 1L, signedMax - 2, signedMax - 1, signedMax, signedMax + 1, signedMax + 2, signedMax*2 + 1); } @Test public void tinyIntUnsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ tinyint unsigned"); Object[] values = getTestValues(8); writeRowsAndCompareValues(tid, values); } @Test public void smallIntUnsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ smallint unsigned"); Object[] values = getTestValues(16); writeRowsAndCompareValues(tid, values); } @Test public void mediumIntUnsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ mediumint unsigned"); Object[] values = getTestValues(24); writeRowsAndCompareValues(tid, values); } @Test public void intUnsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ int unsigned"); Object[] values = getTestValues(32); writeRowsAndCompareValues(tid, values); } @Ignore ("BigInt Unsigned doesn't handle 9223372036854775808 correctly") @Test public void bigIntUnsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ bigint unsigned"); Object[] values = {new BigInteger("0"), new BigInteger("1"), new BigInteger("9223372036854775805"), new BigInteger("9223372036854775806"), new BigInteger("9223372036854775807"), new BigInteger("9223372036854775808"), new BigInteger("9223372036854775809"), new BigInteger("18446744073709551615")}; writeRowsAndCompareValues(tid, values); } @Test public void decimal52Unsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, new SimpleColumn("c1", "MCOMPAT_ decimal unsigned", 5L, 2L)); Object[] values = array(new BigDecimal("0.00"), new BigDecimal("1.00"), new BigDecimal("499.99"), new BigDecimal("500.00"), new BigDecimal("999.99")); writeRowsAndCompareValues(tid, values); } @Test public void decimal2010Unsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, new SimpleColumn("c1", "MCOMPAT_ decimal unsigned", 20L, 10L)); Object[] values = array(new BigDecimal("0.0000000000"), new BigDecimal("1.0000000000"), new BigDecimal("4999999999.9999999999"), new BigDecimal("5000000000.0000000000"), new BigDecimal("9999999999.9999999999")); writeRowsAndCompareValues(tid, values); } @Test public void floatUnsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ float unsigned"); Object[] values = array(0.0f, 1.0f, Float.MAX_VALUE); writeRowsAndCompareValues(tid, values); } @Test public void doubleUnsigned() { int tid = createTableFromTypes(SCHEMA, TABLE, IS_PK, INDEXES, "MCOMPAT_ double unsigned"); Object[] values = array(0.0d, 1.0d, Double.MAX_VALUE); writeRowsAndCompareValues(tid, values); } }