diff --git a/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java b/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java index 6908d519d7..d16888055a 100644 --- a/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java +++ b/jOOQ-test/src/org/jooq/test/_/testcases/FetchTests.java @@ -213,6 +213,32 @@ extends BaseTest Value Map + // ---------------- + + // Grouping by BOOK.ID + Map> map3 = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchGroups(TBook_ID(), TBook_TITLE()); + ArrayList> map3Values = new ArrayList>(map3.values()); + + assertEquals(4, map3.size()); + assertEquals(BOOK_IDS, new ArrayList(map3.keySet())); + for (int i = 0; i < 4; i++) { + assertEquals(1, map3Values.get(i).size()); + assertEquals(BOOK_TITLES.get(i), map3Values.get(i).get(0)); + } + + // Grouping by BOOK.AUTHOR_ID + Map> map4 = create().selectFrom(TBook()).orderBy(TBook_ID()).fetchGroups(TBook_AUTHOR_ID(), TBook_TITLE()); + ArrayList> map4Values = new ArrayList>(map4.values()); + + assertEquals(2, map4.size()); + assertEquals(AUTHOR_IDS, new ArrayList(map4.keySet())); + for (int i = 0; i < 2; i++) { + assertEquals(2, map4Values.get(i).size()); + assertEquals(BOOK_TITLES.get(i * 2 + 0), map4Values.get(i).get(0)); + assertEquals(BOOK_TITLES.get(i * 2 + 1), map4Values.get(i).get(1)); + } } @Test diff --git a/jOOQ/src/main/java/org/jooq/Result.java b/jOOQ/src/main/java/org/jooq/Result.java index 7cb5441431..4c83668912 100644 --- a/jOOQ/src/main/java/org/jooq/Result.java +++ b/jOOQ/src/main/java/org/jooq/Result.java @@ -1819,7 +1819,8 @@ public interface Result extends FieldProvider, List, Attach * one of the result's columns as value *

* An {@link InvalidResultException} is thrown, if the key turns out to be - * non-unique in the result set. + * non-unique in the result set. Use {@link #intoGroups(Field, Field)} + * instead, if your keys are non-unique * * @param The key's generic field type * @param The value's generic field type @@ -1845,6 +1846,21 @@ public interface Result extends FieldProvider, List, Attach */ Map> intoGroups(Field key); + /** + * Return a {@link Map} with one of the result's columns as key and another + * one of the result's columns as value + *

+ * Unlike {@link #intoMap(Field, Field)}, this method allows for non-unique + * keys in the result set. + * + * @param The key's generic field type + * @param The value's generic field type + * @param key The key field. + * @param value The value field + * @return A Map containing the results + */ + Map> intoGroups(Field key, Field value); + /** * Convert this result into an array of arrays *

diff --git a/jOOQ/src/main/java/org/jooq/ResultQuery.java b/jOOQ/src/main/java/org/jooq/ResultQuery.java index b22736ce90..20bc85c4ec 100644 --- a/jOOQ/src/main/java/org/jooq/ResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/ResultQuery.java @@ -485,7 +485,8 @@ public interface ResultQuery extends Query { * columns as key and another one of the result's columns as value *

* An exception is thrown, if the key turns out to be non-unique in the - * result set. + * result set. Use {@link #fetchGroups(Field, Field)} instead, if your keys + * are non-unique * * @param The key's generic field type * @param The value's generic field type @@ -519,6 +520,23 @@ public interface ResultQuery extends Query { */ Map> fetchGroups(Field key) throws DataAccessException; + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and another one of the result's columns as value + *

+ * Unlike {@link #fetchMap(Field, Field)}, this method allows for non-unique + * keys in the result set. + * + * @param The key's generic field type + * @param The value's generic field type + * @param key The key field. + * @param value The value field + * @return A Map containing the results + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Field, Field) + */ + Map> fetchGroups(Field key, Field value) throws DataAccessException; + /** * Execute the query and return the generated result as an Object matrix *

diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java index 898277265a..0a3832ae09 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingSelect.java @@ -242,6 +242,11 @@ abstract class AbstractDelegatingSelect return getDelegate().fetchGroups(key); } + @Override + public final Map> fetchGroups(Field key, Field value) { + return getDelegate().fetchGroups(key, value); + } + @Override public final Object[][] fetchArrays() { return getDelegate().fetchArrays(); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java index 70e202a896..f6d1c5bbc4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java @@ -432,6 +432,11 @@ abstract class AbstractResultQuery extends AbstractQuery imple return fetch().intoGroups(key); } + @Override + public final Map> fetchGroups(Field key, Field value) { + return fetch().intoGroups(key, value); + } + @Override public final Object[][] fetchArrays() { return fetch().intoArray(); diff --git a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java index 65859a09d0..05f60f873a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java @@ -1319,12 +1319,12 @@ class ResultImpl implements Result, AttachableInternal { Map> map = new LinkedHashMap>(); for (R record : this) { - K value = record.getValue(key); - Result result = map.get(value); + K val = record.getValue(key); + Result result = map.get(val); if (result == null) { result = new ResultImpl(configuration, fields); - map.put(value, result); + map.put(val, result); } result.add(record); @@ -1333,6 +1333,26 @@ class ResultImpl implements Result, AttachableInternal { return map; } + @Override + public final Map> intoGroups(Field key, Field value) { + Map> map = new LinkedHashMap>(); + + for (R record : this) { + K k = record.getValue(key); + V v = record.getValue(value); + List result = map.get(k); + + if (result == null) { + result = new ArrayList(); + map.put(k, result); + } + + result.add(v); + } + + return map; + } + @Override public final Object[][] intoArray() throws MappingException { int size = size();