[#2007] Bad type coercion on the right hand side of a comparison

predicate, when the left hand side is Field<Object>
This commit is contained in:
Lukas Eder 2012-12-22 09:47:01 +01:00
parent 8b6e4f2a27
commit f958e32075
2 changed files with 127 additions and 1 deletions

View File

@ -6801,10 +6801,38 @@ public class Factory {
// The default behaviour
else {
return new Val<T>(type.convert(value), type);
T converted = type.convert(value);
return new Val<T>(converted, mostSpecific(converted, type));
}
}
/**
* Get the "most specific" data type between a concrete value and an actual
* coercion data type
* <p>
* [#2007] When coercing a (previously converted) value to a type, it may be that
* the type is still more general than the actual type. This is typically
* the case when <code>dataType == SQLDataType.OTHER</code>, i.e. when
* <code>dataType.getType() == Object.class</code>. In that case, it is wise
* to keep the additional type information of the <code>value</code>
*
* @param value The value
* @param dataType The coercion data type
* @return The most specific data type
*/
private static <T> DataType<T> mostSpecific(T value, DataType<T> dataType) {
if (value != null) {
Class<?> valueType = value.getClass();
Class<T> coercionType = dataType.getType();
if (valueType != coercionType && coercionType.isAssignableFrom(valueType)) {
return (DataType<T>) DefaultDataType.getDataType(null, valueType);
}
}
return dataType;
}
/**
* Get a list of bind values and fields
*/

View File

@ -38,11 +38,18 @@ package org.jooq.test;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.jooq.impl.Factory.fieldByName;
import java.sql.Timestamp;
import org.jooq.Condition;
import org.jooq.Field;
import org.jooq.test.data.Table1;
import org.jooq.types.DayToSecond;
import org.jooq.types.Interval;
import org.jooq.types.YearToMonth;
import org.jmock.Expectations;
import org.junit.Test;
@ -53,6 +60,97 @@ import org.junit.Test;
*/
public class DataTypeTest extends AbstractTest {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void testComparisonPredicateTypeCoercion() throws Exception {
// This test checks whether automatic type coercion works well for
// comparison predicates
Field integer = Table1.FIELD_ID1;
Field string = Table1.FIELD_NAME1;
Field object = fieldByName("ANY");
// Check if a correct type was coerced correctly
// ---------------------------------------------
{
Condition int_int = integer.eq(1);
assertEquals("\"TABLE1\".\"ID1\" = 1", r_refI().render(int_int));
context.checking(new Expectations() {{
oneOf(statement).setInt(1, 1);
}});
assertEquals(2, b_ref().bind(int_int).peekIndex());
context.assertIsSatisfied();
}
{
Condition string_string = string.eq("1");
assertEquals("\"TABLE1\".\"NAME1\" = '1'", r_refI().render(string_string));
context.checking(new Expectations() {{
oneOf(statement).setString(1, "1");
}});
assertEquals(2, b_ref().bind(string_string).peekIndex());
context.assertIsSatisfied();
}
// Check if a convertible type was coerced correctly
// -------------------------------------------------
{
Condition int_string = integer.eq("1");
assertEquals("\"TABLE1\".\"ID1\" = 1", r_refI().render(int_string));
context.checking(new Expectations() {{
oneOf(statement).setInt(1, 1);
}});
assertEquals(2, b_ref().bind(int_string).peekIndex());
context.assertIsSatisfied();
Condition string_int = string.eq(1);
assertEquals("\"TABLE1\".\"NAME1\" = '1'", r_refI().render(string_int));
context.checking(new Expectations() {{
oneOf(statement).setString(1, "1");
}});
assertEquals(2, b_ref().bind(string_int).peekIndex());
context.assertIsSatisfied();
}
// Check if ...
// ------------
{
Condition object_int = object.eq(1);
assertEquals("\"ANY\" = 1", r_refI().render(object_int));
context.checking(new Expectations() {{
oneOf(statement).setInt(1, 1);
}});
assertEquals(2, b_ref().bind(object_int).peekIndex());
context.assertIsSatisfied();
}
{
Condition object_string = object.eq("1");
assertEquals("\"ANY\" = '1'", r_refI().render(object_string));
context.checking(new Expectations() {{
oneOf(statement).setString(1, "1");
}});
assertEquals(2, b_ref().bind(object_string).peekIndex());
context.assertIsSatisfied();
}
{
Condition object_date = object.eq(Timestamp.valueOf("2012-12-21 15:30:00.0"));
assertEquals("\"ANY\" = timestamp '2012-12-21 15:30:00.0'", r_refI().render(object_date));
context.checking(new Expectations() {{
oneOf(statement).setTimestamp(1, Timestamp.valueOf("2012-12-21 15:30:00.0"));
}});
assertEquals(2, b_ref().bind(object_date).peekIndex());
context.assertIsSatisfied();
}
}
@Test
public void testYearToMonth() {