Skip to content

Commit

Permalink
[#9288] Added Records.intoArray() collectors
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaseder committed May 20, 2021
1 parent 41f6d56 commit 541a768
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 58 deletions.
110 changes: 110 additions & 0 deletions jOOQ/src/main/java/org/jooq/Records.java
Expand Up @@ -37,6 +37,10 @@
*/
package org.jooq;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
Expand Down Expand Up @@ -71,6 +75,112 @@
*/
public final class Records {

/**
* Create a collector that can collect {@link Record1} resulting from a
* single column {@link ResultQuery} into an array of that column's type.
* <p>
* For example:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(intoArray(new String[0]));
* </pre></code>
* <p>
* This is the same as the following, but allows for omitting repeating the
* <code>BOOK.TITLE</code> column:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetchArray(BOOK.TITLE);
* </pre></code>
*/
public static final <E, R extends Record1<E>> Collector<R, ?, E[]> intoArray(E[] a) {
return intoArray(a, Record1::value1);
}

/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into an array of a mapped type.
* <p>
* For example:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(intoList(new String[0], r -&gt; r.get(BOOK.TITLE)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetchArray(BOOK.TITLE);
* </pre></code>
*/
public static final <E, R extends Record1<E>> Collector<R, ?, E[]> intoArray(Class<? extends E> componentType) {
return intoArray(componentType, Record1::value1);
}

/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into an array of a mapped type.
* <p>
* For example:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(intoList(new String[0], r -&gt; r.get(BOOK.TITLE)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetchArray(BOOK.TITLE);
* </pre></code>
*/
public static final <E, R extends Record> Collector<R, ?, E[]> intoArray(E[] a, Function<? super R, ? extends E> function) {
return collectingAndThen(Collectors.mapping(function, toCollection(ArrayList::new)), l -> l.toArray(a));
}

/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into an array of a mapped type.
* <p>
* For example:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(intoList(new String[0], r -&gt; r.get(BOOK.TITLE)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* String[] titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetchArray(BOOK.TITLE);
* </pre></code>
*/
@SuppressWarnings("unchecked")
public static final <E, R extends Record> Collector<R, ?, E[]> intoArray(Class<? extends E> componentType, Function<? super R, ? extends E> function) {
return collectingAndThen(Collectors.mapping(function, toCollection(ArrayList::new)), l -> l.toArray((E[]) Array.newInstance(componentType, l.size())));
}

/**
* Create a collector that can collect {@link Record1} resulting from a
* single column {@link ResultQuery} into a {@link List} of that column's
Expand Down
12 changes: 6 additions & 6 deletions jOOQ/src/main/java/org/jooq/impl/FieldsImpl.java
Expand Up @@ -116,12 +116,12 @@ public final RecordMapper<R, Record> mapper(int[] fieldIndexes) {

@Override
public final RecordMapper<R, ?> mapper(String fieldName) {
return mapper(field(fieldName));
return mapper(indexOrFail(this, fieldName));
}

@Override
public final <U> RecordMapper<R, U> mapper(String fieldName, Configuration configuration, Class<? extends U> type) {
return mapper(fieldName, converterOrFail(configuration, field(fieldName).getType(), type));
return mapper(fieldName, converterOrFail(configuration, field(indexOrFail(this, fieldName)).getType(), type));
}

@Override
Expand All @@ -136,12 +136,12 @@ public final RecordMapper<R, Record> mapper(String[] fieldNames) {

@Override
public final RecordMapper<R, ?> mapper(Name fieldName) {
return mapper(field(fieldName));
return mapper(indexOrFail(this, fieldName));
}

@Override
public final <U> RecordMapper<R, U> mapper(Name fieldName, Configuration configuration, Class<? extends U> type) {
return mapper(fieldName, converterOrFail(configuration, field(fieldName).getType(), type));
return mapper(fieldName, converterOrFail(configuration, field(indexOrFail(this, fieldName)).getType(), type));
}

@Override
Expand All @@ -157,7 +157,7 @@ public final RecordMapper<R, Record> mapper(Name[] fieldNames) {
@SuppressWarnings("unchecked")
@Override
public final <T> RecordMapper<R, T> mapper(Field<T> field) {
return (RecordMapper<R, T>) mapper(indexOrFail(fieldsRow(), field));
return (RecordMapper<R, T>) mapper(indexOrFail(this, field));
}

@SuppressWarnings({ "unchecked", "rawtypes" })
Expand All @@ -169,7 +169,7 @@ public final <U> RecordMapper<R, U> mapper(Field<?> field, Configuration configu
@SuppressWarnings("unchecked")
@Override
public final <T, U> RecordMapper<R, U> mapper(Field<T> field, Converter<? super T, ? extends U> converter) {
return (RecordMapper<R, U>) mapper(indexOrFail(fieldsRow(), field), converter);
return (RecordMapper<R, U>) mapper(indexOrFail(this, field), converter);
}

@Override
Expand Down
66 changes: 24 additions & 42 deletions jOOQ/src/main/java/org/jooq/impl/ResultImpl.java
Expand Up @@ -327,17 +327,17 @@ public final Map<Record, Record> intoMap(Field<?>[] keys, Field<?>[] values) {

@Override
public final <E> Map<List<?>, E> intoMap(int[] keyFieldIndexes, Class<? extends E> type) {
return intoMap(fields(keyFieldIndexes), type);
return collect(Records.intoMap(recordType().mapper(keyFieldIndexes).andThen(Record::intoList), recordType().mapper(Tools.configuration(this), type)));
}

@Override
public final <E> Map<List<?>, E> intoMap(String[] keyFieldNames, Class<? extends E> type) {
return intoMap(fields(keyFieldNames), type);
return collect(Records.intoMap(recordType().mapper(keyFieldNames).andThen(Record::intoList), recordType().mapper(Tools.configuration(this), type)));
}

@Override
public final <E> Map<List<?>, E> intoMap(Name[] keyFieldNames, Class<? extends E> type) {
return intoMap(fields(keyFieldNames), type);
return collect(Records.intoMap(recordType().mapper(keyFieldNames).andThen(Record::intoList), recordType().mapper(Tools.configuration(this), type)));
}

@Override
Expand All @@ -347,34 +347,22 @@ public final <E> Map<List<?>, E> intoMap(Field<?>[] keys, Class<? extends E> typ

@Override
public final <E> Map<List<?>, E> intoMap(int[] keyFieldIndexes, RecordMapper<? super R, E> mapper) {
return intoMap(fields(keyFieldIndexes), mapper);
return collect(Records.intoMap(recordType().mapper(keyFieldIndexes).andThen(Record::intoList), mapper));
}

@Override
public final <E> Map<List<?>, E> intoMap(String[] keyFieldNames, RecordMapper<? super R, E> mapper) {
return intoMap(fields(keyFieldNames), mapper);
return collect(Records.intoMap(recordType().mapper(keyFieldNames).andThen(Record::intoList), mapper));
}

@Override
public final <E> Map<List<?>, E> intoMap(Name[] keyFieldNames, RecordMapper<? super R, E> mapper) {
return intoMap(fields(keyFieldNames), mapper);
return collect(Records.intoMap(recordType().mapper(keyFieldNames).andThen(Record::intoList), mapper));
}

@Override
public final <E> Map<List<?>, E> intoMap(Field<?>[] keys, RecordMapper<? super R, E> mapper) {
if (keys == null)
keys = new Field[0];

Map<List<?>, E> map = new LinkedHashMap<>();

for (R record : this) {
List<Object> keyValueList = Tools.map(keys, k -> record.get(k));

if (map.put(keyValueList, mapper.map(record)) != null)
throw new InvalidResultException("Key list " + keyValueList + " is not unique in Result for " + this);
}

return map;
return collect(Records.intoMap(recordType().mapper(keys).andThen(Record::intoList), mapper));
}

@Override
Expand Down Expand Up @@ -569,17 +557,17 @@ public final Map<Record, Result<R>> intoGroups(Field<?>[] keys) {

@Override
public final Map<Record, Result<Record>> intoGroups(int[] keyFieldIndexes, int[] valueFieldIndexes) {
return intoGroups(fields(keyFieldIndexes), fields(valueFieldIndexes));
return collect(intoResultGroups(recordType().mapper(keyFieldIndexes), recordType().mapper(valueFieldIndexes)));
}

@Override
public final Map<Record, Result<Record>> intoGroups(String[] keyFieldNames, String[] valueFieldNames) {
return intoGroups(fields(keyFieldNames), fields(valueFieldNames));
return collect(intoResultGroups(recordType().mapper(keyFieldNames), recordType().mapper(valueFieldNames)));
}

@Override
public final Map<Record, Result<Record>> intoGroups(Name[] keyFieldNames, Name[] valueFieldNames) {
return intoGroups(fields(keyFieldNames), fields(keyFieldNames));
return collect(intoResultGroups(recordType().mapper(keyFieldNames), recordType().mapper(valueFieldNames)));
}

@Override
Expand Down Expand Up @@ -664,13 +652,7 @@ public final <S extends Record> Map<S, Result<R>> intoGroups(Table<S> table) {

@Override
public final <S extends Record, T extends Record> Map<S, Result<T>> intoGroups(Table<S> keyTable, Table<T> valueTable) {
// [#9288] TODO: Can't use collect(Records.intoGroups(recordType().mapper(keyTable), recordType().mapper(valueTable))) yet
Map<S, Result<T>> map = new LinkedHashMap<>();

for (R record : this)
map.computeIfAbsent(record.into(keyTable), k -> DSL.using(Tools.configuration(this)).newResult(valueTable)).add(record.into(valueTable));

return map;
return collect(intoResultGroups(recordType().mapper(keyTable), recordType().mapper(valueTable)));
}

@Override
Expand All @@ -691,67 +673,67 @@ public final Object[][] intoArray() {

@Override
public final Object[][] intoArrays() {
return Tools.map(this, r -> r.intoArray(), Object[][]::new);
return collect(Records.intoArray(new Object[0][], R::intoArray));
}

@Override
public final Object[] intoArray(int fieldIndex) {
return getValues(fieldIndex).toArray((Object[]) Array.newInstance(field(safeIndex(fieldIndex)).getType(), size()));
return collect(Records.intoArray(field(safeIndex(fieldIndex)).getType(), recordType().mapper(fieldIndex)));
}

@Override
public final <U> U[] intoArray(int fieldIndex, Class<? extends U> type) {
return getValues(fieldIndex, type).toArray((U[]) Array.newInstance(type, size()));
return collect(Records.intoArray(type, recordType().mapper(fieldIndex, Tools.configuration(this), type)));
}

@Override
public final <U> U[] intoArray(int fieldIndex, Converter<?, ? extends U> converter) {
return Convert.convertArray(intoArray(fieldIndex), converter);
return collect(Records.intoArray(converter.toType(), recordType().mapper(fieldIndex, converter)));
}

@Override
public final Object[] intoArray(String fieldName) {
return intoArray(indexOrFail(fieldsRow(), fieldName));
return collect(Records.intoArray(field(indexOrFail(this, fieldName)).getType(), recordType().mapper(fieldName)));
}

@Override
public final <U> U[] intoArray(String fieldName, Class<? extends U> type) {
return intoArray(indexOrFail(fieldsRow(), fieldName), type);
return collect(Records.intoArray(type, recordType().mapper(fieldName, Tools.configuration(this), type)));
}

@Override
public final <U> U[] intoArray(String fieldName, Converter<?, ? extends U> converter) {
return Convert.convertArray(intoArray(fieldName), converter);
return collect(Records.intoArray(converter.toType(), recordType().mapper(fieldName, converter)));
}

@Override
public final Object[] intoArray(Name fieldName) {
return intoArray(indexOrFail(fieldsRow(), fieldName));
return collect(Records.intoArray(field(indexOrFail(this, fieldName)).getType(), recordType().mapper(fieldName)));
}

@Override
public final <U> U[] intoArray(Name fieldName, Class<? extends U> type) {
return intoArray(indexOrFail(fieldsRow(), fieldName), type);
return collect(Records.intoArray(type, recordType().mapper(fieldName, Tools.configuration(this), type)));
}

@Override
public final <U> U[] intoArray(Name fieldName, Converter<?, ? extends U> converter) {
return Convert.convertArray(intoArray(fieldName), converter);
return collect(Records.intoArray(converter.toType(), recordType().mapper(fieldName, converter)));
}

@Override
public final <T> T[] intoArray(Field<T> field) {
return getValues(field).toArray((T[]) Array.newInstance(field.getType(), size()));
return collect(Records.intoArray(field.getType(), recordType().mapper(field)));
}

@Override
public final <U> U[] intoArray(Field<?> field, Class<? extends U> type) {
return getValues(field, type).toArray((U[]) Array.newInstance(type, size()));
return collect(Records.intoArray(type, recordType().mapper(field, Tools.configuration(this), type)));
}

@Override
public final <T, U> U[] intoArray(Field<T> field, Converter<? super T, ? extends U> converter) {
return Convert.convertArray(intoArray(field), converter);
return collect(Records.intoArray(converter.toType(), recordType().mapper(field, converter)));
}

@Override
Expand Down

0 comments on commit 541a768

Please sign in to comment.