Skip to content
Draft
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
69 changes: 68 additions & 1 deletion api/src/org/labkey/api/data/ConvertHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;


/**
Expand Down Expand Up @@ -1371,9 +1372,75 @@ public void testMiscConversions()
assertEquals(home.getRowId(), ((Container)ConvertUtils.convert(home.getId(), Container.class)).getRowId());
assertEquals(home.getId(), ConvertUtils.convert(home, 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()
// Note: Keep in sync with LabKeySiteWrapper.getConversionErrorMessage()
// Example: "Could not convert value '2.34' (Double) for Boolean field 'Medical History.Dep Diagnosed in Last 18 Months'"
public static String getStandardConversionErrorMessage(Object value, String fieldName, Class<?> expectedClass)
{
Expand Down
17 changes: 11 additions & 6 deletions api/src/org/labkey/api/data/JdbcType.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ public enum JdbcType implements SimpleConvert
@Override
protected Object _fromNumber(Number n)
{
if (n.doubleValue() == (double) n.longValue())
return n.longValue();
return null; // fallback
return _toLong(n);
}

@Override
Expand Down Expand Up @@ -730,23 +728,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