[jOOQ/jOOQ#9288] Offer Result.intoMap(), intoGroups(), intoSet()

functionality as Collector
This commit is contained in:
Lukas Eder 2021-05-10 17:46:13 +02:00
parent 39f57b928d
commit b50ec7169f
13 changed files with 767 additions and 335 deletions

View File

@ -0,0 +1,82 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import org.jooq.impl.DefaultRecordMapper;
/**
* A type producing records that can be mapped.
*
* @author Lukas Eder
*/
public interface Mappable<R extends Record> {
/**
* Create a record mapper that extracts a value by field index.
*/
RecordMapper<R, ?> mapper(int fieldIndex);
/**
* Create a record mapper that extracts a value by field name.
*/
RecordMapper<R, ?> mapper(String fieldName);
/**
* Create a record mapper that extracts a value by field name.
*/
RecordMapper<R, ?> mapper(Name fieldName);
/**
* Create a record mapper that extracts a value by field reference.
*/
<T> RecordMapper<R, T> mapper(Field<T> field);
/**
* Create a record mapper that maps records to a new
* {@link RecordQualifier#getRecordType()}.
*/
<S extends Record> RecordMapper<R, S> mapper(Table<S> table);
/**
* Create a record mapper that maps records to a {@link Class} using the
* configured {@link Configuration#recordMapperProvider()} (the
* {@link DefaultRecordMapper}, by default).
*/
<E> RecordMapper<R, E> mapper(Configuration configuration, Class<? extends E> type);
}

View File

@ -37,6 +37,8 @@
*/
package org.jooq;
import org.jooq.impl.DefaultRecordMapper;
/**
* A record type for {@link Table}, {@link Cursor}, {@link Result} and other
* objects.
@ -51,7 +53,7 @@ package org.jooq;
*
* @author Lukas Eder
*/
public interface RecordType<R extends Record> extends Fields {
public interface RecordType<R extends Record> extends Fields, Mappable<R> {
/**
* Get the degree of this record type.

View File

@ -37,6 +37,19 @@
*/
package org.jooq;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.jooq.exception.InvalidResultException;
import org.jooq.impl.Internal;
/**
* Common utilities related to {@link Record} types and constructing
* {@link RecordMapper}.
@ -58,6 +71,328 @@ package org.jooq;
*/
public final class Records {
/**
* Create a collector that can collect {@link Record1} resulting from a
* single column {@link ResultQuery} into a {@link List} of that column's
* type.
* <p>
* For example:
* <p>
* <code><pre>
* List&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(toList());
* </pre></code>
* <p>
* This is the same as the following, but allows for omitting repeating the
* <code>BOOK.TITLE</code> column:
* <p>
* <code><pre>
* List&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetch(BOOK.TITLE);
* </pre></code>
*/
public static final <E, R extends Record1<E>> Collector<R, ?, List<E>> toList() {
return Collectors.mapping(Record1::value1, Collectors.toCollection(ArrayList::new));
}
/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into a {@link List} of a mapped type.
* <p>
* For example:
* <p>
* <code><pre>
* List&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(toList(r -&gt; r.get(BOOK.TITLE)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* List&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetch(BOOK.TITLE);
* </pre></code>
*/
public static final <E, R extends Record> Collector<R, ?, List<E>> toList(Function<? super R, ? extends E> function) {
return Collectors.mapping(function, Collectors.toCollection(ArrayList::new));
}
/**
* Create a collector that can collect {@link Record1} resulting from a
* single column {@link ResultQuery} into a {@link Set} of that column's
* type.
* <p>
* For example:
* <p>
* <code><pre>
* Set&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(toSet());
* </pre></code>
* <p>
* This is the same as the following, but allows for omitting repeating the
* <code>BOOK.TITLE</code> column:
* <p>
* <code><pre>
* List&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetchSet(BOOK.TITLE);
* </pre></code>
*/
public static final <E, R extends Record1<E>> Collector<R, ?, Set<E>> toSet() {
return toSet(Record1::value1);
}
/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into a {@link Set} of a mapped type.
* <p>
* For example:
* <p>
* <code><pre>
* Set&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .collect(toSet(r -&gt; r.get(BOOK.TITLE)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* List&lt;String&gt; titles =
* ctx.select(BOOK.TITLE)
* .from(BOOK)
* .fetchSet(BOOK.TITLE);
* </pre></code>
*/
public static final <E, R extends Record> Collector<R, ?, Set<E>> toSet(Function<? super R, ? extends E> function) {
return Collectors.mapping(function, Collectors.toCollection(LinkedHashSet::new));
}
/**
* Create a collector that can collect {@link Record2} resulting from a
* 2-column {@link ResultQuery} into a {@link Map} using the first column as
* key and the second column as value.
* <p>
* Collection throws {@link InvalidResultException} if a key is encountered
* more than once.
* <p>
* For example:
* <p>
* <code><pre>
* Map&lt;Integer, String&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .collect(toMap());
* </pre></code>
* <p>
* This is the same as the following, but allows for omitting repeating the
* <code>BOOK.ID</code> and <code>BOOK.TITLE</code> columns:
* <p>
* <code><pre>
* Map&lt;Integer, String&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .fetchMap(BOOK.ID, BOOK.TITLE);
* </pre></code>
*/
public static final <K, V, R extends Record2<K, V>> Collector<R, ?, Map<K, V>> toMap() {
return toMap(Record2::value1, Record2::value2);
}
/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into a {@link Map} using the result of the argument
* {@link RecordMapper} as key and the record itself as value.
* <p>
* Collection throws {@link InvalidResultException} if a key is encountered
* more than once.
* <p>
* For example:
* <p>
* <code><pre>
* Map&lt;Integer, Record2&lt;Integer, String&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .collect(toMap(r -&gt; r.get(BOOK.ID)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* Map&lt;Integer, Record2&lt;Integer, String&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .fetchMap(BOOK.ID);
* </pre></code>
*/
public static final <K, R extends Record> Collector<R, ?, Map<K, R>> toMap(Function<? super R, ? extends K> keyMapper) {
return toMap(keyMapper, r -> r);
}
/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into a {@link Map} using the result of the argument
* {@link RecordMapper} as key and the result of another argument
* {@link RecordMapper} as value.
* <p>
* Collection throws {@link InvalidResultException} if a key is encountered
* more than once.
* <p>
* For example:
* <p>
* <code><pre>
* Map&lt;Integer, String&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .collect(toMap(r -&gt; r.get(BOOK.ID), r -&gt; r.get(BOOK.TITLE)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* Map&lt;Integer, String&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .fetchMap(BOOK.ID, BOOK.TITLE);
* </pre></code>
*/
public static final <K, V, R extends Record> Collector<R, ?, Map<K, V>> toMap(
Function<? super R, ? extends K> keyMapper,
Function<? super R, ? extends V> valueMapper
) {
return Collectors.toMap(
keyMapper,
valueMapper,
(k1, k2) -> {
throw new InvalidResultException("Key " + k1 + " is not unique in Result");
},
LinkedHashMap::new
);
}
/**
* Create a collector that can collect {@link Record2} resulting from a
* 2-column {@link ResultQuery} into a {@link Map} using the first column as
* key collecting values of the second column into a list of values.
* <p>
* For example:
* <p>
* <code><pre>
* Map&lt;Integer, List&lt;String&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .collect(toGroups());
* </pre></code>
* <p>
* This is the same as the following, but allows for omitting repeating the
* <code>BOOK.ID</code> and <code>BOOK.TITLE</code> columns:
* <p>
* <code><pre>
* Map&lt;Integer, List&lt;String&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .fetchGroups(BOOK.ID, BOOK.TITLE);
* </pre></code>
*/
public static final <K, V, R extends Record2<K, V>> Collector<R, ?, Map<K, List<V>>> toGroups() {
return toGroups(Record2::value1, Record2::value2);
}
/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into a {@link Map} using the result of the argument
* {@link RecordMapper} as key collecting the records themselves into a list
* of values.
* <p>
* For example:
* <p>
* <code><pre>
* Map&lt;Integer, List&lt;Record2&lt;Integer, String&gt;&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .collect(toGroups(r -&gt; r.get(BOOK.ID)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* Map&lt;Integer, List&lt;Record2&lt;Integer, String&gt;&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .fetchGroups(BOOK.ID);
* </pre></code>
*/
@SuppressWarnings("unchecked")
public static final <K, R extends Record> Collector<R, ?, Map<K, Result<R>>> toGroups(Function<? super R, ? extends K> keyMapper) {
return Collectors.groupingBy(
keyMapper,
LinkedHashMap::new,
Collector.<R, Result<R>[], Result<R>>of(
() -> new Result[1],
(x, r) -> {
if (x[0] == null)
x[0] = Internal.result(r);
x[0].add(r);
},
(r1, r2) -> {
r1[0].addAll(r2[0]);
return r1;
},
r -> r[0]
)
);
}
/**
* Create a collector that can collect {@link Record} resulting from a
* {@link ResultQuery} into a {@link Map} using the result of the argument
* {@link RecordMapper} as key collecting the result of another argument
* {@link RecordMapper} into a list of values.
* <p>
* For example:
* <p>
* <code><pre>
* Map&lt;Integer, List&lt;String&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .collect(toGroups(r -&gt; r.get(BOOK.ID), r -&gt; r.get(BOOK.TITLE)));
* </pre></code>
* <p>
* This is the same as the following:
* <p>
* <code><pre>
* Map&lt;Integer, List&lt;String&gt;&gt; books =
* ctx.select(BOOK.ID, BOOK.TITLE)
* .from(BOOK)
* .fetchGroups(BOOK.ID, BOOK.TITLE);
* </pre></code>
*/
public static final <K, V, R extends Record> Collector<R, ?, Map<K, List<V>>> toGroups(
Function<? super R, ? extends K> keyMapper,
Function<? super R, ? extends V> valueMapper
) {
return Collectors.groupingBy(
keyMapper,
LinkedHashMap::new,
Collectors.mapping(
valueMapper,
Collectors.toList()
)
);
}
/**

View File

@ -43,6 +43,8 @@ import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Stream;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.DataTypeException;
@ -310,6 +312,14 @@ public interface Result<R extends Record> extends Fields, List<R>, Attachable, F
*/
boolean isNotEmpty();
/**
* Collect all records of this result.
* <p>
* This is the same as calling {@link Stream#collect(Collector)} on
* {@link #stream()}.
*/
<X, A> X collect(Collector<? super R, A, X> collector);
/**
* Return the generated result as a list of name/value maps.
*

View File

@ -804,7 +804,7 @@ abstract class AbstractRecord extends AbstractStore implements Record {
@Override
public final <E> E into(Class<? extends E> type) {
return (E) Tools.configuration(this).recordMapperProvider().provide((FieldsImpl) fields.fields, type).map(this);
return (E) ((FieldsImpl) fields.fields).mapper(Tools.configuration(this), type).map(this);
}
// [#10191] Java and Kotlin can produce overloads for this method despite

View File

@ -111,8 +111,7 @@ public abstract class DAOImpl<R extends UpdatableRecord<R>, P, T> implements DAO
* using Spring. It is not exposed in the public API.
*/
public /* non-final */ void setConfiguration(Configuration configuration) {
this.configuration = Tools.configuration(configuration);
this.mapper = this.configuration.recordMapperProvider().provide(table.recordType(), type);
this.mapper = table.recordType().mapper(this.configuration = Tools.configuration(configuration), type);
}
public final DSLContext ctx() {

View File

@ -377,8 +377,7 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
}
if (Stream.class.isAssignableFrom(type)) {
RecordMapper<R, Object[]> local = configuration.recordMapperProvider().provide(rowType, Object[].class);
delegate = r -> (E) Stream.of(local.map(r));
delegate = r -> (E) Stream.of(rowType.mapper(configuration, Object[].class).map(r));
return;
}
@ -837,14 +836,14 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
nestedMappingInfo.recordDelegate = newRecord(true, recordType(nestedMappingInfo.row.size()), nestedMappingInfo.row, configuration);
for (java.lang.reflect.Field member : getMatchingMembers(configuration, type, prefix, true))
nestedMappingInfo.mappers.add(configuration
.recordMapperProvider()
.provide((RecordType<AbstractRecord>) nestedMappingInfo.row.fields, member.getType()));
nestedMappingInfo.mappers.add(
nestedMappingInfo.row.fields.mapper(configuration, member.getType())
);
for (Method method : getMatchingSetters(configuration, type, prefix, true))
nestedMappingInfo.mappers.add(configuration
.recordMapperProvider()
.provide((RecordType<AbstractRecord>) nestedMappingInfo.row.fields, method.getParameterTypes()[0]));
nestedMappingInfo.mappers.add(
nestedMappingInfo.row.fields.mapper(configuration, method.getParameterTypes()[0])
);
});
}
}
@ -1110,9 +1109,9 @@ public class DefaultRecordMapper<R extends Record, E> implements RecordMapper<R,
if (nestedMappedFields[i] != null) {
nestedMappingInfo[i].row = row0(nestedMappedFields[i].toArray(EMPTY_FIELD));
nestedMappingInfo[i].recordDelegate = newRecord(true, recordType(nestedMappingInfo[i].row.size()), nestedMappingInfo[i].row, configuration);
nestedMappingInfo[i].mappers.add(configuration
.recordMapperProvider()
.provide((RecordType<AbstractRecord>) nestedMappingInfo[i].row.fields, parameterTypes[propertyIndexes[i] != null ? propertyIndexes[i] : i]));
nestedMappingInfo[i].mappers.add(
nestedMappingInfo[i].row.fields.mapper(configuration, parameterTypes[propertyIndexes[i] != null ? propertyIndexes[i] : i])
);
}
}
}

View File

@ -0,0 +1,71 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.util.function.Function;
import org.jooq.Record;
import org.jooq.RecordMapper;
import org.jooq.RecordType;
/**
* A {@link RecordMapper} implementation offering access to a delegate record
* mapper whose initialisation is delayed until the first record, e.g. for
* {@link ResultQuery} implementations whose {@link RecordType} is unknown prior
* to execution.
*
* @author Lukas Eder
*/
final class DelayedRecordMapper<R extends Record, E> implements RecordMapper<R, E> {
final Function<RecordType<R>, RecordMapper<R, E>> init;
RecordMapper<R, E> delegate;
DelayedRecordMapper(Function<RecordType<R>, RecordMapper<R, E>> init) {
this.init = init;
}
@SuppressWarnings("unchecked")
@Override
public final E map(R record) {
if (delegate == null)
delegate = init.apply((RecordType<R>) ((AbstractRecord) record).fields.fields);
return delegate.map(record);
}
}

View File

@ -50,11 +50,13 @@ import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import org.jooq.Configuration;
import org.jooq.Context;
import org.jooq.DataType;
import org.jooq.Field;
import org.jooq.Name;
import org.jooq.Record;
import org.jooq.RecordMapper;
import org.jooq.RecordType;
import org.jooq.Row;
import org.jooq.SelectField;
@ -91,6 +93,36 @@ final class FieldsImpl<R extends Record> extends AbstractQueryPart implements Re
return fields.length;
}
@Override
public final RecordMapper<R, ?> mapper(int fieldIndex) {
return r -> r.get(fieldIndex);
}
@Override
public final RecordMapper<R, ?> mapper(String fieldName) {
return mapper(field(fieldName));
}
@Override
public final RecordMapper<R, ?> mapper(Name fieldName) {
return mapper(field(fieldName));
}
@Override
public final <T> RecordMapper<R, T> mapper(Field<T> field) {
return (RecordMapper<R, T>) mapper(indexOrFail(fieldsRow(), field));
}
@Override
public final <S extends Record> RecordMapper<R, S> mapper(Table<S> table) {
return r -> r.into(table);
}
@Override
public final <E> RecordMapper<R, E> mapper(Configuration configuration, Class<? extends E> type) {
return configuration.recordMapperProvider().provide(this, type);
}
@Override
@SuppressWarnings("unchecked")
public final <T> Field<T> field(Field<T> field) {

View File

@ -43,6 +43,7 @@ import static org.jooq.impl.ExpressionOperator.MULTIPLY;
import static org.jooq.impl.ExpressionOperator.SUBTRACT;
import static org.jooq.impl.Tools.nullSafe;
import java.lang.reflect.Array;
import java.util.function.Consumer;
import org.jooq.Binding;
@ -61,6 +62,7 @@ import org.jooq.ParamMode;
import org.jooq.Parameter;
// ...
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.Row;
import org.jooq.Schema;
import org.jooq.Sequence;
@ -443,6 +445,10 @@ public final class Internal {
};
}
/**
* JDK agnostic abstraction over {@link Class#arrayType()} and
* {@link Array#newInstance(Class, int)}.
*/
@SuppressWarnings({ "unchecked", "unused" })
public static final <T> Class<T[]> arrayType(Class<T> type) {
@ -450,6 +456,13 @@ public final class Internal {
return (Class<T[]>) java.lang.reflect.Array.newInstance(type, 0).getClass();
return (Class<T[]>) Array.newInstance(type, 0).getClass();
}
/**
* Create an empty result from a {@link Record} using its row type.
*/
public static final <R extends Record> Result<R> result(R record) {
return new ResultImpl<>(Tools.configuration(record), ((AbstractRecord) record).fields);
}
}

View File

@ -38,15 +38,17 @@
package org.jooq.impl;
import static org.jooq.Records.toGroups;
import static org.jooq.Records.toList;
import static org.jooq.Records.toMap;
import static org.jooq.Records.toSet;
import static org.jooq.impl.Tools.EMPTY_FIELD;
import static org.jooq.impl.Tools.converterOrFail;
import static org.jooq.impl.Tools.indexOrFail;
import static org.jooq.impl.Tools.map;
import java.lang.reflect.Array;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@ -57,6 +59,7 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collector;
import org.jooq.Configuration;
import org.jooq.Converter;
@ -88,6 +91,7 @@ import org.jooq.Record8;
import org.jooq.Record9;
import org.jooq.RecordHandler;
import org.jooq.RecordMapper;
import org.jooq.Records;
import org.jooq.Result;
import org.jooq.TXTFormat;
import org.jooq.Table;
@ -147,6 +151,11 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
// XXX: Result API
// -------------------------------------------------------------------------
@Override
public final <X, A> X collect(Collector<? super R, A, X> collector) {
return stream().collect(collector);
}
@Override
public final boolean isEmpty() {
return records.isEmpty();
@ -174,62 +183,70 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <T> List<T> getValues(Field<T> field) {
return (List<T>) getValues(indexOrFail(fieldsRow(), field));
return collect(toList(recordType().mapper(field)));
}
@Override
public final <U> List<U> getValues(Field<?> field, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return getValues(indexOrFail(fieldsRow(), field), type);
}
@Override
public final <T, U> List<U> getValues(Field<T> field, Converter<? super T, ? extends U> converter) {
// [#9288] TODO: Refactor this
return Convert.convert(getValues(field), converter);
}
@Override
public final List<?> getValues(int fieldIndex) {
return Tools.map(this, r -> r.get(fieldIndex));
return collect(toList(recordType().mapper(fieldIndex)));
}
@Override
public final <U> List<U> getValues(int fieldIndex, Class<? extends U> type) {
// [#9288] TODO: Refactor this
Converter converter = converterOrFail(this, field(safeIndex(fieldIndex)).getType(), (Class) type);
return Tools.map(this, r -> (U) converter.from(r.get(fieldIndex)));
}
@Override
public final <U> List<U> getValues(int fieldIndex, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return Convert.convert(getValues(fieldIndex), converter);
}
@Override
public final List<?> getValues(String fieldName) {
return getValues(field(fieldName));
return collect(toList(recordType().mapper(fieldName)));
}
@Override
public final <U> List<U> getValues(String fieldName, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return getValues(indexOrFail(fieldsRow(), fieldName), type);
}
@Override
public final <U> List<U> getValues(String fieldName, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return Convert.convert(getValues(fieldName), converter);
}
@Override
public final List<?> getValues(Name fieldName) {
return getValues(field(fieldName));
return collect(toList(recordType().mapper(fieldName)));
}
@Override
public final <U> List<U> getValues(Name fieldName, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return getValues(indexOrFail(fieldsRow(), fieldName), type);
}
@Override
public final <U> List<U> getValues(Name fieldName, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return Convert.convert(getValues(fieldName), converter);
}
@ -244,65 +261,42 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <K> Map<K, R> intoMap(Field<K> key) {
return intoMap0(indexOrFail(fieldsRow(), key));
return collect(toMap(recordType().mapper(key)));
}
@Override
public final Map<?, R> intoMap(int keyFieldIndex) {
return intoMap0(keyFieldIndex);
return collect(toMap(recordType().mapper(keyFieldIndex)));
}
@Override
public final Map<?, R> intoMap(String keyFieldName) {
return intoMap(field(keyFieldName));
return collect(toMap(recordType().mapper(keyFieldName)));
}
@Override
public final Map<?, R> intoMap(Name keyFieldName) {
return intoMap(field(keyFieldName));
}
private final <K> Map<K, R> intoMap0(int kIndex) {
Map<K, R> map = new LinkedHashMap<>();
for (R record : this)
if (map.put((K) record.get(kIndex), record) != null)
throw new InvalidResultException("Key " + record.get(kIndex) + " is not unique in Result for " + this);
return map;
return collect(toMap(recordType().mapper(keyFieldName)));
}
@Override
public final <K, V> Map<K, V> intoMap(Field<K> key, Field<V> value) {
int kIndex = indexOrFail(fieldsRow(), key);
int vIndex = indexOrFail(fieldsRow(), value);
return intoMap0(kIndex, vIndex);
return collect(toMap(recordType().mapper(key), recordType().mapper(value)));
}
@Override
public final Map<?, ?> intoMap(int keyFieldIndex, int valueFieldIndex) {
return intoMap0(keyFieldIndex, valueFieldIndex);
return collect(toMap(recordType().mapper(keyFieldIndex), recordType().mapper(valueFieldIndex)));
}
@Override
public final Map<?, ?> intoMap(String keyFieldName, String valueFieldName) {
return intoMap(field(keyFieldName), field(valueFieldName));
return collect(toMap(recordType().mapper(keyFieldName), recordType().mapper(valueFieldName)));
}
@Override
public final Map<?, ?> intoMap(Name keyFieldName, Name valueFieldName) {
return intoMap(field(keyFieldName), field(valueFieldName));
}
private final <K, V> Map<K, V> intoMap0(int kIndex, int vIndex) {
Map<K, V> map = new LinkedHashMap<>();
for (R record : this)
if (map.put((K) record.get(kIndex), (V) record.get(vIndex)) != null)
throw new InvalidResultException("Key " + record.get(kIndex) + " is not unique in Result for " + this);
return map;
return collect(toMap(recordType().mapper(keyFieldName), recordType().mapper(valueFieldName)));
}
@Override
@ -393,7 +387,7 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <E> Map<List<?>, E> intoMap(Field<?>[] keys, Class<? extends E> type) {
return intoMap(keys, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return intoMap(keys, recordType().mapper(Tools.configuration(this), type));
}
@Override
@ -430,262 +424,172 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <K> Map<K, R> intoMap(Class<? extends K> keyType) {
return intoMap(Tools.configuration(this).recordMapperProvider().provide(recordType(), keyType));
return collect(toMap(recordType().mapper(Tools.configuration(this), keyType)));
}
@Override
public final <K, V> Map<K, V> intoMap(Class<? extends K> keyType, Class<? extends V> valueType) {
return intoMap(
Tools.configuration(this).recordMapperProvider().provide(recordType(), keyType),
Tools.configuration(this).recordMapperProvider().provide(recordType(), valueType)
);
return collect(toMap(recordType().mapper(Tools.configuration(this), keyType), recordType().mapper(Tools.configuration(this), valueType)));
}
@Override
public final <K, V> Map<K, V> intoMap(Class<? extends K> keyType, RecordMapper<? super R, V> valueMapper) {
return intoMap(Tools.configuration(this).recordMapperProvider().provide(recordType(), keyType), valueMapper);
return collect(toMap(recordType().mapper(Tools.configuration(this), keyType), valueMapper));
}
@Override
public final <K> Map<K, R> intoMap(RecordMapper<? super R, K> keyMapper) {
Map<K, R> map = new LinkedHashMap<>();
for (R record : this) {
K key = keyMapper.map(record);
if (map.put(key, record) != null)
throw new InvalidResultException("Key list " + key + " is not unique in Result for " + this);
}
return map;
return collect(toMap(keyMapper));
}
@Override
public final <K, V> Map<K, V> intoMap(RecordMapper<? super R, K> keyMapper, Class<V> valueType) {
return intoMap(keyMapper, Tools.configuration(this).recordMapperProvider().provide(recordType(), valueType));
return collect(toMap(keyMapper, recordType().mapper(Tools.configuration(this), valueType)));
}
@Override
public final <K, V> Map<K, V> intoMap(RecordMapper<? super R, K> keyMapper, RecordMapper<? super R, V> valueMapper) {
Map<K, V> map = new LinkedHashMap<>();
for (R record : this) {
K key = keyMapper.map(record);
V value = valueMapper.map(record);
if (map.put(key, value) != null)
throw new InvalidResultException("Key list " + key + " is not unique in Result for " + this);
}
return map;
return collect(toMap(keyMapper, valueMapper));
}
@Override
public final <S extends Record> Map<S, R> intoMap(Table<S> table) {
Map<S, R> map = new LinkedHashMap<>();
for (R record : this) {
S key = record.into(table);
if (map.put(key, record) != null)
throw new InvalidResultException("Key list " + key + " is not unique in Result for " + this);
}
return map;
return collect(toMap(recordType().mapper(table)));
}
@Override
public final <S extends Record, T extends Record> Map<S, T> intoMap(Table<S> keyTable, Table<T> valueTable) {
Map<S, T> map = new LinkedHashMap<>();
for (R record : this) {
S key = record.into(keyTable);
T value = record.into(valueTable);
if (map.put(key, value) != null)
throw new InvalidResultException("Key list " + key + " is not unique in Result for " + this);
}
return map;
return collect(toMap(recordType().mapper(keyTable), recordType().mapper(valueTable)));
}
@Override
public final <E, S extends Record> Map<S, E> intoMap(Table<S> table, Class<? extends E> type) {
return intoMap(table, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toMap(recordType().mapper(table), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <E, S extends Record> Map<S, E> intoMap(Table<S> table, RecordMapper<? super R, E> mapper) {
Map<S, E> map = new LinkedHashMap<>();
for (R record : this) {
S key = record.into(table);
if (map.put(key, mapper.map(record)) != null)
throw new InvalidResultException("Key list " + key + " is not unique in Result for " + this);
}
return map;
return collect(toMap(recordType().mapper(table), mapper));
}
@Override
public final <E> Map<?, E> intoMap(int keyFieldIndex, Class<? extends E> type) {
return intoMap(keyFieldIndex, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toMap(recordType().mapper(keyFieldIndex), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <E> Map<?, E> intoMap(String keyFieldName, Class<? extends E> type) {
return intoMap(keyFieldName, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toMap(recordType().mapper(keyFieldName), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <E> Map<?, E> intoMap(Name keyFieldName, Class<? extends E> type) {
return intoMap(keyFieldName, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toMap(recordType().mapper(keyFieldName), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <K, E> Map<K, E> intoMap(Field<K> key, Class<? extends E> type) {
return intoMap(key, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toMap(recordType().mapper(key), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <E> Map<?, E> intoMap(int keyFieldIndex, RecordMapper<? super R, E> mapper) {
return intoMap0(keyFieldIndex, mapper);
return collect(toMap(recordType().mapper(keyFieldIndex), mapper));
}
@Override
public final <E> Map<?, E> intoMap(String keyFieldName, RecordMapper<? super R, E> mapper) {
return intoMap(field(keyFieldName), mapper);
return collect(toMap(recordType().mapper(keyFieldName), mapper));
}
@Override
public final <E> Map<?, E> intoMap(Name keyFieldName, RecordMapper<? super R, E> mapper) {
return intoMap(field(keyFieldName), mapper);
return collect(toMap(recordType().mapper(keyFieldName), mapper));
}
@Override
public final <K, E> Map<K, E> intoMap(Field<K> key, RecordMapper<? super R, E> mapper) {
return intoMap0(indexOrFail(fieldsRow(), key), mapper);
}
private final <K, E> Map<K, E> intoMap0(int kIndex, RecordMapper<? super R, E> mapper) {
Map<K, E> map = new LinkedHashMap<>();
for (R record : this)
if (map.put((K) record.get(kIndex), mapper.map(record)) != null)
throw new InvalidResultException("Key " + record.get(kIndex) + " is not unique in Result for " + this);
return map;
return collect(toMap(recordType().mapper(key), mapper));
}
@Override
public final <K> Map<K, Result<R>> intoGroups(Field<K> key) {
return intoGroups0(indexOrFail(fieldsRow(), key));
return collect(toGroups(recordType().mapper(key)));
}
@Override
public final Map<?, Result<R>> intoGroups(int keyFieldIndex) {
return intoGroups0(keyFieldIndex);
return collect(toGroups(recordType().mapper(keyFieldIndex)));
}
@Override
public final Map<?, Result<R>> intoGroups(String keyFieldName) {
return intoGroups(field(keyFieldName));
return collect(toGroups(recordType().mapper(keyFieldName)));
}
@Override
public final Map<?, Result<R>> intoGroups(Name keyFieldName) {
return intoGroups(field(keyFieldName));
}
private final <K> Map<K, Result<R>> intoGroups0(int keyFieldIndex) {
Map<K, Result<R>> map = new LinkedHashMap<>();
for (R record : this)
map.computeIfAbsent((K) record.get(keyFieldIndex), v -> new ResultImpl<>(configuration, fields)).add(record);
return map;
return collect(toGroups(recordType().mapper(keyFieldName)));
}
@Override
public final <K, V> Map<K, List<V>> intoGroups(Field<K> key, Field<V> value) {
int kIndex = indexOrFail(fieldsRow(), key);
int vIndex = indexOrFail(fieldsRow(), value);
return intoGroups0(kIndex, vIndex);
return collect(toGroups(recordType().mapper(key), recordType().mapper(value)));
}
@Override
public final Map<?, List<?>> intoGroups(int keyFieldIndex, int valueFieldIndex) {
return (Map) intoGroups0(keyFieldIndex, valueFieldIndex);
return (Map) collect(toGroups(recordType().mapper(keyFieldIndex), recordType().mapper(valueFieldIndex)));
}
@Override
public final Map<?, List<?>> intoGroups(String keyFieldName, String valueFieldName) {
return (Map) intoGroups(field(keyFieldName), field(valueFieldName));
return (Map) collect(toGroups(recordType().mapper(keyFieldName), recordType().mapper(valueFieldName)));
}
@Override
public final Map<?, List<?>> intoGroups(Name keyFieldName, Name valueFieldName) {
return (Map) intoGroups(field(keyFieldName), field(valueFieldName));
}
private final <K, V> Map<K, List<V>> intoGroups0(int kIndex, int vIndex) {
Map<K, List<V>> map = new LinkedHashMap<>();
for (R record : this)
map.computeIfAbsent((K) record.get(kIndex), k -> new ArrayList<>()).add((V) record.get(vIndex));
return map;
return (Map) collect(toGroups(recordType().mapper(keyFieldName), recordType().mapper(valueFieldName)));
}
@Override
public final <E> Map<?, List<E>> intoGroups(int keyFieldIndex, Class<? extends E> type) {
return intoGroups(keyFieldIndex, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toGroups(recordType().mapper(keyFieldIndex), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <E> Map<?, List<E>> intoGroups(String keyFieldName, Class<? extends E> type) {
return intoGroups(keyFieldName, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toGroups(recordType().mapper(keyFieldName), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <E> Map<?, List<E>> intoGroups(Name keyFieldName, Class<? extends E> type) {
return intoGroups(keyFieldName, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toGroups(recordType().mapper(keyFieldName), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <K, E> Map<K, List<E>> intoGroups(Field<K> key, Class<? extends E> type) {
return intoGroups(key, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toGroups(recordType().mapper(key), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <K, E> Map<K, List<E>> intoGroups(Field<K> key, RecordMapper<? super R, E> mapper) {
return intoGroups0(indexOrFail(fieldsRow(), key), mapper);
return collect(toGroups(recordType().mapper(key), mapper));
}
@Override
public final <E> Map<?, List<E>> intoGroups(int keyFieldIndex, RecordMapper<? super R, E> mapper) {
return intoGroups0(keyFieldIndex, mapper);
return collect(toGroups(recordType().mapper(keyFieldIndex), mapper));
}
@Override
public final <E> Map<?, List<E>> intoGroups(String keyFieldName, RecordMapper<? super R, E> mapper) {
return intoGroups(field(keyFieldName), mapper);
return collect(toGroups(recordType().mapper(keyFieldName), mapper));
}
@Override
public final <E> Map<?, List<E>> intoGroups(Name keyFieldName, RecordMapper<? super R, E> mapper) {
return intoGroups(field(keyFieldName), mapper);
}
private final <K, E> Map<K, List<E>> intoGroups0(int keyFieldIndex, RecordMapper<? super R, E> mapper) {
Map<K, List<E>> map = new LinkedHashMap<>();
for (R record : this)
map.computeIfAbsent((K) record.get(keyFieldIndex), k -> new ArrayList<>()).add(mapper.map(record));
return map;
return collect(toGroups(recordType().mapper(keyFieldName), mapper));
}
@Override
@ -714,7 +618,7 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
for (Field<?> field : keysRow.fields.fields)
Tools.copyValue(key, field, record, field);
map.computeIfAbsent(key, k -> new ResultImpl<>(configuration(), this.fields)).add(record);
map.computeIfAbsent(key, k -> new ResultImpl<>(Tools.configuration(this), this.fields)).add(record);
}
return map;
@ -751,7 +655,7 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
for (Field<?> field : valuesRow.fields.fields)
Tools.copyValue(value, field, record, field);
map.computeIfAbsent(key, k -> new ResultImpl<>(configuration(), valuesRow)).add(value);
map.computeIfAbsent(key, k -> new ResultImpl<>(Tools.configuration(this), valuesRow)).add(value);
}
return map;
@ -759,22 +663,22 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <E> Map<Record, List<E>> intoGroups(int[] keyFieldIndexes, Class<? extends E> type) {
return intoGroups(keyFieldIndexes, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return intoGroups(keyFieldIndexes, recordType().mapper(Tools.configuration(this), type));
}
@Override
public final <E> Map<Record, List<E>> intoGroups(String[] keyFieldNames, Class<? extends E> type) {
return intoGroups(keyFieldNames, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return intoGroups(keyFieldNames, recordType().mapper(Tools.configuration(this), type));
}
@Override
public final <E> Map<Record, List<E>> intoGroups(Name[] keyFieldNames, Class<? extends E> type) {
return intoGroups(keyFieldNames, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return intoGroups(keyFieldNames, recordType().mapper(Tools.configuration(this), type));
}
@Override
public final <E> Map<Record, List<E>> intoGroups(Field<?>[] keys, Class<? extends E> type) {
return intoGroups(keys, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return intoGroups(keys, recordType().mapper(Tools.configuration(this), type));
}
@Override
@ -811,80 +715,58 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <K> Map<K, Result<R>> intoGroups(Class<? extends K> keyType) {
return intoGroups(Tools.configuration(this).recordMapperProvider().provide(recordType(), keyType));
return collect(toGroups(recordType().mapper(Tools.configuration(this), keyType)));
}
@Override
public final <K, V> Map<K, List<V>> intoGroups(Class<? extends K> keyType, Class<? extends V> valueType) {
return intoGroups(
Tools.configuration(this).recordMapperProvider().provide(recordType(), keyType),
Tools.configuration(this).recordMapperProvider().provide(recordType(), valueType)
);
return collect(toGroups(recordType().mapper(Tools.configuration(this), keyType), recordType().mapper(Tools.configuration(this), valueType)));
}
@Override
public final <K, V> Map<K, List<V>> intoGroups(Class<? extends K> keyType, RecordMapper<? super R, V> valueMapper) {
return intoGroups(Tools.configuration(this).recordMapperProvider().provide(recordType(), keyType), valueMapper);
return collect(toGroups(recordType().mapper(Tools.configuration(this), keyType), valueMapper));
}
@Override
public final <K> Map<K, Result<R>> intoGroups(RecordMapper<? super R, K> keyMapper) {
Map<K, Result<R>> map = new LinkedHashMap<>();
for (R record : this)
map.computeIfAbsent(keyMapper.map(record), k -> new ResultImpl<>(configuration(), fields)).add(record);
return map;
return collect(toGroups(keyMapper));
}
@Override
public final <K, V> Map<K, List<V>> intoGroups(RecordMapper<? super R, K> keyMapper, Class<V> valueType) {
return intoGroups(keyMapper, Tools.configuration(this).recordMapperProvider().provide(recordType(), valueType));
return collect(toGroups(keyMapper, recordType().mapper(Tools.configuration(this), valueType)));
}
@Override
public final <K, V> Map<K, List<V>> intoGroups(RecordMapper<? super R, K> keyMapper, RecordMapper<? super R, V> valueMapper) {
Map<K, List<V>> map = new LinkedHashMap<>();
for (R record : this)
map.computeIfAbsent(keyMapper.map(record), k -> new ArrayList<>()).add(valueMapper.map(record));
return map;
return collect(toGroups(keyMapper, valueMapper));
}
@Override
public final <S extends Record> Map<S, Result<R>> intoGroups(Table<S> table) {
Map<S, Result<R>> map = new LinkedHashMap<>();
for (R record : this)
map.computeIfAbsent(record.into(table), k -> new ResultImpl<>(configuration(), this.fields)).add(record);
return map;
return collect(toGroups(recordType().mapper(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(toGroups(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(configuration()).newResult(valueTable)).add(record.into(valueTable));
map.computeIfAbsent(record.into(keyTable), k -> DSL.using(Tools.configuration(this)).newResult(valueTable)).add(record.into(valueTable));
return map;
}
@Override
public final <E, S extends Record> Map<S, List<E>> intoGroups(Table<S> table, Class<? extends E> type) {
return intoGroups(table, Tools.configuration(this).recordMapperProvider().provide(recordType(), type));
return collect(toGroups(recordType().mapper(table), recordType().mapper(Tools.configuration(this), type)));
}
@Override
public final <E, S extends Record> Map<S, List<E>> intoGroups(Table<S> table, RecordMapper<? super R, E> mapper) {
Map<S, List<E>> map = new LinkedHashMap<>();
for (R record : this)
map.computeIfAbsent(record.into(table), k -> new ArrayList<>()).add(mapper.map(record));
return map;
return collect(toGroups(recordType().mapper(table), mapper));
}
@Override
@ -960,71 +842,74 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <E> Set<E> intoSet(RecordMapper<? super R, E> mapper) {
Set<E> result = new LinkedHashSet<>();
for (R record : this)
result.add(mapper.map(record));
return result;
return collect(toSet(mapper));
}
@Override
public final Set<?> intoSet(int fieldIndex) {
return new LinkedHashSet<>(getValues(fieldIndex));
return collect(toSet(recordType().mapper(fieldIndex)));
}
@Override
public final <U> Set<U> intoSet(int fieldIndex, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(fieldIndex, type));
}
@Override
public final <U> Set<U> intoSet(int fieldIndex, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(fieldIndex, converter));
}
@Override
public final Set<?> intoSet(String fieldName) {
return new LinkedHashSet<>(getValues(fieldName));
return collect(toSet(recordType().mapper(fieldName)));
}
@Override
public final <U> Set<U> intoSet(String fieldName, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(fieldName, type));
}
@Override
public final <U> Set<U> intoSet(String fieldName, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(fieldName, converter));
}
@Override
public final Set<?> intoSet(Name fieldName) {
return new LinkedHashSet<>(getValues(fieldName));
return collect(toSet(recordType().mapper(fieldName)));
}
@Override
public final <U> Set<U> intoSet(Name fieldName, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(fieldName, type));
}
@Override
public final <U> Set<U> intoSet(Name fieldName, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(fieldName, converter));
}
@Override
public final <T> Set<T> intoSet(Field<T> field) {
return new LinkedHashSet<>(getValues(field));
return collect(toSet(recordType().mapper(field)));
}
@Override
public final <U> Set<U> intoSet(Field<?> field, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(field, type));
}
@Override
public final <T, U> Set<U> intoSet(Field<T> field, Converter<? super T, ? extends U> converter) {
// [#9288] TODO: Refactor this
return new LinkedHashSet<>(getValues(field, converter));
}
@ -1154,13 +1039,12 @@ final class ResultImpl<R extends Record> extends AbstractResult<R> implements Re
@Override
public final <E> List<E> into(Class<? extends E> type) {
RecordMapper<R, E> mapper = Tools.configuration(this).recordMapperProvider().provide(recordType(), type);
return Tools.map(this, mapper::map);
return Tools.map(this, recordType().mapper(Tools.configuration(this), type)::map);
}
@Override
public final <Z extends Record> Result<Z> into(Table<Z> table) {
Result<Z> list = new ResultImpl<>(configuration(), (AbstractRow) table.fieldsRow());
Result<Z> list = new ResultImpl<>(Tools.configuration(this), (AbstractRow) table.fieldsRow());
for (R record : this)
list.add(record.into(table));

View File

@ -37,6 +37,9 @@
*/
package org.jooq.impl;
import static org.jooq.Records.toGroups;
import static org.jooq.Records.toMap;
import static org.jooq.Records.toSet;
import static org.jooq.impl.Tools.blocking;
import java.lang.reflect.Array;
@ -52,13 +55,14 @@ import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
// ...
import java.util.stream.Collector;
import java.util.stream.Stream;
import org.jooq.Configuration;
import org.jooq.Converter;
import org.jooq.Cursor;
import org.jooq.Field;
import org.jooq.Mappable;
import org.jooq.Name;
import org.jooq.QueryPartInternal;
import org.jooq.Record;
@ -86,6 +90,7 @@ import org.jooq.Record8;
import org.jooq.Record9;
import org.jooq.RecordHandler;
import org.jooq.RecordMapper;
import org.jooq.Records;
import org.jooq.Result;
import org.jooq.ResultQuery;
import org.jooq.Results;
@ -105,7 +110,7 @@ import io.r2dbc.spi.ConnectionFactory;
*
* @author Lukas Eder
*/
interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQuery<R> {
interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQuery<R>, Mappable<R> {
@Override
default ResultQuery<Record> coerce(Field<?>... fields) {
@ -782,82 +787,82 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default <K> Map<K, R> fetchMap(Field<K> key) {
return fetch().intoMap(key);
return collect(toMap(mapper(key)));
}
@Override
default Map<?, R> fetchMap(int keyFieldIndex) {
return fetch().intoMap(keyFieldIndex);
return collect(toMap(mapper(keyFieldIndex)));
}
@Override
default Map<?, R> fetchMap(String keyFieldName) {
return fetch().intoMap(keyFieldName);
return collect(toMap(mapper(keyFieldName)));
}
@Override
default Map<?, R> fetchMap(Name keyFieldName) {
return fetch().intoMap(keyFieldName);
return collect(toMap(mapper(keyFieldName)));
}
@Override
default <K, V> Map<K, V> fetchMap(Field<K> key, Field<V> value) {
return fetch().intoMap(key, value);
return collect(toMap(mapper(key), mapper(value)));
}
@Override
default Map<?, ?> fetchMap(int keyFieldIndex, int valueFieldIndex) {
return fetch().intoMap(keyFieldIndex, valueFieldIndex);
return collect(toMap(mapper(keyFieldIndex), mapper(valueFieldIndex)));
}
@Override
default Map<?, ?> fetchMap(String keyFieldName, String valueFieldName) {
return fetch().intoMap(keyFieldName, valueFieldName);
return collect(toMap(mapper(keyFieldName), mapper(valueFieldName)));
}
@Override
default Map<?, ?> fetchMap(Name keyFieldName, Name valueFieldName) {
return fetch().intoMap(keyFieldName, valueFieldName);
return collect(toMap(mapper(keyFieldName), mapper(valueFieldName)));
}
@Override
default <K, E> Map<K, E> fetchMap(Field<K> key, Class<? extends E> type) {
return fetch().intoMap(key, type);
return collect(toMap(mapper(key), mapper(Tools.configuration(this), type)));
}
@Override
default <E> Map<?, E> fetchMap(int keyFieldIndex, Class<? extends E> type) {
return fetch().intoMap(keyFieldIndex, type);
return collect(toMap(mapper(keyFieldIndex), mapper(Tools.configuration(this), type)));
}
@Override
default <E> Map<?, E> fetchMap(String keyFieldName, Class<? extends E> type) {
return fetch().intoMap(keyFieldName, type);
return collect(toMap(mapper(keyFieldName), mapper(Tools.configuration(this), type)));
}
@Override
default <E> Map<?, E> fetchMap(Name keyFieldName, Class<? extends E> type) {
return fetch().intoMap(keyFieldName, type);
return collect(toMap(mapper(keyFieldName), mapper(Tools.configuration(this), type)));
}
@Override
default <K, E> Map<K, E> fetchMap(Field<K> key, RecordMapper<? super R, E> mapper) {
return fetch().intoMap(key, mapper);
return collect(toMap(mapper(key), mapper));
}
@Override
default <E> Map<?, E> fetchMap(int keyFieldIndex, RecordMapper<? super R, E> mapper) {
return fetch().intoMap(keyFieldIndex, mapper);
return collect(toMap(mapper(keyFieldIndex), mapper));
}
@Override
default <E> Map<?, E> fetchMap(String keyFieldName, RecordMapper<? super R, E> mapper) {
return fetch().intoMap(keyFieldName, mapper);
return collect(toMap(mapper(keyFieldName), mapper));
}
@Override
default <E> Map<?, E> fetchMap(Name keyFieldName, RecordMapper<? super R, E> mapper) {
return fetch().intoMap(keyFieldName, mapper);
return collect(toMap(mapper(keyFieldName), mapper));
}
@Override
@ -942,52 +947,52 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default <K> Map<K, R> fetchMap(Class<? extends K> keyType) {
return fetch().intoMap(keyType);
return collect(toMap(mapper(Tools.configuration(this), keyType)));
}
@Override
default <K, V> Map<K, V> fetchMap(Class<? extends K> keyType, Class<? extends V> valueType) {
return fetch().intoMap(keyType, valueType);
return collect(toMap(mapper(Tools.configuration(this), keyType), mapper(Tools.configuration(this), valueType)));
}
@Override
default <K, V> Map<K, V> fetchMap(Class<? extends K> keyType, RecordMapper<? super R, V> valueMapper) {
return fetch().intoMap(keyType, valueMapper);
return collect(toMap(mapper(Tools.configuration(this), keyType), valueMapper));
}
@Override
default <K> Map<K, R> fetchMap(RecordMapper<? super R, K> keyMapper) {
return fetch().intoMap(keyMapper);
return collect(toMap(keyMapper));
}
@Override
default <K, V> Map<K, V> fetchMap(RecordMapper<? super R, K> keyMapper, Class<V> valueType) {
return fetch().intoMap(keyMapper, valueType);
return collect(toMap(keyMapper, mapper(Tools.configuration(this), valueType)));
}
@Override
default <K, V> Map<K, V> fetchMap(RecordMapper<? super R, K> keyMapper, RecordMapper<? super R, V> valueMapper) {
return fetch().intoMap(keyMapper, valueMapper);
return collect(toMap(keyMapper, valueMapper));
}
@Override
default <S extends Record> Map<S, R> fetchMap(Table<S> table) {
return fetch().intoMap(table);
return collect(toMap(mapper(table)));
}
@Override
default <S extends Record, T extends Record> Map<S, T> fetchMap(Table<S> keyTable, Table<T> valueTable) {
return fetch().intoMap(keyTable, valueTable);
return collect(toMap(mapper(keyTable), mapper(valueTable)));
}
@Override
default <E, S extends Record> Map<S, E> fetchMap(Table<S> table, Class<? extends E> type) {
return fetch().intoMap(table, type);
return collect(toMap(mapper(table), mapper(Tools.configuration(this), type)));
}
@Override
default <E, S extends Record> Map<S, E> fetchMap(Table<S> table, RecordMapper<? super R, E> mapper) {
return fetch().intoMap(table, mapper);
return collect(toMap(mapper(table), mapper));
}
@Override
@ -997,82 +1002,82 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default <K> Map<K, Result<R>> fetchGroups(Field<K> key) {
return fetch().intoGroups(key);
return collect(toGroups(mapper(key)));
}
@Override
default Map<?, Result<R>> fetchGroups(int keyFieldIndex) {
return fetch().intoGroups(keyFieldIndex);
return collect(toGroups(mapper(keyFieldIndex)));
}
@Override
default Map<?, Result<R>> fetchGroups(String keyFieldName) {
return fetch().intoGroups(keyFieldName);
return collect(toGroups(mapper(keyFieldName)));
}
@Override
default Map<?, Result<R>> fetchGroups(Name keyFieldName) {
return fetch().intoGroups(keyFieldName);
return collect(toGroups(mapper(keyFieldName)));
}
@Override
default <K, V> Map<K, List<V>> fetchGroups(Field<K> key, Field<V> value) {
return fetch().intoGroups(key, value);
return collect(toGroups(mapper(key), mapper(value)));
}
@Override
default Map<?, List<?>> fetchGroups(int keyFieldIndex, int valueFieldIndex) {
return fetch().intoGroups(keyFieldIndex, valueFieldIndex);
return (Map) collect(toGroups(mapper(keyFieldIndex), mapper(valueFieldIndex)));
}
@Override
default Map<?, List<?>> fetchGroups(String keyFieldName, String valueFieldName) {
return fetch().intoGroups(keyFieldName, valueFieldName);
return (Map) collect(toGroups(mapper(keyFieldName), mapper(valueFieldName)));
}
@Override
default Map<?, List<?>> fetchGroups(Name keyFieldName, Name valueFieldName) {
return fetch().intoGroups(keyFieldName, valueFieldName);
return (Map) collect(toGroups(mapper(keyFieldName), mapper(valueFieldName)));
}
@Override
default <K, E> Map<K, List<E>> fetchGroups(Field<K> key, Class<? extends E> type) {
return fetch().intoGroups(key, type);
return collect(toGroups(mapper(key), mapper(Tools.configuration(this), type)));
}
@Override
default <E> Map<?, List<E>> fetchGroups(int keyFieldIndex, Class<? extends E> type) {
return fetch().intoGroups(keyFieldIndex, type);
return collect(toGroups(mapper(keyFieldIndex), mapper(Tools.configuration(this), type)));
}
@Override
default <E> Map<?, List<E>> fetchGroups(String keyFieldName, Class<? extends E> type) {
return fetch().intoGroups(keyFieldName, type);
return collect(toGroups(mapper(keyFieldName), mapper(Tools.configuration(this), type)));
}
@Override
default <E> Map<?, List<E>> fetchGroups(Name keyFieldName, Class<? extends E> type) {
return fetch().intoGroups(keyFieldName, type);
return collect(toGroups(mapper(keyFieldName), mapper(Tools.configuration(this), type)));
}
@Override
default <K, E> Map<K, List<E>> fetchGroups(Field<K> key, RecordMapper<? super R, E> mapper) {
return fetch().intoGroups(key, mapper);
return collect(toGroups(mapper(key), mapper));
}
@Override
default <E> Map<?, List<E>> fetchGroups(int keyFieldIndex, RecordMapper<? super R, E> mapper) {
return fetch().intoGroups(keyFieldIndex, mapper);
return collect(toGroups(mapper(keyFieldIndex), mapper));
}
@Override
default <E> Map<?, List<E>> fetchGroups(String keyFieldName, RecordMapper<? super R, E> mapper) {
return fetch().intoGroups(keyFieldName, mapper);
return collect(toGroups(mapper(keyFieldName), mapper));
}
@Override
default <E> Map<?, List<E>> fetchGroups(Name keyFieldName, RecordMapper<? super R, E> mapper) {
return fetch().intoGroups(keyFieldName, mapper);
return collect(toGroups(mapper(keyFieldName), mapper));
}
@Override
@ -1157,52 +1162,53 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default <K> Map<K, Result<R>> fetchGroups(Class<? extends K> keyType) {
return fetch().intoGroups(keyType);
return collect(toGroups(mapper(Tools.configuration(this), keyType)));
}
@Override
default <K, V> Map<K, List<V>> fetchGroups(Class<? extends K> keyType, Class<? extends V> valueType) {
return fetch().intoGroups(keyType, valueType);
return collect(toGroups(mapper(Tools.configuration(this), keyType), mapper(Tools.configuration(this), valueType)));
}
@Override
default <K, V> Map<K, List<V>> fetchGroups(Class<? extends K> keyType, RecordMapper<? super R, V> valueMapper) {
return fetch().intoGroups(keyType, valueMapper);
return collect(toGroups(mapper(Tools.configuration(this), keyType), valueMapper));
}
@Override
default <K> Map<K, Result<R>> fetchGroups(RecordMapper<? super R, K> keyMapper) {
return fetch().intoGroups(keyMapper);
return collect(toGroups(keyMapper));
}
@Override
default <K, V> Map<K, List<V>> fetchGroups(RecordMapper<? super R, K> keyMapper, Class<V> valueType) {
return fetch().intoGroups(keyMapper, valueType);
return collect(toGroups(keyMapper, mapper(Tools.configuration(this), valueType)));
}
@Override
default <K, V> Map<K, List<V>> fetchGroups(RecordMapper<? super R, K> keyMapper, RecordMapper<? super R, V> valueMapper) {
return fetch().intoGroups(keyMapper, valueMapper);
return collect(toGroups(keyMapper, valueMapper));
}
@Override
default <S extends Record> Map<S, Result<R>> fetchGroups(Table<S> table) {
return fetch().intoGroups(table);
return collect(toGroups(mapper(table)));
}
@Override
default <S extends Record, T extends Record> Map<S, Result<T>> fetchGroups(Table<S> keyTable, Table<T> valueTable) {
// [#9288] TODO: Can't use collect(toGroups(recordType().mapper(keyTable), recordType().mapper(valueTable))) yet
return fetch().intoGroups(keyTable, valueTable);
}
@Override
default <E, S extends Record> Map<S, List<E>> fetchGroups(Table<S> table, Class<? extends E> type) {
return fetch().intoGroups(table, type);
return collect(toGroups(mapper(table), mapper(Tools.configuration(this), type)));
}
@Override
default <E, S extends Record> Map<S, List<E>> fetchGroups(Table<S> table, RecordMapper<? super R, E> mapper) {
return fetch().intoGroups(table, mapper);
return collect(toGroups(mapper(table), mapper));
}
@Override
@ -1293,66 +1299,74 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default <E> Set<E> fetchSet(RecordMapper<? super R, E> mapper) {
return fetch().intoSet(mapper);
return collect(toSet(mapper));
}
@Override
default Set<?> fetchSet(int fieldIndex) {
return fetch().intoSet(fieldIndex);
return collect(toSet(mapper(fieldIndex)));
}
@Override
default <U> Set<U> fetchSet(int fieldIndex, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return fetch().intoSet(fieldIndex, type);
}
@Override
default <U> Set<U> fetchSet(int fieldIndex, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return fetch().intoSet(fieldIndex, converter);
}
@Override
default Set<?> fetchSet(String fieldName) {
return fetch().intoSet(fieldName);
return collect(toSet(mapper(fieldName)));
}
@Override
default <U> Set<U> fetchSet(String fieldName, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return fetch().intoSet(fieldName, type);
}
@Override
default <U> Set<U> fetchSet(String fieldName, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return fetch().intoSet(fieldName, converter);
}
@Override
default Set<?> fetchSet(Name fieldName) {
return fetch().intoSet(fieldName);
return collect(toSet(mapper(fieldName)));
}
@Override
default <U> Set<U> fetchSet(Name fieldName, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return fetch().intoSet(fieldName, type);
}
@Override
default <U> Set<U> fetchSet(Name fieldName, Converter<?, ? extends U> converter) {
// [#9288] TODO: Refactor this
return fetch().intoSet(fieldName, converter);
}
@Override
default <T> Set<T> fetchSet(Field<T> field) {
return fetch().intoSet(field);
return collect(toSet(mapper(field)));
}
@Override
default <U> Set<U> fetchSet(Field<?> field, Class<? extends U> type) {
// [#9288] TODO: Refactor this
return fetch().intoSet(field, type);
}
@Override
default <T, U> Set<U> fetchSet(Field<T> field, Converter<? super T, ? extends U> converter) {
// [#9288] TODO: Refactor this
return fetch().intoSet(field, converter);
}
@Override
@ -1387,4 +1401,35 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
return false;
}
@Override
default RecordMapper<R, ?> mapper(int fieldIndex) {
return new DelayedRecordMapper<>(t -> t.mapper(fieldIndex));
}
@Override
default RecordMapper<R, ?> mapper(String fieldName) {
return new DelayedRecordMapper<>(t -> t.mapper(fieldName));
}
@Override
default RecordMapper<R, ?> mapper(Name fieldName) {
return new DelayedRecordMapper<>(t -> t.mapper(fieldName));
}
@Override
default <T> RecordMapper<R, T> mapper(Field<T> field) {
return new DelayedRecordMapper<>(t -> t.mapper(field));
}
@Override
default <S extends Record> RecordMapper<R, S> mapper(Table<S> table) {
return new DelayedRecordMapper<>(t -> t.mapper(table));
}
@Override
default <E> RecordMapper<R, E> mapper(Configuration configuration, Class<? extends E> type) {
return new DelayedRecordMapper<>(t -> t.mapper(configuration, type));
}
}

View File

@ -56,7 +56,6 @@ import static org.jooq.impl.CacheType.REFLECTION_CACHE_HAS_COLUMN_ANNOTATIONS;
// ...
// ...
// ...
import static org.jooq.SQLDialect.CUBRID;
import static org.jooq.SQLDialect.DERBY;
// ...
import static org.jooq.SQLDialect.FIREBIRD;
@ -247,6 +246,7 @@ import org.jooq.EnumType;
import org.jooq.ExecuteContext;
import org.jooq.ExecuteListener;
import org.jooq.Field;
import org.jooq.Fields;
import org.jooq.ForeignKey;
import org.jooq.JSON;
import org.jooq.JSONB;
@ -262,7 +262,6 @@ import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.RecordQualifier;
import org.jooq.RecordType;
import org.jooq.RenderContext;
import org.jooq.RenderContext.CastMode;
import org.jooq.Result;
@ -1687,11 +1686,11 @@ final class Tools {
return map(values, (v, i) -> field(v, types[i]), Field[]::new);
}
static final IllegalArgumentException indexFail(Row row, Field<?> field) {
static final IllegalArgumentException indexFail(Fields row, Field<?> field) {
return new IllegalArgumentException("Field (" + field + ") is not contained in Row " + row);
}
static final int indexOrFail(Row row, Field<?> field) {
static final int indexOrFail(Fields row, Field<?> field) {
int result = row.indexOf(field);
if (result < 0)
@ -1700,11 +1699,11 @@ final class Tools {
return result;
}
static final IllegalArgumentException indexFail(Row row, String fieldName) {
static final IllegalArgumentException indexFail(Fields row, String fieldName) {
throw new IllegalArgumentException("Field (" + fieldName + ") is not contained in Row " + row);
}
static final int indexOrFail(Row row, String fieldName) {
static final int indexOrFail(Fields row, String fieldName) {
int result = row.indexOf(fieldName);
if (result < 0)
@ -1713,11 +1712,11 @@ final class Tools {
return result;
}
static final IllegalArgumentException indexFail(Row row, Name fieldName) {
static final IllegalArgumentException indexFail(Fields row, Name fieldName) {
throw new IllegalArgumentException("Field (" + fieldName + ") is not contained in Row " + row);
}
static final int indexOrFail(Row row, Name fieldName) {
static final int indexOrFail(Fields row, Name fieldName) {
int result = row.indexOf(fieldName);
if (result < 0)
@ -1726,45 +1725,6 @@ final class Tools {
return result;
}
/**
* A utility method that fails with an exception if
* {@link RecordType#indexOf(Field)} doesn't return any index.
*/
static final int indexOrFail(RecordType<?> row, Field<?> field) {
int result = row.indexOf(field);
if (result < 0)
throw new IllegalArgumentException("Field (" + field + ") is not contained in RecordType " + row);
return result;
}
/**
* A utility method that fails with an exception if
* {@link RecordType#indexOf(String)} doesn't return any index.
*/
static final int indexOrFail(RecordType<?> row, String fieldName) {
int result = row.indexOf(fieldName);
if (result < 0)
throw new IllegalArgumentException("Field (" + fieldName + ") is not contained in RecordType " + row);
return result;
}
/**
* A utility method that fails with an exception if
* {@link RecordType#indexOf(Name)} doesn't return any index.
*/
static final int indexOrFail(RecordType<?> row, Name fieldName) {
int result = row.indexOf(fieldName);
if (result < 0)
throw new IllegalArgumentException("Field (" + fieldName + ") is not contained in RecordType " + row);
return result;
}
private static final <T> List<T> newListWithCapacity(Iterable<?> it) {
return it instanceof Collection ? new ArrayList<>(((Collection<?>) it).size()) : new ArrayList<>();
}