diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index b8a55063d5..182b88ceac 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -1419,6 +1419,60 @@ public abstract class jOOQAbstractTest< assertEquals(new Timestamp(1), SQLDataType.TIMESTAMP.convert(new Timestamp(1))); } + @Test + public void testConversionResult() throws Exception { + assertEquals( + Arrays.asList((byte) 1, (byte) 2), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, Byte.class)); + assertEquals( + Arrays.asList((short) 1, (short) 2), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, Short.class)); + assertEquals( + Arrays.asList(1, 2), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, Integer.class)); + assertEquals( + Arrays.asList(1L, 2L), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, Long.class)); + assertEquals( + Arrays.asList(1.0f, 2.0f), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, Float.class)); + assertEquals( + Arrays.asList(1.0, 2.0), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, Double.class)); + assertEquals( + Arrays.asList(new BigInteger("1"), new BigInteger("2")), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, BigInteger.class)); + assertEquals( + Arrays.asList(new BigDecimal("1"), new BigDecimal("2")), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(0, BigDecimal.class)); + + + assertEquals( + Arrays.asList((byte) 1, (byte) 2), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), Byte.class)); + assertEquals( + Arrays.asList((short) 1, (short) 2), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), Short.class)); + assertEquals( + Arrays.asList(1, 2), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), Integer.class)); + assertEquals( + Arrays.asList(1L, 2L), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), Long.class)); + assertEquals( + Arrays.asList(1.0f, 2.0f), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), Float.class)); + assertEquals( + Arrays.asList(1.0, 2.0), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), Double.class)); + assertEquals( + Arrays.asList(new BigInteger("1"), new BigInteger("2")), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), BigInteger.class)); + assertEquals( + Arrays.asList(new BigDecimal("1"), new BigDecimal("2")), + create().selectFrom(TAuthor()).orderBy(TAuthor_ID()).fetch(TAuthor_ID().getName(), BigDecimal.class)); + } + @Test public void testForUpdateClauses() throws Exception { switch (getDialect()) { diff --git a/jOOQ/src/main/java/org/jooq/Result.java b/jOOQ/src/main/java/org/jooq/Result.java index 34700883fe..ede5852d52 100644 --- a/jOOQ/src/main/java/org/jooq/Result.java +++ b/jOOQ/src/main/java/org/jooq/Result.java @@ -1267,6 +1267,16 @@ public interface Result extends FieldProvider, List, Attach */ List getValues(int fieldIndex); + /** + * Convenience method to fetch all values for a given field. This is + * especially useful, when selecting only a single field. + * + * @param fieldIndex The values' field index + * @param type The type used for type conversion + * @return The values + */ + List getValues(int fieldIndex, Class type); + /** * Convenience method to fetch all values for a given field. This is * especially useful, when selecting only a single field. @@ -1276,6 +1286,16 @@ public interface Result extends FieldProvider, List, Attach */ List getValues(String fieldName); + /** + * Convenience method to fetch all values for a given field. This is + * especially useful, when selecting only a single field. + * + * @param fieldName The values' field name + * @param type The type used for type conversion + * @return The values + */ + List getValues(String fieldName, Class type); + /** * Convenience method to fetch all values for a given field. This is * especially useful, when selecting only a single field. diff --git a/jOOQ/src/main/java/org/jooq/ResultQuery.java b/jOOQ/src/main/java/org/jooq/ResultQuery.java index 3bf0fb6a34..e49e109820 100644 --- a/jOOQ/src/main/java/org/jooq/ResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/ResultQuery.java @@ -114,6 +114,17 @@ public interface ResultQuery extends Query { */ List fetch(int fieldIndex) throws SQLException; + /** + * Execute the query and return all values for a field index from the + * generated result. + *

+ * This is the same as calling {@link #fetch()} and then + * {@link Result#getValues(int, Class)} + * + * @return The resulting values. + */ + List fetch(int fieldIndex, Class type) throws SQLException; + /** * Execute the query and return all values for a field name from the * generated result. @@ -125,6 +136,17 @@ public interface ResultQuery extends Query { */ List fetch(String fieldName) throws SQLException; + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * This is the same as calling {@link #fetch()} and then + * {@link Result#getValues(String, Class)} + * + * @return The resulting values. + */ + List fetch(String fieldName, Class type) throws SQLException; + /** * Execute the query and return return at most one resulting value for a * field from the generated result. diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java index b0b1831599..e430d17ed0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java @@ -116,11 +116,21 @@ abstract class AbstractDelegatingSelect extends AbstractQueryP return query.fetch(fieldIndex); } + @Override + public final List fetch(int fieldIndex, Class type) throws SQLException { + return query.fetch(fieldIndex, type); + } + @Override public final List fetch(String fieldName) throws SQLException { return query.fetch(fieldName); } + @Override + public final List fetch(String fieldName, Class type) throws SQLException { + return query.fetch(fieldName, type); + } + @Override public final T fetchOne(Field field) throws SQLException { return query.fetchOne(field); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java index 5e6c855944..89178c4ba4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java @@ -155,11 +155,21 @@ abstract class AbstractResultQuery extends AbstractQuery imple return fetch().getValues(fieldIndex); } + @Override + public final List fetch(int fieldIndex, Class type) throws SQLException { + return fetch().getValues(fieldIndex, type); + } + @Override public final List fetch(String fieldName) throws SQLException { return fetch().getValues(fieldName); } + @Override + public final List fetch(String fieldName, Class type) throws SQLException { + return fetch().getValues(fieldName, type); + } + @Override public final T fetchOne(Field field) throws SQLException { R record = fetchOne(); diff --git a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java index bcec5a0777..1fdc5e313b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java @@ -630,11 +630,21 @@ class ResultImpl implements Result, AttachableInternal { return getValues(getField(fieldIndex)); } + @Override + public final List getValues(int fieldIndex, Class type) { + return TypeUtils.convert(getValues(fieldIndex), type); + } + @Override public final List getValues(String fieldName) { return getValues(getField(fieldName)); } + @Override + public final List getValues(String fieldName, Class type) { + return TypeUtils.convert(getValues(fieldName), type); + } + @Override public final List getValuesAsBigDecimal(Field field) { List result = new ArrayList(); diff --git a/jOOQ/src/main/java/org/jooq/impl/TypeUtils.java b/jOOQ/src/main/java/org/jooq/impl/TypeUtils.java index 26fcf12ca1..b75978f794 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TypeUtils.java +++ b/jOOQ/src/main/java/org/jooq/impl/TypeUtils.java @@ -41,8 +41,10 @@ import java.math.BigInteger; import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.jooq.SQLDialectNotSupportedException; @@ -77,7 +79,7 @@ final class TypeUtils { } @SuppressWarnings("unchecked") - public static Object[] convertArray(Object[] from, Class toClass) { + static Object[] convertArray(Object[] from, Class toClass) { if (from == null) { return null; } @@ -108,6 +110,52 @@ final class TypeUtils { } } + /** + * Convert an object to a type. These are the conversion rules: + *

    + *
  • null is always converted to null, + * regardless of the target type.
  • + *
  • Identity conversion is always possible
  • + *
  • All types can be converted to String
  • + *
  • All types can be converted to Object
  • + *
  • All Number types can be converted to other + * Number types
  • + *
  • All Number or String types can be converted + * to Boolean. Possible (case-insensitive) values for + * true: + *
      + *
    • 1
    • + *
    • y
    • + *
    • yes
    • + *
    • true
    • + *
    • on
    • + *
    • enabled
    • + *
    + *

    + * Possible (case-insensitive) values for false: + *

      + *
    • 0
    • + *
    • n
    • + *
    • no
    • + *
    • false
    • + *
    • off
    • + *
    • disabled
    • + *
    + *

    + * All other values evaluate to null

  • + *
  • All Date types can be converted into each other
  • + *
  • byte[] can be converted into String, using + * the platform's default charset
  • + *
  • Object[] can be converted into any other array type, if + * array elements can be converted, too
  • + *
  • All other combinations that are not listed above will result in an + * undisclosed unchecked exception.
  • + *
+ * + * @param from The object to convert + * @param toClass The target type + * @return The converted object + */ @SuppressWarnings("unchecked") public static T convert(Object from, Class toClass) { if (from == null) { @@ -190,5 +238,23 @@ final class TypeUtils { throw new SQLDialectNotSupportedException("Cannot convert from " + from + " to " + toClass); } + /** + * Convert a list of objects to a list of T, using + * {@link #convert(Object, Class)} + * + * @param list The list of objects + * @param type The target type + * @return The list of converted objects + */ + public static List convert(List list, Class type) { + List result = new ArrayList(); + + for (Object o : list) { + result.add(convert(o, type)); + } + + return result; + } + private TypeUtils() {} }