From: <mro...@us...> - 2012-08-12 18:01:00
|
Revision: 57031 http://firebird.svn.sourceforge.net/firebird/?rev=57031&view=rev Author: mrotteveel Date: 2012-08-12 18:00:53 +0000 (Sun, 12 Aug 2012) Log Message: ----------- * Code cleanup of FBBigDecimalField * Add unit tests for FBBigDecimalField * Treat DECIMAL fields as DECIMAL instead of NUMERIC Modified Paths: -------------- client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBBigDecimalField.java client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBField.java client-java/trunk/src/test/org/firebirdsql/jdbc/field/TestFBBigDecimalField.java Modified: client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBBigDecimalField.java =================================================================== --- client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBBigDecimalField.java 2012-08-12 09:52:36 UTC (rev 57030) +++ client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBBigDecimalField.java 2012-08-12 18:00:53 UTC (rev 57031) @@ -19,6 +19,7 @@ package org.firebirdsql.jdbc.field; +import org.firebirdsql.gds.ISCConstants; import org.firebirdsql.gds.XSQLVAR; import java.sql.SQLException; @@ -42,13 +43,15 @@ private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE); - private int fieldType = 0; // 1.- Short, 2.- Integer, 3.- Long + private final FieldDataSize fieldDataSize; - FBBigDecimalField(XSQLVAR field, FieldDataProvider dataProvider, int fieldType, - int requiredType) throws SQLException + FBBigDecimalField(XSQLVAR field, FieldDataProvider dataProvider, int requiredType) throws SQLException { super(field, dataProvider, requiredType); - this.fieldType = fieldType; + fieldDataSize = FieldDataSize.getFieldDataSize(field); + if (fieldDataSize == null) { + throw new SQLException("FBBigDecimal, unsupported field sqltype: " + field.sqltype); + } } public boolean getBoolean() throws SQLException { @@ -71,8 +74,6 @@ } public double getDouble() throws SQLException { - if (getFieldData()==null) return DOUBLE_NULL_VALUE; - BigDecimal value = getBigDecimal(); if (value == BIGDECIMAL_NULL_VALUE) @@ -82,18 +83,12 @@ } public float getFloat() throws SQLException { - if (getFieldData()==null) return FLOAT_NULL_VALUE; - - double value = getDouble(); - - float cValue = (float) value; - // check if value is within bounds - if (cValue == Float.POSITIVE_INFINITY || - cValue == Float.NEGATIVE_INFINITY) - throw (SQLException)createException( - FLOAT_CONVERSION_ERROR + " " + value).fillInStackTrace(); - - return cValue; + BigDecimal value = getBigDecimal(); + + if (value == BIGDECIMAL_NULL_VALUE) + return FLOAT_NULL_VALUE; + + return value.floatValue(); } public int getInt() throws SQLException { @@ -140,8 +135,6 @@ } public String getString() throws SQLException { - if (getFieldData()==null) return STRING_NULL_VALUE; - BigDecimal value = getBigDecimal(); if (value == BIGDECIMAL_NULL_VALUE) @@ -153,21 +146,7 @@ public BigDecimal getBigDecimal() throws SQLException { if (getFieldData()==null) return BIGDECIMAL_NULL_VALUE; - long longValue; - - if (fieldType==2) - longValue = field.decodeInt(getFieldData()); - else - if (fieldType==3) - longValue = field.decodeLong(getFieldData()); - else - if (fieldType==1) - longValue = field.decodeShort(getFieldData()); - else - throw (SQLException)createException( - BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); - - return BigDecimal.valueOf(longValue, -field.sqlscale); + return fieldDataSize.decode(field, getFieldData()); } //--- setXXX methods @@ -181,7 +160,7 @@ } public void setDouble(double value) throws SQLException { - setBigDecimal(new BigDecimal(Double.toString(value))); + setBigDecimal(BigDecimal.valueOf(value)); } public void setFloat(float value) throws SQLException { @@ -219,42 +198,113 @@ setNull(); return; } - - value = value.setScale(-field.sqlscale, BigDecimal.ROUND_HALF_UP); - if (fieldType == 1) { + setFieldData(fieldDataSize.encode(field, value)); + } + + /** + * Enum for handling the different fielddata sizes of NUMERIC/DECIMAL fields. + * + * @author <a href="mailto:mro...@us...">Mark Rotteveel</a> + */ + private enum FieldDataSize { + SHORT { + @Override + protected BigDecimal decode(final XSQLVAR field, final byte[] fieldData) { + long value = field.decodeShort(fieldData); + return BigDecimal.valueOf(value, -field.sqlscale); + } - // check if value is within bounds - if (value.unscaledValue().compareTo(MAX_SHORT) > 0 || - value.unscaledValue().compareTo(MIN_SHORT) < 0) - throw (SQLException)createException( - BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); + @Override + protected byte[] encode(final XSQLVAR field, final BigDecimal value) throws SQLException { + BigInteger unscaledValue = normalize(value, -field.sqlscale); + if (unscaledValue.compareTo(MAX_SHORT) > 0 || unscaledValue.compareTo(MIN_SHORT) < 0) { + throw (SQLException)createException(BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); + } + return field.encodeShort(unscaledValue.shortValue()); + } + }, + INTEGER { + @Override + protected BigDecimal decode(final XSQLVAR field, final byte[] fieldData) { + long value = field.decodeInt(fieldData); + return BigDecimal.valueOf(value, -field.sqlscale); + } - setFieldData(field.encodeShort(value.unscaledValue().shortValue())); - } else - if (fieldType == 2) { + @Override + protected byte[] encode(final XSQLVAR field, final BigDecimal value) throws SQLException { + BigInteger unscaledValue = normalize(value, -field.sqlscale); + if (unscaledValue.compareTo(MAX_INT) > 0 || unscaledValue.compareTo(MIN_INT) < 0) { + throw (SQLException)createException(BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); + } + return field.encodeInt(unscaledValue.intValue()); + } + }, + LONG { + @Override + protected BigDecimal decode(final XSQLVAR field, final byte[] fieldData) { + long value = field.decodeLong(fieldData); + return BigDecimal.valueOf(value, -field.sqlscale); + } - // check if value is within bounds - if (value.unscaledValue().compareTo(MAX_INT) > 0 || - value.unscaledValue().compareTo(MIN_INT) < 0) - throw (SQLException)createException( - BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); + @Override + protected byte[] encode(final XSQLVAR field, final BigDecimal value) throws SQLException { + BigInteger unscaledValue = normalize(value, -field.sqlscale); + if (unscaledValue.compareTo(MAX_LONG) > 0 || unscaledValue.compareTo(MIN_LONG) < 0) { + throw (SQLException)createException(BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); + } + return field.encodeLong(unscaledValue.longValue()); + } + }; + + /** + * Decodes the provided fieldData to a BigDecimal + * + * @param field XSQLVAR field instance + * @param fieldData encoded data + * @return BigDecimal instance + */ + protected abstract BigDecimal decode(final XSQLVAR field, final byte[] fieldData); - setFieldData(field.encodeInt(value.unscaledValue().intValue())); - } else - if (fieldType == 3) { - - // check if value is within bounds - if (value.unscaledValue().compareTo(MAX_LONG) > 0 || - value.unscaledValue().compareTo(MIN_LONG) < 0) - throw (SQLException)createException( - BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); - - setFieldData(field.encodeLong(value.unscaledValue().longValue())); - } else - throw (SQLException)createException( - BIGDECIMAL_CONVERSION_ERROR).fillInStackTrace(); - + /** + * Encodes the provided BigDecimal to fieldData + * @param field XSQLVAR field instance + * @param value BigDecimal instance + * @return encoded data + * @throws SQLException + */ + protected abstract byte[] encode(final XSQLVAR field, final BigDecimal value) throws SQLException; + + /** + * Helper method to rescale the BigDecimal to the provided scale and return the unscaled value of + * the resulting BigDecimal. + * + * @param value BigDecimal instance + * @param scale Required scale + * @return Unscaled value of the rescaled BigDecimal + */ + private static BigInteger normalize(final BigDecimal value, final int scale) { + BigDecimal valueToScale = value.setScale(scale, BigDecimal.ROUND_HALF_UP); + return valueToScale.unscaledValue(); + } + + /** + * Returns the FieldDataSize instance for the provided field. + * @param field XSQLVAR field instance + * @return FieldDataSize for the field, or null if none match + */ + protected static FieldDataSize getFieldDataSize(XSQLVAR field) { + switch (field.sqltype & ~1) { + case ISCConstants.SQL_SHORT: + return SHORT; + case ISCConstants.SQL_LONG: + return INTEGER; + case ISCConstants.SQL_INT64: + return LONG; + default: + return null; + } + } } } Modified: client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBField.java =================================================================== --- client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBField.java 2012-08-12 09:52:36 UTC (rev 57030) +++ client-java/trunk/src/main/org/firebirdsql/jdbc/field/FBField.java 2012-08-12 18:00:53 UTC (rev 57031) @@ -364,19 +364,19 @@ if (field.sqlscale == 0) return new FBShortField(field, dataProvider, Types.SMALLINT); else - return new FBBigDecimalField(field, dataProvider, 1, Types.NUMERIC); + return new FBBigDecimalField(field, dataProvider, field.sqlsubtype == 2 ? Types.DECIMAL : Types.NUMERIC); else if (isType(field, Types.INTEGER)) if (field.sqlscale == 0) return new FBIntegerField(field, dataProvider, Types.INTEGER); else - return new FBBigDecimalField(field, dataProvider,2, Types.NUMERIC); + return new FBBigDecimalField(field, dataProvider, field.sqlsubtype == 2 ? Types.DECIMAL : Types.NUMERIC); else if (isType(field, Types.BIGINT)) if (field.sqlscale == 0) return new FBLongField(field, dataProvider, Types.BIGINT); else - return new FBBigDecimalField(field, dataProvider,3, Types.NUMERIC); + return new FBBigDecimalField(field, dataProvider, field.sqlsubtype == 2 ? Types.DECIMAL : Types.NUMERIC); else if (isType(field, Types.FLOAT)) return new FBFloatField(field, dataProvider, Types.FLOAT); Modified: client-java/trunk/src/test/org/firebirdsql/jdbc/field/TestFBBigDecimalField.java =================================================================== --- client-java/trunk/src/test/org/firebirdsql/jdbc/field/TestFBBigDecimalField.java 2012-08-12 09:52:36 UTC (rev 57030) +++ client-java/trunk/src/test/org/firebirdsql/jdbc/field/TestFBBigDecimalField.java 2012-08-12 18:00:53 UTC (rev 57031) @@ -18,66 +18,646 @@ */ package org.firebirdsql.jdbc.field; +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.math.BigInteger; import java.sql.SQLException; +import java.sql.Types; import org.firebirdsql.gds.ISCConstants; import org.firebirdsql.gds.XSQLVAR; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.integration.junit4.JMock; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; - -public class TestFBBigDecimalField extends BaseTestFBField { - - public TestFBBigDecimalField(String testName) { - super(testName); +/** + * Tests for {@link FBBigDecimalField} + */ +@RunWith(JMock.class) +public class TestFBBigDecimalField { + Mockery context = new JUnit4Mockery(); + + private FieldDataProvider fieldData; + + @Before + public void setUp() { + fieldData = context.mock(FieldDataProvider.class); } + + // TODO Add set<PrimitiveNumber> tests for out of range condition; in current implementation duplicates setBigDecimal out of range tests + // TODO Add tests for unsupported conversions + // TODO Add set/getObject test - protected void setUp() throws SQLException{ - final XSQLVAR[] xsqlvars = new XSQLVAR[1]; - xsqlvars[0] = createXSQLVAR(); - xsqlvars[0].sqltype = ISCConstants.SQL_INT64; + @Test + public void getBigDecimalNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -2; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); - field = FBField.createField(xsqlvars[0], createDataProvider(xsqlvars), null, false); + assertNull("Expected null result", field.getBigDecimal()); } - protected void tearDown() { + + @Test + public void getBigDecimalShort() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeShort((short) 231))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + BigDecimal expectedValue = new BigDecimal("23.1"); + assertEquals(expectedValue, field.getBigDecimal()); } - - public void testDouble() throws SQLException { + @Test + public void getBigDecimalInteger() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -4; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeInt(34))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + BigDecimal expectedValue = new BigDecimal("0.0034"); + assertEquals(expectedValue, field.getBigDecimal()); } - - public void testFloat() throws SQLException { + + @Test + public void getBigDecimalLong() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -8; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong(51300000000L))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + BigDecimal expectedValue = new BigDecimal("513.00000000"); + assertEquals(expectedValue, field.getBigDecimal()); } - - public void testBigDecimal() throws SQLException { + + @Test + public void setBigDecimalShort() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeShort((short)4320)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + // TODO Might need to add separate test for the rescaling applied here + field.setBigDecimal(new BigDecimal("43.2")); } - - public void testObject() throws SQLException { + + @Test(expected = TypeConversionException.class) + public void setBigDecimalShortTooHigh() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + xsqlvar.sqlscale = -2; + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(BigDecimal.valueOf(Short.MAX_VALUE + 1, 2)); } - - public void testString() throws SQLException { + + @Test(expected = TypeConversionException.class) + public void setBigDecimalShortTooLow() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + xsqlvar.sqlscale = -2; + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(BigDecimal.valueOf(Short.MIN_VALUE - 1, 2)); } - - public void testAsciiStream() throws SQLException { + + @Test + public void setBigDecimalShortNull() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + xsqlvar.sqlscale = -1; + setNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(null); } - - public void testBinaryStream() throws SQLException { + + @Test + public void setBigDecimalInteger() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -3; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeInt(1234567)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(new BigDecimal("1234.567")); } - - public void testBoolean() throws SQLException { + + @Test(expected = TypeConversionException.class) + public void setBigDecimalIntegerTooHigh() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -2; + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(BigDecimal.valueOf(Integer.MAX_VALUE + 1L, 2)); } - - public void testBytes() throws SQLException { + + @Test(expected = TypeConversionException.class) + public void setBigDecimalIntegerTooLow() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -2; + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(BigDecimal.valueOf(Integer.MIN_VALUE - 1L, 2)); } - - public void testDate() throws SQLException { + + @Test + public void setBigDecimalIntegerNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + setNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(null); } - - public void testTime() throws SQLException { + + @Test + public void setBigDecimalLong() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -5; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeLong(1234567890123L)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(new BigDecimal("12345678.90123")); } - - public void testTimestamp() throws SQLException { + + @Test(expected = TypeConversionException.class) + public void setBigDecimalLongTooHigh() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + BigInteger value = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); + field.setBigDecimal(new BigDecimal(value, 2)); } + + @Test(expected = TypeConversionException.class) + public void setBigDecimalLongTooLow() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + BigInteger value = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE); + field.setBigDecimal(new BigDecimal(value, 2)); + } + + @Test + public void setBigDecimalLongNull() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -1; + setNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBigDecimal(null); + } + + @Test + public void getBooleanTrue() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + // NOTE: We could use 0 for the test, but in that case Jaybird would not have create a FBBigDecimalField + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeShort((short)10))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertTrue("Expected true from getBoolean", field.getBoolean()); + } + + @Test + public void getBooleanFalse() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + // NOTE: We could use 0 for the test, but in that case Jaybird would not have create a FBBigDecimalField + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + // NOTE Any value other than 10 would do + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeShort((short)0))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertFalse("Expected false from getBoolean", field.getBoolean()); + } + + @Test + public void setBooleanTrue() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + // NOTE: We could use 0 for the test, but in that case Jaybird would not have create a FBBigDecimalField + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeShort((short)10)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBoolean(true); + } + + @Test + public void setBooleanFalse() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + // NOTE: We could use 0 for the test, but in that case Jaybird would not have create a FBBigDecimalField + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeShort((short)0)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setBoolean(false); + } + + @Test + public void getByteNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -6; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Expected getByte() to return 0 for NULL value", 0, field.getByte()); + } + + @Test + public void getByte() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeInt(Byte.MIN_VALUE * 100))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Unexpected value for getByte()", Byte.MIN_VALUE, field.getByte()); + } + + @Test(expected = TypeConversionException.class) + public void getByteTooHigh() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeInt((Byte.MAX_VALUE + 1)* 100))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.getByte(); + } + + @Test(expected = TypeConversionException.class) + public void getByteTooLow() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeInt((Byte.MIN_VALUE - 1)* 100))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.getByte(); + } + + @Test + public void setByte() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -7; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeLong(-340000000L)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setByte((byte) -34); + } + + @Test + public void getDoubleNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -6; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Expected getDouble() to return 0.0 for NULL value", 0.0, field.getDouble(), 0.0); + } + + @Test + public void getDouble() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong(Long.MIN_VALUE))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Unexpected value for getDouble()", Long.MIN_VALUE / 100.0, field.getDouble(), 0.0); + } + + @Test + public void setDouble() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeShort((short)4691)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setDouble(469.1234567); + } + + @Test + public void getFloatNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -6; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Expected getFloat() to return 0.0 for NULL value", 0.0, field.getFloat(), 0.0); + } + + @Test + public void getFloat() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong(Long.MAX_VALUE))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Unexpected value for getFloat()", Long.MAX_VALUE / 100.0f, field.getFloat(), 0.0); + } + + @Test + public void setFloat() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -5; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeLong(46912344L)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); - public void testUnicodeStream() throws SQLException { + field.setFloat(469.1234567f); } + @Test + public void getIntNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Expected getInt() to return 0 for NULL value", 0, field.getInt()); + } + + @Test + public void getInt() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -6; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong(987654321098765L))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Unexpected value from getInt()", 987654321, field.getInt()); + } + + @Test(expected = TypeConversionException.class) + public void getIntTooHigh() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong((Integer.MAX_VALUE + 1L) * 100))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.getInt(); + } + + @Test(expected = TypeConversionException.class) + public void getIntTooLow() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong((Integer.MIN_VALUE - 1L) * 100))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.getInt(); + } + + @Test + public void setInteger() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeInt(1234560)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setInteger(123456); + } + + @Test + public void getLongNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Expected getLong() to return 0 for NULL value", 0, field.getLong()); + } + + @Test + public void getLong() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong(Long.MAX_VALUE))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Unexpected value from getLong()", Long.MAX_VALUE / 100, field.getLong()); + } + + @Test + public void setLong() throws SQLException { + final XSQLVAR xsqlvar = createShortXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeShort((short)3500)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setLong(35); + } + + @Test + public void setNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + setNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setNull(); + } + + @Test + public void getShortNull() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -1; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Expected getShort() to return 0 for NULL value", 0, field.getShort()); + } + + @Test + public void getShort() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -4; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeInt(123456789))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Unexpected value from getShort()", 12345, field.getShort()); + } + + @Test(expected = TypeConversionException.class) + public void getShortTooHigh() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeInt((Short.MAX_VALUE + 1) * 100))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.getShort(); + } + + @Test(expected = TypeConversionException.class) + public void getShortTooLow() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeInt((Short.MIN_VALUE - 1) * 100))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.getShort(); + } + + @Test + public void setShort() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -3; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeLong(Short.MIN_VALUE * 1000L)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setShort(Short.MIN_VALUE); + } + + @Test + public void getStringNull() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -1; + toReturnNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertNull(field.getString()); + } + + @Test + public void getString() throws SQLException { + final XSQLVAR xsqlvar = createLongXSQLVAR(); + xsqlvar.sqlscale = -2; + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(xsqlvar.encodeLong(456789123))); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + assertEquals("Unexpected value from getString()", "4567891.23", field.getString()); + } + + @Test + public void setString() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + context.checking(new Expectations() {{ + oneOf(fieldData).setFieldData(xsqlvar.encodeInt(789123)); + }}); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setString("78912.3456"); + } + + @Test + public void setStringNull() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + setNullExpectations(); + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setString(null); + } + + @Test(expected = TypeConversionException.class) + public void setStringNonNumber() throws SQLException { + final XSQLVAR xsqlvar = createIntegerXSQLVAR(); + xsqlvar.sqlscale = -1; + FBBigDecimalField field = new FBBigDecimalField(xsqlvar, fieldData, Types.NUMERIC); + + field.setString("NotANumber"); + } + + @Test(expected = SQLException.class) + public void constructWithUnsupportedSqlType() throws SQLException { + final XSQLVAR xsqlvar = new XSQLVAR(); + xsqlvar.sqltype = ISCConstants.SQL_VARYING; + + new FBBigDecimalField(xsqlvar, fieldData, Types.VARCHAR); + } + + /** + * Expectations to return null from fieldData. + */ + private void toReturnNullExpectations() { + context.checking(new Expectations() {{ + atLeast(1).of(fieldData).getFieldData(); will(returnValue(null)); + }}); + } + + /** + * Expectations for setting field to null + */ + private void setNullExpectations() { + context.checking(new Expectations() {{ + one(fieldData).setFieldData(null); + }}); + } + + private static XSQLVAR createShortXSQLVAR() { + XSQLVAR xsqlvar = new XSQLVAR(); + xsqlvar.sqltype = ISCConstants.SQL_SHORT; + return xsqlvar; + } + + private static XSQLVAR createIntegerXSQLVAR() { + XSQLVAR xsqlvar = new XSQLVAR(); + xsqlvar.sqltype = ISCConstants.SQL_LONG; + return xsqlvar; + } + + private static XSQLVAR createLongXSQLVAR() { + XSQLVAR xsqlvar = new XSQLVAR(); + xsqlvar.sqltype = ISCConstants.SQL_INT64; + return xsqlvar; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |