Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions api/src/org/labkey/api/data/ConvertHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;


/**
Expand Down Expand Up @@ -1266,6 +1267,72 @@ public void testTrim()
assertEquals(" x ", ConvertUtils.convert(" x "));
assertEquals(" x ", ConvertUtils.convert(" x ", String.class));
}

Exception ex(Callable c)
{
try
{
c.call();
return null;
}
catch (Exception x)
{
return x;
}
}

@Test
public void testNumber()
{
// fractions -> integer
assertTrue(ex(()->JdbcType.BIGINT.convert("5.0001")) instanceof ConversionException);
assertTrue(ex(()->JdbcType.BIGINT.convert(new BigDecimal("5.0001"))) instanceof ConversionException);
assertTrue(ex(()->JdbcType.BIGINT.convert(5.0001f)) instanceof ConversionException);
assertTrue(ex(()->JdbcType.BIGINT.convert(5.0001d)) instanceof ConversionException);
assertTrue(ex(()->JdbcType.BIGINT.convert(5.0001d)).getMessage().startsWith("Could not convert '"));

assertTrue(ex(()->JdbcType.INTEGER.convert("5.0001")) instanceof ConversionException);
assertTrue(ex(()->JdbcType.INTEGER.convert(new BigDecimal("5.0001"))) instanceof ConversionException);
assertTrue(ex(()->JdbcType.INTEGER.convert(5.0001f)) instanceof ConversionException);
assertTrue(ex(()->JdbcType.INTEGER.convert(5.0001d)) instanceof ConversionException);

assertTrue(ex(()->JdbcType.SMALLINT.convert("5.0001")) instanceof ConversionException);
assertTrue(ex(()->JdbcType.SMALLINT.convert(new BigDecimal("5.0001"))) instanceof ConversionException);
assertTrue(ex(()->JdbcType.SMALLINT.convert(5.0001f)) instanceof ConversionException);
assertTrue(ex(()->JdbcType.SMALLINT.convert(5.0001d)) instanceof ConversionException);

assertTrue(ex(()->PropertyType.BIGINT.convert("5.0001")) instanceof ConversionException);
assertTrue(ex(()->PropertyType.BIGINT.convert(new BigDecimal("5.0001"))) instanceof ConversionException);
assertTrue(ex(()->PropertyType.BIGINT.convert(5.0001f)) instanceof ConversionException);
assertTrue(ex(()->PropertyType.BIGINT.convert(5.0001d)) instanceof ConversionException);
assertTrue(ex(()->PropertyType.BIGINT.convert(5.0001d)).getMessage().startsWith("Could not convert '"));

assertTrue(ex(()->PropertyType.INTEGER.convert("5.0001")) instanceof ConversionException);
assertTrue(ex(()->PropertyType.INTEGER.convert(new BigDecimal("5.0001"))) instanceof ConversionException);
assertTrue(ex(()->PropertyType.INTEGER.convert(5.0001f)) instanceof ConversionException);
assertTrue(ex(()->PropertyType.INTEGER.convert(5.0001d)) instanceof ConversionException);

assertTrue(ex(()->ConvertUtils.convert("5.0001", Long.class)) instanceof ConversionException);
assertTrue(ex(()->ConvertUtils.convert(new BigDecimal("5.0001"), Long.class)) instanceof ConversionException);
assertTrue(ex(()->ConvertUtils.convert(5.0001f, Long.class)) instanceof ConversionException);
assertTrue(ex(()->ConvertUtils.convert(5.0001d, Long.class)) instanceof ConversionException);
assertTrue(ex(()->ConvertUtils.convert(5.0001d)).getMessage().startsWith("Could not convert '"));

// OOR
assertTrue(ex(()->JdbcType.TINYINT.convert(Long.MAX_VALUE)) instanceof ConversionException);
assertTrue(ex(()->JdbcType.TINYINT.convert(10_000_000_000d)) instanceof ConversionException);
assertTrue(ex(()->JdbcType.TINYINT.convert("10000000000")) instanceof ConversionException);
assertTrue(ex(()->PropertyType.INTEGER.convert(Long.MAX_VALUE)) instanceof ConversionException);
assertTrue(ex(()->PropertyType.INTEGER.convert(10_000_000_000d)) instanceof ConversionException);
assertTrue(ex(()->PropertyType.INTEGER.convert("10000000000")) instanceof ConversionException);
assertTrue(ex(()->ConvertUtils.convert(10_000_000_000d, Short.class)) instanceof ConversionException);
assertTrue(ex(()->ConvertUtils.convert("10000000000", Short.class)) instanceof ConversionException);
assertEquals(Long.MAX_VALUE, ConvertUtils.convert(BigDecimal.valueOf(Long.MAX_VALUE), Long.class));
assertEquals(Long.MIN_VALUE, ConvertUtils.convert(BigDecimal.valueOf(Long.MIN_VALUE), Long.class));
// precision of Double is not high enough for this equality test to work for any random integer this large
assertEquals(Long.MAX_VALUE, ConvertUtils.convert(Double.valueOf(Long.MAX_VALUE), Long.class));
assertEquals(Long.MIN_VALUE, ConvertUtils.convert(Double.valueOf(Long.MIN_VALUE), Long.class));
}
}

// Note: Keep in sync with LabKeySiteWrapper.getConversionErrorMessage()
Expand Down
15 changes: 11 additions & 4 deletions api/src/org/labkey/api/data/JdbcType.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public enum JdbcType
@Override
protected Object _fromNumber(Number n)
{
return n.longValue();
return _toLong(n);
}

@Override
Expand Down Expand Up @@ -605,23 +605,30 @@ private static Boolean _toBoolean(Number n)
return Boolean.FALSE;
if (1 == n.intValue())
return Boolean.TRUE;

throw new ConversionException("Expected boolean value");
}

private static Long _toLong(Number n)
{
if (n instanceof Long l)
return l;
if (!(n instanceof BigDecimal) && n.doubleValue() == (double)n.longValue())
return n.longValue();
return ConvertHelper.convert(n, Long.class);
}

private static Integer _toInt(Number n)
{
if (n.doubleValue() != (double)n.intValue())
throw new ConversionException("Expected integer value");
throw new ConversionException("Could not convert '" + n + "' to an integer");
return n.intValue();
}


private static Short _toShort(Number n)
{
if (n.doubleValue() != (double)n.shortValue())
throw new ConversionException("Expected integer value");
throw new ConversionException("Could not convert '" + n + "' to a short integer");
return n.shortValue();
}

Expand Down