From 416f9cc088db9db98e242892b6033f7feb47d8ff Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 22 Dec 2020 17:51:22 +0100 Subject: [PATCH] [jOOQ/jOOQ#3185] Let ResultQuery, InsertResultStep, UpdateResultStep, DeleteResultStep extend Fetchable --- .../main/java/org/jooq/DeleteResultStep.java | 69 +- jOOQ/src/main/java/org/jooq/Fetchable.java | 4151 +++++++++++++++++ .../main/java/org/jooq/InsertResultStep.java | 60 +- jOOQ/src/main/java/org/jooq/ResultQuery.java | 4086 +--------------- .../main/java/org/jooq/UpdateResultStep.java | 68 +- .../java/org/jooq/impl/AbstractCursor.java | 1467 +----- .../jooq/impl/AbstractDelegatingQuery.java | 5 +- .../impl/AbstractDelegatingRowCountQuery.java | 6 +- .../java/org/jooq/impl/AbstractFetchable.java | 1212 +++++ .../java/org/jooq/impl/AbstractQuery.java | 3 +- .../java/org/jooq/impl/AbstractRecord.java | 6 +- .../java/org/jooq/impl/AbstractResult.java | 1441 ++++++ .../org/jooq/impl/AbstractResultQuery.java | 1118 +---- .../org/jooq/impl/AbstractRowCountQuery.java | 3 +- .../main/java/org/jooq/impl/CursorImpl.java | 181 +- .../main/java/org/jooq/impl/DeleteImpl.java | 15 +- .../main/java/org/jooq/impl/InsertImpl.java | 15 +- .../java/org/jooq/impl/ResultAsCursor.java | 92 + .../main/java/org/jooq/impl/ResultImpl.java | 2 +- .../main/java/org/jooq/impl/SelectImpl.java | 1068 +---- jOOQ/src/main/java/org/jooq/impl/Tools.java | 2 +- .../main/java/org/jooq/impl/UpdateImpl.java | 15 +- 22 files changed, 7061 insertions(+), 8024 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/Fetchable.java create mode 100644 jOOQ/src/main/java/org/jooq/impl/AbstractFetchable.java create mode 100644 jOOQ/src/main/java/org/jooq/impl/AbstractResult.java create mode 100644 jOOQ/src/main/java/org/jooq/impl/ResultAsCursor.java diff --git a/jOOQ/src/main/java/org/jooq/DeleteResultStep.java b/jOOQ/src/main/java/org/jooq/DeleteResultStep.java index 5f577e0a1d..033667f9fa 100644 --- a/jOOQ/src/main/java/org/jooq/DeleteResultStep.java +++ b/jOOQ/src/main/java/org/jooq/DeleteResultStep.java @@ -37,23 +37,6 @@ */ package org.jooq; -// ... -// ... -// ... -import static org.jooq.SQLDialect.FIREBIRD; -import static org.jooq.SQLDialect.MARIADB; -// ... -import static org.jooq.SQLDialect.POSTGRES; -// ... - -import java.util.Optional; - -import org.jooq.exception.DataAccessException; -import org.jooq.exception.TooManyRowsException; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - /** * This type is used for the {@link Delete}'s DSL API. *

@@ -93,56 +76,6 @@ import org.jetbrains.annotations.Nullable; * * @author Lukas Eder */ -public interface DeleteResultStep extends Delete { - - /** - * The result holding returned values as specified by the - * {@link DeleteReturningStep}. - * - * @return The returned values as specified by the - * {@link DeleteReturningStep}. Note: - *

    - *
  • Not all databases / JDBC drivers support returning several - * values on multi-row inserts!
  • - *
  • This may return an empty Result in case jOOQ - * could not retrieve any generated keys from the JDBC driver.
  • - *
- * @throws DataAccessException if something went wrong executing the query - * @see DeleteQuery#getReturnedRecords() - */ - @NotNull - @Support({ FIREBIRD, MARIADB, POSTGRES }) - Result fetch() throws DataAccessException; - - /** - * The record holding returned values as specified by the - * {@link DeleteReturningStep}. - * - * @return The returned value as specified by the - * {@link DeleteReturningStep}. This may return null in - * case jOOQ could not retrieve any generated keys from the JDBC - * driver. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see DeleteQuery#getReturnedRecord() - */ - @Nullable - @Support({ FIREBIRD, MARIADB, POSTGRES }) - R fetchOne() throws DataAccessException, TooManyRowsException; - - - /** - * The record holding returned values as specified by the - * {@link DeleteReturningStep}. - * - * @return The returned value as specified by the - * {@link DeleteReturningStep} - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see DeleteQuery#getReturnedRecord() - */ - @NotNull - @Support({ FIREBIRD, MARIADB, POSTGRES }) - Optional fetchOptional() throws DataAccessException, TooManyRowsException; +public interface DeleteResultStep extends Delete, Fetchable { } diff --git a/jOOQ/src/main/java/org/jooq/Fetchable.java b/jOOQ/src/main/java/org/jooq/Fetchable.java new file mode 100644 index 0000000000..916948ac33 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/Fetchable.java @@ -0,0 +1,4151 @@ +/* + * 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 java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.Spliterator; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; +import java.util.function.Consumer; +import java.util.stream.Collector; +import java.util.stream.Stream; + +import javax.sql.DataSource; + +import org.jooq.conf.Settings; +import org.jooq.exception.DataAccessException; +import org.jooq.exception.InvalidResultException; +import org.jooq.exception.MappingException; +import org.jooq.exception.NoDataFoundException; +import org.jooq.exception.TooManyRowsException; +import org.jooq.impl.DefaultRecordMapper; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface Fetchable extends Iterable { + + /** + * Execute the query and return the generated result. + *

+ * The result and its contained records are attached to the original + * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} + * to override this behaviour. + *

Lifecycle guarantees

This method completes the whole + * {@link ConnectionProvider} and {@link ExecuteListener} lifecycles, + * eagerly fetching all results into memory. Underlying JDBC + * {@link ResultSet}s are always closed. Underlying JDBC + * {@link PreparedStatement}s are closed, unless + * {@link ResultQuery#keepStatement(boolean)} is set. + *

+ * In order to keep open {@link ResultSet}s and fetch records lazily, use + * {@link #fetchLazy()} instead and then operate on {@link Cursor}. + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + Result fetch() throws DataAccessException; + + /** + * Execute the query and return the generated result as a JDBC + * {@link ResultSet}. + *

+ * This is the same as calling {@link #fetchLazy()}. + * {@link Cursor#resultSet() resultSet()} and will return a + * {@link ResultSet} wrapping the JDBC driver's ResultSet. + * Closing this ResultSet may close the producing + * {@link Statement} or {@link PreparedStatement}, depending on your setting + * for {@link ResultQuery#keepStatement(boolean)}. + *

+ * You can use this method when you want to use jOOQ for query execution, + * but not for result fetching. The returned ResultSet can also + * be used with {@link DSLContext#fetch(ResultSet)}. + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + ResultSet fetchResultSet() throws DataAccessException; + + /** + * Execute the query using {@link #fetch()} and return the generated result + * as an {@link Iterator}. + *

+ * {@inheritDoc} + */ + @NotNull + @Override + Iterator iterator() throws DataAccessException; + + + + /** + * Execute the query using {@link #fetch()} and pass all results to a + * consumer. + *

+ * This is essentially the same as {@link #fetch()}. + *

+ * {@inheritDoc} + */ + @Override + default void forEach(Consumer action) { + Iterable.super.forEach(action); + } + + /** + * Execute the query using {@link #fetch()} and return the generated result + * as an {@link Spliterator}. + *

+ * {@inheritDoc} + */ + @NotNull + @Override + default Spliterator spliterator() { + return Iterable.super.spliterator(); + } + + + /** + * Stream this query. + *

+ * This is just a synonym for {@link #stream()}. + *

+ * Clients should ensure the {@link Stream} is properly closed, e.g. in a + * try-with-resources statement: + *

+ *

+     * try (Stream<R> stream = query.stream()) {
+     *     // Do things with stream
+     * }
+     * 
+ *

+ * If users prefer more fluent style streaming of queries, {@link ResultSet} + * can be registered and closed via {@link ExecuteListener}, or via "smart" + * third-party {@link DataSource}s. + *

+ * Depending on your JDBC driver's default behaviour, this may load the + * whole database result into the driver's memory. In order to indicate to + * the driver that you may not want to fetch all records at once, use + * {@link ResultQuery#fetchSize(int)} prior to calling this method. + * + * @return The result. + * @throws DataAccessException if something went wrong executing the query + * @see #stream() + */ + @NotNull + Stream fetchStream() throws DataAccessException; + + /** + * Stream this query, mapping records into a custom type. + *

+ * This is the same as calling + * fetchStream().map(r -> r.into(type)). See + * {@link Record#into(Class)} for more details. + *

+ * Clients should ensure the {@link Stream} is properly closed, e.g. in a + * try-with-resources statement: + *

+ *

+     * try (Stream<R> stream = query.stream()) {
+     *     // Do things with stream
+     * }
+     * 
+ *

+ * If users prefer more fluent style streaming of queries, {@link ResultSet} + * can be registered and closed via {@link ExecuteListener}, or via "smart" + * third-party {@link DataSource}s. + *

+ * Depending on your JDBC driver's default behaviour, this may load the + * whole database result into the driver's memory. In order to indicate to + * the driver that you may not want to fetch all records at once, use + * {@link ResultQuery#fetchSize(int)} prior to calling this method. + * + * @param The generic entity type. + * @param type The entity type. + * @see Record#into(Class) + * @see Result#into(Class) + * @see DefaultRecordMapper + * @return The results. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + */ + @NotNull + Stream fetchStreamInto(Class type) throws DataAccessException, MappingException; + + /** + * Stream this query, mapping records into a custom record. + *

+ * This is the same as calling + * fetchStream().map(r -> r.into(table)). See + * {@link Record#into(Table)} for more details. + *

+ * The result and its contained records are attached to the original + * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} + * to override this behaviour. + *

+ * Clients should ensure the {@link Stream} is properly closed, e.g. in a + * try-with-resources statement: + *

+ *

+     * try (Stream<R> stream = query.stream()) {
+     *     // Do things with stream
+     * }
+     * 
+ *

+ * If users prefer more fluent style streaming of queries, {@link ResultSet} + * can be registered and closed via {@link ExecuteListener}, or via "smart" + * third-party {@link DataSource}s. + *

+ * Depending on your JDBC driver's default behaviour, this may load the + * whole database result into the driver's memory. In order to indicate to + * the driver that you may not want to fetch all records at once, use + * {@link ResultQuery#fetchSize(int)} prior to calling this method. + * + * @param The generic table record type. + * @param table The table type. + * @return The results. This will never be null. + * @see Record#into(Table) + * @see Result#into(Table) + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + Stream fetchStreamInto(Table table) throws DataAccessException; + + /** + * Stream this query. + *

+ * This is essentially the same as {@link #fetchLazy()} but instead of + * returning a {@link Cursor}, a Java 8 {@link Stream} is returned. Clients + * should ensure the {@link Stream} is properly closed, e.g. in a + * try-with-resources statement: + *

+ *

+     * try (Stream<R> stream = query.stream()) {
+     *     // Do things with stream
+     * }
+     * 
+ *

+ * If users prefer more fluent style streaming of queries, {@link ResultSet} + * can be registered and closed via {@link ExecuteListener}, or via "smart" + * third-party {@link DataSource}s. + *

+ * Depending on your JDBC driver's default behaviour, this may load the + * whole database result into the driver's memory. In order to indicate to + * the driver that you may not want to fetch all records at once, use + * {@link ResultQuery#fetchSize(int)} prior to calling this method. + * + * @return The result. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + Stream stream() throws DataAccessException; + + /** + * Reduce the execution results of this query using a {@link Collector}. + *

+ * This works in the same way as calling the following code: + * + *

+     * 
+     * try (Stream<R> stream = resultQuery.stream()) {
+     *     X result = stream.collect(collector);
+     * }
+     * 
+     * 
+ * + * ... with the exception of allowing client code to ignore the need for + * managing resources, which are handled inside of the + * collect() method. + * + * @param collector The collector that collects all records and accumulates + * them into a result type. + * @return The result of the collection. + * @throws DataAccessException if something went wrong executing the query + */ + X collect(Collector collector) throws DataAccessException; + + + + /** + * Execute the query and "lazily" return the generated result. + *

+ * The returned {@link Cursor} holds a reference to the executed + * {@link PreparedStatement} and the associated {@link ResultSet}. Data can + * be fetched (or iterated over) lazily, fetching records from the + * {@link ResultSet} one by one. + *

+ * Depending on your JDBC driver's default behaviour, this may load the + * whole database result into the driver's memory. In order to indicate to + * the driver that you may not want to fetch all records at once, use + * {@link ResultQuery#fetchSize(int)} prior to calling this method. + *

+ * Client code is responsible for closing the cursor after use. + * + * @return The resulting cursor. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see ResultQuery#fetchSize(int) + */ + @NotNull + Cursor fetchLazy() throws DataAccessException; + + /** + * Execute a query, possibly returning several result sets. + *

+ * Example (Sybase ASE): + *

+ *

+     * String sql = "sp_help 'my_table'";
+ *

+ * The result and its contained records are attached to the original + * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} + * to override this behaviour. + * + * @return The resulting records. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + Results fetchMany() throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + *

+ * This is the same as calling {@link #fetch()} and then + * {@link Result#getValues(Field)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + List fetch(Field field) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + *

+ * This is the same as calling {@link #fetch()} and then + * {@link Result#getValues(Field, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(Field, Class) + */ + @NotNull + List fetch(Field field, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + *

+ * This is the same as calling {@link #fetch()} and then + * {@link Result#getValues(Field, Converter)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(Field, Converter) + */ + @NotNull + List fetch(Field field, Converter converter) throws DataAccessException; + + /** + * 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)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + List fetch(int fieldIndex) throws DataAccessException; + + /** + * 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)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(int, Class) + */ + @NotNull + List fetch(int fieldIndex, Class type) throws DataAccessException; + + /** + * 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, Converter)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(int, Converter) + */ + @NotNull + List fetch(int fieldIndex, Converter converter) throws DataAccessException; + + /** + * 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)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + List fetch(String fieldName) throws DataAccessException; + + /** + * 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)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(String, Class) + */ + @NotNull + List fetch(String fieldName, Class type) throws DataAccessException; + + /** + * 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, Converter)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(String, Converter) + */ + @NotNull + List fetch(String fieldName, Converter converter) throws DataAccessException; + + /** + * 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(Name)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + List fetch(Name fieldName) throws DataAccessException; + + /** + * 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(Name, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(Name, Class) + */ + @NotNull + List fetch(Name fieldName, Class type) throws DataAccessException; + + /** + * 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(Name, Converter)} + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Record#get(Name, Converter) + */ + @NotNull + List fetch(Name fieldName, Converter converter) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Field)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + T fetchOne(Field field) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Field, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(Field field, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Field, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(Field field, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(int)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Object fetchOne(int fieldIndex) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(int, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(int fieldIndex, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(int, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(int fieldIndex, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(String)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Object fetchOne(String fieldName) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(String, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(String fieldName, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(String, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(String fieldName, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Name)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Object fetchOne(Name fieldName) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a field name + * from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Name, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(Name fieldName, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Name, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchOne(Name fieldName, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting record. + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @return The resulting record or null if the query returns no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + R fetchOne() throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value into a + * custom mapper callback. + * + * @return The custom mapped record or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + E fetchOne(RecordMapper mapper) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting record as a name/value + * map. + * + * @return The resulting record or null if the query returns no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + * @see Result#intoMaps() + * @see Record#intoMap() + */ + @Nullable + Map fetchOneMap() throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting record as an array + *

+ * You can access data like this + *

query.fetchOneArray()[fieldIndex]
+ * + * @return The resulting record or null if the query returns no + * records. + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Object[] fetchOneArray() throws DataAccessException, TooManyRowsException; + + /** + * Map resulting records onto a custom type. + *

+ * This is the same as calling

+     * E result = null;
+     * Record r = q.fetchOne();
+     *
+     * if (r != null)
+     *     result = r.into(type);
+     * 
. See {@link Record#into(Class)} for more details + * + * @param The generic entity type. + * @param type The entity type. + * @return The resulting record or null if the query returns no + * records. + * @see Record#into(Class) + * @see Result#into(Class) + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws TooManyRowsException if the query returned more than one record + * @see DefaultRecordMapper + */ + @Nullable + E fetchOneInto(Class type) throws DataAccessException, MappingException, TooManyRowsException; + + /** + * Map resulting records onto a custom record. + *

+ * This is the same as calling

+     * Z result = null;
+     * Record r = q.fetchOne();
+     *
+     * if (r != null)
+     *     result = r.into(table);
+     * 
. See {@link Record#into(Table)} for more details + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @param The generic table record type. + * @param table The table type. + * @return The resulting record or null if the query returns no + * records. + * @see Record#into(Table) + * @see Result#into(Table) + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Z fetchOneInto(Table table) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field from + * the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(Field)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + T fetchSingle(Field field) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field from + * the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(Field, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(Field field, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field from + * the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(Field, Converter)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(Field field, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field + * index from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(int)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Object fetchSingle(int fieldIndex) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field + * index from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(int, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(int fieldIndex, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field + * index from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(int, Converter)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(int fieldIndex, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field name + * from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(String)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Object fetchSingle(String fieldName) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field name + * from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(String, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(String fieldName, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field name + * from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(String, Converter)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(String fieldName, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field name + * from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(Name)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + Object fetchSingle(Name fieldName) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field name + * from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(Name, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(Name fieldName, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value for a field name + * from the generated result. + *

+ * This is the same as calling {@link #fetchSingle()} and then + * {@link Record#get(Name, Converter)} + * + * @return The resulting value. Unlike other {@link #fetchSingle()} methods, + * which never produce null records, this can be null + * if the resulting value in the record is null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @Nullable + U fetchSingle(Name fieldName, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting record. + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @return The resulting value. This is never null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + R fetchSingle() throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting value into a custom + * mapper callback. + * + * @return The resulting value. This is never null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + E fetchSingle(RecordMapper mapper) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting record as a name/value + * map. + * + * @return The resulting value. This is never null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + * @see Result#intoMaps() + * @see Record#intoMap() + */ + @NotNull + Map fetchSingleMap() throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Execute the query and return exactly one resulting record as an array + *

+ * You can access data like this + *

query.fetchSingleArray()[fieldIndex]
+ * + * @return The resulting value. This is never null. + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Object[] fetchSingleArray() throws DataAccessException, NoDataFoundException, TooManyRowsException; + + /** + * Map resulting records onto a custom type. + *

+ * This is the same as calling

+     * E result = null;
+     * Record r = q.fetchSingle();
+     *
+     * if (r != null)
+     *     result = r.into(type);
+     * 
. See {@link Record#into(Class)} for more details + * + * @param The generic entity type. + * @param type The entity type. + * @return The resulting value. + * @see Record#into(Class) + * @see Result#into(Class) + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + * @see DefaultRecordMapper + */ + // [#10774] This is @Nullable in rare cases, which can be annoying for Kotlin users in most cases + E fetchSingleInto(Class type) throws DataAccessException, MappingException, NoDataFoundException, TooManyRowsException; + + /** + * Map resulting records onto a custom record. + *

+ * This is the same as calling

+     * Z result = null;
+     * Record r = q.fetchSingle();
+     *
+     * if (r != null)
+     *     result = r.into(table);
+     * 
. See {@link Record#into(Table)} for more details + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @param The generic table record type. + * @param table The table type. + * @return The resulting value. This is never null. + * @see Record#into(Table) + * @see Result#into(Table) + * @throws DataAccessException if something went wrong executing the query + * @throws NoDataFoundException if the query returned no records + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Z fetchSingleInto(Table table) throws DataAccessException, NoDataFoundException, TooManyRowsException; + + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(Field)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(Field field) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(Field, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(Field field, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(Field, Converter)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(Field field, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(int)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(int fieldIndex) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(int, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(int fieldIndex, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(int, Converter)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(int fieldIndex, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(String)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(String fieldName) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(String, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(String fieldName, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(String, Converter)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(String fieldName, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(Name)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(Name fieldName) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(Name, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(Name fieldName, Class type) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOptional()} and then + * {@link Record#get(Name, Converter)} + * + * @return The resulting value + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(Name fieldName, Converter converter) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting record. + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @return The resulting record + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional() throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting value into a + * custom mapper callback. + * + * @return The custom mapped record + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptional(RecordMapper mapper) throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting record as a name/value + * map. + * + * @return The resulting record + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + * @see Result#intoMaps() + * @see Record#intoMap() + */ + @NotNull + Optional> fetchOptionalMap() throws DataAccessException, TooManyRowsException; + + /** + * Execute the query and return at most one resulting record as an array. + * + * @return The resulting record + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptionalArray() throws DataAccessException, TooManyRowsException; + + /** + * Map resulting records onto a custom type. + *

+ * This is the same as calling

+     * Optional<E> result = q.fetchOptional().map(r -> r.into(type));
+     * 
. See {@link Record#into(Class)} for more details + * + * @param The generic entity type. + * @param type The entity type. + * @return The resulting record + * @see Record#into(Class) + * @see Result#into(Class) + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws TooManyRowsException if the query returned more than one record + * @see DefaultRecordMapper + */ + @NotNull + Optional fetchOptionalInto(Class type) throws DataAccessException, MappingException, TooManyRowsException; + + /** + * Map resulting records onto a custom record. + *

+ * This is the same as calling

+     * Optional<Z> result = q.fetchOptional().map(r -> r.into(table));
+     * 
. See {@link Record#into(Table)} for more details + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @param The generic table record type. + * @param table The table type. + * @return The resulting record + * @see Record#into(Table) + * @see Result#into(Table) + * @throws DataAccessException if something went wrong executing the query + * @throws TooManyRowsException if the query returned more than one record + */ + @NotNull + Optional fetchOptionalInto(Table table) throws DataAccessException, TooManyRowsException; + + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Field)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + T fetchAny(Field field) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a field from + * the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Field, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(Field field, Class type) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Field, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(Field field, Converter converter) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(int)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + Object fetchAny(int fieldIndex) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a field + * index from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(int, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(int fieldIndex, Class type) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field index from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(int, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(int fieldIndex, Converter converter) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(String)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + Object fetchAny(String fieldName) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(String, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(String fieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(String, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(String fieldName, Converter converter) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Name)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + Object fetchAny(Name fieldName) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Name, Class)} + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(Name fieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return at most one resulting value for a + * field name from the generated result. + *

+ * This is the same as calling {@link #fetchOne()} and then + * {@link Record#get(Name, Converter)} + * + * @return The resulting value or null if the query returned no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + U fetchAny(Name fieldName, Converter converter) throws DataAccessException; + + /** + * Execute the query and return at most one resulting record. + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @return The first resulting record or null if the query + * returns no records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + R fetchAny() throws DataAccessException; + + /** + * Execute the query and return at most one resulting record. + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @return The first resulting record or null if the query + * returns no records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + E fetchAny(RecordMapper mapper) throws DataAccessException; + + /** + * Execute the query and return at most one resulting record as a name/value + * map. + * + * @return The resulting record or null if the query returns no + * records. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoMaps() + * @see Record#intoMap() + */ + @Nullable + Map fetchAnyMap() throws DataAccessException; + + /** + * Execute the query and return at most one resulting record as an array + *

+ * You can access data like this + *

query.fetchAnyArray()[fieldIndex]
+ * + * @return The resulting record or null if the query returns no + * records. + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + Object[] fetchAnyArray() throws DataAccessException; + + /** + * Map resulting records onto a custom type. + *

+ * This is the same as calling

+     * E result = null;
+     * Record r = q.fetchAny();
+     *
+     * if (r != null)
+     *     result = r.into(type);
+     * 
. See {@link Record#into(Class)} for more details + * + * @param The generic entity type. + * @param type The entity type. + * @return The resulting record or null if the query returns no + * records. + * @see Record#into(Class) + * @see Result#into(Class) + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see DefaultRecordMapper + */ + @Nullable + E fetchAnyInto(Class type) throws DataAccessException, MappingException; + + /** + * Map resulting records onto a custom record. + *

+ * This is the same as calling

+     * Z result = null;
+     * Record r = q.fetchOne();
+     *
+     * if (r != null)
+     *     result = r.into(table);
+     * 
. See {@link Record#into(Table)} for more details + *

+ * The resulting record is attached to the original {@link Configuration} by + * default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @param The generic table record type. + * @param table The table type. + * @return The resulting record or null if the query returns no + * records. + * @see Record#into(Table) + * @see Result#into(Table) + * @throws DataAccessException if something went wrong executing the query + */ + @Nullable + Z fetchAnyInto(Table table) throws DataAccessException; + + /** + * Execute the query and return the generated result as a list of name/value + * maps. + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMaps() + * @see Record#intoMap() + */ + @NotNull + List> fetchMaps() throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and the corresponding records as value. + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(Field)} instead, if your keys are + * non-unique + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param The key's generic field type + * @param key The key field. Client code must assure that this field is + * unique in the result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(Field) + */ + @NotNull + Map fetchMap(Field key) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and the corresponding records as value. + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(int)} instead, if your keys are + * non-unique + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key field. Client code must assure that this + * field is unique in the result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(int) + */ + @NotNull + Map fetchMap(int keyFieldIndex) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and the corresponding records as value. + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(String)} instead, if your keys are + * non-unique + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field. Client code must assure that this + * field is unique in the result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(String) + */ + @NotNull + Map fetchMap(String keyFieldName) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and the corresponding records as value. + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(Name)} instead, if your keys are + * non-unique + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field. Client code must assure that this + * field is unique in the result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(Name) + */ + @NotNull + Map fetchMap(Name keyFieldName) 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 + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(Field, Field)} instead, if your keys + * are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param The key's generic field type + * @param The value's generic field type + * @param key The key field. Client code must assure that this field is + * unique in the result set. + * @param value The value field + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(Field, Field) + */ + @NotNull + Map fetchMap(Field key, Field value) 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 + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(int, int)} instead, if your keys are + * non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key field. Client code must assure that this + * field is unique in the result set. + * @param valueFieldIndex The value field + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(int, int) + */ + @NotNull + Map fetchMap(int keyFieldIndex, int valueFieldIndex) 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 + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(String, String)} instead, if your keys + * are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field. Client code must assure that this + * field is unique in the result set. + * @param valueFieldName The value field + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(String, String) + */ + @NotNull + Map fetchMap(String keyFieldName, String valueFieldName) 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 + *

+ * An exception is thrown, if the key turns out to be non-unique in the + * result set. Use {@link #fetchGroups(Name, Name)} instead, if your keys + * are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field. Client code must assure that this + * field is unique in the result set. + * @param valueFieldName The value field + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key field returned two or more + * equal values from the result set. + * @see Result#intoMap(Name, Name) + */ + @NotNull + Map fetchMap(Name keyFieldName, Name valueFieldName) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Field[])} instead, if your keys are + * non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys. Client code must assure that keys are unique in the + * result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Field[]) + */ + @NotNull + Map fetchMap(Field[] keys) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(int[])} instead, if your keys are + * non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys. Client code must assure that keys are + * unique in the result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(int[]) + */ + @NotNull + Map fetchMap(int[] keyFieldIndexes) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(String[])} instead, if your keys are + * non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(String[]) + */ + @NotNull + Map fetchMap(String[] keyFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Name[])} instead, if your keys are + * non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Name[]) + */ + @NotNull + Map fetchMap(Name[] keyFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Field[], Field[])} instead, if your + * keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys. Client code must assure that keys are unique in the + * result set. + * @param values The values. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Field[], Field[]) + */ + @NotNull + Map fetchMap(Field[] keys, Field[] values) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(int[], int[])} instead, if your keys + * are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys. Client code must assure that keys are + * unique in the result set. + * @param valueFieldIndexes The values. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(int[], int[]) + */ + @NotNull + Map fetchMap(int[] keyFieldIndexes, int[] valueFieldIndexes) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(String[], String[])} instead, if your + * keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. + * @param valueFieldNames The values. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(String[], String[]) + */ + @NotNull + Map fetchMap(String[] keyFieldNames, String[] valueFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with keys as a map key and the + * corresponding record as value. + *

+ * An exception is thrown, if the keys turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Name[], Name[])} instead, if your + * keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. + * @param valueFieldNames The values. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Name[], Name[]) + */ + @NotNull + Map fetchMap(Name[] keyFieldNames, Name[] valueFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Field[], Class)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys. Client code must assure that keys are unique in the + * result set. If this is null or an empty array, + * the resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(Field[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(Field[] keys, Class type) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(int[], Class)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys. Client code must assure that keys are + * unique in the result set. If this is null or an + * empty array, the resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(int[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(int[] keyFieldIndexes, Class type) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(String[], Class)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. If this is null or an + * empty array, the resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(String[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(String[] keyFieldNames, Class type) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Name[], Class)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. If this is null or an + * empty array, the resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(Name[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(Name[] keyFieldNames, Class type) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Field[], RecordMapper)} + * instead, if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys. Client code must assure that keys are unique in the + * result set. If this is null or an empty array, + * the resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(Field[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(Field[] keys, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(int[], RecordMapper)} instead, + * if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys. Client code must assure that keys are + * unique in the result set. If this is null or an + * empty array, the resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(int[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(int[] keyFieldIndexes, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(String[], RecordMapper)} + * instead, if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. If this is null or an + * empty array, the resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(String[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(String[] keyFieldNames, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Name[], RecordMapper)} + * instead, if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. Client code must assure that keys are + * unique in the result set. If this is null or an + * empty array, the resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(Name[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map, E> fetchMap(Name[] keyFieldNames, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Class)} instead, if your keys + * are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyType The key type. If this is null, the resulting + * map will contain at most one entry. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Class) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(Class keyType) throws DataAccessException, MappingException, InvalidResultException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Class, Class)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyType The key type. If this is null, the resulting + * map will contain at most one entry. + * @param valueType The value type. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Class, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(Class keyType, Class valueType) throws DataAccessException, MappingException, InvalidResultException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Class, RecordMapper)} instead, + * if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyType The key type. If this is null, the resulting + * map will contain at most one entry. + * @param valueMapper The value mapper. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Class, RecordMapper) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(Class keyType, RecordMapper valueMapper) throws DataAccessException, InvalidResultException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(RecordMapper)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyMapper The key mapper. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(RecordMapper) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(RecordMapper keyMapper) throws DataAccessException, InvalidResultException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(RecordMapper, Class)} instead, + * if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyMapper The key mapper. + * @param valueType The value type. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(RecordMapper, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(RecordMapper keyMapper, Class valueType) throws DataAccessException, InvalidResultException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(RecordMapper, RecordMapper)} + * instead, if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyMapper The key mapper. + * @param valueMapper The value mapper. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(RecordMapper, RecordMapper) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(RecordMapper keyMapper, RecordMapper valueMapper) throws DataAccessException, InvalidResultException, MappingException; + + /** + * Execute the query and return a {@link Map} with table as a map key and + * the corresponding record as value. + *

+ * An {@link InvalidResultException} is thrown, if the keys turn out to be + * non-unique in the result set. Use {@link #fetchGroups(Table)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param table The key table. Client code must assure that keys are unique + * in the result set. May not be null. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Table) + */ + @NotNull + Map fetchMap(Table table) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with table as a map key and + * the corresponding record as value. + *

+ * An {@link InvalidResultException} is thrown, if the keys turn out to be + * non-unique in the result set. Use {@link #fetchGroups(Table, Table)} + * instead, if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyTable The key table. Client code must assure that keys are + * unique in the result set. May not be null. + * @param valueTable The value table. May not be null. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key list is non-unique in the + * result set. + * @see Result#intoMap(Table, Table) + */ + @NotNull + Map fetchMap(Table keyTable, Table valueTable) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given table and mapped into the given entity type. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Table, Class)} instead, if + * your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param table The key table. Client code must assure that keys are unique + * in the result set. May not be null. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(Table, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(Table table, Class type) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given table and mapped by the given mapper. + *

+ * An {@link InvalidResultException} is thrown, if the keys are non-unique + * in the result set. Use {@link #fetchGroups(Table, RecordMapper)} instead, + * if your keys are non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param table The key table. Client code must assure that keys are unique + * in the result set. May not be null. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the keys are non-unique in the result + * set. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoMap(Table, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map fetchMap(Table table, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped into the given entity type. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Field, Class)} instead, if your key + * is non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param key The key. Client code must assure that key is unique in the + * result set. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(Field, Class) + */ + @NotNull + Map fetchMap(Field key, Class type) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped into the given entity type. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(int, Class)} instead, if your key + * is non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key. Client code must assure that key is unique + * in the result set. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(int, Class) + */ + @NotNull + Map fetchMap(int keyFieldIndex, Class type) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped into the given entity type. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(String, Class)} instead, if your key + * is non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key. Client code must assure that key is unique + * in the result set. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(String, Class) + */ + @NotNull + Map fetchMap(String keyFieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped into the given entity type. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Name, Class)} instead, if your key + * is non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key. Client code must assure that key is unique + * in the result set. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(Name, Class) + */ + @NotNull + Map fetchMap(Name keyFieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped by the given mapper. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Field, Class)} instead, if your key + * is non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param key The key. Client code must assure that key is unique in the + * result set. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(Field, Class) + */ + @NotNull + Map fetchMap(Field key, RecordMapper mapper) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped by the given mapper. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(int, Class)} instead, if your key is + * non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key. Client code must assure that key is unique + * in the result set. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(int, Class) + */ + @NotNull + Map fetchMap(int keyFieldIndex, RecordMapper mapper) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped by the given mapper. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(String, Class)} instead, if your key + * is non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key. Client code must assure that key is unique + * in the result set. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(String, Class) + */ + @NotNull + Map fetchMap(String keyFieldName, RecordMapper mapper) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key and mapped by the given mapper. + *

+ * An exception is thrown, if the key turn out to be non-unique in the + * result set. Use {@link #fetchGroups(Name, Class)} instead, if your key + * is non-unique. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key. Client code must assure that key is unique + * in the result set. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws InvalidResultException if the key is non-unique in the result + * set. + * @see Result#intoMap(Name, Class) + */ + @NotNull + Map fetchMap(Name keyFieldName, RecordMapper mapper) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and a list of corresponding records as value. + *

+ * Unlike {@link #fetchMap(Field)}, this method allows for non-unique keys + * in the result set. + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param The key's generic field type + * @param key The key field. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Field) + */ + @NotNull + Map> fetchGroups(Field key) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and a list of corresponding records as value. + *

+ * Unlike {@link #fetchMap(int)}, this method allows for non-unique keys in + * the result set. + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key field index. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(int) + */ + @NotNull + Map> fetchGroups(int keyFieldIndex) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and a list of corresponding records as value. + *

+ * Unlike {@link #fetchMap(String)}, this method allows for non-unique keys + * in the result set. + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(String) + */ + @NotNull + Map> fetchGroups(String keyFieldName) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with one of the result's + * columns as key and a list of corresponding records as value. + *

+ * Unlike {@link #fetchMap(Name)}, this method allows for non-unique keys + * in the result set. + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Name) + */ + @NotNull + Map> fetchGroups(Name keyFieldName) 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. + *

+ * The resulting map is iteration order preserving. + * + * @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. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Field, Field) + */ + @NotNull + Map> fetchGroups(Field key, Field value) 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(int, int)}, this method allows for non-unique + * keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key field index. + * @param valueFieldIndex The value field index. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(int, int) + */ + @NotNull + Map> fetchGroups(int keyFieldIndex, int valueFieldIndex) 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(String, String)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @param valueFieldName The value field name. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(String, String) + */ + @NotNull + Map> fetchGroups(String keyFieldName, String valueFieldName) 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(Name, Name)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @param valueFieldName The value field name. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Name, Name) + */ + @NotNull + Map> fetchGroups(Name keyFieldName, Name valueFieldName) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(Field[])}, this method allows for non-unique keys + * in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Field[]) + */ + @NotNull + Map> fetchGroups(Field[] keys) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(int[])}, this method allows for non-unique keys + * in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(int[]) + */ + @NotNull + Map> fetchGroups(int[] keyFieldIndexes) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(String[])}, this method allows for non-unique + * keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(String[]) + */ + @NotNull + Map> fetchGroups(String[] keyFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(Name[])}, this method allows for non-unique + * keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Name[]) + */ + @NotNull + Map> fetchGroups(Name[] keyFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(Field[], Field[])}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @param values The values. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Field[], Field[]) + */ + @NotNull + Map> fetchGroups(Field[] keys, Field[] values) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(int[], int[])}, this method allows for non-unique + * keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @param valueFieldIndexes The values. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(int[], int[]) + */ + @NotNull + Map> fetchGroups(int[] keyFieldIndexes, int[] valueFieldIndexes) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(String[], String[])}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @param valueFieldNames The values. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(String[], String[]) + */ + @NotNull + Map> fetchGroups(String[] keyFieldNames, String[] valueFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given keys. + *

+ * Unlike {@link #fetchMap(Name[], Name[])}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys used for result grouping. If this is + * null or an empty array, the resulting map will + * contain at most one entry. + * @param valueFieldNames The values returned per group. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Name[], Name[]) + */ + @NotNull + Map> fetchGroups(Name[] keyFieldNames, Name[] valueFieldNames) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * Unlike {@link #fetchMap(Field[], Class)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys. If this is null or an empty array, the + * resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Field[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Field[] keys, Class type) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * Unlike {@link #fetchMap(int[], Class)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys. If this is null or an empty + * array, the resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(int[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(int[] keyFieldIndexes, Class type) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * Unlike {@link #fetchMap(String[], Class)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. If this is null or an empty + * array, the resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(String[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(String[] keyFieldNames, Class type) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped into the given entity type. + *

+ * Unlike {@link #fetchMap(Name[], Class)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. If this is null or an empty + * array, the resulting map will contain at most one entry. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Name[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Name[] keyFieldNames, Class type) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * Unlike {@link #fetchMap(Field[], RecordMapper)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keys The keys. If this is null or an empty array, the + * resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing grouped results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Field[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Field[] keys, RecordMapper mapper) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * Unlike {@link #fetchMap(int[], RecordMapper)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndexes The keys. If this is null or an empty + * array, the resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(int[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(int[] keyFieldIndexes, RecordMapper mapper) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * Unlike {@link #fetchMap(String[], RecordMapper)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. If this is null or an empty + * array, the resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(String[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(String[] keyFieldNames, RecordMapper mapper) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given keys and mapped by the given mapper. + *

+ * Unlike {@link #fetchMap(Name[], RecordMapper)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldNames The keys. If this is null or an empty + * array, the resulting map will contain at most one entry. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Name[], Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Name[] keyFieldNames, RecordMapper mapper) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * Unlike {@link #fetchMap(Class)}, this method allows for non-unique keys + * in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyType The key type. If this is null, the resulting + * map will contain at most one entry. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Class keyType) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * Unlike {@link #fetchMap(Class, Class)}, this method allows for non-unique + * keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyType The key type. If this is null, the resulting + * map will contain at most one entry. + * @param valueType The value type. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Class keyType, Class valueType) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * Unlike {@link #fetchMap(Class, RecordMapper)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyType The key type. If this is null, the resulting + * map will contain at most one entry. + * @param valueMapper The value mapper. + * @return A Map containing grouped results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Class keyType, RecordMapper valueMapper) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * Unlike {@link #fetchMap(RecordMapper, RecordMapper)}, this method allows + * for non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyMapper The key mapper. + * @return A Map containing the results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(RecordMapper keyMapper) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * Unlike {@link #fetchMap(RecordMapper, Class)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyMapper The key mapper. + * @param valueType The value type. + * @return A Map containing the results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(RecordMapper keyMapper, Class valueType) throws MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given key entity and mapped into the given entity type. + *

+ * The grouping semantics is governed by the key type's + * {@link Object#equals(Object)} and {@link Object#hashCode()} + * implementation, not necessarily the values as fetched from the database. + *

+ * Unlike {@link #fetchMap(RecordMapper, RecordMapper)}, this method allows + * for non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyMapper The key mapper. + * @param valueMapper The value mapper. + * @return A Map containing the results. This will never be + * null. + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(RecordMapper keyMapper, RecordMapper valueMapper) throws MappingException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given table. + *

+ * Unlike {@link #fetchMap(Table)}, this method allows for non-unique keys + * in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param table The key table. May not be null. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Table) + */ + @NotNull + Map> fetchGroups(Table table) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with the result grouped by the + * given table. + *

+ * Unlike {@link #fetchMap(Table, Table)}, this method allows for non-unique + * keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param keyTable The key table. May not be null. + * @param valueTable The value table. May not be null. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoGroups(Table, Table) + */ + @NotNull + Map> fetchGroups(Table keyTable, Table valueTable) throws DataAccessException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given table and mapped into the given entity type. + *

+ * Unlike {@link #fetchMap(Table, Class)}, this method allows for non-unique + * keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param table The key table. May not be null. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Table, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Table table, Class type) throws DataAccessException, MappingException; + + /** + * Execute the query and return a {@link Map} with results grouped by the + * given table and mapped by the given mapper. + *

+ * Unlike {@link #fetchMap(Table, RecordMapper)}, this method allows for + * non-unique keys in the result set. + *

+ * The resulting map is iteration order preserving. + * + * @param table The key table. May not be null. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Table, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Table table, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped + * into the given entity type. + *

+ * The resulting map is iteration order preserving. + * + * @param The key's generic field type + * @param The generic entity type. + * @param key The key field. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Field, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Field key, Class type) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped + * into the given entity type. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key field index. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(int, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(int keyFieldIndex, Class type) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped + * into the given entity type. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(String, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(String keyFieldName, Class type) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped + * into the given entity type. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @param type The entity type. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Name, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Name keyFieldName, Class type) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped by + * the given mapper. + *

+ * The resulting map is iteration order preserving. + * + * @param The key's generic field type + * @param The generic entity type. + * @param key The key field. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Field, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Field key, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped by + * the given mapper. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldIndex The key field index. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(int, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(int keyFieldIndex, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped by + * the given mapper. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(String, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(String keyFieldName, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Return a {@link Map} with results grouped by the given key and mapped by + * the given mapper. + *

+ * The resulting map is iteration order preserving. + * + * @param keyFieldName The key field name. + * @param mapper The mapper callback. + * @return A Map containing the results. This will never be + * null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + * @see Result#intoGroups(Name, Class) + * @see DefaultRecordMapper + */ + @NotNull + Map> fetchGroups(Name keyFieldName, RecordMapper mapper) throws DataAccessException, MappingException; + + /** + * Execute the query and return the generated result as an Object matrix. + *

+ * You can access data like this + *

query.fetchArray()[recordIndex][fieldIndex]
+ * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArrays() + */ + @NotNull + Object[][] fetchArrays() throws DataAccessException; + + /** + * Execute the query and return the generated result as an array of records. + *

+ * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#toArray(Object[]) + */ + @NotNull + R[] fetchArray() throws DataAccessException; + + /** + * Execute the query and return all values for a field index from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldIndex)[recordIndex]
+ * + * @return The resulting values. This may be an array type more concrete + * than Object[], depending on whether jOOQ has any + * knowledge about fieldIndex's actual type. This will + * never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(int) + */ + @NotNull + Object[] fetchArray(int fieldIndex) throws DataAccessException; + + /** + * Execute the query and return all values for a field index from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldIndex)[recordIndex]
+ *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(int, Class) + */ + @NotNull + U[] fetchArray(int fieldIndex, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field index from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldIndex)[recordIndex]
+ * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(int, Converter) + */ + @NotNull + U[] fetchArray(int fieldIndex, Converter converter) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldName)[recordIndex]
+ * + * @return The resulting values. This may be an array type more concrete + * than Object[], depending on whether jOOQ has any + * knowledge about fieldName's actual type. This will + * never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(String) + */ + @NotNull + Object[] fetchArray(String fieldName) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldName)[recordIndex]
+ *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(String, Converter) + */ + @NotNull + U[] fetchArray(String fieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldName)[recordIndex]
+ * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(String, Class) + */ + @NotNull + U[] fetchArray(String fieldName, Converter converter) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldName)[recordIndex]
+ * + * @return The resulting values. This may be an array type more concrete + * than Object[], depending on whether jOOQ has any + * knowledge about fieldName's actual type. This will + * never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Name) + */ + @NotNull + Object[] fetchArray(Name fieldName) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldName)[recordIndex]
+ *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Name, Converter) + */ + @NotNull + U[] fetchArray(Name fieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * You can access data like this + *

query.fetchArray(fieldName)[recordIndex]
+ * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Name, Class) + */ + @NotNull + U[] fetchArray(Name fieldName, Converter converter) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + *

+ * You can access data like this + *

query.fetchArray(field)[recordIndex]
+ * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Field) + */ + @NotNull + T[] fetchArray(Field field) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + *

+ * You can access data like this + *

query.fetchArray(field)[recordIndex]
+ *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Field, Class) + */ + @NotNull + U[] fetchArray(Field field, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + *

+ * You can access data like this + *

query.fetchArray(field)[recordIndex]
+ * + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Field, Converter) + */ + @NotNull + U[] fetchArray(Field field, Converter converter) throws DataAccessException; + + /** + * Fetch results into a custom mapper callback. + * + * @param mapper The mapper callback + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + Set fetchSet(RecordMapper mapper) throws DataAccessException; + + /** + * Execute the query and return all values for a field index from the + * generated result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(int) + */ + @NotNull + Set fetchSet(int fieldIndex) throws DataAccessException; + + /** + * Execute the query and return all values for a field index from the + * generated result. + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(int, Class) + */ + @NotNull + Set fetchSet(int fieldIndex, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field index from the + * generated result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(int, Converter) + */ + @NotNull + Set fetchSet(int fieldIndex, Converter converter) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(String) + */ + @NotNull + Set fetchSet(String fieldName) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(String, Converter) + */ + @NotNull + Set fetchSet(String fieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(String, Class) + */ + @NotNull + Set fetchSet(String fieldName, Converter converter) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Name) + */ + @NotNull + Set fetchSet(Name fieldName) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Name, Converter) + */ + @NotNull + Set fetchSet(Name fieldName, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field name from the + * generated result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Name, Class) + */ + @NotNull + Set fetchSet(Name fieldName, Converter converter) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Field) + */ + @NotNull + Set fetchSet(Field field) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + *

+ * The {@link Converter} that is provided by + * {@link Configuration#converterProvider()} will be used to convert the + * value to U + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Field, Class) + */ + @NotNull + Set fetchSet(Field field, Class type) throws DataAccessException; + + /** + * Execute the query and return all values for a field from the generated + * result. + * + * @return The resulting values. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @see Result#intoArray(Field, Converter) + */ + @NotNull + Set fetchSet(Field field, Converter converter) throws DataAccessException; + + /** + * Map resulting records onto a custom type. + *

+ * This is the same as calling fetch().into(type). See + * {@link Record#into(Class)} for more details + * + * @param The generic entity type. + * @param type The entity type. + * @see Record#into(Class) + * @see Result#into(Class) + * @see DefaultRecordMapper + * @return The results. This will never be null. + * @throws DataAccessException if something went wrong executing the query + * @throws MappingException wrapping any reflection or data type conversion + * exception that might have occurred while mapping records + */ + @NotNull + List fetchInto(Class type) throws DataAccessException, MappingException; + + /** + * Map resulting records onto a custom record. + *

+ * This is the same as calling fetch().into(table). See + * {@link Record#into(Table)} for more details + *

+ * The result and its contained records are attached to the original + * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} + * to override this behaviour. + * + * @param The generic table record type. + * @param table The table type. + * @return The results. This will never be null. + * @see Record#into(Table) + * @see Result#into(Table) + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + Result fetchInto(Table table) throws DataAccessException; + + /** + * Fetch results into a custom handler callback. + *

+ * The resulting records are attached to the original {@link Configuration} + * by default. Use {@link Settings#isAttachRecords()} to override this + * behaviour. + * + * @param handler The handler callback + * @return Convenience result, returning the parameter handler itself + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + > H fetchInto(H handler) throws DataAccessException; + + /** + * Fetch results into a custom mapper callback. + * + * @param mapper The mapper callback + * @return The result. This will never be null. + * @throws DataAccessException if something went wrong executing the query + */ + @NotNull + List fetch(RecordMapper mapper) throws DataAccessException; + + + + /** + * Fetch results in a new {@link CompletionStage}. + *

+ * The result is asynchronously completed by a task running in an + * {@link Executor} provided by the underlying + * {@link Configuration#executorProvider()}. + * + * @return The completion stage. The completed result will never be + * null. + */ + @NotNull + CompletionStage> fetchAsync(); + + /** + * Fetch results in a new {@link CompletionStage} that is asynchronously + * completed by a task running in the given executor. + * + * @return The completion stage. The completed result will never be + * null. + */ + @NotNull + CompletionStage> fetchAsync(Executor executor); + + +} diff --git a/jOOQ/src/main/java/org/jooq/InsertResultStep.java b/jOOQ/src/main/java/org/jooq/InsertResultStep.java index 11ed633dca..caaa6971ef 100644 --- a/jOOQ/src/main/java/org/jooq/InsertResultStep.java +++ b/jOOQ/src/main/java/org/jooq/InsertResultStep.java @@ -37,14 +37,6 @@ */ package org.jooq; -import java.util.Optional; - -import org.jooq.exception.DataAccessException; -import org.jooq.exception.TooManyRowsException; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - /** * This type is used for the {@link Insert}'s DSL API. *

@@ -95,56 +87,6 @@ import org.jetbrains.annotations.Nullable; * * @author Lukas Eder */ -public interface InsertResultStep extends Insert { - - /** - * The result holding returned values as specified by the - * {@link InsertReturningStep}. - * - * @return The returned values as specified by the - * {@link InsertReturningStep}. Note: - *

    - *
  • Not all databases / JDBC drivers support returning several - * values on multi-row inserts!
  • This may return an empty - * Result in case jOOQ could not retrieve any generated - * keys from the JDBC driver.
  • - *
- * @throws DataAccessException if something went wrong executing the query - * @see InsertQuery#getReturnedRecords() - */ - @NotNull - @Support - Result fetch() throws DataAccessException; - - /** - * The record holding returned values as specified by the - * {@link InsertReturningStep}. - * - * @return The returned value as specified by the - * {@link InsertReturningStep}. This may return null in - * case jOOQ could not retrieve any generated keys from the JDBC - * driver. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see InsertQuery#getReturnedRecord() - */ - @Nullable - @Support - R fetchOne() throws DataAccessException, TooManyRowsException; - - - /** - * The record holding returned values as specified by the - * {@link InsertReturningStep}. - * - * @return The returned value as specified by the - * {@link InsertReturningStep} - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see InsertQuery#getReturnedRecord() - */ - @NotNull - @Support - Optional fetchOptional() throws DataAccessException, TooManyRowsException; +public interface InsertResultStep extends Insert, Fetchable { } diff --git a/jOOQ/src/main/java/org/jooq/ResultQuery.java b/jOOQ/src/main/java/org/jooq/ResultQuery.java index a4d197fccd..2f64238a8a 100644 --- a/jOOQ/src/main/java/org/jooq/ResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/ResultQuery.java @@ -138,7 +138,7 @@ import org.jetbrains.annotations.Nullable; public interface ResultQuery extends Query - , Iterable + , Fetchable , org.reactivestreams.Publisher { @@ -152,4090 +152,6 @@ extends @Nullable Result getResult(); - /** - * Execute the query and return the generated result. - *

- * This is the same as calling {@link #execute()} and then - * {@link #getResult()} - *

- * The result and its contained records are attached to the original - * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} - * to override this behaviour. - *

Lifecycle guarantees

This method completes the whole - * {@link ConnectionProvider} and {@link ExecuteListener} lifecycles, - * eagerly fetching all results into memory. Underlying JDBC - * {@link ResultSet}s are always closed. Underlying JDBC - * {@link PreparedStatement}s are closed, unless - * {@link #keepStatement(boolean)} is set. - *

- * In order to keep open {@link ResultSet}s and fetch records lazily, use - * {@link #fetchLazy()} instead and then operate on {@link Cursor}. - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - Result fetch() throws DataAccessException; - - /** - * Execute the query and return the generated result as a JDBC - * {@link ResultSet}. - *

- * This is the same as calling {@link #fetchLazy()}. - * {@link Cursor#resultSet() resultSet()} and will return a - * {@link ResultSet} wrapping the JDBC driver's ResultSet. - * Closing this ResultSet may close the producing - * {@link Statement} or {@link PreparedStatement}, depending on your setting - * for {@link #keepStatement(boolean)}. - *

- * You can use this method when you want to use jOOQ for query execution, - * but not for result fetching. The returned ResultSet can also - * be used with {@link DSLContext#fetch(ResultSet)}. - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - ResultSet fetchResultSet() throws DataAccessException; - - /** - * Execute the query using {@link #fetch()} and return the generated result - * as an {@link Iterator}. - *

- * {@inheritDoc} - */ - @NotNull - @Override - Iterator iterator() throws DataAccessException; - - - - /** - * Execute the query using {@link #fetch()} and pass all results to a - * consumer. - *

- * This is essentially the same as {@link #fetch()}. - *

- * {@inheritDoc} - */ - @Override - default void forEach(Consumer action) { - Iterable.super.forEach(action); - } - - /** - * Execute the query using {@link #fetch()} and return the generated result - * as an {@link Spliterator}. - *

- * {@inheritDoc} - */ - @NotNull - @Override - default Spliterator spliterator() { - return Iterable.super.spliterator(); - } - - /** - * Stream this query. - *

- * This is just a synonym for {@link #stream()}. - *

- * Clients should ensure the {@link Stream} is properly closed, e.g. in a - * try-with-resources statement: - *

- *

-     * try (Stream<R> stream = query.stream()) {
-     *     // Do things with stream
-     * }
-     * 
- *

- * If users prefer more fluent style streaming of queries, {@link ResultSet} - * can be registered and closed via {@link ExecuteListener}, or via "smart" - * third-party {@link DataSource}s. - *

- * Depending on your JDBC driver's default behaviour, this may load the - * whole database result into the driver's memory. In order to indicate to - * the driver that you may not want to fetch all records at once, use - * {@link #fetchSize(int)} prior to calling this method. - * - * @return The result. - * @throws DataAccessException if something went wrong executing the query - * @see #stream() - */ - @NotNull - Stream fetchStream() throws DataAccessException; - - /** - * Stream this query, mapping records into a custom type. - *

- * This is the same as calling - * fetchStream().map(r -> r.into(type)). See - * {@link Record#into(Class)} for more details. - *

- * Clients should ensure the {@link Stream} is properly closed, e.g. in a - * try-with-resources statement: - *

- *

-     * try (Stream<R> stream = query.stream()) {
-     *     // Do things with stream
-     * }
-     * 
- *

- * If users prefer more fluent style streaming of queries, {@link ResultSet} - * can be registered and closed via {@link ExecuteListener}, or via "smart" - * third-party {@link DataSource}s. - *

- * Depending on your JDBC driver's default behaviour, this may load the - * whole database result into the driver's memory. In order to indicate to - * the driver that you may not want to fetch all records at once, use - * {@link #fetchSize(int)} prior to calling this method. - * - * @param The generic entity type. - * @param type The entity type. - * @see Record#into(Class) - * @see Result#into(Class) - * @see DefaultRecordMapper - * @return The results. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - */ - @NotNull - Stream fetchStreamInto(Class type) throws DataAccessException, MappingException; - - /** - * Stream this query, mapping records into a custom record. - *

- * This is the same as calling - * fetchStream().map(r -> r.into(table)). See - * {@link Record#into(Table)} for more details. - *

- * The result and its contained records are attached to the original - * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} - * to override this behaviour. - *

- * Clients should ensure the {@link Stream} is properly closed, e.g. in a - * try-with-resources statement: - *

- *

-     * try (Stream<R> stream = query.stream()) {
-     *     // Do things with stream
-     * }
-     * 
- *

- * If users prefer more fluent style streaming of queries, {@link ResultSet} - * can be registered and closed via {@link ExecuteListener}, or via "smart" - * third-party {@link DataSource}s. - *

- * Depending on your JDBC driver's default behaviour, this may load the - * whole database result into the driver's memory. In order to indicate to - * the driver that you may not want to fetch all records at once, use - * {@link #fetchSize(int)} prior to calling this method. - * - * @param The generic table record type. - * @param table The table type. - * @return The results. This will never be null. - * @see Record#into(Table) - * @see Result#into(Table) - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - Stream fetchStreamInto(Table table) throws DataAccessException; - - /** - * Stream this query. - *

- * This is essentially the same as {@link #fetchLazy()} but instead of - * returning a {@link Cursor}, a Java 8 {@link Stream} is returned. Clients - * should ensure the {@link Stream} is properly closed, e.g. in a - * try-with-resources statement: - *

- *

-     * try (Stream<R> stream = query.stream()) {
-     *     // Do things with stream
-     * }
-     * 
- *

- * If users prefer more fluent style streaming of queries, {@link ResultSet} - * can be registered and closed via {@link ExecuteListener}, or via "smart" - * third-party {@link DataSource}s. - *

- * Depending on your JDBC driver's default behaviour, this may load the - * whole database result into the driver's memory. In order to indicate to - * the driver that you may not want to fetch all records at once, use - * {@link #fetchSize(int)} prior to calling this method. - * - * @return The result. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - Stream stream() throws DataAccessException; - - /** - * Reduce the execution results of this query using a {@link Collector}. - *

- * This works in the same way as calling the following code: - * - *

-     * 
-     * try (Stream<R> stream = resultQuery.stream()) {
-     *     X result = stream.collect(collector);
-     * }
-     * 
-     * 
- * - * ... with the exception of allowing client code to ignore the need for - * managing resources, which are handled inside of the - * collect() method. - * - * @param collector The collector that collects all records and accumulates - * them into a result type. - * @return The result of the collection. - * @throws DataAccessException if something went wrong executing the query - */ - X collect(Collector collector) throws DataAccessException; - - - - /** - * Execute the query and "lazily" return the generated result. - *

- * The returned {@link Cursor} holds a reference to the executed - * {@link PreparedStatement} and the associated {@link ResultSet}. Data can - * be fetched (or iterated over) lazily, fetching records from the - * {@link ResultSet} one by one. - *

- * Depending on your JDBC driver's default behaviour, this may load the - * whole database result into the driver's memory. In order to indicate to - * the driver that you may not want to fetch all records at once, use - * {@link #fetchSize(int)} prior to calling this method. - *

- * Client code is responsible for closing the cursor after use. - * - * @return The resulting cursor. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see #fetchSize(int) - */ - @NotNull - Cursor fetchLazy() throws DataAccessException; - - /** - * Execute a query, possibly returning several result sets. - *

- * Example (Sybase ASE): - *

- *

-     * String sql = "sp_help 'my_table'";
- *

- * The result and its contained records are attached to the original - * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} - * to override this behaviour. - * - * @return The resulting records. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - Results fetchMany() throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - *

- * This is the same as calling {@link #fetch()} and then - * {@link Result#getValues(Field)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - List fetch(Field field) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - *

- * This is the same as calling {@link #fetch()} and then - * {@link Result#getValues(Field, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(Field, Class) - */ - @NotNull - List fetch(Field field, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - *

- * This is the same as calling {@link #fetch()} and then - * {@link Result#getValues(Field, Converter)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(Field, Converter) - */ - @NotNull - List fetch(Field field, Converter converter) throws DataAccessException; - - /** - * 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)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - List fetch(int fieldIndex) throws DataAccessException; - - /** - * 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)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(int, Class) - */ - @NotNull - List fetch(int fieldIndex, Class type) throws DataAccessException; - - /** - * 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, Converter)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(int, Converter) - */ - @NotNull - List fetch(int fieldIndex, Converter converter) throws DataAccessException; - - /** - * 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)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - List fetch(String fieldName) throws DataAccessException; - - /** - * 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)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(String, Class) - */ - @NotNull - List fetch(String fieldName, Class type) throws DataAccessException; - - /** - * 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, Converter)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(String, Converter) - */ - @NotNull - List fetch(String fieldName, Converter converter) throws DataAccessException; - - /** - * 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(Name)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - List fetch(Name fieldName) throws DataAccessException; - - /** - * 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(Name, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(Name, Class) - */ - @NotNull - List fetch(Name fieldName, Class type) throws DataAccessException; - - /** - * 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(Name, Converter)} - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Record#get(Name, Converter) - */ - @NotNull - List fetch(Name fieldName, Converter converter) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Field)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - T fetchOne(Field field) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Field, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(Field field, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Field, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(Field field, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(int)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Object fetchOne(int fieldIndex) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(int, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(int fieldIndex, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(int, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(int fieldIndex, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(String)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Object fetchOne(String fieldName) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(String, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(String fieldName, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(String, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(String fieldName, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Name)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Object fetchOne(Name fieldName) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a field name - * from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Name, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(Name fieldName, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Name, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchOne(Name fieldName, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting record. - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @return The resulting record or null if the query returns no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - R fetchOne() throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value into a - * custom mapper callback. - * - * @return The custom mapped record or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - E fetchOne(RecordMapper mapper) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting record as a name/value - * map. - * - * @return The resulting record or null if the query returns no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see Result#intoMaps() - * @see Record#intoMap() - */ - @Nullable - Map fetchOneMap() throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting record as an array - *

- * You can access data like this - *

query.fetchOneArray()[fieldIndex]
- * - * @return The resulting record or null if the query returns no - * records. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Object[] fetchOneArray() throws DataAccessException, TooManyRowsException; - - /** - * Map resulting records onto a custom type. - *

- * This is the same as calling

-     * E result = null;
-     * Record r = q.fetchOne();
-     *
-     * if (r != null)
-     *     result = r.into(type);
-     * 
. See {@link Record#into(Class)} for more details - * - * @param The generic entity type. - * @param type The entity type. - * @return The resulting record or null if the query returns no - * records. - * @see Record#into(Class) - * @see Result#into(Class) - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws TooManyRowsException if the query returned more than one record - * @see DefaultRecordMapper - */ - @Nullable - E fetchOneInto(Class type) throws DataAccessException, MappingException, TooManyRowsException; - - /** - * Map resulting records onto a custom record. - *

- * This is the same as calling

-     * Z result = null;
-     * Record r = q.fetchOne();
-     *
-     * if (r != null)
-     *     result = r.into(table);
-     * 
. See {@link Record#into(Table)} for more details - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @param The generic table record type. - * @param table The table type. - * @return The resulting record or null if the query returns no - * records. - * @see Record#into(Table) - * @see Result#into(Table) - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Z fetchOneInto(Table table) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field from - * the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(Field)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - T fetchSingle(Field field) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field from - * the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(Field, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(Field field, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field from - * the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(Field, Converter)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(Field field, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field - * index from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(int)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Object fetchSingle(int fieldIndex) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field - * index from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(int, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(int fieldIndex, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field - * index from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(int, Converter)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(int fieldIndex, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field name - * from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(String)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Object fetchSingle(String fieldName) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field name - * from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(String, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(String fieldName, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field name - * from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(String, Converter)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(String fieldName, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field name - * from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(Name)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - Object fetchSingle(Name fieldName) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field name - * from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(Name, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(Name fieldName, Class type) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value for a field name - * from the generated result. - *

- * This is the same as calling {@link #fetchSingle()} and then - * {@link Record#get(Name, Converter)} - * - * @return The resulting value. Unlike other {@link #fetchSingle()} methods, - * which never produce null records, this can be null - * if the resulting value in the record is null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @Nullable - U fetchSingle(Name fieldName, Converter converter) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting record. - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @return The resulting value. This is never null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - R fetchSingle() throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting value into a custom - * mapper callback. - * - * @return The resulting value. This is never null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - E fetchSingle(RecordMapper mapper) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting record as a name/value - * map. - * - * @return The resulting value. This is never null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - * @see Result#intoMaps() - * @see Record#intoMap() - */ - @NotNull - Map fetchSingleMap() throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Execute the query and return exactly one resulting record as an array - *

- * You can access data like this - *

query.fetchSingleArray()[fieldIndex]
- * - * @return The resulting value. This is never null. - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Object[] fetchSingleArray() throws DataAccessException, NoDataFoundException, TooManyRowsException; - - /** - * Map resulting records onto a custom type. - *

- * This is the same as calling

-     * E result = null;
-     * Record r = q.fetchSingle();
-     *
-     * if (r != null)
-     *     result = r.into(type);
-     * 
. See {@link Record#into(Class)} for more details - * - * @param The generic entity type. - * @param type The entity type. - * @return The resulting value. - * @see Record#into(Class) - * @see Result#into(Class) - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - * @see DefaultRecordMapper - */ - // [#10774] This is @Nullable in rare cases, which can be annoying for Kotlin users in most cases - E fetchSingleInto(Class type) throws DataAccessException, MappingException, NoDataFoundException, TooManyRowsException; - - /** - * Map resulting records onto a custom record. - *

- * This is the same as calling

-     * Z result = null;
-     * Record r = q.fetchSingle();
-     *
-     * if (r != null)
-     *     result = r.into(table);
-     * 
. See {@link Record#into(Table)} for more details - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @param The generic table record type. - * @param table The table type. - * @return The resulting value. This is never null. - * @see Record#into(Table) - * @see Result#into(Table) - * @throws DataAccessException if something went wrong executing the query - * @throws NoDataFoundException if the query returned no records - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Z fetchSingleInto(Table table) throws DataAccessException, NoDataFoundException, TooManyRowsException; - - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(Field)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(Field field) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(Field, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(Field field, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(Field, Converter)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(Field field, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(int)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(int fieldIndex) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(int, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(int fieldIndex, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(int, Converter)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(int fieldIndex, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(String)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(String fieldName) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(String, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(String fieldName, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(String, Converter)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(String fieldName, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(Name)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(Name fieldName) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(Name, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(Name fieldName, Class type) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOptional()} and then - * {@link Record#get(Name, Converter)} - * - * @return The resulting value - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(Name fieldName, Converter converter) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting record. - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @return The resulting record - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional() throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting value into a - * custom mapper callback. - * - * @return The custom mapped record - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptional(RecordMapper mapper) throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting record as a name/value - * map. - * - * @return The resulting record - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see Result#intoMaps() - * @see Record#intoMap() - */ - @NotNull - Optional> fetchOptionalMap() throws DataAccessException, TooManyRowsException; - - /** - * Execute the query and return at most one resulting record as an array. - * - * @return The resulting record - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptionalArray() throws DataAccessException, TooManyRowsException; - - /** - * Map resulting records onto a custom type. - *

- * This is the same as calling

-     * Optional<E> result = q.fetchOptional().map(r -> r.into(type));
-     * 
. See {@link Record#into(Class)} for more details - * - * @param The generic entity type. - * @param type The entity type. - * @return The resulting record - * @see Record#into(Class) - * @see Result#into(Class) - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws TooManyRowsException if the query returned more than one record - * @see DefaultRecordMapper - */ - @NotNull - Optional fetchOptionalInto(Class type) throws DataAccessException, MappingException, TooManyRowsException; - - /** - * Map resulting records onto a custom record. - *

- * This is the same as calling

-     * Optional<Z> result = q.fetchOptional().map(r -> r.into(table));
-     * 
. See {@link Record#into(Table)} for more details - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @param The generic table record type. - * @param table The table type. - * @return The resulting record - * @see Record#into(Table) - * @see Result#into(Table) - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - */ - @NotNull - Optional fetchOptionalInto(Table table) throws DataAccessException, TooManyRowsException; - - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Field)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - T fetchAny(Field field) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a field from - * the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Field, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(Field field, Class type) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Field, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(Field field, Converter converter) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(int)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - Object fetchAny(int fieldIndex) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a field - * index from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(int, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(int fieldIndex, Class type) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field index from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(int, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(int fieldIndex, Converter converter) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(String)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - Object fetchAny(String fieldName) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(String, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(String fieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(String, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(String fieldName, Converter converter) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Name)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - Object fetchAny(Name fieldName) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Name, Class)} - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(Name fieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return at most one resulting value for a - * field name from the generated result. - *

- * This is the same as calling {@link #fetchOne()} and then - * {@link Record#get(Name, Converter)} - * - * @return The resulting value or null if the query returned no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - U fetchAny(Name fieldName, Converter converter) throws DataAccessException; - - /** - * Execute the query and return at most one resulting record. - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @return The first resulting record or null if the query - * returns no records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - R fetchAny() throws DataAccessException; - - /** - * Execute the query and return at most one resulting record. - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @return The first resulting record or null if the query - * returns no records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - E fetchAny(RecordMapper mapper) throws DataAccessException; - - /** - * Execute the query and return at most one resulting record as a name/value - * map. - * - * @return The resulting record or null if the query returns no - * records. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoMaps() - * @see Record#intoMap() - */ - @Nullable - Map fetchAnyMap() throws DataAccessException; - - /** - * Execute the query and return at most one resulting record as an array - *

- * You can access data like this - *

query.fetchAnyArray()[fieldIndex]
- * - * @return The resulting record or null if the query returns no - * records. - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - Object[] fetchAnyArray() throws DataAccessException; - - /** - * Map resulting records onto a custom type. - *

- * This is the same as calling

-     * E result = null;
-     * Record r = q.fetchAny();
-     *
-     * if (r != null)
-     *     result = r.into(type);
-     * 
. See {@link Record#into(Class)} for more details - * - * @param The generic entity type. - * @param type The entity type. - * @return The resulting record or null if the query returns no - * records. - * @see Record#into(Class) - * @see Result#into(Class) - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see DefaultRecordMapper - */ - @Nullable - E fetchAnyInto(Class type) throws DataAccessException, MappingException; - - /** - * Map resulting records onto a custom record. - *

- * This is the same as calling

-     * Z result = null;
-     * Record r = q.fetchOne();
-     *
-     * if (r != null)
-     *     result = r.into(table);
-     * 
. See {@link Record#into(Table)} for more details - *

- * The resulting record is attached to the original {@link Configuration} by - * default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @param The generic table record type. - * @param table The table type. - * @return The resulting record or null if the query returns no - * records. - * @see Record#into(Table) - * @see Result#into(Table) - * @throws DataAccessException if something went wrong executing the query - */ - @Nullable - Z fetchAnyInto(Table table) throws DataAccessException; - - /** - * Execute the query and return the generated result as a list of name/value - * maps. - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMaps() - * @see Record#intoMap() - */ - @NotNull - List> fetchMaps() throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and the corresponding records as value. - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(Field)} instead, if your keys are - * non-unique - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param The key's generic field type - * @param key The key field. Client code must assure that this field is - * unique in the result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(Field) - */ - @NotNull - Map fetchMap(Field key) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and the corresponding records as value. - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(int)} instead, if your keys are - * non-unique - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key field. Client code must assure that this - * field is unique in the result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(int) - */ - @NotNull - Map fetchMap(int keyFieldIndex) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and the corresponding records as value. - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(String)} instead, if your keys are - * non-unique - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field. Client code must assure that this - * field is unique in the result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(String) - */ - @NotNull - Map fetchMap(String keyFieldName) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and the corresponding records as value. - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(Name)} instead, if your keys are - * non-unique - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field. Client code must assure that this - * field is unique in the result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(Name) - */ - @NotNull - Map fetchMap(Name keyFieldName) 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 - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(Field, Field)} instead, if your keys - * are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param The key's generic field type - * @param The value's generic field type - * @param key The key field. Client code must assure that this field is - * unique in the result set. - * @param value The value field - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(Field, Field) - */ - @NotNull - Map fetchMap(Field key, Field value) 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 - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(int, int)} instead, if your keys are - * non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key field. Client code must assure that this - * field is unique in the result set. - * @param valueFieldIndex The value field - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(int, int) - */ - @NotNull - Map fetchMap(int keyFieldIndex, int valueFieldIndex) 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 - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(String, String)} instead, if your keys - * are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field. Client code must assure that this - * field is unique in the result set. - * @param valueFieldName The value field - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(String, String) - */ - @NotNull - Map fetchMap(String keyFieldName, String valueFieldName) 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 - *

- * An exception is thrown, if the key turns out to be non-unique in the - * result set. Use {@link #fetchGroups(Name, Name)} instead, if your keys - * are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field. Client code must assure that this - * field is unique in the result set. - * @param valueFieldName The value field - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key field returned two or more - * equal values from the result set. - * @see Result#intoMap(Name, Name) - */ - @NotNull - Map fetchMap(Name keyFieldName, Name valueFieldName) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Field[])} instead, if your keys are - * non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys. Client code must assure that keys are unique in the - * result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Field[]) - */ - @NotNull - Map fetchMap(Field[] keys) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(int[])} instead, if your keys are - * non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys. Client code must assure that keys are - * unique in the result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(int[]) - */ - @NotNull - Map fetchMap(int[] keyFieldIndexes) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(String[])} instead, if your keys are - * non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(String[]) - */ - @NotNull - Map fetchMap(String[] keyFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Name[])} instead, if your keys are - * non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Name[]) - */ - @NotNull - Map fetchMap(Name[] keyFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Field[], Field[])} instead, if your - * keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys. Client code must assure that keys are unique in the - * result set. - * @param values The values. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Field[], Field[]) - */ - @NotNull - Map fetchMap(Field[] keys, Field[] values) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(int[], int[])} instead, if your keys - * are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys. Client code must assure that keys are - * unique in the result set. - * @param valueFieldIndexes The values. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(int[], int[]) - */ - @NotNull - Map fetchMap(int[] keyFieldIndexes, int[] valueFieldIndexes) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(String[], String[])} instead, if your - * keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. - * @param valueFieldNames The values. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(String[], String[]) - */ - @NotNull - Map fetchMap(String[] keyFieldNames, String[] valueFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with keys as a map key and the - * corresponding record as value. - *

- * An exception is thrown, if the keys turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Name[], Name[])} instead, if your - * keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. - * @param valueFieldNames The values. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Name[], Name[]) - */ - @NotNull - Map fetchMap(Name[] keyFieldNames, Name[] valueFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Field[], Class)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys. Client code must assure that keys are unique in the - * result set. If this is null or an empty array, - * the resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(Field[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(Field[] keys, Class type) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(int[], Class)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys. Client code must assure that keys are - * unique in the result set. If this is null or an - * empty array, the resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(int[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(int[] keyFieldIndexes, Class type) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(String[], Class)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. If this is null or an - * empty array, the resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(String[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(String[] keyFieldNames, Class type) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Name[], Class)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. If this is null or an - * empty array, the resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(Name[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(Name[] keyFieldNames, Class type) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Field[], RecordMapper)} - * instead, if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys. Client code must assure that keys are unique in the - * result set. If this is null or an empty array, - * the resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(Field[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(Field[] keys, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(int[], RecordMapper)} instead, - * if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys. Client code must assure that keys are - * unique in the result set. If this is null or an - * empty array, the resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(int[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(int[] keyFieldIndexes, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(String[], RecordMapper)} - * instead, if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. If this is null or an - * empty array, the resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(String[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(String[] keyFieldNames, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Name[], RecordMapper)} - * instead, if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. Client code must assure that keys are - * unique in the result set. If this is null or an - * empty array, the resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(Name[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map, E> fetchMap(Name[] keyFieldNames, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Class)} instead, if your keys - * are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyType The key type. If this is null, the resulting - * map will contain at most one entry. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Class) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(Class keyType) throws DataAccessException, MappingException, InvalidResultException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Class, Class)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyType The key type. If this is null, the resulting - * map will contain at most one entry. - * @param valueType The value type. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Class, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(Class keyType, Class valueType) throws DataAccessException, MappingException, InvalidResultException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Class, RecordMapper)} instead, - * if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyType The key type. If this is null, the resulting - * map will contain at most one entry. - * @param valueMapper The value mapper. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Class, RecordMapper) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(Class keyType, RecordMapper valueMapper) throws DataAccessException, InvalidResultException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(RecordMapper)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyMapper The key mapper. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(RecordMapper) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(RecordMapper keyMapper) throws DataAccessException, InvalidResultException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(RecordMapper, Class)} instead, - * if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyMapper The key mapper. - * @param valueType The value type. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(RecordMapper, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(RecordMapper keyMapper, Class valueType) throws DataAccessException, InvalidResultException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(RecordMapper, RecordMapper)} - * instead, if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyMapper The key mapper. - * @param valueMapper The value mapper. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(RecordMapper, RecordMapper) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(RecordMapper keyMapper, RecordMapper valueMapper) throws DataAccessException, InvalidResultException, MappingException; - - /** - * Execute the query and return a {@link Map} with table as a map key and - * the corresponding record as value. - *

- * An {@link InvalidResultException} is thrown, if the keys turn out to be - * non-unique in the result set. Use {@link #fetchGroups(Table)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param table The key table. Client code must assure that keys are unique - * in the result set. May not be null. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Table) - */ - @NotNull - Map fetchMap(Table table) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with table as a map key and - * the corresponding record as value. - *

- * An {@link InvalidResultException} is thrown, if the keys turn out to be - * non-unique in the result set. Use {@link #fetchGroups(Table, Table)} - * instead, if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyTable The key table. Client code must assure that keys are - * unique in the result set. May not be null. - * @param valueTable The value table. May not be null. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key list is non-unique in the - * result set. - * @see Result#intoMap(Table, Table) - */ - @NotNull - Map fetchMap(Table keyTable, Table valueTable) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given table and mapped into the given entity type. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Table, Class)} instead, if - * your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param table The key table. Client code must assure that keys are unique - * in the result set. May not be null. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(Table, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(Table table, Class type) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given table and mapped by the given mapper. - *

- * An {@link InvalidResultException} is thrown, if the keys are non-unique - * in the result set. Use {@link #fetchGroups(Table, RecordMapper)} instead, - * if your keys are non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param table The key table. Client code must assure that keys are unique - * in the result set. May not be null. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the keys are non-unique in the result - * set. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoMap(Table, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map fetchMap(Table table, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped into the given entity type. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Field, Class)} instead, if your key - * is non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param key The key. Client code must assure that key is unique in the - * result set. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(Field, Class) - */ - @NotNull - Map fetchMap(Field key, Class type) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped into the given entity type. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(int, Class)} instead, if your key - * is non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key. Client code must assure that key is unique - * in the result set. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(int, Class) - */ - @NotNull - Map fetchMap(int keyFieldIndex, Class type) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped into the given entity type. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(String, Class)} instead, if your key - * is non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key. Client code must assure that key is unique - * in the result set. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(String, Class) - */ - @NotNull - Map fetchMap(String keyFieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped into the given entity type. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Name, Class)} instead, if your key - * is non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key. Client code must assure that key is unique - * in the result set. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(Name, Class) - */ - @NotNull - Map fetchMap(Name keyFieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped by the given mapper. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Field, Class)} instead, if your key - * is non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param key The key. Client code must assure that key is unique in the - * result set. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(Field, Class) - */ - @NotNull - Map fetchMap(Field key, RecordMapper mapper) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped by the given mapper. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(int, Class)} instead, if your key is - * non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key. Client code must assure that key is unique - * in the result set. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(int, Class) - */ - @NotNull - Map fetchMap(int keyFieldIndex, RecordMapper mapper) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped by the given mapper. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(String, Class)} instead, if your key - * is non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key. Client code must assure that key is unique - * in the result set. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(String, Class) - */ - @NotNull - Map fetchMap(String keyFieldName, RecordMapper mapper) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key and mapped by the given mapper. - *

- * An exception is thrown, if the key turn out to be non-unique in the - * result set. Use {@link #fetchGroups(Name, Class)} instead, if your key - * is non-unique. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key. Client code must assure that key is unique - * in the result set. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws InvalidResultException if the key is non-unique in the result - * set. - * @see Result#intoMap(Name, Class) - */ - @NotNull - Map fetchMap(Name keyFieldName, RecordMapper mapper) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and a list of corresponding records as value. - *

- * Unlike {@link #fetchMap(Field)}, this method allows for non-unique keys - * in the result set. - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param The key's generic field type - * @param key The key field. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Field) - */ - @NotNull - Map> fetchGroups(Field key) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and a list of corresponding records as value. - *

- * Unlike {@link #fetchMap(int)}, this method allows for non-unique keys in - * the result set. - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key field index. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(int) - */ - @NotNull - Map> fetchGroups(int keyFieldIndex) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and a list of corresponding records as value. - *

- * Unlike {@link #fetchMap(String)}, this method allows for non-unique keys - * in the result set. - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(String) - */ - @NotNull - Map> fetchGroups(String keyFieldName) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with one of the result's - * columns as key and a list of corresponding records as value. - *

- * Unlike {@link #fetchMap(Name)}, this method allows for non-unique keys - * in the result set. - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Name) - */ - @NotNull - Map> fetchGroups(Name keyFieldName) 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. - *

- * The resulting map is iteration order preserving. - * - * @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. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Field, Field) - */ - @NotNull - Map> fetchGroups(Field key, Field value) 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(int, int)}, this method allows for non-unique - * keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key field index. - * @param valueFieldIndex The value field index. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(int, int) - */ - @NotNull - Map> fetchGroups(int keyFieldIndex, int valueFieldIndex) 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(String, String)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @param valueFieldName The value field name. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(String, String) - */ - @NotNull - Map> fetchGroups(String keyFieldName, String valueFieldName) 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(Name, Name)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @param valueFieldName The value field name. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Name, Name) - */ - @NotNull - Map> fetchGroups(Name keyFieldName, Name valueFieldName) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(Field[])}, this method allows for non-unique keys - * in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Field[]) - */ - @NotNull - Map> fetchGroups(Field[] keys) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(int[])}, this method allows for non-unique keys - * in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(int[]) - */ - @NotNull - Map> fetchGroups(int[] keyFieldIndexes) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(String[])}, this method allows for non-unique - * keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(String[]) - */ - @NotNull - Map> fetchGroups(String[] keyFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(Name[])}, this method allows for non-unique - * keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Name[]) - */ - @NotNull - Map> fetchGroups(Name[] keyFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(Field[], Field[])}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @param values The values. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Field[], Field[]) - */ - @NotNull - Map> fetchGroups(Field[] keys, Field[] values) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(int[], int[])}, this method allows for non-unique - * keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @param valueFieldIndexes The values. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(int[], int[]) - */ - @NotNull - Map> fetchGroups(int[] keyFieldIndexes, int[] valueFieldIndexes) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(String[], String[])}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @param valueFieldNames The values. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(String[], String[]) - */ - @NotNull - Map> fetchGroups(String[] keyFieldNames, String[] valueFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given keys. - *

- * Unlike {@link #fetchMap(Name[], Name[])}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys used for result grouping. If this is - * null or an empty array, the resulting map will - * contain at most one entry. - * @param valueFieldNames The values returned per group. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Name[], Name[]) - */ - @NotNull - Map> fetchGroups(Name[] keyFieldNames, Name[] valueFieldNames) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * Unlike {@link #fetchMap(Field[], Class)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys. If this is null or an empty array, the - * resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Field[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Field[] keys, Class type) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * Unlike {@link #fetchMap(int[], Class)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys. If this is null or an empty - * array, the resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(int[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(int[] keyFieldIndexes, Class type) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * Unlike {@link #fetchMap(String[], Class)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. If this is null or an empty - * array, the resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(String[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(String[] keyFieldNames, Class type) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped into the given entity type. - *

- * Unlike {@link #fetchMap(Name[], Class)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. If this is null or an empty - * array, the resulting map will contain at most one entry. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Name[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Name[] keyFieldNames, Class type) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * Unlike {@link #fetchMap(Field[], RecordMapper)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keys The keys. If this is null or an empty array, the - * resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing grouped results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Field[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Field[] keys, RecordMapper mapper) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * Unlike {@link #fetchMap(int[], RecordMapper)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndexes The keys. If this is null or an empty - * array, the resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(int[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(int[] keyFieldIndexes, RecordMapper mapper) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * Unlike {@link #fetchMap(String[], RecordMapper)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. If this is null or an empty - * array, the resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(String[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(String[] keyFieldNames, RecordMapper mapper) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given keys and mapped by the given mapper. - *

- * Unlike {@link #fetchMap(Name[], RecordMapper)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldNames The keys. If this is null or an empty - * array, the resulting map will contain at most one entry. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Name[], Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Name[] keyFieldNames, RecordMapper mapper) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * Unlike {@link #fetchMap(Class)}, this method allows for non-unique keys - * in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyType The key type. If this is null, the resulting - * map will contain at most one entry. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Class keyType) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * Unlike {@link #fetchMap(Class, Class)}, this method allows for non-unique - * keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyType The key type. If this is null, the resulting - * map will contain at most one entry. - * @param valueType The value type. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Class keyType, Class valueType) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * Unlike {@link #fetchMap(Class, RecordMapper)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyType The key type. If this is null, the resulting - * map will contain at most one entry. - * @param valueMapper The value mapper. - * @return A Map containing grouped results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Class keyType, RecordMapper valueMapper) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * Unlike {@link #fetchMap(RecordMapper, RecordMapper)}, this method allows - * for non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyMapper The key mapper. - * @return A Map containing the results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(RecordMapper keyMapper) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * Unlike {@link #fetchMap(RecordMapper, Class)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyMapper The key mapper. - * @param valueType The value type. - * @return A Map containing the results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(RecordMapper keyMapper, Class valueType) throws MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given key entity and mapped into the given entity type. - *

- * The grouping semantics is governed by the key type's - * {@link Object#equals(Object)} and {@link Object#hashCode()} - * implementation, not necessarily the values as fetched from the database. - *

- * Unlike {@link #fetchMap(RecordMapper, RecordMapper)}, this method allows - * for non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyMapper The key mapper. - * @param valueMapper The value mapper. - * @return A Map containing the results. This will never be - * null. - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(RecordMapper keyMapper, RecordMapper valueMapper) throws MappingException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given table. - *

- * Unlike {@link #fetchMap(Table)}, this method allows for non-unique keys - * in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param table The key table. May not be null. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Table) - */ - @NotNull - Map> fetchGroups(Table table) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with the result grouped by the - * given table. - *

- * Unlike {@link #fetchMap(Table, Table)}, this method allows for non-unique - * keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param keyTable The key table. May not be null. - * @param valueTable The value table. May not be null. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoGroups(Table, Table) - */ - @NotNull - Map> fetchGroups(Table keyTable, Table valueTable) throws DataAccessException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given table and mapped into the given entity type. - *

- * Unlike {@link #fetchMap(Table, Class)}, this method allows for non-unique - * keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param table The key table. May not be null. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Table, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Table table, Class type) throws DataAccessException, MappingException; - - /** - * Execute the query and return a {@link Map} with results grouped by the - * given table and mapped by the given mapper. - *

- * Unlike {@link #fetchMap(Table, RecordMapper)}, this method allows for - * non-unique keys in the result set. - *

- * The resulting map is iteration order preserving. - * - * @param table The key table. May not be null. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Table, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Table table, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped - * into the given entity type. - *

- * The resulting map is iteration order preserving. - * - * @param The key's generic field type - * @param The generic entity type. - * @param key The key field. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Field, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Field key, Class type) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped - * into the given entity type. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key field index. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(int, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(int keyFieldIndex, Class type) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped - * into the given entity type. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(String, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(String keyFieldName, Class type) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped - * into the given entity type. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @param type The entity type. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Name, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Name keyFieldName, Class type) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped by - * the given mapper. - *

- * The resulting map is iteration order preserving. - * - * @param The key's generic field type - * @param The generic entity type. - * @param key The key field. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Field, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Field key, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped by - * the given mapper. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldIndex The key field index. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(int, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(int keyFieldIndex, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped by - * the given mapper. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(String, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(String keyFieldName, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Return a {@link Map} with results grouped by the given key and mapped by - * the given mapper. - *

- * The resulting map is iteration order preserving. - * - * @param keyFieldName The key field name. - * @param mapper The mapper callback. - * @return A Map containing the results. This will never be - * null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - * @see Result#intoGroups(Name, Class) - * @see DefaultRecordMapper - */ - @NotNull - Map> fetchGroups(Name keyFieldName, RecordMapper mapper) throws DataAccessException, MappingException; - - /** - * Execute the query and return the generated result as an Object matrix. - *

- * You can access data like this - *

query.fetchArray()[recordIndex][fieldIndex]
- * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArrays() - */ - @NotNull - Object[][] fetchArrays() throws DataAccessException; - - /** - * Execute the query and return the generated result as an array of records. - *

- * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#toArray(Object[]) - */ - @NotNull - R[] fetchArray() throws DataAccessException; - - /** - * Execute the query and return all values for a field index from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldIndex)[recordIndex]
- * - * @return The resulting values. This may be an array type more concrete - * than Object[], depending on whether jOOQ has any - * knowledge about fieldIndex's actual type. This will - * never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(int) - */ - @NotNull - Object[] fetchArray(int fieldIndex) throws DataAccessException; - - /** - * Execute the query and return all values for a field index from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldIndex)[recordIndex]
- *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(int, Class) - */ - @NotNull - U[] fetchArray(int fieldIndex, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field index from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldIndex)[recordIndex]
- * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(int, Converter) - */ - @NotNull - U[] fetchArray(int fieldIndex, Converter converter) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldName)[recordIndex]
- * - * @return The resulting values. This may be an array type more concrete - * than Object[], depending on whether jOOQ has any - * knowledge about fieldName's actual type. This will - * never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(String) - */ - @NotNull - Object[] fetchArray(String fieldName) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldName)[recordIndex]
- *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(String, Converter) - */ - @NotNull - U[] fetchArray(String fieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldName)[recordIndex]
- * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(String, Class) - */ - @NotNull - U[] fetchArray(String fieldName, Converter converter) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldName)[recordIndex]
- * - * @return The resulting values. This may be an array type more concrete - * than Object[], depending on whether jOOQ has any - * knowledge about fieldName's actual type. This will - * never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Name) - */ - @NotNull - Object[] fetchArray(Name fieldName) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldName)[recordIndex]
- *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Name, Converter) - */ - @NotNull - U[] fetchArray(Name fieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * You can access data like this - *

query.fetchArray(fieldName)[recordIndex]
- * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Name, Class) - */ - @NotNull - U[] fetchArray(Name fieldName, Converter converter) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - *

- * You can access data like this - *

query.fetchArray(field)[recordIndex]
- * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Field) - */ - @NotNull - T[] fetchArray(Field field) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - *

- * You can access data like this - *

query.fetchArray(field)[recordIndex]
- *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Field, Class) - */ - @NotNull - U[] fetchArray(Field field, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - *

- * You can access data like this - *

query.fetchArray(field)[recordIndex]
- * - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Field, Converter) - */ - @NotNull - U[] fetchArray(Field field, Converter converter) throws DataAccessException; - - /** - * Fetch results into a custom mapper callback. - * - * @param mapper The mapper callback - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - Set fetchSet(RecordMapper mapper) throws DataAccessException; - - /** - * Execute the query and return all values for a field index from the - * generated result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(int) - */ - @NotNull - Set fetchSet(int fieldIndex) throws DataAccessException; - - /** - * Execute the query and return all values for a field index from the - * generated result. - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(int, Class) - */ - @NotNull - Set fetchSet(int fieldIndex, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field index from the - * generated result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(int, Converter) - */ - @NotNull - Set fetchSet(int fieldIndex, Converter converter) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(String) - */ - @NotNull - Set fetchSet(String fieldName) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(String, Converter) - */ - @NotNull - Set fetchSet(String fieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(String, Class) - */ - @NotNull - Set fetchSet(String fieldName, Converter converter) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Name) - */ - @NotNull - Set fetchSet(Name fieldName) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Name, Converter) - */ - @NotNull - Set fetchSet(Name fieldName, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field name from the - * generated result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Name, Class) - */ - @NotNull - Set fetchSet(Name fieldName, Converter converter) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Field) - */ - @NotNull - Set fetchSet(Field field) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - *

- * The {@link Converter} that is provided by - * {@link Configuration#converterProvider()} will be used to convert the - * value to U - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Field, Class) - */ - @NotNull - Set fetchSet(Field field, Class type) throws DataAccessException; - - /** - * Execute the query and return all values for a field from the generated - * result. - * - * @return The resulting values. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @see Result#intoArray(Field, Converter) - */ - @NotNull - Set fetchSet(Field field, Converter converter) throws DataAccessException; - - /** - * Map resulting records onto a custom type. - *

- * This is the same as calling fetch().into(type). See - * {@link Record#into(Class)} for more details - * - * @param The generic entity type. - * @param type The entity type. - * @see Record#into(Class) - * @see Result#into(Class) - * @see DefaultRecordMapper - * @return The results. This will never be null. - * @throws DataAccessException if something went wrong executing the query - * @throws MappingException wrapping any reflection or data type conversion - * exception that might have occurred while mapping records - */ - @NotNull - List fetchInto(Class type) throws DataAccessException, MappingException; - - /** - * Map resulting records onto a custom record. - *

- * This is the same as calling fetch().into(table). See - * {@link Record#into(Table)} for more details - *

- * The result and its contained records are attached to the original - * {@link Configuration} by default. Use {@link Settings#isAttachRecords()} - * to override this behaviour. - * - * @param The generic table record type. - * @param table The table type. - * @return The results. This will never be null. - * @see Record#into(Table) - * @see Result#into(Table) - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - Result fetchInto(Table table) throws DataAccessException; - - /** - * Fetch results into a custom handler callback. - *

- * The resulting records are attached to the original {@link Configuration} - * by default. Use {@link Settings#isAttachRecords()} to override this - * behaviour. - * - * @param handler The handler callback - * @return Convenience result, returning the parameter handler itself - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - > H fetchInto(H handler) throws DataAccessException; - - /** - * Fetch results into a custom mapper callback. - * - * @param mapper The mapper callback - * @return The result. This will never be null. - * @throws DataAccessException if something went wrong executing the query - */ - @NotNull - List fetch(RecordMapper mapper) throws DataAccessException; - - - - /** - * Fetch results in a new {@link CompletionStage}. - *

- * The result is asynchronously completed by a task running in an - * {@link Executor} provided by the underlying - * {@link Configuration#executorProvider()}. - * - * @return The completion stage. The completed result will never be - * null. - */ - @NotNull - CompletionStage> fetchAsync(); - - /** - * Fetch results in a new {@link CompletionStage} that is asynchronously - * completed by a task running in the given executor. - * - * @return The completion stage. The completed result will never be - * null. - */ - @NotNull - CompletionStage> fetchAsync(Executor executor); - - - /** * The record type produced by this query. */ diff --git a/jOOQ/src/main/java/org/jooq/UpdateResultStep.java b/jOOQ/src/main/java/org/jooq/UpdateResultStep.java index dcdb2139ae..ca25ed6411 100644 --- a/jOOQ/src/main/java/org/jooq/UpdateResultStep.java +++ b/jOOQ/src/main/java/org/jooq/UpdateResultStep.java @@ -37,22 +37,6 @@ */ package org.jooq; -// ... -// ... -// ... -import static org.jooq.SQLDialect.FIREBIRD; -// ... -import static org.jooq.SQLDialect.POSTGRES; -// ... - -import java.util.Optional; - -import org.jooq.exception.DataAccessException; -import org.jooq.exception.TooManyRowsException; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - /** * This type is used for the {@link Update}'s DSL API. *

@@ -95,56 +79,6 @@ import org.jetbrains.annotations.Nullable; * * @author Lukas Eder */ -public interface UpdateResultStep extends Update { - - /** - * The result holding returned values as specified by the - * {@link UpdateReturningStep}. - * - * @return The returned values as specified by the - * {@link UpdateReturningStep}. Note: - *

    - *
  • Not all databases / JDBC drivers support returning several - * values on multi-row inserts!
  • This may return an empty - * Result in case jOOQ could not retrieve any generated - * keys from the JDBC driver.
  • - *
- * @throws DataAccessException if something went wrong executing the query - * @see UpdateQuery#getReturnedRecords() - */ - @NotNull - @Support({ FIREBIRD, POSTGRES }) - Result fetch() throws DataAccessException; - - /** - * The record holding returned values as specified by the - * {@link UpdateReturningStep}. - * - * @return The returned value as specified by the - * {@link UpdateReturningStep}. This may return null in - * case jOOQ could not retrieve any generated keys from the JDBC - * driver. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see UpdateQuery#getReturnedRecord() - */ - @Nullable - @Support({ FIREBIRD, POSTGRES }) - R fetchOne() throws DataAccessException, TooManyRowsException; - - - /** - * The record holding returned values as specified by the - * {@link UpdateReturningStep}. - * - * @return The returned value as specified by the - * {@link UpdateReturningStep}. - * @throws DataAccessException if something went wrong executing the query - * @throws TooManyRowsException if the query returned more than one record - * @see UpdateQuery#getReturnedRecord() - */ - @NotNull - @Support({ FIREBIRD, POSTGRES }) - Optional fetchOptional() throws DataAccessException, TooManyRowsException; +public interface UpdateResultStep extends Update, Fetchable { } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java b/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java index 0b893c057f..af65a3b920 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java @@ -37,1405 +37,200 @@ */ package org.jooq.impl; -import static java.lang.Math.max; -import static java.lang.Math.min; -import static org.jooq.XMLFormat.RecordFormat.COLUMN_NAME_ELEMENTS; -import static org.jooq.XMLFormat.RecordFormat.VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE; -import static org.jooq.conf.SettingsTools.renderLocale; -import static org.jooq.impl.DSL.insertInto; -import static org.jooq.impl.DSL.name; -import static org.jooq.impl.DSL.table; -import static org.jooq.tools.StringUtils.abbreviate; -import static org.jooq.tools.StringUtils.leftPad; -import static org.jooq.tools.StringUtils.rightPad; - -import java.io.Writer; -import java.sql.Date; -import java.sql.Timestamp; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Deque; -import java.util.Iterator; import java.util.List; -import java.util.TreeMap; +import java.util.Optional; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Collector; import java.util.stream.Stream; +import java.util.stream.StreamSupport; -import javax.xml.bind.DatatypeConverter; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.jooq.CSVFormat; -import org.jooq.ChartFormat; -import org.jooq.ChartFormat.Display; import org.jooq.Configuration; -import org.jooq.Constants; import org.jooq.Cursor; -import org.jooq.DSLContext; -import org.jooq.DataType; -import org.jooq.EnumType; -import org.jooq.Field; -import org.jooq.Fields; -import org.jooq.Formattable; -import org.jooq.JSON; -import org.jooq.JSONB; -import org.jooq.JSONFormat; -import org.jooq.Name; import org.jooq.Record; -import org.jooq.RecordType; +import org.jooq.RecordHandler; +import org.jooq.RecordMapper; import org.jooq.Result; -import org.jooq.Row; -import org.jooq.Schema; -import org.jooq.TXTFormat; import org.jooq.Table; -import org.jooq.TableField; -import org.jooq.TableRecord; -import org.jooq.XML; -import org.jooq.XMLFormat; -import org.jooq.exception.IOException; -import org.jooq.tools.StringUtils; -import org.jooq.tools.json.JSONValue; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.AttributesImpl; /** * @author Lukas Eder */ -abstract class AbstractCursor extends AbstractFormattable implements Fields, Iterable { +abstract class AbstractCursor extends AbstractResult implements Cursor { /** * Generated UID */ - private static final long serialVersionUID = -3412555195899758746L; - - final AbstractRow fields; - Configuration configuration; + private static final long serialVersionUID = 866689823212695960L; AbstractCursor(Configuration configuration, AbstractRow row) { - this.configuration = configuration; - this.fields = row; + super(configuration, row); } - // ------------------------------------------------------------------------- - // XXX: RecordType API of subtypes - // ------------------------------------------------------------------------- - - @SuppressWarnings("unchecked") - public final RecordType recordType() { - return (RecordType) fields.fields; - } - - @Override - public final Row fieldsRow() { - return fields; - } - - @Override - public final Stream> fieldStream() { - return fields.fieldStream(); + public final Stream stream() { + return StreamSupport.stream( + Spliterators.spliteratorUnknownSize( + iterator(), + Spliterator.ORDERED | Spliterator.NONNULL + ), + false + ).onClose(() -> close()); } + @Override + public final X collect(Collector collector) { + return stream().collect(collector); + } @Override - public final Field field(Field field) { - return fields.field(field); + public final boolean hasNext() { + return iterator().hasNext(); } - /** - * @deprecated This method hides static import {@link DSL#field(String)}. - */ + @Override + public final Result fetch() { + return fetch(Integer.MAX_VALUE); + } + + @Override + @Deprecated + public final R fetchOne() { + return fetchNext(); + } + + @Override + @Deprecated + public final E fetchOne(RecordMapper mapper) { + return fetchNext(mapper); + } + + @Override + @Deprecated + public final > H fetchOneInto(H handler) { + return fetchNextInto(handler); + } + + @Override + @Deprecated + public final Z fetchOneInto(Table table) { + return fetchNextInto(table); + } + + @Override + @Deprecated + public final E fetchOneInto(Class type) { + return fetchNextInto(type); + } + + @Override + public final R fetchNext() { + Result result = fetch(1); + + if (result.size() == 1) + return result.get(0); + + return null; + } + + + @Override @Deprecated - public final Field field(String name) { - return fields.field(name); + public final Optional fetchOptional() { + return fetchNextOptional(); } - /** - * @deprecated This method hides static import {@link DSL#field(String, Class)}. - */ @Override @Deprecated - public final Field field(String name, Class type) { - return fields.field(name, type); + public final Optional fetchOptional(RecordMapper mapper) { + return fetchNextOptional(mapper); } - /** - * @deprecated This method hides static import {@link DSL#field(String, DataType)}. - */ @Override @Deprecated - public final Field field(String name, DataType dataType) { - return fields.field(name, dataType); + public final Optional fetchOptionalInto(Class type) { + return fetchNextOptionalInto(type); } - /** - * @deprecated This method hides static import {@link DSL#field(Name)}. - */ @Override @Deprecated - public final Field field(Name name) { - return fields.field(name); - } - - /** - * @deprecated This method hides static import {@link DSL#field(Name, Class)}. - */ - @Override - @Deprecated - public final Field field(Name name, Class type) { - return fields.field(name, type); - } - - /** - * @deprecated This method hides static import {@link DSL#field(Name, DataType)}. - */ - @Override - @Deprecated - public final Field field(Name name, DataType dataType) { - return fields.field(name, dataType); + public final Optional fetchOptionalInto(Table table) { + return fetchNextOptionalInto(table); } @Override - public final Field field(int index) { - return fields.field(index); + public final Optional fetchNextOptional() { + return Optional.ofNullable(fetchNext()); } @Override - public final Field field(int index, Class type) { - return fields.field(index, type); + public final Optional fetchNextOptional(RecordMapper mapper) { + return Optional.ofNullable(fetchNext(mapper)); } @Override - public final Field field(int index, DataType dataType) { - return fields.field(index, dataType); + public final Optional fetchNextOptionalInto(Class type) { + return Optional.ofNullable(fetchNextInto(type)); } @Override - public final Field[] fields() { - return fields.fields().clone(); + public final Optional fetchNextOptionalInto(Table table) { + return Optional.ofNullable(fetchNextInto(table)); + } + + + + @Override + public final Result fetch(int number) { + return fetchNext(number); } @Override - public final Field[] fields(Field... f) { - return fields.fields(f); - } - - @Override - public final Field[] fields(int... indexes) { - return fields.fields(indexes); - } - - @Override - public final Field[] fields(String... names) { - return fields.fields(names); - } - - @Override - public final Field[] fields(Name... names) { - return fields.fields(names); - } - - @Override - public final int indexOf(Field field) { - return fields.indexOf(field); - } - - @Override - public final int indexOf(String fieldName) { - return fields.indexOf(fieldName); - } - - @Override - public final int indexOf(Name fieldName) { - return fields.indexOf(fieldName); - } - - @Override - public final Class[] types() { - return fields.types(); - } - - @Override - public final Class type(int index) { - return fields.type(index); - } - - @Override - public final Class type(String name) { - return fields.type(name); - } - - @Override - public final Class type(Name name) { - return fields.type(name); - } - - @Override - public final DataType[] dataTypes() { - return fields.dataTypes(); - } - - @Override - public final DataType dataType(int index) { - return fields.dataType(index); - } - - @Override - public final DataType dataType(String name) { - return fields.dataType(name); - } - - @Override - public final DataType dataType(Name name) { - return fields.dataType(name); - } - - // ------------------------------------------------------------------------- - // XXX: Formattable API - // ------------------------------------------------------------------------- - - @Override - public final void format(Writer writer, TXTFormat format) { - try { - - // Numeric columns have greater max width because values are aligned - final int NUM_COL_MAX_WIDTH = format.maxColWidth() == Integer.MAX_VALUE ? Integer.MAX_VALUE : 2 * format.maxColWidth(); - - // The max number of records that will be considered for formatting purposes - final int MAX_RECORDS = min(50, format.maxRows()); - final Deque buffer = new ArrayDeque<>(); - final Iterator it = iterator(); - - // Buffer some rows for formatting purposes - for (int i = 0; i < MAX_RECORDS && it.hasNext(); i++) - buffer.offer(it.next()); - - // Get max decimal places for numeric type columns - int size = fields.size(); - final int[] decimalPlaces = new int[size]; - final int[] widths = new int[size]; - - for (int index = 0; index < size; index++) { - if (Number.class.isAssignableFrom(fields.field(index).getType())) { - List decimalPlacesList = new ArrayList<>(1 + buffer.size()); - - // Initialize - decimalPlacesList.add(0); - - // Collect all decimal places for the column values - for (R record : buffer) - decimalPlacesList.add(decimalPlaces(format0(record.get(index), record.changed(index), true))); - - // Find max - decimalPlaces[index] = Collections.max(decimalPlacesList); - } - } - - // Get max column widths - int colMaxWidth; - for (int index = 0; index < size; index++) { - - // Is number column? - boolean isNumCol = Number.class.isAssignableFrom(fields.field(index).getType()); - - colMaxWidth = isNumCol ? NUM_COL_MAX_WIDTH : format.maxColWidth(); - - // Collect all widths for the column - List widthList = new ArrayList<>(1 + buffer.size()); - - // Add column name width first - widthList.add(min(colMaxWidth, max(format.minColWidth(), fields.field(index).getName().length()))); - - // Add column values width - for (R record : buffer) { - String value = format0(record.get(index), record.changed(index), true); - - // Align number values before width is calculated - if (isNumCol) - value = alignNumberValue(decimalPlaces[index], value); - - widthList.add(min(colMaxWidth, value.length())); - } - - // Find max - widths[index] = Collections.max(widthList); - } - - // Begin the writing - // --------------------------------------------------------------------- - - // Write top line - if (format.horizontalTableBorder()) - formatHorizontalLine(writer, format, widths); - - // Write headers - if (format.verticalTableBorder()) - writer.append('|'); - - for (int index = 0; index < size; index++) { - if (index > 0) - if (format.verticalCellBorder()) - writer.append('|'); - else - writer.append(' '); - - String padded; - - if (Number.class.isAssignableFrom(fields.field(index).getType())) - padded = leftPad(fields.field(index).getName(), widths[index]); - else - padded = rightPad(fields.field(index).getName(), widths[index]); - - writer.append(abbreviate(padded, widths[index])); - } - - if (format.verticalTableBorder()) - writer.append('|'); - - writer.append('\n'); - - // Write separator - if (format.horizontalHeaderBorder()) - formatHorizontalLine(writer, format, widths); - - // Write records - int i; - - recordLoop: - for (i = 0; i < format.maxRows(); i++) { - R record = buffer.pollFirst(); - - if (record == null) - if (it.hasNext()) - record = it.next(); - else - break recordLoop; - - // Write separator - if (i > 0 && format.horizontalCellBorder()) - formatHorizontalLine(writer, format, widths); - - if (format.verticalTableBorder()) - writer.append('|'); - - for (int index = 0; index < size; index++) { - if (index > 0) - if (format.verticalCellBorder()) - writer.append('|'); - else - writer.append(' '); - - String value = - StringUtils.replace( - StringUtils.replace( - StringUtils.replace( - format0(record.get(index), record.changed(index), true), "\n", "{lf}" - ), "\r", "{cr}" - ), "\t", "{tab}" - ); - - String padded; - if (Number.class.isAssignableFrom(fields.field(index).getType())) { - // Align number value before left pad - value = alignNumberValue(decimalPlaces[index], value); - - // Left pad - padded = leftPad(value, widths[index]); - } - else { - // Right pad - padded = rightPad(value, widths[index]); - } - - writer.append(abbreviate(padded, widths[index])); - } - - if (format.verticalTableBorder()) - writer.append('|'); - - writer.append('\n'); - } - - // Write bottom line - if (format.horizontalTableBorder() && i > 0) - formatHorizontalLine(writer, format, widths); - - // Write truncation message, if applicable - if (it.hasNext()) { - if (format.verticalTableBorder()) - writer.append('|'); - - writer.append("...record(s) truncated...\n"); - } - - writer.flush(); - } - catch (java.io.IOException e) { - throw new IOException("Exception while writing TEXT", e); - } - } - - private final void formatHorizontalLine(Writer writer, TXTFormat format, final int[] widths) throws java.io.IOException { - if (format.verticalTableBorder()) - if (format.intersectLines()) - writer.append('+'); - else - writer.append('-'); - - int size = fields.size(); - for (int index = 0; index < size; index++) { - if (index > 0) - if (format.verticalCellBorder()) - if (format.intersectLines()) - writer.append('+'); - else - writer.append('-'); - else - writer.append(' '); - - writer.append(rightPad("", widths[index], "-")); - } - - if (format.verticalTableBorder()) - if (format.intersectLines()) - writer.append('+'); - else - writer.append('-'); - - writer.append('\n'); - } - - private static final String alignNumberValue(Integer columnDecimalPlaces, String value) { - if (!"{null}".equals(value) && columnDecimalPlaces != 0) { - int decimalPlaces = decimalPlaces(value); - int rightPadSize = value.length() + columnDecimalPlaces - decimalPlaces; - - if (decimalPlaces == 0) { - // If integer value, add one for decimal point - value = rightPad(value, rightPadSize + 1); - } - else { - value = rightPad(value, rightPadSize); - } - } - - return value; - } - - private static final int decimalPlaces(String value) { - int decimalPlaces = 0; - - int dotIndex = value.indexOf("."); - if (dotIndex != -1) - decimalPlaces = value.length() - dotIndex - 1; - - return decimalPlaces; - } - - @Override - public final void formatCSV(Writer writer, CSVFormat format) { - try { - if (format.header()) { - String sep1 = ""; - for (Field field : fields.fields.fields) { - writer.append(sep1); - writer.append(formatCSV0(field.getName(), format)); - - sep1 = format.delimiter(); - } - - writer.append(format.newline()); - } - - for (Record record : this) { - String sep2 = ""; - - int size = fields.size(); - for (int index = 0; index < size; index++) { - writer.append(sep2); - writer.append(formatCSV0(record.getValue(index), format)); - - sep2 = format.delimiter(); - } - - writer.append(format.newline()); - } - - writer.flush(); - } - catch (java.io.IOException e) { - throw new IOException("Exception while writing CSV", e); - } - } - - private final String formatCSV0(Object value, CSVFormat format) { - - // [#2741] TODO: This logic will be externalised in new SPI - // [#4746] Escape null and empty strings - if (value == null) - return format.nullString(); - - if ("".equals(value.toString())) - return format.emptyString(); - - // [#7802] Nested records should generate nested CSV data structures - String result = (value instanceof Formattable) - ? ((Formattable) value).formatCSV(format) - : format0(value, false, false); - - switch (format.quote()) { - case NEVER: - return result; - - case SPECIAL_CHARACTERS: - if (!StringUtils.containsAny(result, ',', ';', '\t', '"', '\n', '\r', '\'', '\\')) - return result; - - // no break - case ALWAYS: - default: - return format.quoteString() - + StringUtils.replace( - StringUtils.replace( - result, "\\", "\\\\" - ), format.quoteString(), format.quoteString() + format.quoteString() - ) - + format.quoteString(); - } - } - - @Override - public final void formatJSON(Writer writer, JSONFormat format) { - if (format == null) - format = JSONFormat.DEFAULT_FOR_RESULTS; - - try { - String separator; - int recordLevel = format.header() ? 2 : 1; - - if (format.header()) { - if (format.format()) - writer.append('{').append(format.newline()) - .append(format.indentString(1)).append("\"fields\": ["); - else - writer.append("{\"fields\":["); - - separator = ""; - - for (Field field : fields.fields.fields) { - writer.append(separator); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(2)); - - writer.append('{'); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(3)); - - if (field instanceof TableField) { - Table table = ((TableField) field).getTable(); - - if (table != null) { - Schema schema = table.getSchema(); - - if (schema != null) { - writer.append("\"schema\":"); - - if (format.format()) - writer.append(' '); - - JSONValue.writeJSONString(schema.getName(), writer); - writer.append(','); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(3)); - } - - writer.append("\"table\":"); - - if (format.format()) - writer.append(' '); - - JSONValue.writeJSONString(table.getName(), writer); - writer.append(','); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(3)); - } - } - - writer.append("\"name\":"); - - if (format.format()) - writer.append(' '); - - JSONValue.writeJSONString(field.getName(), writer); - writer.append(','); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(3)); - - writer.append("\"type\":"); - - if (format.format()) - writer.append(' '); - - JSONValue.writeJSONString(field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings())), writer); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(2)); - - writer.append('}'); - separator = ","; - } - - if (format.format()) - writer.append(format.newline()).append(format.indentString(1)).append("],") - .append(format.newline()).append(format.indentString(1)).append("\"records\": "); - else - writer.append("],\"records\":"); - } - - writer.append('['); - separator = ""; - - switch (format.recordFormat()) { - case ARRAY: - for (Record record : this) { - writer.append(separator); - - if (format.format()) - writer.append(format.newline()); - - formatJSONArray0(record, fields, format, recordLevel, writer); - separator = ","; - } - - break; - case OBJECT: - for (Record record : this) { - writer.append(separator); - - if (format.format()) - writer.append(format.newline()); - - formatJSONMap0(record, fields, format, recordLevel, writer); - separator = ","; - } - - break; - default: - throw new IllegalArgumentException("Format not supported: " + format); - } - - if (format.format()) { - writer.append(format.newline()); - - if (format.header()) - writer.append(format.indentString(1)); - } - - writer.append(']'); - - if (format.header()) - writer.append(format.newline()).append('}'); - - writer.flush(); - } - catch (java.io.IOException e) { - throw new IOException("Exception while writing JSON", e); - } - } - - private static final void formatJSON0(Object value, Writer writer, JSONFormat format) throws java.io.IOException { - - // [#2741] TODO: This logic will be externalised in new SPI - if (value instanceof byte[]) { - JSONValue.writeJSONString(DatatypeConverter.printBase64Binary((byte[]) value), writer); - } - - // [#6563] Arrays can be serialised natively in JSON - else if (value instanceof Object[]) { - Object[] array = (Object[]) value; - writer.append('['); - - for (int i = 0; i < array.length; i++) { - if (i > 0) - writer.append(','); - - formatJSON0(array[i], writer, format); - } - - writer.append(']'); - } - - // [#7782] Nested records should generate nested JSON data structures - else if (value instanceof Formattable) { - ((Formattable) value).formatJSON(writer, format); - } - - else if (value instanceof JSON && !format.quoteNested()) { - writer.write(((JSON) value).data()); - } - else if (value instanceof JSONB && !format.quoteNested()) { - writer.write(((JSONB) value).data()); - } - - else { - JSONValue.writeJSONString(value, writer); - } - } - - static final void formatJSONMap0(Record record, AbstractRow fields, JSONFormat format, int recordLevel, Writer writer) throws java.io.IOException { - String separator = ""; - int size = fields.size(); - boolean wrapRecords = format.wrapSingleColumnRecords() || size > 1; - - if (wrapRecords) - if (format.format()) - writer.append(format.indentString(recordLevel)).append('{'); - else - writer.append('{'); - - for (int index = 0; index < size; index++) { - writer.append(separator); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(recordLevel + 1)); - - if (wrapRecords) { - JSONValue.writeJSONString(record.field(index).getName(), writer); - writer.append(':'); - - if (format.format()) - writer.append(' '); - } - - formatJSON0(record.get(index), writer, format); - separator = ","; - } - - if (wrapRecords) - if (format.format()) - writer.append(format.newline()).append(format.indentString(recordLevel)).append('}'); - else - writer.append('}'); - } - - static final void formatJSONArray0(Record record, AbstractRow fields, JSONFormat format, int recordLevel, Writer writer) throws java.io.IOException { - String separator = ""; - - int size = fields.size(); - if (format.wrapSingleColumnRecords() || size > 1) - if (format.format()) - writer.append(format.indentString(recordLevel)).append('['); - else - writer.append('['); - - for (int index = 0; index < size; index++) { - writer.append(separator); - - if (format.format()) - writer.append(format.newline()).append(format.indentString(recordLevel + 1)); - - formatJSON0(record.get(index), writer, format); - separator = ","; - } - - if (format.wrapSingleColumnRecords() || size > 1) - if (format.format()) - writer.append(format.newline()).append(format.indentString(recordLevel)).append(']'); - else - writer.append(']'); - } - - @Override - public final void formatXML(Writer writer, XMLFormat format) { - if (format == null) - format = XMLFormat.DEFAULT_FOR_RESULTS; - - String newline = format.newline(); - int recordLevel = format.header() ? 2 : 1; - - try { - writer.append(""); - - if (format.header()) { - writer.append(newline).append(format.indentString(1)).append(""); - - for (Field field : fields.fields.fields) { - writer.append(newline).append(format.indentString(2)).append(" table = ((TableField) field).getTable(); - - if (table != null) { - Schema schema = table.getSchema(); - - if (schema != null) { - writer.append(" schema=\""); - writer.append(escapeXML(schema.getName())); - writer.append("\""); - } - - writer.append(" table=\""); - writer.append(escapeXML(table.getName())); - writer.append("\""); - } - } - - writer.append(" name=\""); - writer.append(escapeXML(field.getName())); - writer.append("\""); - writer.append(" type=\""); - writer.append(field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings()))); - writer.append("\"/>"); - } - - writer.append(newline).append(format.indentString(1)).append(""); - writer.append(newline).append(format.indentString(1)).append(""); - } - - for (Record record : this) { - writer.append(newline).append(format.indentString(recordLevel)); - formatXMLRecord(writer, format, recordLevel, record, fields); - } - - if (format.header()) - writer.append(newline).append(format.indentString(1)).append(""); - - writer.append(newline).append(""); - writer.flush(); - } - catch (java.io.IOException e) { - throw new IOException("Exception while writing XML", e); - } - } - - static final void formatXMLRecord( - Writer writer, - XMLFormat format, - int recordLevel, - Record record, - AbstractRow fields - ) - throws java.io.IOException { - String newline = format.newline(); - - writer.append(""); - - int size = fields.size(); - for (int index = 0; index < size; index++) { - Object value = record.get(index); - - writer.append(newline).append(format.indentString(recordLevel + 1)); - String tag = format.recordFormat() == COLUMN_NAME_ELEMENTS - ? escapeXML(fields.field(index).getName()) - : "value"; - - writer.append("<" + tag); - if (format.recordFormat() == VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE) { - writer.append(" field=\""); - writer.append(escapeXML(fields.field(index).getName())); - writer.append("\""); - } - - if (value == null) { - writer.append("/>"); - } - else { - writer.append(">"); - - if (value instanceof Formattable) - ((Formattable) value).formatXML(writer, format); - else if (value instanceof XML && !format.quoteNested()) - writer.append(((XML) value).data()); - else - writer.append(escapeXML(format0(value, false, false))); - - writer.append(""); - } - } - - writer.append(newline).append(format.indentString(recordLevel)).append(""); - } - - @SuppressWarnings("unchecked") - @Override - public final void formatChart(Writer writer, ChartFormat format) { - Result result; - - if (this instanceof Result) - result = (Result) this; - else if (this instanceof Cursor) - result = ((Cursor) this).fetch(); - else - throw new IllegalStateException(); - - try { - DSLContext ctx = configuration.dsl(); - Field category = fields.field(format.category()); - TreeMap> groups = new TreeMap<>(result.intoGroups(format.category())); - - if (!format.categoryAsText()) { - if (Date.class.isAssignableFrom(category.getType())) { - Date categoryMin = (Date) groups.firstKey(); - Date categoryMax = (Date) groups.lastKey(); - - for (Date i = categoryMin; i.before(categoryMax); i = new Date(i.getYear(), i.getMonth(), i.getDate() + 1)) - if (!groups.containsKey(i)) - groups.put(i, (Result) ctx.newResult(fields.fields.fields)); - } - } - - List categories = new ArrayList<>(groups.keySet()); - - int categoryPadding = 1; - int categoryWidth = 0; - for (Object o : categories) - categoryWidth = Math.max(categoryWidth, ("" + o).length()); - - double axisMin = Double.POSITIVE_INFINITY; - double axisMax = Double.NEGATIVE_INFINITY; - - for (Result values : groups.values()) { - double sum = 0; - - for (int i = 0; i < format.values().length; i++) { - if (format.display() == Display.DEFAULT) - sum = 0; - - for (Record r : values) - sum = sum + r.get(format.values()[i], double.class); - - if (sum < axisMin) - axisMin = sum; - - if (sum > axisMax) - axisMax = sum; - } - } - - int verticalLegendWidth = format.showVerticalLegend() - ? Math.max( - format.numericFormat().format(axisMin).length(), - format.numericFormat().format(axisMax).length() - ) - : 0; - - int horizontalLegendHeight = format.showHorizontalLegend() ? 1 : 0; - - int verticalBorderWidth = format.showVerticalLegend() ? 1 : 0; - int horizontalBorderHeight = format.showHorizontalLegend() ? 1 : 0; - - int chartHeight = format.height() - horizontalLegendHeight - horizontalBorderHeight; - int chartWidth = format.width() - verticalLegendWidth - verticalBorderWidth; - - double barWidth = (double) chartWidth / groups.size(); - double axisStep = (axisMax - axisMin) / (chartHeight - 1); - - for (int y = chartHeight - 1; y >= 0; y--) { - double axisLegend = axisMax - (axisStep * (chartHeight - 1 - y)); - double axisLegendPercent = (axisLegend - axisMin) / (axisMax - axisMin); - - if (format.showVerticalLegend()) { - String axisLegendString = (format.display() == Display.HUNDRED_PERCENT_STACKED) - ? format.numericFormat().format(axisLegendPercent * 100.0) + "%" - : format.numericFormat().format(axisLegend); - - for (int x = axisLegendString.length(); x < verticalLegendWidth; x++) - writer.write(' '); - - writer.write(axisLegendString); - - for (int x = 0; x < verticalBorderWidth; x++) - writer.write('|'); - } - - for (int x = 0; x < chartWidth; x++) { - int index = (int) (x / barWidth); - - Result group = groups.get(categories.get(index)); - double[] values = new double[format.values().length]; - - for (Record record : group) - for (int i = 0; i < values.length; i++) - values[i] = values[i] + record.get(format.values()[i], double.class); - - if (format.display() == Display.STACKED || format.display() == Display.HUNDRED_PERCENT_STACKED) - for (int i = 1; i < values.length; i++) - values[i] = values[i] + values[i - 1]; - - if (format.display() == Display.HUNDRED_PERCENT_STACKED) - for (int i = 0; i < values.length; i++) - values[i] = values[i] / values[values.length - 1]; - - int shadeIndex = -1; - for (int i = values.length - 1; i >= 0; i--) - if ((format.display() == Display.HUNDRED_PERCENT_STACKED ? axisLegendPercent : axisLegend) > values[i]) - break; - else - shadeIndex = i; - - if (shadeIndex == -1) - writer.write(' '); - else - writer.write(format.shades()[shadeIndex % format.shades().length]); - } - - writer.write(format.newline()); - } - - if (format.showHorizontalLegend()) { - for (int y = 0; y < horizontalBorderHeight; y++) { - if (format.showVerticalLegend()) { - for (int x = 0; x < verticalLegendWidth; x++) - writer.write('-'); - - for (int x = 0; x < verticalBorderWidth; x++) - writer.write('+'); - } - - for (int x = 0; x < chartWidth; x++) - writer.write('-'); - - writer.write(format.newline()); - } - - for (int y = 0; y < horizontalLegendHeight; y++) { - if (format.showVerticalLegend()) { - for (int x = 0; x < verticalLegendWidth; x++) - writer.write(' '); - - for (int x = 0; x < verticalBorderWidth; x++) - writer.write('|'); - } - - double rounding = 0.0; - for (double x = 0.0; x < chartWidth;) { - String label = "" + categories.get((int) (x / barWidth)); - int length = label.length(); - - double padding = Math.max(categoryPadding, (barWidth - length) / 2); - - rounding = (rounding + padding - Math.floor(padding)) % 1; - x = x + (padding + rounding); - for (int i = 0; i < (int) (padding + rounding); i++) - writer.write(' '); - - x = x + length; - if (x >= chartWidth) - break; - writer.write(label); - - rounding = (rounding + padding - Math.floor(padding)) % 1; - x = x + (padding + rounding); - for (int i = 0; i < (int) (padding + rounding); i++) - writer.write(' '); - } - - writer.write(format.newline()); - } - } - } - catch (java.io.IOException e) { - throw new IOException("Exception while writing Chart", e); - } - } - - @Override - public final void formatInsert(Writer writer) { - formatInsert(writer, null, fields.fields.fields); - } - - @Override - public final void formatInsert(Writer writer, Table table, Field... f) { - DSLContext ctx = configuration.dsl(); - - try { - for (R record : this) { - if (table == null) - if (record instanceof TableRecord) - table = ((TableRecord) record).getTable(); - else - table = table(name("UNKNOWN_TABLE")); - - writer.append(ctx.renderInlined(insertInto(table, f).values(record.intoArray()))) - .append(";\n"); - } - - writer.flush(); - } - catch (java.io.IOException e) { - throw new IOException("Exception while writing INSERTs", e); - } - } - - @Override - public final void formatHTML(Writer writer) { - try { - writer.append(""); - writer.append(""); - writer.append(""); - - for (Field field : fields.fields.fields) { - writer.append(""); - } - - writer.append(""); - writer.append(""); - writer.append(""); - - for (Record record : this) { - writer.append(""); - - int size = fields.size(); - for (int index = 0; index < size; index++) { - writer.append(""); - } - - writer.append(""); - } - - writer.append(""); - writer.append("
"); - writer.append(escapeXML(field.getName())); - writer.append("
"); - writer.append(escapeXML(format0(record.getValue(index), false, true))); - writer.append("
"); - - writer.flush(); - } - catch (java.io.IOException e) { - throw new IOException("Exception while writing HTML", e); - } - } - - @Override - public final Document intoXML(XMLFormat format) { - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document document = builder.newDocument(); - - Element eResult = document.createElement("result"); - - if (format.xmlns()) - eResult.setAttribute("xmlns", Constants.NS_EXPORT); - document.appendChild(eResult); - - Element eRecordParent = eResult; - - if (format.header()) { - Element eFields = document.createElement("fields"); - eResult.appendChild(eFields); - - for (Field field : fields.fields.fields) { - Element eField = document.createElement("field"); - - if (field instanceof TableField) { - Table table = ((TableField) field).getTable(); - - if (table != null) { - Schema schema = table.getSchema(); - - if (schema != null) { - eField.setAttribute("schema", schema.getName()); - } - - eField.setAttribute("table", table.getName()); - } - } - - eField.setAttribute("name", field.getName()); - eField.setAttribute("type", field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings()))); - eFields.appendChild(eField); - } - - Element eRecords = document.createElement("records"); - eResult.appendChild(eRecords); - eRecordParent = eRecords; - } - - for (Record record : this) { - Element eRecord = document.createElement("record"); - eRecordParent.appendChild(eRecord); - - int size = fields.size(); - for (int index = 0; index < size; index++) { - Field field = fields.field(index); - Object value = record.get(index); - - String tag = format.recordFormat() == COLUMN_NAME_ELEMENTS - ? escapeXML(fields.field(index).getName()) - : "value"; - - Element eValue = document.createElement(tag); - - if (format.recordFormat() == VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE) - eValue.setAttribute("field", field.getName()); - eRecord.appendChild(eValue); - - if (value != null) { - eValue.setTextContent(format0(value, false, false)); - } - } - } - - return document; - } - catch (ParserConfigurationException ignore) { - throw new RuntimeException(ignore); - } - } - - @Override - public final H intoXML(H handler, XMLFormat format) throws SAXException { - Attributes empty = new AttributesImpl(); - - handler.startDocument(); - - if (format.xmlns()) - handler.startPrefixMapping("", Constants.NS_EXPORT); - - handler.startElement("", "", "result", empty); - if (format.header()) { - handler.startElement("", "", "fields", empty); - - for (Field field : fields.fields.fields) { - AttributesImpl attrs = new AttributesImpl(); - - if (field instanceof TableField) { - Table table = ((TableField) field).getTable(); - - if (table != null) { - Schema schema = table.getSchema(); - - if (schema != null) { - attrs.addAttribute("", "", "schema", "CDATA", schema.getName()); - } - - attrs.addAttribute("", "", "table", "CDATA", table.getName()); - } - } - - attrs.addAttribute("", "", "name", "CDATA", field.getName()); - attrs.addAttribute("", "", "type", "CDATA", field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings()))); - - handler.startElement("", "", "field", attrs); - handler.endElement("", "", "field"); - } - - handler.endElement("", "", "fields"); - handler.startElement("", "", "records", empty); - } - - for (Record record : this) { - handler.startElement("", "", "record", empty); - - int size = fields.size(); - for (int index = 0; index < size; index++) { - Field field = fields.field(index); - Object value = record.get(index); - - String tag = format.recordFormat() == COLUMN_NAME_ELEMENTS - ? escapeXML(fields.field(index).getName()) - : "value"; - - AttributesImpl attrs = new AttributesImpl(); - - if (format.recordFormat() == VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE) - attrs.addAttribute("", "", "field", "CDATA", field.getName()); - - handler.startElement("", "", tag, attrs); - - if (value != null) { - char[] chars = format0(value, false, false).toCharArray(); - handler.characters(chars, 0, chars.length); - } - - handler.endElement("", "", tag); - } - - handler.endElement("", "", "record"); - } - - if (format.header()) - handler.endElement("", "", "records"); - - if (format.xmlns()) - handler.endPrefixMapping(""); - - handler.endDocument(); + public final > H fetchNextInto(H handler) { + handler.next(fetchNext()); return handler; } - /** - * @param value The value to be formatted - * @param visual Whether the formatted output is to be consumed visually - * (HTML, TEXT) or by a machine (CSV, JSON, XML) - */ - private static final String format0(Object value, boolean changed, boolean visual) { + @Override + public final > H fetchInto(H handler) { + while (hasNext()) + fetchNextInto(handler); - // [#2741] TODO: This logic will be externalised in new SPI - String formatted = changed && visual ? "*" : ""; - - if (value == null) { - formatted += visual ? "{null}" : null; - } - else if (value.getClass() == byte[].class) { - formatted += DatatypeConverter.printBase64Binary((byte[]) value); - } - else if (value.getClass().isArray()) { - // [#6545] Nested arrays - if (value.getClass().getComponentType().isArray()) - formatted += Arrays.deepToString((Object[]) value); - else - formatted += Arrays.toString((Object[]) value); - } - else if (value instanceof EnumType) { - formatted += ((EnumType) value).getLiteral(); - } - else if (value instanceof Record) { - formatted += ((Record) value).valuesRow().toString(); - } - - // [#5238] Oracle DATE is really a TIMESTAMP(0)... - else if (value instanceof Date) { - String date = value.toString(); - - if (Date.valueOf(date).equals(value)) - formatted += date; - else - formatted += new Timestamp(((Date) value).getTime()); - } - else { - formatted += value.toString(); - } - - return formatted; + return handler; } - private static final String escapeXML(String string) { - return StringUtils.replaceEach(string, - new String[] { "\"", "'", "<", ">", "&" }, - new String[] { """, "'", "<", ">", "&"}); + @Override + public final E fetchNext(RecordMapper mapper) { + R record = fetchNext(); + return record == null ? null : mapper.map(record); + } + + @Override + public final List fetch(RecordMapper mapper) { + return fetch().map(mapper); + } + + @Override + public final E fetchNextInto(Class clazz) { + R record = fetchNext(); + return record == null ? null : record.into(clazz); + } + + @Override + public final List fetchInto(Class clazz) { + return fetch().into(clazz); + } + + @Override + public final Z fetchNextInto(Table table) { + return fetchNext().into(table); + } + + @Override + public final Result fetchInto(Table table) { + return fetch().into(table); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingQuery.java index 6d6d8a0e03..fdea4e2dba 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingQuery.java @@ -46,12 +46,15 @@ import org.jooq.Configuration; import org.jooq.Context; import org.jooq.Param; import org.jooq.Query; +import org.jooq.Record; import org.jooq.conf.ParamType; /** * @author Lukas Eder */ -abstract class AbstractDelegatingQuery extends AbstractQueryPart implements Query { +abstract class AbstractDelegatingQuery + extends AbstractFetchable + implements Query { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingRowCountQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingRowCountQuery.java index 6567c79416..2a14476ed5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingRowCountQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDelegatingRowCountQuery.java @@ -39,12 +39,16 @@ package org.jooq.impl; // ... +import org.jooq.Fetchable; +import org.jooq.Record; import org.jooq.RowCountQuery; /** * @author Lukas Eder */ -abstract class AbstractDelegatingRowCountQuery extends AbstractDelegatingQuery implements RowCountQuery { +abstract class AbstractDelegatingRowCountQuery + extends AbstractDelegatingQuery + implements RowCountQuery, Fetchable { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractFetchable.java b/jOOQ/src/main/java/org/jooq/impl/AbstractFetchable.java new file mode 100644 index 0000000000..d0bc829c99 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractFetchable.java @@ -0,0 +1,1212 @@ +/* + * 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 static org.jooq.impl.Tools.blocking; + +import java.lang.reflect.Array; +import java.sql.ResultSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +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.Attachable; +import org.jooq.Configuration; +import org.jooq.Converter; +import org.jooq.Cursor; +import org.jooq.Fetchable; +import org.jooq.Field; +import org.jooq.Name; +import org.jooq.Record; +import org.jooq.RecordHandler; +import org.jooq.RecordMapper; +import org.jooq.Result; +import org.jooq.Results; +import org.jooq.Table; +import org.jooq.exception.DataAccessException; + +abstract class AbstractFetchable extends AbstractQueryPart implements Fetchable, Attachable { + + /** + * Generated UID + */ + private static final long serialVersionUID = 3663286102135167198L; + + @Override + public Configuration configuration() { + return super.configuration(); + } + + @Override + public /* non-final */ Result fetch() throws DataAccessException { + throw new DataAccessException("Attempt to call fetch() on " + getClass()); + } + + @Override + public /* non-final */ Cursor fetchLazy() throws DataAccessException { + return new ResultAsCursor(fetch()); + } + + @Override + public /* non-final */ Results fetchMany() throws DataAccessException { + throw new DataAccessException("Attempt to call fetchMany() on " + getClass()); + } + + /* non-final */ Cursor fetchLazyNonAutoClosing() { + return fetchLazy(); + } + + @Override + public final ResultSet fetchResultSet() { + return fetchLazy().resultSet(); + } + + @Override + public final Iterator iterator() { + return fetch().iterator(); + } + + @Override + public final CompletionStage> fetchAsync() { + return fetchAsync(Tools.configuration(this).executorProvider().provide()); + } + + @Override + public final CompletionStage> fetchAsync(Executor executor) { + return ExecutorProviderCompletionStage.of(CompletableFuture.supplyAsync(blocking(this::fetch), executor), () -> executor); + } + + @Override + public final Stream fetchStream() { + return Stream.of(1).flatMap(i -> fetchLazy().stream()); + } + + @Override + public final Stream fetchStreamInto(Class type) { + return fetchStream().map(r -> r.into(type)); + } + + @Override + public final Stream fetchStreamInto(Table table) { + return fetchStream().map(r -> r.into(table)); + } + + @Override + public final Stream stream() { + return fetchStream(); + } + + @Override + public final X collect(Collector collector) { + try (Cursor c = fetchLazyNonAutoClosing()) { + return c.collect(collector); + } + } + + + @Override + public final List fetch(Field field) { + return fetch().getValues(field); + } + + @Override + public final List fetch(Field field, Class type) { + return fetch().getValues(field, type); + } + + @Override + public final List fetch(Field field, Converter converter) { + return fetch().getValues(field, converter); + } + + @Override + public final List fetch(int fieldIndex) { + return fetch().getValues(fieldIndex); + } + + @Override + public final List fetch(int fieldIndex, Class type) { + return fetch().getValues(fieldIndex, type); + } + + @Override + public final List fetch(int fieldIndex, Converter converter) { + return fetch().getValues(fieldIndex, converter); + } + + @Override + public final List fetch(String fieldName) { + return fetch().getValues(fieldName); + } + + @Override + public final List fetch(String fieldName, Class type) { + return fetch().getValues(fieldName, type); + } + + @Override + public final List fetch(String fieldName, Converter converter) { + return fetch().getValues(fieldName, converter); + } + + @Override + public final List fetch(Name fieldName) { + return fetch().getValues(fieldName); + } + + @Override + public final List fetch(Name fieldName, Class type) { + return fetch().getValues(fieldName, type); + } + + @Override + public final List fetch(Name fieldName, Converter converter) { + return fetch().getValues(fieldName, converter); + } + + @Override + public final T fetchOne(Field field) { + R record = fetchOne(); + return record == null ? null : record.get(field); + } + + @Override + public final U fetchOne(Field field, Class type) { + R record = fetchOne(); + return record == null ? null : record.get(field, type); + } + + @Override + public final U fetchOne(Field field, Converter converter) { + R record = fetchOne(); + return record == null ? null : record.get(field, converter); + } + + @Override + public final Object fetchOne(int fieldIndex) { + R record = fetchOne(); + return record == null ? null : record.get(fieldIndex); + } + + @Override + public final U fetchOne(int fieldIndex, Class type) { + R record = fetchOne(); + return record == null ? null : record.get(fieldIndex, type); + } + + @Override + public final U fetchOne(int fieldIndex, Converter converter) { + R record = fetchOne(); + return record == null ? null : record.get(fieldIndex, converter); + } + + @Override + public final Object fetchOne(String fieldName) { + R record = fetchOne(); + return record == null ? null : record.get(fieldName); + } + + @Override + public final U fetchOne(String fieldName, Class type) { + R record = fetchOne(); + return record == null ? null : record.get(fieldName, type); + } + + @Override + public final U fetchOne(String fieldName, Converter converter) { + R record = fetchOne(); + return record == null ? null : record.get(fieldName, converter); + } + + @Override + public final Object fetchOne(Name fieldName) { + R record = fetchOne(); + return record == null ? null : record.get(fieldName); + } + + @Override + public final U fetchOne(Name fieldName, Class type) { + R record = fetchOne(); + return record == null ? null : record.get(fieldName, type); + } + + @Override + public final U fetchOne(Name fieldName, Converter converter) { + R record = fetchOne(); + return record == null ? null : record.get(fieldName, converter); + } + + @Override + public final R fetchOne() { + return Tools.fetchOne(fetchLazyNonAutoClosing(), hasLimit1()); + } + + @Override + public final E fetchOne(RecordMapper mapper) { + R record = fetchOne(); + return record == null ? null : mapper.map(record); + } + + @Override + public final Map fetchOneMap() { + R record = fetchOne(); + return record == null ? null : record.intoMap(); + } + + @Override + public final Object[] fetchOneArray() { + R record = fetchOne(); + return record == null ? null : record.intoArray(); + } + + @Override + public final E fetchOneInto(Class type) { + R record = fetchOne(); + return record == null ? null : record.into(type); + } + + @Override + public final Z fetchOneInto(Table table) { + R record = fetchOne(); + return record == null ? null : record.into(table); + } + + @Override + public final T fetchSingle(Field field) { + return fetchSingle().get(field); + } + + @Override + public final U fetchSingle(Field field, Class type) { + return fetchSingle().get(field, type); + } + + @Override + public final U fetchSingle(Field field, Converter converter) { + return fetchSingle().get(field, converter); + } + + @Override + public final Object fetchSingle(int fieldIndex) { + return fetchSingle().get(fieldIndex); + } + + @Override + public final U fetchSingle(int fieldIndex, Class type) { + return fetchSingle().get(fieldIndex, type); + } + + @Override + public final U fetchSingle(int fieldIndex, Converter converter) { + return fetchSingle().get(fieldIndex, converter); + } + + @Override + public final Object fetchSingle(String fieldName) { + return fetchSingle().get(fieldName); + } + + @Override + public final U fetchSingle(String fieldName, Class type) { + return fetchSingle().get(fieldName, type); + } + + @Override + public final U fetchSingle(String fieldName, Converter converter) { + return fetchSingle().get(fieldName, converter); + } + + @Override + public final Object fetchSingle(Name fieldName) { + return fetchSingle().get(fieldName); + } + + @Override + public final U fetchSingle(Name fieldName, Class type) { + return fetchSingle().get(fieldName, type); + } + + @Override + public final U fetchSingle(Name fieldName, Converter converter) { + return fetchSingle().get(fieldName, converter); + } + + @Override + public final R fetchSingle() { + return Tools.fetchSingle(fetchLazyNonAutoClosing(), hasLimit1()); + } + + @Override + public final E fetchSingle(RecordMapper mapper) { + return mapper.map(fetchSingle()); + } + + @Override + public final Map fetchSingleMap() { + return fetchSingle().intoMap(); + } + + @Override + public final Object[] fetchSingleArray() { + return fetchSingle().intoArray(); + } + + @Override + public final E fetchSingleInto(Class type) { + return fetchSingle().into(type); + } + + @Override + public final Z fetchSingleInto(Table table) { + return fetchSingle().into(table); + } + + + @Override + public final Optional fetchOptional(Field field) { + return Optional.ofNullable(fetchOne(field)); + } + + @Override + public final Optional fetchOptional(Field field, Class type) { + return Optional.ofNullable(fetchOne(field, type)); + } + + @Override + public final Optional fetchOptional(Field field, Converter converter) { + return Optional.ofNullable(fetchOne(field, converter)); + } + + @Override + public final Optional fetchOptional(int fieldIndex) { + return Optional.ofNullable(fetchOne(fieldIndex)); + } + + @Override + public final Optional fetchOptional(int fieldIndex, Class type) { + return Optional.ofNullable(fetchOne(fieldIndex, type)); + } + + @Override + public final Optional fetchOptional(int fieldIndex, Converter converter) { + return Optional.ofNullable(fetchOne(fieldIndex, converter)); + } + + @Override + public final Optional fetchOptional(String fieldName) { + return Optional.ofNullable(fetchOne(fieldName)); + } + + @Override + public final Optional fetchOptional(String fieldName, Class type) { + return Optional.ofNullable(fetchOne(fieldName, type)); + } + + @Override + public final Optional fetchOptional(String fieldName, Converter converter) { + return Optional.ofNullable(fetchOne(fieldName, converter)); + } + + @Override + public final Optional fetchOptional(Name fieldName) { + return Optional.ofNullable(fetchOne(fieldName)); + } + + @Override + public final Optional fetchOptional(Name fieldName, Class type) { + return Optional.ofNullable(fetchOne(fieldName, type)); + } + + @Override + public final Optional fetchOptional(Name fieldName, Converter converter) { + return Optional.ofNullable(fetchOne(fieldName, converter)); + } + + @Override + public final Optional fetchOptional() { + return Optional.ofNullable(fetchOne()); + } + + @Override + public final Optional fetchOptional(RecordMapper mapper) { + return Optional.ofNullable(fetchOne(mapper)); + } + + @Override + public final Optional> fetchOptionalMap() { + return Optional.ofNullable(fetchOneMap()); + } + + @Override + public final Optional fetchOptionalArray() { + return Optional.ofNullable(fetchOneArray()); + } + + @Override + public final Optional fetchOptionalInto(Class type) { + return Optional.ofNullable(fetchOneInto(type)); + } + + @Override + public final Optional fetchOptionalInto(Table table) { + return Optional.ofNullable(fetchOneInto(table)); + } + + + @Override + public final T fetchAny(Field field) { + R record = fetchAny(); + return record == null ? null : record.get(field); + } + + @Override + public final U fetchAny(Field field, Class type) { + R record = fetchAny(); + return record == null ? null : record.get(field, type); + } + + @Override + public final U fetchAny(Field field, Converter converter) { + R record = fetchAny(); + return record == null ? null : record.get(field, converter); + } + + @Override + public final Object fetchAny(int fieldIndex) { + R record = fetchAny(); + return record == null ? null : record.get(fieldIndex); + } + + @Override + public final U fetchAny(int fieldIndex, Class type) { + R record = fetchAny(); + return record == null ? null : record.get(fieldIndex, type); + } + + @Override + public final U fetchAny(int fieldIndex, Converter converter) { + R record = fetchAny(); + return record == null ? null : record.get(fieldIndex, converter); + } + + @Override + public final Object fetchAny(String fieldName) { + R record = fetchAny(); + return record == null ? null : record.get(fieldName); + } + + @Override + public final U fetchAny(String fieldName, Class type) { + R record = fetchAny(); + return record == null ? null : record.get(fieldName, type); + } + + @Override + public final U fetchAny(String fieldName, Converter converter) { + R record = fetchAny(); + return record == null ? null : record.get(fieldName, converter); + } + + @Override + public final Object fetchAny(Name fieldName) { + R record = fetchAny(); + return record == null ? null : record.get(fieldName); + } + + @Override + public final U fetchAny(Name fieldName, Class type) { + R record = fetchAny(); + return record == null ? null : record.get(fieldName, type); + } + + @Override + public final U fetchAny(Name fieldName, Converter converter) { + R record = fetchAny(); + return record == null ? null : record.get(fieldName, converter); + } + + @Override + public final R fetchAny() { + Cursor c = fetchLazyNonAutoClosing(); + + try { + return c.fetchNext(); + } + finally { + c.close(); + } + } + + @Override + public final E fetchAny(RecordMapper mapper) { + R record = fetchAny(); + return record == null ? null : mapper.map(record); + } + + @Override + public final Map fetchAnyMap() { + R record = fetchAny(); + return record == null ? null : record.intoMap(); + } + + @Override + public final Object[] fetchAnyArray() { + R record = fetchAny(); + return record == null ? null : record.intoArray(); + } + + @Override + public final E fetchAnyInto(Class type) { + R record = fetchAny(); + return record == null ? null : record.into(type); + } + + @Override + public final Z fetchAnyInto(Table table) { + R record = fetchAny(); + return record == null ? null : record.into(table); + } + + @Override + public final Map fetchMap(Field key) { + return fetch().intoMap(key); + } + + @Override + public final Map fetchMap(int keyFieldIndex) { + return fetch().intoMap(keyFieldIndex); + } + + @Override + public final Map fetchMap(String keyFieldName) { + return fetch().intoMap(keyFieldName); + } + + @Override + public final Map fetchMap(Name keyFieldName) { + return fetch().intoMap(keyFieldName); + } + + @Override + public final Map fetchMap(Field key, Field value) { + return fetch().intoMap(key, value); + } + + @Override + public final Map fetchMap(int keyFieldIndex, int valueFieldIndex) { + return fetch().intoMap(keyFieldIndex, valueFieldIndex); + } + + @Override + public final Map fetchMap(String keyFieldName, String valueFieldName) { + return fetch().intoMap(keyFieldName, valueFieldName); + } + + @Override + public final Map fetchMap(Name keyFieldName, Name valueFieldName) { + return fetch().intoMap(keyFieldName, valueFieldName); + } + + @Override + public final Map fetchMap(Field key, Class type) { + return fetch().intoMap(key, type); + } + + @Override + public final Map fetchMap(int keyFieldIndex, Class type) { + return fetch().intoMap(keyFieldIndex, type); + } + + @Override + public final Map fetchMap(String keyFieldName, Class type) { + return fetch().intoMap(keyFieldName, type); + } + + @Override + public final Map fetchMap(Name keyFieldName, Class type) { + return fetch().intoMap(keyFieldName, type); + } + + @Override + public final Map fetchMap(Field key, RecordMapper mapper) { + return fetch().intoMap(key, mapper); + } + + @Override + public final Map fetchMap(int keyFieldIndex, RecordMapper mapper) { + return fetch().intoMap(keyFieldIndex, mapper); + } + + @Override + public final Map fetchMap(String keyFieldName, RecordMapper mapper) { + return fetch().intoMap(keyFieldName, mapper); + } + + @Override + public final Map fetchMap(Name keyFieldName, RecordMapper mapper) { + return fetch().intoMap(keyFieldName, mapper); + } + + @Override + public final Map fetchMap(Field[] keys) { + return fetch().intoMap(keys); + } + + @Override + public final Map fetchMap(int[] keyFieldIndexes) { + return fetch().intoMap(keyFieldIndexes); + } + + @Override + public final Map fetchMap(String[] keyFieldNames) { + return fetch().intoMap(keyFieldNames); + } + + @Override + public final Map fetchMap(Name[] keyFieldNames) { + return fetch().intoMap(keyFieldNames); + } + + @Override + public final Map fetchMap(Field[] keys, Field[] values) { + return fetch().intoMap(keys, values); + } + + @Override + public final Map fetchMap(int[] keyFieldIndexes, int[] valueFieldIndexes) { + return fetch().intoMap(keyFieldIndexes, valueFieldIndexes); + } + + @Override + public final Map fetchMap(String[] keyFieldNames, String[] valueFieldNames) { + return fetch().intoMap(keyFieldNames, valueFieldNames); + } + + @Override + public final Map fetchMap(Name[] keyFieldNames, Name[] valueFieldNames) { + return fetch().intoMap(keyFieldNames, valueFieldNames); + } + + @Override + public final Map, E> fetchMap(Field[] keys, Class type) { + return fetch().intoMap(keys, type); + } + + @Override + public final Map, E> fetchMap(int[] keyFieldIndexes, Class type) { + return fetch().intoMap(keyFieldIndexes, type); + } + + @Override + public final Map, E> fetchMap(String[] keyFieldNames, Class type) { + return fetch().intoMap(keyFieldNames, type); + } + + @Override + public final Map, E> fetchMap(Name[] keyFieldNames, Class type) { + return fetch().intoMap(keyFieldNames, type); + } + + @Override + public final Map, E> fetchMap(Field[] keys, RecordMapper mapper) { + return fetch().intoMap(keys, mapper); + } + + @Override + public final Map, E> fetchMap(int[] keyFieldIndexes, RecordMapper mapper) { + return fetch().intoMap(keyFieldIndexes, mapper); + } + + @Override + public final Map, E> fetchMap(String[] keyFieldNames, RecordMapper mapper) { + return fetch().intoMap(keyFieldNames, mapper); + } + + @Override + public final Map, E> fetchMap(Name[] keyFieldNames, RecordMapper mapper) { + return fetch().intoMap(keyFieldNames, mapper); + } + + @Override + public final Map fetchMap(Class keyType) { + return fetch().intoMap(keyType); + } + + @Override + public final Map fetchMap(Class keyType, Class valueType) { + return fetch().intoMap(keyType, valueType); + } + + @Override + public final Map fetchMap(Class keyType, RecordMapper valueMapper) { + return fetch().intoMap(keyType, valueMapper); + } + + @Override + public final Map fetchMap(RecordMapper keyMapper) { + return fetch().intoMap(keyMapper); + } + + @Override + public final Map fetchMap(RecordMapper keyMapper, Class valueType) { + return fetch().intoMap(keyMapper, valueType); + } + + @Override + public final Map fetchMap(RecordMapper keyMapper, RecordMapper valueMapper) { + return fetch().intoMap(keyMapper, valueMapper); + } + + @Override + public final Map fetchMap(Table table) { + return fetch().intoMap(table); + } + + @Override + public final Map fetchMap(Table keyTable, Table valueTable) { + return fetch().intoMap(keyTable, valueTable); + } + + @Override + public final Map fetchMap(Table table, Class type) { + return fetch().intoMap(table, type); + } + + @Override + public final Map fetchMap(Table table, RecordMapper mapper) { + return fetch().intoMap(table, mapper); + } + + @Override + public final List> fetchMaps() { + return fetch().intoMaps(); + } + + @Override + public final Map> fetchGroups(Field key) { + return fetch().intoGroups(key); + } + + @Override + public final Map> fetchGroups(int keyFieldIndex) { + return fetch().intoGroups(keyFieldIndex); + } + + @Override + public final Map> fetchGroups(String keyFieldName) { + return fetch().intoGroups(keyFieldName); + } + + @Override + public final Map> fetchGroups(Name keyFieldName) { + return fetch().intoGroups(keyFieldName); + } + + @Override + public final Map> fetchGroups(Field key, Field value) { + return fetch().intoGroups(key, value); + } + + @Override + public final Map> fetchGroups(int keyFieldIndex, int valueFieldIndex) { + return fetch().intoGroups(keyFieldIndex, valueFieldIndex); + } + + @Override + public final Map> fetchGroups(String keyFieldName, String valueFieldName) { + return fetch().intoGroups(keyFieldName, valueFieldName); + } + + @Override + public final Map> fetchGroups(Name keyFieldName, Name valueFieldName) { + return fetch().intoGroups(keyFieldName, valueFieldName); + } + + @Override + public final Map> fetchGroups(Field key, Class type) { + return fetch().intoGroups(key, type); + } + + @Override + public final Map> fetchGroups(int keyFieldIndex, Class type) { + return fetch().intoGroups(keyFieldIndex, type); + } + + @Override + public final Map> fetchGroups(String keyFieldName, Class type) { + return fetch().intoGroups(keyFieldName, type); + } + + @Override + public final Map> fetchGroups(Name keyFieldName, Class type) { + return fetch().intoGroups(keyFieldName, type); + } + + @Override + public final Map> fetchGroups(Field key, RecordMapper mapper) { + return fetch().intoGroups(key, mapper); + } + + @Override + public final Map> fetchGroups(int keyFieldIndex, RecordMapper mapper) { + return fetch().intoGroups(keyFieldIndex, mapper); + } + + @Override + public final Map> fetchGroups(String keyFieldName, RecordMapper mapper) { + return fetch().intoGroups(keyFieldName, mapper); + } + + @Override + public final Map> fetchGroups(Name keyFieldName, RecordMapper mapper) { + return fetch().intoGroups(keyFieldName, mapper); + } + + @Override + public final Map> fetchGroups(Field[] keys) { + return fetch().intoGroups(keys); + } + + @Override + public final Map> fetchGroups(int[] keyFieldIndexes) { + return fetch().intoGroups(keyFieldIndexes); + } + + @Override + public final Map> fetchGroups(String[] keyFieldNames) { + return fetch().intoGroups(keyFieldNames); + } + + @Override + public final Map> fetchGroups(Name[] keyFieldNames) { + return fetch().intoGroups(keyFieldNames); + } + + @Override + public final Map> fetchGroups(Field[] keys, Field[] values) { + return fetch().intoGroups(keys, values); + } + + @Override + public final Map> fetchGroups(int[] keyFieldIndexes, int[] valueFieldIndexes) { + return fetch().intoGroups(keyFieldIndexes, valueFieldIndexes); + } + + @Override + public final Map> fetchGroups(String[] keyFieldNames, String[] valueFieldNames) { + return fetch().intoGroups(keyFieldNames, valueFieldNames); + } + + @Override + public final Map> fetchGroups(Name[] keyFieldNames, Name[] valueFieldNames) { + return fetch().intoGroups(keyFieldNames, valueFieldNames); + } + + @Override + public final Map> fetchGroups(Field[] keys, Class type) { + return fetch().intoGroups(keys, type); + } + + @Override + public final Map> fetchGroups(int[] keyFieldIndexes, Class type) { + return fetch().intoGroups(keyFieldIndexes, type); + } + + @Override + public final Map> fetchGroups(String[] keyFieldNames, Class type) { + return fetch().intoGroups(keyFieldNames, type); + } + + @Override + public final Map> fetchGroups(Name[] keyFieldNames, Class type) { + return fetch().intoGroups(keyFieldNames, type); + } + + @Override + public final Map> fetchGroups(int[] keyFieldIndexes, RecordMapper mapper) { + return fetch().intoGroups(keyFieldIndexes, mapper); + } + + @Override + public final Map> fetchGroups(String[] keyFieldNames, RecordMapper mapper) { + return fetch().intoGroups(keyFieldNames, mapper); + } + + @Override + public final Map> fetchGroups(Name[] keyFieldNames, RecordMapper mapper) { + return fetch().intoGroups(keyFieldNames, mapper); + } + + @Override + public final Map> fetchGroups(Field[] keys, RecordMapper mapper) { + return fetch().intoGroups(keys, mapper); + } + + @Override + public final Map> fetchGroups(Class keyType) { + return fetch().intoGroups(keyType); + } + + @Override + public final Map> fetchGroups(Class keyType, Class valueType) { + return fetch().intoGroups(keyType, valueType); + } + + @Override + public final Map> fetchGroups(Class keyType, RecordMapper valueMapper) { + return fetch().intoGroups(keyType, valueMapper); + } + + @Override + public final Map> fetchGroups(RecordMapper keyMapper) { + return fetch().intoGroups(keyMapper); + } + + @Override + public final Map> fetchGroups(RecordMapper keyMapper, Class valueType) { + return fetch().intoGroups(keyMapper, valueType); + } + + @Override + public final Map> fetchGroups(RecordMapper keyMapper, RecordMapper valueMapper) { + return fetch().intoGroups(keyMapper, valueMapper); + } + + @Override + public final Map> fetchGroups(Table table) { + return fetch().intoGroups(table); + } + + @Override + public final Map> fetchGroups(Table keyTable, Table valueTable) { + return fetch().intoGroups(keyTable, valueTable); + } + + @Override + public final Map> fetchGroups(Table table, Class type) { + return fetch().intoGroups(table, type); + } + + @Override + public final Map> fetchGroups(Table table, RecordMapper mapper) { + return fetch().intoGroups(table, mapper); + } + + @Override + public final Object[][] fetchArrays() { + return fetch().intoArrays(); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public final R[] fetchArray() { + Class recordType; + + // TODO [#3185] Pull up getRecordType() + if (this instanceof AbstractResultQuery) + recordType = ((AbstractResultQuery) this).getRecordType(); + else if (this instanceof SelectImpl) + recordType = ((SelectImpl) this).getRecordType(); + else + throw new DataAccessException("Attempt to call fetchArray() on " + getClass()); + + Result r = fetch(); + return r.toArray((R[]) Array.newInstance(recordType, r.size())); + } + + @Override + public final Object[] fetchArray(int fieldIndex) { + return fetch().intoArray(fieldIndex); + } + + @Override + public final U[] fetchArray(int fieldIndex, Class type) { + return fetch().intoArray(fieldIndex, type); + } + + @Override + public final U[] fetchArray(int fieldIndex, Converter converter) { + return fetch().intoArray(fieldIndex, converter); + } + + @Override + public final Object[] fetchArray(String fieldName) { + return fetch().intoArray(fieldName); + } + + @Override + public final U[] fetchArray(String fieldName, Class type) { + return fetch().intoArray(fieldName, type); + } + + @Override + public final U[] fetchArray(String fieldName, Converter converter) { + return fetch().intoArray(fieldName, converter); + } + + @Override + public final Object[] fetchArray(Name fieldName) { + return fetch().intoArray(fieldName); + } + + @Override + public final U[] fetchArray(Name fieldName, Class type) { + return fetch().intoArray(fieldName, type); + } + + @Override + public final U[] fetchArray(Name fieldName, Converter converter) { + return fetch().intoArray(fieldName, converter); + } + + @Override + public final T[] fetchArray(Field field) { + return fetch().intoArray(field); + } + + @Override + public final U[] fetchArray(Field field, Class type) { + return fetch().intoArray(field, type); + } + + @Override + public final U[] fetchArray(Field field, Converter converter) { + return fetch().intoArray(field, converter); + } + + @Override + public final Set fetchSet(RecordMapper mapper) { + return fetch().intoSet(mapper); + } + + @Override + public final Set fetchSet(int fieldIndex) { + return fetch().intoSet(fieldIndex); + } + + @Override + public final Set fetchSet(int fieldIndex, Class type) { + return fetch().intoSet(fieldIndex, type); + } + + @Override + public final Set fetchSet(int fieldIndex, Converter converter) { + return fetch().intoSet(fieldIndex, converter); + } + + @Override + public final Set fetchSet(String fieldName) { + return fetch().intoSet(fieldName); + } + + @Override + public final Set fetchSet(String fieldName, Class type) { + return fetch().intoSet(fieldName, type); + } + + @Override + public final Set fetchSet(String fieldName, Converter converter) { + return fetch().intoSet(fieldName, converter); + } + + @Override + public final Set fetchSet(Name fieldName) { + return fetch().intoSet(fieldName); + } + + @Override + public final Set fetchSet(Name fieldName, Class type) { + return fetch().intoSet(fieldName, type); + } + + @Override + public final Set fetchSet(Name fieldName, Converter converter) { + return fetch().intoSet(fieldName, converter); + } + + @Override + public final Set fetchSet(Field field) { + return fetch().intoSet(field); + } + + @Override + public final Set fetchSet(Field field, Class type) { + return fetch().intoSet(field, type); + } + + @Override + public final Set fetchSet(Field field, Converter converter) { + return fetch().intoSet(field, converter); + } + @Override + public final List fetchInto(Class type) { + return fetch().into(type); + } + + @Override + public final Result fetchInto(Table table) { + return fetch().into(table); + } + + @Override + public final > H fetchInto(H handler) { + return fetch().into(handler); + } + + @Override + public final List fetch(RecordMapper mapper) { + return fetch().map(mapper); + } + + @SuppressWarnings("rawtypes") + private final boolean hasLimit1() { + if (this instanceof SelectQueryImpl) { + Limit l = ((SelectQueryImpl) this).getLimit(); + return !l.withTies() && !l.percent() && l.limitOne(); + } + + return false; + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java index 3d708a1ac6..8301112a5c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractQuery.java @@ -73,6 +73,7 @@ import org.jooq.ExecuteContext; import org.jooq.ExecuteListener; import org.jooq.Param; import org.jooq.Query; +import org.jooq.Record; import org.jooq.RenderContext; import org.jooq.Select; import org.jooq.conf.ParamType; @@ -88,7 +89,7 @@ import org.jooq.tools.JooqLogger; /** * @author Lukas Eder */ -abstract class AbstractQuery extends AbstractQueryPart implements Query { +abstract class AbstractQuery extends AbstractFetchable implements Query { private static final long serialVersionUID = -8046199737354507547L; private static final JooqLogger log = JooqLogger.getLogger(AbstractQuery.class); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java index 378bec04f6..d7cb011214 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java @@ -1069,10 +1069,10 @@ abstract class AbstractRecord extends AbstractStore implements Record { try { switch (format.recordFormat()) { case ARRAY: - AbstractCursor.formatJSONArray0(this, fields, format, 0, writer); + AbstractResult.formatJSONArray0(this, fields, format, 0, writer); break; case OBJECT: - AbstractCursor.formatJSONMap0(this, fields, format, 0, writer); + AbstractResult.formatJSONMap0(this, fields, format, 0, writer); break; default: throw new IllegalArgumentException("Format not supported: " + format); @@ -1092,7 +1092,7 @@ abstract class AbstractRecord extends AbstractStore implements Record { log.debug("XMLFormat.header currently not supported for Record.formatXML()"); try { - AbstractCursor.formatXMLRecord(writer, format, 0, this, fields); + AbstractResult.formatXMLRecord(writer, format, 0, this, fields); } catch (java.io.IOException e) { throw new IOException("Exception while writing XML", e); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java new file mode 100644 index 0000000000..57f1bb5e0c --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java @@ -0,0 +1,1441 @@ +/* + * 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 static java.lang.Math.max; +import static java.lang.Math.min; +import static org.jooq.XMLFormat.RecordFormat.COLUMN_NAME_ELEMENTS; +import static org.jooq.XMLFormat.RecordFormat.VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE; +import static org.jooq.conf.SettingsTools.renderLocale; +import static org.jooq.impl.DSL.insertInto; +import static org.jooq.impl.DSL.name; +import static org.jooq.impl.DSL.table; +import static org.jooq.tools.StringUtils.abbreviate; +import static org.jooq.tools.StringUtils.leftPad; +import static org.jooq.tools.StringUtils.rightPad; + +import java.io.Writer; +import java.sql.Date; +import java.sql.Timestamp; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Deque; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; +import java.util.stream.Stream; + +import javax.xml.bind.DatatypeConverter; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.jooq.CSVFormat; +import org.jooq.ChartFormat; +import org.jooq.ChartFormat.Display; +import org.jooq.Configuration; +import org.jooq.Constants; +import org.jooq.Cursor; +import org.jooq.DSLContext; +import org.jooq.DataType; +import org.jooq.EnumType; +import org.jooq.Field; +import org.jooq.Fields; +import org.jooq.Formattable; +import org.jooq.JSON; +import org.jooq.JSONB; +import org.jooq.JSONFormat; +import org.jooq.Name; +import org.jooq.Record; +import org.jooq.RecordType; +import org.jooq.Result; +import org.jooq.Row; +import org.jooq.Schema; +import org.jooq.TXTFormat; +import org.jooq.Table; +import org.jooq.TableField; +import org.jooq.TableRecord; +import org.jooq.XML; +import org.jooq.XMLFormat; +import org.jooq.exception.IOException; +import org.jooq.tools.StringUtils; +import org.jooq.tools.json.JSONValue; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * @author Lukas Eder + */ +abstract class AbstractResult extends AbstractFormattable implements Fields, Iterable { + + /** + * Generated UID + */ + private static final long serialVersionUID = -3412555195899758746L; + + final AbstractRow fields; + Configuration configuration; + + AbstractResult(Configuration configuration, AbstractRow row) { + this.configuration = configuration; + this.fields = row; + } + + // ------------------------------------------------------------------------- + // XXX: RecordType API of subtypes + // ------------------------------------------------------------------------- + + @SuppressWarnings("unchecked") + public final RecordType recordType() { + return (RecordType) fields.fields; + } + + @Override + public final Row fieldsRow() { + return fields; + } + + + + @Override + public final Stream> fieldStream() { + return fields.fieldStream(); + } + + + + @Override + public final Field field(Field field) { + return fields.field(field); + } + + /** + * @deprecated This method hides static import {@link DSL#field(String)}. + */ + @Override + @Deprecated + public final Field field(String name) { + return fields.field(name); + } + + /** + * @deprecated This method hides static import {@link DSL#field(String, Class)}. + */ + @Override + @Deprecated + public final Field field(String name, Class type) { + return fields.field(name, type); + } + + /** + * @deprecated This method hides static import {@link DSL#field(String, DataType)}. + */ + @Override + @Deprecated + public final Field field(String name, DataType dataType) { + return fields.field(name, dataType); + } + + /** + * @deprecated This method hides static import {@link DSL#field(Name)}. + */ + @Override + @Deprecated + public final Field field(Name name) { + return fields.field(name); + } + + /** + * @deprecated This method hides static import {@link DSL#field(Name, Class)}. + */ + @Override + @Deprecated + public final Field field(Name name, Class type) { + return fields.field(name, type); + } + + /** + * @deprecated This method hides static import {@link DSL#field(Name, DataType)}. + */ + @Override + @Deprecated + public final Field field(Name name, DataType dataType) { + return fields.field(name, dataType); + } + + @Override + public final Field field(int index) { + return fields.field(index); + } + + @Override + public final Field field(int index, Class type) { + return fields.field(index, type); + } + + @Override + public final Field field(int index, DataType dataType) { + return fields.field(index, dataType); + } + + @Override + public final Field[] fields() { + return fields.fields().clone(); + } + + @Override + public final Field[] fields(Field... f) { + return fields.fields(f); + } + + @Override + public final Field[] fields(int... indexes) { + return fields.fields(indexes); + } + + @Override + public final Field[] fields(String... names) { + return fields.fields(names); + } + + @Override + public final Field[] fields(Name... names) { + return fields.fields(names); + } + + @Override + public final int indexOf(Field field) { + return fields.indexOf(field); + } + + @Override + public final int indexOf(String fieldName) { + return fields.indexOf(fieldName); + } + + @Override + public final int indexOf(Name fieldName) { + return fields.indexOf(fieldName); + } + + @Override + public final Class[] types() { + return fields.types(); + } + + @Override + public final Class type(int index) { + return fields.type(index); + } + + @Override + public final Class type(String name) { + return fields.type(name); + } + + @Override + public final Class type(Name name) { + return fields.type(name); + } + + @Override + public final DataType[] dataTypes() { + return fields.dataTypes(); + } + + @Override + public final DataType dataType(int index) { + return fields.dataType(index); + } + + @Override + public final DataType dataType(String name) { + return fields.dataType(name); + } + + @Override + public final DataType dataType(Name name) { + return fields.dataType(name); + } + + // ------------------------------------------------------------------------- + // XXX: Formattable API + // ------------------------------------------------------------------------- + + @Override + public final void format(Writer writer, TXTFormat format) { + try { + + // Numeric columns have greater max width because values are aligned + final int NUM_COL_MAX_WIDTH = format.maxColWidth() == Integer.MAX_VALUE ? Integer.MAX_VALUE : 2 * format.maxColWidth(); + + // The max number of records that will be considered for formatting purposes + final int MAX_RECORDS = min(50, format.maxRows()); + final Deque buffer = new ArrayDeque<>(); + final Iterator it = iterator(); + + // Buffer some rows for formatting purposes + for (int i = 0; i < MAX_RECORDS && it.hasNext(); i++) + buffer.offer(it.next()); + + // Get max decimal places for numeric type columns + int size = fields.size(); + final int[] decimalPlaces = new int[size]; + final int[] widths = new int[size]; + + for (int index = 0; index < size; index++) { + if (Number.class.isAssignableFrom(fields.field(index).getType())) { + List decimalPlacesList = new ArrayList<>(1 + buffer.size()); + + // Initialize + decimalPlacesList.add(0); + + // Collect all decimal places for the column values + for (R record : buffer) + decimalPlacesList.add(decimalPlaces(format0(record.get(index), record.changed(index), true))); + + // Find max + decimalPlaces[index] = Collections.max(decimalPlacesList); + } + } + + // Get max column widths + int colMaxWidth; + for (int index = 0; index < size; index++) { + + // Is number column? + boolean isNumCol = Number.class.isAssignableFrom(fields.field(index).getType()); + + colMaxWidth = isNumCol ? NUM_COL_MAX_WIDTH : format.maxColWidth(); + + // Collect all widths for the column + List widthList = new ArrayList<>(1 + buffer.size()); + + // Add column name width first + widthList.add(min(colMaxWidth, max(format.minColWidth(), fields.field(index).getName().length()))); + + // Add column values width + for (R record : buffer) { + String value = format0(record.get(index), record.changed(index), true); + + // Align number values before width is calculated + if (isNumCol) + value = alignNumberValue(decimalPlaces[index], value); + + widthList.add(min(colMaxWidth, value.length())); + } + + // Find max + widths[index] = Collections.max(widthList); + } + + // Begin the writing + // --------------------------------------------------------------------- + + // Write top line + if (format.horizontalTableBorder()) + formatHorizontalLine(writer, format, widths); + + // Write headers + if (format.verticalTableBorder()) + writer.append('|'); + + for (int index = 0; index < size; index++) { + if (index > 0) + if (format.verticalCellBorder()) + writer.append('|'); + else + writer.append(' '); + + String padded; + + if (Number.class.isAssignableFrom(fields.field(index).getType())) + padded = leftPad(fields.field(index).getName(), widths[index]); + else + padded = rightPad(fields.field(index).getName(), widths[index]); + + writer.append(abbreviate(padded, widths[index])); + } + + if (format.verticalTableBorder()) + writer.append('|'); + + writer.append('\n'); + + // Write separator + if (format.horizontalHeaderBorder()) + formatHorizontalLine(writer, format, widths); + + // Write records + int i; + + recordLoop: + for (i = 0; i < format.maxRows(); i++) { + R record = buffer.pollFirst(); + + if (record == null) + if (it.hasNext()) + record = it.next(); + else + break recordLoop; + + // Write separator + if (i > 0 && format.horizontalCellBorder()) + formatHorizontalLine(writer, format, widths); + + if (format.verticalTableBorder()) + writer.append('|'); + + for (int index = 0; index < size; index++) { + if (index > 0) + if (format.verticalCellBorder()) + writer.append('|'); + else + writer.append(' '); + + String value = + StringUtils.replace( + StringUtils.replace( + StringUtils.replace( + format0(record.get(index), record.changed(index), true), "\n", "{lf}" + ), "\r", "{cr}" + ), "\t", "{tab}" + ); + + String padded; + if (Number.class.isAssignableFrom(fields.field(index).getType())) { + // Align number value before left pad + value = alignNumberValue(decimalPlaces[index], value); + + // Left pad + padded = leftPad(value, widths[index]); + } + else { + // Right pad + padded = rightPad(value, widths[index]); + } + + writer.append(abbreviate(padded, widths[index])); + } + + if (format.verticalTableBorder()) + writer.append('|'); + + writer.append('\n'); + } + + // Write bottom line + if (format.horizontalTableBorder() && i > 0) + formatHorizontalLine(writer, format, widths); + + // Write truncation message, if applicable + if (it.hasNext()) { + if (format.verticalTableBorder()) + writer.append('|'); + + writer.append("...record(s) truncated...\n"); + } + + writer.flush(); + } + catch (java.io.IOException e) { + throw new IOException("Exception while writing TEXT", e); + } + } + + private final void formatHorizontalLine(Writer writer, TXTFormat format, final int[] widths) throws java.io.IOException { + if (format.verticalTableBorder()) + if (format.intersectLines()) + writer.append('+'); + else + writer.append('-'); + + int size = fields.size(); + for (int index = 0; index < size; index++) { + if (index > 0) + if (format.verticalCellBorder()) + if (format.intersectLines()) + writer.append('+'); + else + writer.append('-'); + else + writer.append(' '); + + writer.append(rightPad("", widths[index], "-")); + } + + if (format.verticalTableBorder()) + if (format.intersectLines()) + writer.append('+'); + else + writer.append('-'); + + writer.append('\n'); + } + + private static final String alignNumberValue(Integer columnDecimalPlaces, String value) { + if (!"{null}".equals(value) && columnDecimalPlaces != 0) { + int decimalPlaces = decimalPlaces(value); + int rightPadSize = value.length() + columnDecimalPlaces - decimalPlaces; + + if (decimalPlaces == 0) { + // If integer value, add one for decimal point + value = rightPad(value, rightPadSize + 1); + } + else { + value = rightPad(value, rightPadSize); + } + } + + return value; + } + + private static final int decimalPlaces(String value) { + int decimalPlaces = 0; + + int dotIndex = value.indexOf("."); + if (dotIndex != -1) + decimalPlaces = value.length() - dotIndex - 1; + + return decimalPlaces; + } + + @Override + public final void formatCSV(Writer writer, CSVFormat format) { + try { + if (format.header()) { + String sep1 = ""; + for (Field field : fields.fields.fields) { + writer.append(sep1); + writer.append(formatCSV0(field.getName(), format)); + + sep1 = format.delimiter(); + } + + writer.append(format.newline()); + } + + for (Record record : this) { + String sep2 = ""; + + int size = fields.size(); + for (int index = 0; index < size; index++) { + writer.append(sep2); + writer.append(formatCSV0(record.getValue(index), format)); + + sep2 = format.delimiter(); + } + + writer.append(format.newline()); + } + + writer.flush(); + } + catch (java.io.IOException e) { + throw new IOException("Exception while writing CSV", e); + } + } + + private final String formatCSV0(Object value, CSVFormat format) { + + // [#2741] TODO: This logic will be externalised in new SPI + // [#4746] Escape null and empty strings + if (value == null) + return format.nullString(); + + if ("".equals(value.toString())) + return format.emptyString(); + + // [#7802] Nested records should generate nested CSV data structures + String result = (value instanceof Formattable) + ? ((Formattable) value).formatCSV(format) + : format0(value, false, false); + + switch (format.quote()) { + case NEVER: + return result; + + case SPECIAL_CHARACTERS: + if (!StringUtils.containsAny(result, ',', ';', '\t', '"', '\n', '\r', '\'', '\\')) + return result; + + // no break + case ALWAYS: + default: + return format.quoteString() + + StringUtils.replace( + StringUtils.replace( + result, "\\", "\\\\" + ), format.quoteString(), format.quoteString() + format.quoteString() + ) + + format.quoteString(); + } + } + + @Override + public final void formatJSON(Writer writer, JSONFormat format) { + if (format == null) + format = JSONFormat.DEFAULT_FOR_RESULTS; + + try { + String separator; + int recordLevel = format.header() ? 2 : 1; + + if (format.header()) { + if (format.format()) + writer.append('{').append(format.newline()) + .append(format.indentString(1)).append("\"fields\": ["); + else + writer.append("{\"fields\":["); + + separator = ""; + + for (Field field : fields.fields.fields) { + writer.append(separator); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(2)); + + writer.append('{'); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(3)); + + if (field instanceof TableField) { + Table table = ((TableField) field).getTable(); + + if (table != null) { + Schema schema = table.getSchema(); + + if (schema != null) { + writer.append("\"schema\":"); + + if (format.format()) + writer.append(' '); + + JSONValue.writeJSONString(schema.getName(), writer); + writer.append(','); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(3)); + } + + writer.append("\"table\":"); + + if (format.format()) + writer.append(' '); + + JSONValue.writeJSONString(table.getName(), writer); + writer.append(','); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(3)); + } + } + + writer.append("\"name\":"); + + if (format.format()) + writer.append(' '); + + JSONValue.writeJSONString(field.getName(), writer); + writer.append(','); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(3)); + + writer.append("\"type\":"); + + if (format.format()) + writer.append(' '); + + JSONValue.writeJSONString(field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings())), writer); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(2)); + + writer.append('}'); + separator = ","; + } + + if (format.format()) + writer.append(format.newline()).append(format.indentString(1)).append("],") + .append(format.newline()).append(format.indentString(1)).append("\"records\": "); + else + writer.append("],\"records\":"); + } + + writer.append('['); + separator = ""; + + switch (format.recordFormat()) { + case ARRAY: + for (Record record : this) { + writer.append(separator); + + if (format.format()) + writer.append(format.newline()); + + formatJSONArray0(record, fields, format, recordLevel, writer); + separator = ","; + } + + break; + case OBJECT: + for (Record record : this) { + writer.append(separator); + + if (format.format()) + writer.append(format.newline()); + + formatJSONMap0(record, fields, format, recordLevel, writer); + separator = ","; + } + + break; + default: + throw new IllegalArgumentException("Format not supported: " + format); + } + + if (format.format()) { + writer.append(format.newline()); + + if (format.header()) + writer.append(format.indentString(1)); + } + + writer.append(']'); + + if (format.header()) + writer.append(format.newline()).append('}'); + + writer.flush(); + } + catch (java.io.IOException e) { + throw new IOException("Exception while writing JSON", e); + } + } + + private static final void formatJSON0(Object value, Writer writer, JSONFormat format) throws java.io.IOException { + + // [#2741] TODO: This logic will be externalised in new SPI + if (value instanceof byte[]) { + JSONValue.writeJSONString(DatatypeConverter.printBase64Binary((byte[]) value), writer); + } + + // [#6563] Arrays can be serialised natively in JSON + else if (value instanceof Object[]) { + Object[] array = (Object[]) value; + writer.append('['); + + for (int i = 0; i < array.length; i++) { + if (i > 0) + writer.append(','); + + formatJSON0(array[i], writer, format); + } + + writer.append(']'); + } + + // [#7782] Nested records should generate nested JSON data structures + else if (value instanceof Formattable) { + ((Formattable) value).formatJSON(writer, format); + } + + else if (value instanceof JSON && !format.quoteNested()) { + writer.write(((JSON) value).data()); + } + else if (value instanceof JSONB && !format.quoteNested()) { + writer.write(((JSONB) value).data()); + } + + else { + JSONValue.writeJSONString(value, writer); + } + } + + static final void formatJSONMap0(Record record, AbstractRow fields, JSONFormat format, int recordLevel, Writer writer) throws java.io.IOException { + String separator = ""; + int size = fields.size(); + boolean wrapRecords = format.wrapSingleColumnRecords() || size > 1; + + if (wrapRecords) + if (format.format()) + writer.append(format.indentString(recordLevel)).append('{'); + else + writer.append('{'); + + for (int index = 0; index < size; index++) { + writer.append(separator); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(recordLevel + 1)); + + if (wrapRecords) { + JSONValue.writeJSONString(record.field(index).getName(), writer); + writer.append(':'); + + if (format.format()) + writer.append(' '); + } + + formatJSON0(record.get(index), writer, format); + separator = ","; + } + + if (wrapRecords) + if (format.format()) + writer.append(format.newline()).append(format.indentString(recordLevel)).append('}'); + else + writer.append('}'); + } + + static final void formatJSONArray0(Record record, AbstractRow fields, JSONFormat format, int recordLevel, Writer writer) throws java.io.IOException { + String separator = ""; + + int size = fields.size(); + if (format.wrapSingleColumnRecords() || size > 1) + if (format.format()) + writer.append(format.indentString(recordLevel)).append('['); + else + writer.append('['); + + for (int index = 0; index < size; index++) { + writer.append(separator); + + if (format.format()) + writer.append(format.newline()).append(format.indentString(recordLevel + 1)); + + formatJSON0(record.get(index), writer, format); + separator = ","; + } + + if (format.wrapSingleColumnRecords() || size > 1) + if (format.format()) + writer.append(format.newline()).append(format.indentString(recordLevel)).append(']'); + else + writer.append(']'); + } + + @Override + public final void formatXML(Writer writer, XMLFormat format) { + if (format == null) + format = XMLFormat.DEFAULT_FOR_RESULTS; + + String newline = format.newline(); + int recordLevel = format.header() ? 2 : 1; + + try { + writer.append(""); + + if (format.header()) { + writer.append(newline).append(format.indentString(1)).append(""); + + for (Field field : fields.fields.fields) { + writer.append(newline).append(format.indentString(2)).append(" table = ((TableField) field).getTable(); + + if (table != null) { + Schema schema = table.getSchema(); + + if (schema != null) { + writer.append(" schema=\""); + writer.append(escapeXML(schema.getName())); + writer.append("\""); + } + + writer.append(" table=\""); + writer.append(escapeXML(table.getName())); + writer.append("\""); + } + } + + writer.append(" name=\""); + writer.append(escapeXML(field.getName())); + writer.append("\""); + writer.append(" type=\""); + writer.append(field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings()))); + writer.append("\"/>"); + } + + writer.append(newline).append(format.indentString(1)).append(""); + writer.append(newline).append(format.indentString(1)).append(""); + } + + for (Record record : this) { + writer.append(newline).append(format.indentString(recordLevel)); + formatXMLRecord(writer, format, recordLevel, record, fields); + } + + if (format.header()) + writer.append(newline).append(format.indentString(1)).append(""); + + writer.append(newline).append(""); + writer.flush(); + } + catch (java.io.IOException e) { + throw new IOException("Exception while writing XML", e); + } + } + + static final void formatXMLRecord( + Writer writer, + XMLFormat format, + int recordLevel, + Record record, + AbstractRow fields + ) + throws java.io.IOException { + String newline = format.newline(); + + writer.append(""); + + int size = fields.size(); + for (int index = 0; index < size; index++) { + Object value = record.get(index); + + writer.append(newline).append(format.indentString(recordLevel + 1)); + String tag = format.recordFormat() == COLUMN_NAME_ELEMENTS + ? escapeXML(fields.field(index).getName()) + : "value"; + + writer.append("<" + tag); + if (format.recordFormat() == VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE) { + writer.append(" field=\""); + writer.append(escapeXML(fields.field(index).getName())); + writer.append("\""); + } + + if (value == null) { + writer.append("/>"); + } + else { + writer.append(">"); + + if (value instanceof Formattable) + ((Formattable) value).formatXML(writer, format); + else if (value instanceof XML && !format.quoteNested()) + writer.append(((XML) value).data()); + else + writer.append(escapeXML(format0(value, false, false))); + + writer.append(""); + } + } + + writer.append(newline).append(format.indentString(recordLevel)).append(""); + } + + @SuppressWarnings("unchecked") + @Override + public final void formatChart(Writer writer, ChartFormat format) { + Result result; + + if (this instanceof Result) + result = (Result) this; + else if (this instanceof Cursor) + result = ((Cursor) this).fetch(); + else + throw new IllegalStateException(); + + try { + DSLContext ctx = configuration.dsl(); + Field category = fields.field(format.category()); + TreeMap> groups = new TreeMap<>(result.intoGroups(format.category())); + + if (!format.categoryAsText()) { + if (Date.class.isAssignableFrom(category.getType())) { + Date categoryMin = (Date) groups.firstKey(); + Date categoryMax = (Date) groups.lastKey(); + + for (Date i = categoryMin; i.before(categoryMax); i = new Date(i.getYear(), i.getMonth(), i.getDate() + 1)) + if (!groups.containsKey(i)) + groups.put(i, (Result) ctx.newResult(fields.fields.fields)); + } + } + + List categories = new ArrayList<>(groups.keySet()); + + int categoryPadding = 1; + int categoryWidth = 0; + for (Object o : categories) + categoryWidth = Math.max(categoryWidth, ("" + o).length()); + + double axisMin = Double.POSITIVE_INFINITY; + double axisMax = Double.NEGATIVE_INFINITY; + + for (Result values : groups.values()) { + double sum = 0; + + for (int i = 0; i < format.values().length; i++) { + if (format.display() == Display.DEFAULT) + sum = 0; + + for (Record r : values) + sum = sum + r.get(format.values()[i], double.class); + + if (sum < axisMin) + axisMin = sum; + + if (sum > axisMax) + axisMax = sum; + } + } + + int verticalLegendWidth = format.showVerticalLegend() + ? Math.max( + format.numericFormat().format(axisMin).length(), + format.numericFormat().format(axisMax).length() + ) + : 0; + + int horizontalLegendHeight = format.showHorizontalLegend() ? 1 : 0; + + int verticalBorderWidth = format.showVerticalLegend() ? 1 : 0; + int horizontalBorderHeight = format.showHorizontalLegend() ? 1 : 0; + + int chartHeight = format.height() - horizontalLegendHeight - horizontalBorderHeight; + int chartWidth = format.width() - verticalLegendWidth - verticalBorderWidth; + + double barWidth = (double) chartWidth / groups.size(); + double axisStep = (axisMax - axisMin) / (chartHeight - 1); + + for (int y = chartHeight - 1; y >= 0; y--) { + double axisLegend = axisMax - (axisStep * (chartHeight - 1 - y)); + double axisLegendPercent = (axisLegend - axisMin) / (axisMax - axisMin); + + if (format.showVerticalLegend()) { + String axisLegendString = (format.display() == Display.HUNDRED_PERCENT_STACKED) + ? format.numericFormat().format(axisLegendPercent * 100.0) + "%" + : format.numericFormat().format(axisLegend); + + for (int x = axisLegendString.length(); x < verticalLegendWidth; x++) + writer.write(' '); + + writer.write(axisLegendString); + + for (int x = 0; x < verticalBorderWidth; x++) + writer.write('|'); + } + + for (int x = 0; x < chartWidth; x++) { + int index = (int) (x / barWidth); + + Result group = groups.get(categories.get(index)); + double[] values = new double[format.values().length]; + + for (Record record : group) + for (int i = 0; i < values.length; i++) + values[i] = values[i] + record.get(format.values()[i], double.class); + + if (format.display() == Display.STACKED || format.display() == Display.HUNDRED_PERCENT_STACKED) + for (int i = 1; i < values.length; i++) + values[i] = values[i] + values[i - 1]; + + if (format.display() == Display.HUNDRED_PERCENT_STACKED) + for (int i = 0; i < values.length; i++) + values[i] = values[i] / values[values.length - 1]; + + int shadeIndex = -1; + for (int i = values.length - 1; i >= 0; i--) + if ((format.display() == Display.HUNDRED_PERCENT_STACKED ? axisLegendPercent : axisLegend) > values[i]) + break; + else + shadeIndex = i; + + if (shadeIndex == -1) + writer.write(' '); + else + writer.write(format.shades()[shadeIndex % format.shades().length]); + } + + writer.write(format.newline()); + } + + if (format.showHorizontalLegend()) { + for (int y = 0; y < horizontalBorderHeight; y++) { + if (format.showVerticalLegend()) { + for (int x = 0; x < verticalLegendWidth; x++) + writer.write('-'); + + for (int x = 0; x < verticalBorderWidth; x++) + writer.write('+'); + } + + for (int x = 0; x < chartWidth; x++) + writer.write('-'); + + writer.write(format.newline()); + } + + for (int y = 0; y < horizontalLegendHeight; y++) { + if (format.showVerticalLegend()) { + for (int x = 0; x < verticalLegendWidth; x++) + writer.write(' '); + + for (int x = 0; x < verticalBorderWidth; x++) + writer.write('|'); + } + + double rounding = 0.0; + for (double x = 0.0; x < chartWidth;) { + String label = "" + categories.get((int) (x / barWidth)); + int length = label.length(); + + double padding = Math.max(categoryPadding, (barWidth - length) / 2); + + rounding = (rounding + padding - Math.floor(padding)) % 1; + x = x + (padding + rounding); + for (int i = 0; i < (int) (padding + rounding); i++) + writer.write(' '); + + x = x + length; + if (x >= chartWidth) + break; + writer.write(label); + + rounding = (rounding + padding - Math.floor(padding)) % 1; + x = x + (padding + rounding); + for (int i = 0; i < (int) (padding + rounding); i++) + writer.write(' '); + } + + writer.write(format.newline()); + } + } + } + catch (java.io.IOException e) { + throw new IOException("Exception while writing Chart", e); + } + } + + @Override + public final void formatInsert(Writer writer) { + formatInsert(writer, null, fields.fields.fields); + } + + @Override + public final void formatInsert(Writer writer, Table table, Field... f) { + DSLContext ctx = configuration.dsl(); + + try { + for (R record : this) { + if (table == null) + if (record instanceof TableRecord) + table = ((TableRecord) record).getTable(); + else + table = table(name("UNKNOWN_TABLE")); + + writer.append(ctx.renderInlined(insertInto(table, f).values(record.intoArray()))) + .append(";\n"); + } + + writer.flush(); + } + catch (java.io.IOException e) { + throw new IOException("Exception while writing INSERTs", e); + } + } + + @Override + public final void formatHTML(Writer writer) { + try { + writer.append(""); + writer.append(""); + writer.append(""); + + for (Field field : fields.fields.fields) { + writer.append(""); + } + + writer.append(""); + writer.append(""); + writer.append(""); + + for (Record record : this) { + writer.append(""); + + int size = fields.size(); + for (int index = 0; index < size; index++) { + writer.append(""); + } + + writer.append(""); + } + + writer.append(""); + writer.append("
"); + writer.append(escapeXML(field.getName())); + writer.append("
"); + writer.append(escapeXML(format0(record.getValue(index), false, true))); + writer.append("
"); + + writer.flush(); + } + catch (java.io.IOException e) { + throw new IOException("Exception while writing HTML", e); + } + } + + @Override + public final Document intoXML(XMLFormat format) { + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.newDocument(); + + Element eResult = document.createElement("result"); + + if (format.xmlns()) + eResult.setAttribute("xmlns", Constants.NS_EXPORT); + document.appendChild(eResult); + + Element eRecordParent = eResult; + + if (format.header()) { + Element eFields = document.createElement("fields"); + eResult.appendChild(eFields); + + for (Field field : fields.fields.fields) { + Element eField = document.createElement("field"); + + if (field instanceof TableField) { + Table table = ((TableField) field).getTable(); + + if (table != null) { + Schema schema = table.getSchema(); + + if (schema != null) { + eField.setAttribute("schema", schema.getName()); + } + + eField.setAttribute("table", table.getName()); + } + } + + eField.setAttribute("name", field.getName()); + eField.setAttribute("type", field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings()))); + eFields.appendChild(eField); + } + + Element eRecords = document.createElement("records"); + eResult.appendChild(eRecords); + eRecordParent = eRecords; + } + + for (Record record : this) { + Element eRecord = document.createElement("record"); + eRecordParent.appendChild(eRecord); + + int size = fields.size(); + for (int index = 0; index < size; index++) { + Field field = fields.field(index); + Object value = record.get(index); + + String tag = format.recordFormat() == COLUMN_NAME_ELEMENTS + ? escapeXML(fields.field(index).getName()) + : "value"; + + Element eValue = document.createElement(tag); + + if (format.recordFormat() == VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE) + eValue.setAttribute("field", field.getName()); + eRecord.appendChild(eValue); + + if (value != null) { + eValue.setTextContent(format0(value, false, false)); + } + } + } + + return document; + } + catch (ParserConfigurationException ignore) { + throw new RuntimeException(ignore); + } + } + + @Override + public final H intoXML(H handler, XMLFormat format) throws SAXException { + Attributes empty = new AttributesImpl(); + + handler.startDocument(); + + if (format.xmlns()) + handler.startPrefixMapping("", Constants.NS_EXPORT); + + handler.startElement("", "", "result", empty); + if (format.header()) { + handler.startElement("", "", "fields", empty); + + for (Field field : fields.fields.fields) { + AttributesImpl attrs = new AttributesImpl(); + + if (field instanceof TableField) { + Table table = ((TableField) field).getTable(); + + if (table != null) { + Schema schema = table.getSchema(); + + if (schema != null) { + attrs.addAttribute("", "", "schema", "CDATA", schema.getName()); + } + + attrs.addAttribute("", "", "table", "CDATA", table.getName()); + } + } + + attrs.addAttribute("", "", "name", "CDATA", field.getName()); + attrs.addAttribute("", "", "type", "CDATA", field.getDataType().getTypeName().toUpperCase(renderLocale(configuration.settings()))); + + handler.startElement("", "", "field", attrs); + handler.endElement("", "", "field"); + } + + handler.endElement("", "", "fields"); + handler.startElement("", "", "records", empty); + } + + for (Record record : this) { + handler.startElement("", "", "record", empty); + + int size = fields.size(); + for (int index = 0; index < size; index++) { + Field field = fields.field(index); + Object value = record.get(index); + + String tag = format.recordFormat() == COLUMN_NAME_ELEMENTS + ? escapeXML(fields.field(index).getName()) + : "value"; + + AttributesImpl attrs = new AttributesImpl(); + + if (format.recordFormat() == VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE) + attrs.addAttribute("", "", "field", "CDATA", field.getName()); + + handler.startElement("", "", tag, attrs); + + if (value != null) { + char[] chars = format0(value, false, false).toCharArray(); + handler.characters(chars, 0, chars.length); + } + + handler.endElement("", "", tag); + } + + handler.endElement("", "", "record"); + } + + if (format.header()) + handler.endElement("", "", "records"); + + if (format.xmlns()) + handler.endPrefixMapping(""); + + handler.endDocument(); + return handler; + } + + /** + * @param value The value to be formatted + * @param visual Whether the formatted output is to be consumed visually + * (HTML, TEXT) or by a machine (CSV, JSON, XML) + */ + private static final String format0(Object value, boolean changed, boolean visual) { + + // [#2741] TODO: This logic will be externalised in new SPI + String formatted = changed && visual ? "*" : ""; + + if (value == null) { + formatted += visual ? "{null}" : null; + } + else if (value.getClass() == byte[].class) { + formatted += DatatypeConverter.printBase64Binary((byte[]) value); + } + else if (value.getClass().isArray()) { + // [#6545] Nested arrays + if (value.getClass().getComponentType().isArray()) + formatted += Arrays.deepToString((Object[]) value); + else + formatted += Arrays.toString((Object[]) value); + } + else if (value instanceof EnumType) { + formatted += ((EnumType) value).getLiteral(); + } + else if (value instanceof Record) { + formatted += ((Record) value).valuesRow().toString(); + } + + // [#5238] Oracle DATE is really a TIMESTAMP(0)... + else if (value instanceof Date) { + String date = value.toString(); + + if (Date.valueOf(date).equals(value)) + formatted += date; + else + formatted += new Timestamp(((Date) value).getTime()); + } + else { + formatted += value.toString(); + } + + return formatted; + } + + private static final String escapeXML(String string) { + return StringUtils.replaceEach(string, + new String[] { "\"", "'", "<", ">", "&" }, + new String[] { """, "'", "<", ">", "&"}); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java index 30535aa59b..1f398d9a8b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResultQuery.java @@ -42,31 +42,19 @@ package org.jooq.impl; import static org.jooq.SQLDialect.POSTGRES; import static org.jooq.impl.DSL.field; import static org.jooq.impl.DSL.name; -import static org.jooq.impl.Tools.blocking; import static org.jooq.impl.Tools.consumeResultSets; import static org.jooq.impl.Tools.executeStatementAndGetFirstResultSet; -import java.lang.reflect.Array; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; 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.DSLContext; import org.jooq.ExecuteContext; @@ -96,8 +84,6 @@ import org.jooq.Record6; import org.jooq.Record7; import org.jooq.Record8; import org.jooq.Record9; -import org.jooq.RecordHandler; -import org.jooq.RecordMapper; import org.jooq.Result; import org.jooq.ResultQuery; import org.jooq.Results; @@ -112,7 +98,7 @@ import org.jooq.tools.jdbc.MockResultSet; * * @author Lukas Eder */ -abstract class AbstractResultQuery extends AbstractQuery implements ResultQuery { +abstract class AbstractResultQuery extends AbstractQuery implements ResultQuery { /** * Generated UID @@ -330,16 +316,6 @@ abstract class AbstractResultQuery extends AbstractQuery imple return result; } - @Override - public final ResultSet fetchResultSet() { - return fetchLazy().resultSet(); - } - - @Override - public final Iterator iterator() { - return fetch().iterator(); - } - @@ -402,43 +378,6 @@ abstract class AbstractResultQuery extends AbstractQuery imple }); } - @Override - public final CompletionStage> fetchAsync() { - return fetchAsync(Tools.configuration(this).executorProvider().provide()); - } - - @Override - public final CompletionStage> fetchAsync(Executor executor) { - return ExecutorProviderCompletionStage.of(CompletableFuture.supplyAsync(blocking(this::fetch), executor), () -> executor); - } - - @Override - public final Stream fetchStream() { - return Stream.of(1).flatMap(i -> fetchLazy().stream()); - } - - @Override - public final Stream fetchStreamInto(Class type) { - return fetchStream().map(r -> r.into(type)); - } - - @Override - public final Stream fetchStreamInto(Table table) { - return fetchStream().map(r -> r.into(table)); - } - - @Override - public final Stream stream() { - return fetchStream(); - } - - @Override - public final X collect(Collector collector) { - try (Cursor c = fetchLazyNonAutoClosing()) { - return c.collect(collector); - } - } - @Override @@ -461,6 +400,7 @@ abstract class AbstractResultQuery extends AbstractQuery imple * When we manage the lifecycle of a returned {@link Cursor} internally in * jOOQ, then the cursor must not be auto-closed. */ + @Override final Cursor fetchLazyNonAutoClosing() { final boolean previousAutoClosing = autoclosing; @@ -491,1031 +431,6 @@ abstract class AbstractResultQuery extends AbstractQuery imple return results; } - @Override - public final List fetch(Field field) { - return fetch().getValues(field); - } - - @Override - public final List fetch(Field field, Class type) { - return fetch().getValues(field, type); - } - - @Override - public final List fetch(Field field, Converter converter) { - return fetch().getValues(field, converter); - } - - @Override - public final List fetch(int fieldIndex) { - return fetch().getValues(fieldIndex); - } - - @Override - public final List fetch(int fieldIndex, Class type) { - return fetch().getValues(fieldIndex, type); - } - - @Override - public final List fetch(int fieldIndex, Converter converter) { - return fetch().getValues(fieldIndex, converter); - } - - @Override - public final List fetch(String fieldName) { - return fetch().getValues(fieldName); - } - - @Override - public final List fetch(String fieldName, Class type) { - return fetch().getValues(fieldName, type); - } - - @Override - public final List fetch(String fieldName, Converter converter) { - return fetch().getValues(fieldName, converter); - } - - @Override - public final List fetch(Name fieldName) { - return fetch().getValues(fieldName); - } - - @Override - public final List fetch(Name fieldName, Class type) { - return fetch().getValues(fieldName, type); - } - - @Override - public final List fetch(Name fieldName, Converter converter) { - return fetch().getValues(fieldName, converter); - } - - @Override - public final T fetchOne(Field field) { - R record = fetchOne(); - return record == null ? null : record.get(field); - } - - @Override - public final U fetchOne(Field field, Class type) { - R record = fetchOne(); - return record == null ? null : record.get(field, type); - } - - @Override - public final U fetchOne(Field field, Converter converter) { - R record = fetchOne(); - return record == null ? null : record.get(field, converter); - } - - @Override - public final Object fetchOne(int fieldIndex) { - R record = fetchOne(); - return record == null ? null : record.get(fieldIndex); - } - - @Override - public final U fetchOne(int fieldIndex, Class type) { - R record = fetchOne(); - return record == null ? null : record.get(fieldIndex, type); - } - - @Override - public final U fetchOne(int fieldIndex, Converter converter) { - R record = fetchOne(); - return record == null ? null : record.get(fieldIndex, converter); - } - - @Override - public final Object fetchOne(String fieldName) { - R record = fetchOne(); - return record == null ? null : record.get(fieldName); - } - - @Override - public final U fetchOne(String fieldName, Class type) { - R record = fetchOne(); - return record == null ? null : record.get(fieldName, type); - } - - @Override - public final U fetchOne(String fieldName, Converter converter) { - R record = fetchOne(); - return record == null ? null : record.get(fieldName, converter); - } - - @Override - public final Object fetchOne(Name fieldName) { - R record = fetchOne(); - return record == null ? null : record.get(fieldName); - } - - @Override - public final U fetchOne(Name fieldName, Class type) { - R record = fetchOne(); - return record == null ? null : record.get(fieldName, type); - } - - @Override - public final U fetchOne(Name fieldName, Converter converter) { - R record = fetchOne(); - return record == null ? null : record.get(fieldName, converter); - } - - @Override - public final R fetchOne() { - return Tools.fetchOne(fetchLazyNonAutoClosing(), hasLimit1()); - } - - @Override - public final E fetchOne(RecordMapper mapper) { - R record = fetchOne(); - return record == null ? null : mapper.map(record); - } - - @Override - public final Map fetchOneMap() { - R record = fetchOne(); - return record == null ? null : record.intoMap(); - } - - @Override - public final Object[] fetchOneArray() { - R record = fetchOne(); - return record == null ? null : record.intoArray(); - } - - @Override - public final E fetchOneInto(Class type) { - R record = fetchOne(); - return record == null ? null : record.into(type); - } - - @Override - public final Z fetchOneInto(Table table) { - R record = fetchOne(); - return record == null ? null : record.into(table); - } - - @Override - public final T fetchSingle(Field field) { - return fetchSingle().get(field); - } - - @Override - public final U fetchSingle(Field field, Class type) { - return fetchSingle().get(field, type); - } - - @Override - public final U fetchSingle(Field field, Converter converter) { - return fetchSingle().get(field, converter); - } - - @Override - public final Object fetchSingle(int fieldIndex) { - return fetchSingle().get(fieldIndex); - } - - @Override - public final U fetchSingle(int fieldIndex, Class type) { - return fetchSingle().get(fieldIndex, type); - } - - @Override - public final U fetchSingle(int fieldIndex, Converter converter) { - return fetchSingle().get(fieldIndex, converter); - } - - @Override - public final Object fetchSingle(String fieldName) { - return fetchSingle().get(fieldName); - } - - @Override - public final U fetchSingle(String fieldName, Class type) { - return fetchSingle().get(fieldName, type); - } - - @Override - public final U fetchSingle(String fieldName, Converter converter) { - return fetchSingle().get(fieldName, converter); - } - - @Override - public final Object fetchSingle(Name fieldName) { - return fetchSingle().get(fieldName); - } - - @Override - public final U fetchSingle(Name fieldName, Class type) { - return fetchSingle().get(fieldName, type); - } - - @Override - public final U fetchSingle(Name fieldName, Converter converter) { - return fetchSingle().get(fieldName, converter); - } - - @Override - public final R fetchSingle() { - return Tools.fetchSingle(fetchLazyNonAutoClosing(), hasLimit1()); - } - - @Override - public final E fetchSingle(RecordMapper mapper) { - return mapper.map(fetchSingle()); - } - - @Override - public final Map fetchSingleMap() { - return fetchSingle().intoMap(); - } - - @Override - public final Object[] fetchSingleArray() { - return fetchSingle().intoArray(); - } - - @Override - public final E fetchSingleInto(Class type) { - return fetchSingle().into(type); - } - - @Override - public final Z fetchSingleInto(Table table) { - return fetchSingle().into(table); - } - - - @Override - public final Optional fetchOptional(Field field) { - return Optional.ofNullable(fetchOne(field)); - } - - @Override - public final Optional fetchOptional(Field field, Class type) { - return Optional.ofNullable(fetchOne(field, type)); - } - - @Override - public final Optional fetchOptional(Field field, Converter converter) { - return Optional.ofNullable(fetchOne(field, converter)); - } - - @Override - public final Optional fetchOptional(int fieldIndex) { - return Optional.ofNullable(fetchOne(fieldIndex)); - } - - @Override - public final Optional fetchOptional(int fieldIndex, Class type) { - return Optional.ofNullable(fetchOne(fieldIndex, type)); - } - - @Override - public final Optional fetchOptional(int fieldIndex, Converter converter) { - return Optional.ofNullable(fetchOne(fieldIndex, converter)); - } - - @Override - public final Optional fetchOptional(String fieldName) { - return Optional.ofNullable(fetchOne(fieldName)); - } - - @Override - public final Optional fetchOptional(String fieldName, Class type) { - return Optional.ofNullable(fetchOne(fieldName, type)); - } - - @Override - public final Optional fetchOptional(String fieldName, Converter converter) { - return Optional.ofNullable(fetchOne(fieldName, converter)); - } - - @Override - public final Optional fetchOptional(Name fieldName) { - return Optional.ofNullable(fetchOne(fieldName)); - } - - @Override - public final Optional fetchOptional(Name fieldName, Class type) { - return Optional.ofNullable(fetchOne(fieldName, type)); - } - - @Override - public final Optional fetchOptional(Name fieldName, Converter converter) { - return Optional.ofNullable(fetchOne(fieldName, converter)); - } - - @Override - public final Optional fetchOptional() { - return Optional.ofNullable(fetchOne()); - } - - @Override - public final Optional fetchOptional(RecordMapper mapper) { - return Optional.ofNullable(fetchOne(mapper)); - } - - @Override - public final Optional> fetchOptionalMap() { - return Optional.ofNullable(fetchOneMap()); - } - - @Override - public final Optional fetchOptionalArray() { - return Optional.ofNullable(fetchOneArray()); - } - - @Override - public final Optional fetchOptionalInto(Class type) { - return Optional.ofNullable(fetchOneInto(type)); - } - - @Override - public final Optional fetchOptionalInto(Table table) { - return Optional.ofNullable(fetchOneInto(table)); - } - - - @Override - public final T fetchAny(Field field) { - R record = fetchAny(); - return record == null ? null : record.get(field); - } - - @Override - public final U fetchAny(Field field, Class type) { - R record = fetchAny(); - return record == null ? null : record.get(field, type); - } - - @Override - public final U fetchAny(Field field, Converter converter) { - R record = fetchAny(); - return record == null ? null : record.get(field, converter); - } - - @Override - public final Object fetchAny(int fieldIndex) { - R record = fetchAny(); - return record == null ? null : record.get(fieldIndex); - } - - @Override - public final U fetchAny(int fieldIndex, Class type) { - R record = fetchAny(); - return record == null ? null : record.get(fieldIndex, type); - } - - @Override - public final U fetchAny(int fieldIndex, Converter converter) { - R record = fetchAny(); - return record == null ? null : record.get(fieldIndex, converter); - } - - @Override - public final Object fetchAny(String fieldName) { - R record = fetchAny(); - return record == null ? null : record.get(fieldName); - } - - @Override - public final U fetchAny(String fieldName, Class type) { - R record = fetchAny(); - return record == null ? null : record.get(fieldName, type); - } - - @Override - public final U fetchAny(String fieldName, Converter converter) { - R record = fetchAny(); - return record == null ? null : record.get(fieldName, converter); - } - - @Override - public final Object fetchAny(Name fieldName) { - R record = fetchAny(); - return record == null ? null : record.get(fieldName); - } - - @Override - public final U fetchAny(Name fieldName, Class type) { - R record = fetchAny(); - return record == null ? null : record.get(fieldName, type); - } - - @Override - public final U fetchAny(Name fieldName, Converter converter) { - R record = fetchAny(); - return record == null ? null : record.get(fieldName, converter); - } - - @Override - public final R fetchAny() { - Cursor c = fetchLazyNonAutoClosing(); - - try { - return c.fetchNext(); - } - finally { - c.close(); - } - } - - @Override - public final E fetchAny(RecordMapper mapper) { - R record = fetchAny(); - return record == null ? null : mapper.map(record); - } - - @Override - public final Map fetchAnyMap() { - R record = fetchAny(); - return record == null ? null : record.intoMap(); - } - - @Override - public final Object[] fetchAnyArray() { - R record = fetchAny(); - return record == null ? null : record.intoArray(); - } - - @Override - public final E fetchAnyInto(Class type) { - R record = fetchAny(); - return record == null ? null : record.into(type); - } - - @Override - public final Z fetchAnyInto(Table table) { - R record = fetchAny(); - return record == null ? null : record.into(table); - } - - @Override - public final Map fetchMap(Field key) { - return fetch().intoMap(key); - } - - @Override - public final Map fetchMap(int keyFieldIndex) { - return fetch().intoMap(keyFieldIndex); - } - - @Override - public final Map fetchMap(String keyFieldName) { - return fetch().intoMap(keyFieldName); - } - - @Override - public final Map fetchMap(Name keyFieldName) { - return fetch().intoMap(keyFieldName); - } - - @Override - public final Map fetchMap(Field key, Field value) { - return fetch().intoMap(key, value); - } - - @Override - public final Map fetchMap(int keyFieldIndex, int valueFieldIndex) { - return fetch().intoMap(keyFieldIndex, valueFieldIndex); - } - - @Override - public final Map fetchMap(String keyFieldName, String valueFieldName) { - return fetch().intoMap(keyFieldName, valueFieldName); - } - - @Override - public final Map fetchMap(Name keyFieldName, Name valueFieldName) { - return fetch().intoMap(keyFieldName, valueFieldName); - } - - @Override - public final Map fetchMap(Field key, Class type) { - return fetch().intoMap(key, type); - } - - @Override - public final Map fetchMap(int keyFieldIndex, Class type) { - return fetch().intoMap(keyFieldIndex, type); - } - - @Override - public final Map fetchMap(String keyFieldName, Class type) { - return fetch().intoMap(keyFieldName, type); - } - - @Override - public final Map fetchMap(Name keyFieldName, Class type) { - return fetch().intoMap(keyFieldName, type); - } - - @Override - public final Map fetchMap(Field key, RecordMapper mapper) { - return fetch().intoMap(key, mapper); - } - - @Override - public final Map fetchMap(int keyFieldIndex, RecordMapper mapper) { - return fetch().intoMap(keyFieldIndex, mapper); - } - - @Override - public final Map fetchMap(String keyFieldName, RecordMapper mapper) { - return fetch().intoMap(keyFieldName, mapper); - } - - @Override - public final Map fetchMap(Name keyFieldName, RecordMapper mapper) { - return fetch().intoMap(keyFieldName, mapper); - } - - @Override - public final Map fetchMap(Field[] keys) { - return fetch().intoMap(keys); - } - - @Override - public final Map fetchMap(int[] keyFieldIndexes) { - return fetch().intoMap(keyFieldIndexes); - } - - @Override - public final Map fetchMap(String[] keyFieldNames) { - return fetch().intoMap(keyFieldNames); - } - - @Override - public final Map fetchMap(Name[] keyFieldNames) { - return fetch().intoMap(keyFieldNames); - } - - @Override - public final Map fetchMap(Field[] keys, Field[] values) { - return fetch().intoMap(keys, values); - } - - @Override - public final Map fetchMap(int[] keyFieldIndexes, int[] valueFieldIndexes) { - return fetch().intoMap(keyFieldIndexes, valueFieldIndexes); - } - - @Override - public final Map fetchMap(String[] keyFieldNames, String[] valueFieldNames) { - return fetch().intoMap(keyFieldNames, valueFieldNames); - } - - @Override - public final Map fetchMap(Name[] keyFieldNames, Name[] valueFieldNames) { - return fetch().intoMap(keyFieldNames, valueFieldNames); - } - - @Override - public final Map, E> fetchMap(Field[] keys, Class type) { - return fetch().intoMap(keys, type); - } - - @Override - public final Map, E> fetchMap(int[] keyFieldIndexes, Class type) { - return fetch().intoMap(keyFieldIndexes, type); - } - - @Override - public final Map, E> fetchMap(String[] keyFieldNames, Class type) { - return fetch().intoMap(keyFieldNames, type); - } - - @Override - public final Map, E> fetchMap(Name[] keyFieldNames, Class type) { - return fetch().intoMap(keyFieldNames, type); - } - - @Override - public final Map, E> fetchMap(Field[] keys, RecordMapper mapper) { - return fetch().intoMap(keys, mapper); - } - - @Override - public final Map, E> fetchMap(int[] keyFieldIndexes, RecordMapper mapper) { - return fetch().intoMap(keyFieldIndexes, mapper); - } - - @Override - public final Map, E> fetchMap(String[] keyFieldNames, RecordMapper mapper) { - return fetch().intoMap(keyFieldNames, mapper); - } - - @Override - public final Map, E> fetchMap(Name[] keyFieldNames, RecordMapper mapper) { - return fetch().intoMap(keyFieldNames, mapper); - } - - @Override - public final Map fetchMap(Class keyType) { - return fetch().intoMap(keyType); - } - - @Override - public final Map fetchMap(Class keyType, Class valueType) { - return fetch().intoMap(keyType, valueType); - } - - @Override - public final Map fetchMap(Class keyType, RecordMapper valueMapper) { - return fetch().intoMap(keyType, valueMapper); - } - - @Override - public final Map fetchMap(RecordMapper keyMapper) { - return fetch().intoMap(keyMapper); - } - - @Override - public final Map fetchMap(RecordMapper keyMapper, Class valueType) { - return fetch().intoMap(keyMapper, valueType); - } - - @Override - public final Map fetchMap(RecordMapper keyMapper, RecordMapper valueMapper) { - return fetch().intoMap(keyMapper, valueMapper); - } - - @Override - public final Map fetchMap(Table table) { - return fetch().intoMap(table); - } - - @Override - public final Map fetchMap(Table keyTable, Table valueTable) { - return fetch().intoMap(keyTable, valueTable); - } - - @Override - public final Map fetchMap(Table table, Class type) { - return fetch().intoMap(table, type); - } - - @Override - public final Map fetchMap(Table table, RecordMapper mapper) { - return fetch().intoMap(table, mapper); - } - - @Override - public final List> fetchMaps() { - return fetch().intoMaps(); - } - - @Override - public final Map> fetchGroups(Field key) { - return fetch().intoGroups(key); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex) { - return fetch().intoGroups(keyFieldIndex); - } - - @Override - public final Map> fetchGroups(String keyFieldName) { - return fetch().intoGroups(keyFieldName); - } - - @Override - public final Map> fetchGroups(Name keyFieldName) { - return fetch().intoGroups(keyFieldName); - } - - @Override - public final Map> fetchGroups(Field key, Field value) { - return fetch().intoGroups(key, value); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex, int valueFieldIndex) { - return fetch().intoGroups(keyFieldIndex, valueFieldIndex); - } - - @Override - public final Map> fetchGroups(String keyFieldName, String valueFieldName) { - return fetch().intoGroups(keyFieldName, valueFieldName); - } - - @Override - public final Map> fetchGroups(Name keyFieldName, Name valueFieldName) { - return fetch().intoGroups(keyFieldName, valueFieldName); - } - - @Override - public final Map> fetchGroups(Field key, Class type) { - return fetch().intoGroups(key, type); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex, Class type) { - return fetch().intoGroups(keyFieldIndex, type); - } - - @Override - public final Map> fetchGroups(String keyFieldName, Class type) { - return fetch().intoGroups(keyFieldName, type); - } - - @Override - public final Map> fetchGroups(Name keyFieldName, Class type) { - return fetch().intoGroups(keyFieldName, type); - } - - @Override - public final Map> fetchGroups(Field key, RecordMapper mapper) { - return fetch().intoGroups(key, mapper); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex, RecordMapper mapper) { - return fetch().intoGroups(keyFieldIndex, mapper); - } - - @Override - public final Map> fetchGroups(String keyFieldName, RecordMapper mapper) { - return fetch().intoGroups(keyFieldName, mapper); - } - - @Override - public final Map> fetchGroups(Name keyFieldName, RecordMapper mapper) { - return fetch().intoGroups(keyFieldName, mapper); - } - - @Override - public final Map> fetchGroups(Field[] keys) { - return fetch().intoGroups(keys); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes) { - return fetch().intoGroups(keyFieldIndexes); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames) { - return fetch().intoGroups(keyFieldNames); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames) { - return fetch().intoGroups(keyFieldNames); - } - - @Override - public final Map> fetchGroups(Field[] keys, Field[] values) { - return fetch().intoGroups(keys, values); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes, int[] valueFieldIndexes) { - return fetch().intoGroups(keyFieldIndexes, valueFieldIndexes); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames, String[] valueFieldNames) { - return fetch().intoGroups(keyFieldNames, valueFieldNames); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames, Name[] valueFieldNames) { - return fetch().intoGroups(keyFieldNames, valueFieldNames); - } - - @Override - public final Map> fetchGroups(Field[] keys, Class type) { - return fetch().intoGroups(keys, type); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes, Class type) { - return fetch().intoGroups(keyFieldIndexes, type); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames, Class type) { - return fetch().intoGroups(keyFieldNames, type); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames, Class type) { - return fetch().intoGroups(keyFieldNames, type); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes, RecordMapper mapper) { - return fetch().intoGroups(keyFieldIndexes, mapper); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames, RecordMapper mapper) { - return fetch().intoGroups(keyFieldNames, mapper); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames, RecordMapper mapper) { - return fetch().intoGroups(keyFieldNames, mapper); - } - - @Override - public final Map> fetchGroups(Field[] keys, RecordMapper mapper) { - return fetch().intoGroups(keys, mapper); - } - - @Override - public final Map> fetchGroups(Class keyType) { - return fetch().intoGroups(keyType); - } - - @Override - public final Map> fetchGroups(Class keyType, Class valueType) { - return fetch().intoGroups(keyType, valueType); - } - - @Override - public final Map> fetchGroups(Class keyType, RecordMapper valueMapper) { - return fetch().intoGroups(keyType, valueMapper); - } - - @Override - public final Map> fetchGroups(RecordMapper keyMapper) { - return fetch().intoGroups(keyMapper); - } - - @Override - public final Map> fetchGroups(RecordMapper keyMapper, Class valueType) { - return fetch().intoGroups(keyMapper, valueType); - } - - @Override - public final Map> fetchGroups(RecordMapper keyMapper, RecordMapper valueMapper) { - return fetch().intoGroups(keyMapper, valueMapper); - } - - @Override - public final Map> fetchGroups(Table table) { - return fetch().intoGroups(table); - } - - @Override - public final Map> fetchGroups(Table keyTable, Table valueTable) { - return fetch().intoGroups(keyTable, valueTable); - } - - @Override - public final Map> fetchGroups(Table table, Class type) { - return fetch().intoGroups(table, type); - } - - @Override - public final Map> fetchGroups(Table table, RecordMapper mapper) { - return fetch().intoGroups(table, mapper); - } - - @Override - public final Object[][] fetchArrays() { - return fetch().intoArrays(); - } - - @SuppressWarnings("unchecked") - @Override - public final R[] fetchArray() { - Result r = fetch(); - return r.toArray((R[]) Array.newInstance(getRecordType(), r.size())); - } - - @Override - public final Object[] fetchArray(int fieldIndex) { - return fetch().intoArray(fieldIndex); - } - - @Override - public final U[] fetchArray(int fieldIndex, Class type) { - return fetch().intoArray(fieldIndex, type); - } - - @Override - public final U[] fetchArray(int fieldIndex, Converter converter) { - return fetch().intoArray(fieldIndex, converter); - } - - @Override - public final Object[] fetchArray(String fieldName) { - return fetch().intoArray(fieldName); - } - - @Override - public final U[] fetchArray(String fieldName, Class type) { - return fetch().intoArray(fieldName, type); - } - - @Override - public final U[] fetchArray(String fieldName, Converter converter) { - return fetch().intoArray(fieldName, converter); - } - - @Override - public final Object[] fetchArray(Name fieldName) { - return fetch().intoArray(fieldName); - } - - @Override - public final U[] fetchArray(Name fieldName, Class type) { - return fetch().intoArray(fieldName, type); - } - - @Override - public final U[] fetchArray(Name fieldName, Converter converter) { - return fetch().intoArray(fieldName, converter); - } - - @Override - public final T[] fetchArray(Field field) { - return fetch().intoArray(field); - } - - @Override - public final U[] fetchArray(Field field, Class type) { - return fetch().intoArray(field, type); - } - - @Override - public final U[] fetchArray(Field field, Converter converter) { - return fetch().intoArray(field, converter); - } - - @Override - public final Set fetchSet(RecordMapper mapper) { - return fetch().intoSet(mapper); - } - - @Override - public final Set fetchSet(int fieldIndex) { - return fetch().intoSet(fieldIndex); - } - - @Override - public final Set fetchSet(int fieldIndex, Class type) { - return fetch().intoSet(fieldIndex, type); - } - - @Override - public final Set fetchSet(int fieldIndex, Converter converter) { - return fetch().intoSet(fieldIndex, converter); - } - - @Override - public final Set fetchSet(String fieldName) { - return fetch().intoSet(fieldName); - } - - @Override - public final Set fetchSet(String fieldName, Class type) { - return fetch().intoSet(fieldName, type); - } - - @Override - public final Set fetchSet(String fieldName, Converter converter) { - return fetch().intoSet(fieldName, converter); - } - - @Override - public final Set fetchSet(Name fieldName) { - return fetch().intoSet(fieldName); - } - - @Override - public final Set fetchSet(Name fieldName, Class type) { - return fetch().intoSet(fieldName, type); - } - - @Override - public final Set fetchSet(Name fieldName, Converter converter) { - return fetch().intoSet(fieldName, converter); - } - - @Override - public final Set fetchSet(Field field) { - return fetch().intoSet(field); - } - - @Override - public final Set fetchSet(Field field, Class type) { - return fetch().intoSet(field, type); - } - - @Override - public final Set fetchSet(Field field, Converter converter) { - return fetch().intoSet(field, converter); - } - @SuppressWarnings("unchecked") @Override public final Class getRecordType() { @@ -1527,41 +442,12 @@ abstract class AbstractResultQuery extends AbstractQuery imple abstract Class getRecordType0(); - @Override - public final List fetchInto(Class type) { - return fetch().into(type); - } - - @Override - public final Result fetchInto(Table table) { - return fetch().into(table); - } - - @Override - public final > H fetchInto(H handler) { - return fetch().into(handler); - } - - @Override - public final List fetch(RecordMapper mapper) { - return fetch().map(mapper); - } @Override public final Result getResult() { return result; } - @SuppressWarnings("rawtypes") - private final boolean hasLimit1() { - if (this instanceof SelectQueryImpl) { - Limit l = ((SelectQueryImpl) this).getLimit(); - return !l.withTies() && !l.percent() && l.limitOne(); - } - - return false; - } - @SuppressWarnings("unchecked") @Override public final ResultQuery coerce(Table table) { diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRowCountQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRowCountQuery.java index b75072a6cd..502c98cf96 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRowCountQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRowCountQuery.java @@ -38,12 +38,13 @@ package org.jooq.impl; import org.jooq.Configuration; +import org.jooq.Record; import org.jooq.RowCountQuery; /** * @author Lukas Eder */ -abstract class AbstractRowCountQuery extends AbstractQuery implements RowCountQuery { +abstract class AbstractRowCountQuery extends AbstractQuery implements RowCountQuery { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java b/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java index 4f751372d7..94c52642fb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java @@ -65,27 +65,16 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.stream.Collector; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; import org.jooq.BindingGetResultSetContext; -import org.jooq.Cursor; import org.jooq.ExecuteContext; import org.jooq.ExecuteListener; import org.jooq.Field; // ... import org.jooq.Record; -import org.jooq.RecordHandler; -import org.jooq.RecordMapper; import org.jooq.Result; -import org.jooq.Table; import org.jooq.exception.ControlFlowSignal; import org.jooq.tools.JooqLogger; import org.jooq.tools.jdbc.JDBC41ResultSet; @@ -94,7 +83,7 @@ import org.jooq.tools.jdbc.JDBCUtils; /** * @author Lukas Eder */ -final class CursorImpl extends AbstractCursor implements Cursor { +final class CursorImpl extends AbstractCursor { private static final JooqLogger log = JooqLogger.getLogger(CursorImpl.class); @@ -214,127 +203,6 @@ final class CursorImpl extends AbstractCursor implements Cu return iterator; } - - @Override - public final Stream stream() { - return StreamSupport.stream( - Spliterators.spliteratorUnknownSize( - iterator(), - Spliterator.ORDERED | Spliterator.NONNULL - ), - false - ).onClose(() -> close()); - } - - @Override - public final X collect(Collector collector) { - return stream().collect(collector); - } - - - @Override - public final boolean hasNext() { - return iterator().hasNext(); - } - - @Override - public final Result fetch() { - return fetch(Integer.MAX_VALUE); - } - - @Override - @Deprecated - public final R fetchOne() { - return fetchNext(); - } - - @Override - @Deprecated - public final E fetchOne(RecordMapper mapper) { - return fetchNext(mapper); - } - - @Override - @Deprecated - public final > H fetchOneInto(H handler) { - return fetchNextInto(handler); - } - - @Override - @Deprecated - public final Z fetchOneInto(Table table) { - return fetchNextInto(table); - } - - @Override - @Deprecated - public final E fetchOneInto(Class type) { - return fetchNextInto(type); - } - - @Override - public final R fetchNext() { - Result result = fetch(1); - - if (result.size() == 1) { - return result.get(0); - } - - return null; - } - - - - @Override - @Deprecated - public Optional fetchOptional() { - return fetchNextOptional(); - } - - @Override - @Deprecated - public Optional fetchOptional(RecordMapper mapper) { - return fetchNextOptional(mapper); - } - - @Override - @Deprecated - public Optional fetchOptionalInto(Class type) { - return fetchNextOptionalInto(type); - } - - @Override - @Deprecated - public Optional fetchOptionalInto(Table table) { - return fetchNextOptionalInto(table); - } - - @Override - public final Optional fetchNextOptional() { - return Optional.ofNullable(fetchNext()); - } - - @Override - public final Optional fetchNextOptional(RecordMapper mapper) { - return Optional.ofNullable(fetchNext(mapper)); - } - - @Override - public final Optional fetchNextOptionalInto(Class type) { - return Optional.ofNullable(fetchNextInto(type)); - } - - @Override - public final Optional fetchNextOptionalInto(Table table) { - return Optional.ofNullable(fetchNextInto(table)); - } - - - @Override - public final Result fetch(int number) { - return fetchNext(number); - } - @Override public final Result fetchNext(int number) { // [#1157] This invokes listener.fetchStart(ctx), which has to be called @@ -354,53 +222,6 @@ final class CursorImpl extends AbstractCursor implements Cu return result; } - @Override - public final > H fetchNextInto(H handler) { - handler.next(fetchNext()); - return handler; - } - - @Override - public final > H fetchInto(H handler) { - while (hasNext()) { - fetchNextInto(handler); - } - - return handler; - } - - @Override - public final E fetchNext(RecordMapper mapper) { - R record = fetchNext(); - return record == null ? null : mapper.map(record); - } - - @Override - public final List fetch(RecordMapper mapper) { - return fetch().map(mapper); - } - - @Override - public final E fetchNextInto(Class clazz) { - R record = fetchNext(); - return record == null ? null : record.into(clazz); - } - - @Override - public final List fetchInto(Class clazz) { - return fetch().into(clazz); - } - - @Override - public final Z fetchNextInto(Table table) { - return fetchNext().into(table); - } - - @Override - public final Result fetchInto(Table table) { - return fetch().into(table); - } - @Override public final void close() { JDBCUtils.safeClose(rs); diff --git a/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java b/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java index 7fdb4fd3f2..95d7f04181 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/DeleteImpl.java @@ -93,7 +93,7 @@ import org.jooq.TableLike; */ @SuppressWarnings({ "rawtypes", "unchecked" }) final class DeleteImpl - extends AbstractDelegatingRowCountQuery> + extends AbstractDelegatingRowCountQuery> implements // Cascading interface implementations for Delete behaviour @@ -519,17 +519,4 @@ final class DeleteImpl getDelegate().execute(); return returningResult ? (Result) getDelegate().getResult() : getDelegate().getReturnedRecords(); } - - @Override - public final R fetchOne() { - getDelegate().execute(); - return filterOne(returningResult ? (Result) getDelegate().getResult() : getDelegate().getReturnedRecords()); - } - - - @Override - public final Optional fetchOptional() { - return Optional.ofNullable(fetchOne()); - } - } diff --git a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java index 8817f3b95f..e51a604096 100644 --- a/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/InsertImpl.java @@ -146,7 +146,7 @@ import org.jooq.UniqueKey; */ @SuppressWarnings({ "rawtypes", "unchecked" }) final class InsertImpl - extends AbstractDelegatingRowCountQuery> + extends AbstractDelegatingRowCountQuery> implements // Cascading interface implementations for Insert behaviour @@ -1562,17 +1562,4 @@ final class InsertImpl) getDelegate().getResult() : getDelegate().getReturnedRecords(); } - - @Override - public final R fetchOne() { - getDelegate().execute(); - return filterOne(returningResult ? (Result) getDelegate().getResult() : getDelegate().getReturnedRecords()); - } - - - @Override - public final Optional fetchOptional() { - return Optional.ofNullable(fetchOne()); - } - } diff --git a/jOOQ/src/main/java/org/jooq/impl/ResultAsCursor.java b/jOOQ/src/main/java/org/jooq/impl/ResultAsCursor.java new file mode 100644 index 0000000000..65aa45d7bd --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/ResultAsCursor.java @@ -0,0 +1,92 @@ +/* + * 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.sql.ResultSet; +import java.util.Iterator; + +import org.jooq.Record; +import org.jooq.Result; + +/** + * @author Lukas Eder + */ +final class ResultAsCursor extends AbstractCursor { + + /** + * Generated UID + */ + private static final long serialVersionUID = 3711590697891578695L; + private final Result result; + private int index; + + ResultAsCursor(Result result) { + super(result.configuration(), (AbstractRow) result.fieldsRow()); + + this.result = result; + } + + @Override + public final Iterator iterator() { + return result.iterator(); + } + + @Override + public final Result fetchNext(int number) { + Result r = new ResultImpl(configuration, fields); + + for (int i = 0; i < number && i + index < result.size(); i++) + r.add(result.get(i + index)); + + index += number; + return r; + } + + @Override + public void close() {} + + @Override + public boolean isClosed() { + return false; + } + + @Override + public final ResultSet resultSet() { + return result.intoResultSet(); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java index 5e0779e65e..d88810e4ba 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java @@ -101,7 +101,7 @@ import org.jooq.tools.jdbc.MockResultSet; * @author Ivan Dugic */ @SuppressWarnings({"rawtypes", "unchecked" }) -final class ResultImpl extends AbstractCursor implements Result { +final class ResultImpl extends AbstractResult implements Result { /** * Generated UID diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java index fb15080729..0fccc6ac0a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectImpl.java @@ -43,21 +43,12 @@ import static org.jooq.impl.DSL.notExists; import static org.jooq.impl.DSL.table; import static org.jooq.impl.Tools.EMPTY_FIELD; -import java.sql.ResultSet; import java.util.Arrays; import java.util.Collection; -import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; // ... import java.util.function.BiFunction; import java.util.function.Function; -import java.util.stream.Collector; import java.util.stream.Stream; import org.jooq.BetweenAndStep; @@ -65,7 +56,6 @@ import org.jooq.BetweenAndStepR; import org.jooq.Comparator; import org.jooq.Condition; import org.jooq.Configuration; -import org.jooq.Converter; import org.jooq.Cursor; import org.jooq.DataType; import org.jooq.Field; @@ -102,8 +92,6 @@ import org.jooq.Record6; import org.jooq.Record7; import org.jooq.Record8; import org.jooq.Record9; -import org.jooq.RecordHandler; -import org.jooq.RecordMapper; import org.jooq.Result; import org.jooq.ResultQuery; import org.jooq.Results; @@ -169,7 +157,7 @@ import org.jooq.WindowDefinition; * @author Lukas Eder */ @SuppressWarnings({ "unchecked", "rawtypes" }) -final class SelectImpl extends AbstractDelegatingQuery> implements +final class SelectImpl extends AbstractDelegatingQuery> implements // Cascading interface implementations for Select behaviour SelectSelectStep, @@ -2880,16 +2868,6 @@ final class SelectImpl iterator() { - return getDelegate().iterator(); - } - @@ -2906,31 +2884,6 @@ final class SelectImpl fetchStream() { - return getDelegate().fetchStream(); - } - - @Override - public final Stream fetchStreamInto(Class type) { - return getDelegate().fetchStreamInto(type); - } - - @Override - public final Stream fetchStreamInto(Table table) { - return getDelegate().fetchStreamInto(table); - } - - @Override - public final Stream stream() { - return getDelegate().stream(); - } - - @Override - public final X collect(Collector collector) { - return getDelegate().collect(collector); - } - @Override @@ -2938,1025 +2891,16 @@ final class SelectImpl fetchLazyNonAutoClosing() { + return ((SelectQueryImpl) getDelegate()).fetchLazyNonAutoClosing(); + } + @Override public final Results fetchMany() { return getDelegate().fetchMany(); } - @Override - public final List fetch(Field field) { - return getDelegate().fetch(field); - } - - @Override - public final List fetch(Field field, Class type) { - return getDelegate().fetch(field, type); - } - - @Override - public final List fetch(Field field, Converter converter) { - return getDelegate().fetch(field, converter); - } - - @Override - public final List fetch(int fieldIndex) { - return getDelegate().fetch(fieldIndex); - } - - @Override - public final List fetch(int fieldIndex, Class type) { - return getDelegate().fetch(fieldIndex, type); - } - - @Override - public final List fetch(int fieldIndex, Converter converter) { - return getDelegate().fetch(fieldIndex, converter); - } - - @Override - public final List fetch(String fieldName) { - return getDelegate().fetch(fieldName); - } - - @Override - public final List fetch(String fieldName, Class type) { - return getDelegate().fetch(fieldName, type); - } - - @Override - public final List fetch(String fieldName, Converter converter) { - return getDelegate().fetch(fieldName, converter); - } - - @Override - public final List fetch(Name fieldName) { - return getDelegate().fetch(fieldName); - } - - @Override - public final List fetch(Name fieldName, Class type) { - return getDelegate().fetch(fieldName, type); - } - - @Override - public final List fetch(Name fieldName, Converter converter) { - return getDelegate().fetch(fieldName, converter); - } - - @Override - public final T fetchOne(Field field) { - return getDelegate().fetchOne(field); - } - - @Override - public final T fetchOne(Field field, Class type) { - return getDelegate().fetchOne(field, type); - } - - @Override - public final U fetchOne(Field field, Converter converter) { - return getDelegate().fetchOne(field, converter); - } - - @Override - public final Object fetchOne(int fieldIndex) { - return getDelegate().fetchOne(fieldIndex); - } - - @Override - public final T fetchOne(int fieldIndex, Class type) { - return getDelegate().fetchOne(fieldIndex, type); - } - - @Override - public final U fetchOne(int fieldIndex, Converter converter) { - return getDelegate().fetchOne(fieldIndex, converter); - } - - @Override - public final Object fetchOne(String fieldName) { - return getDelegate().fetchOne(fieldName); - } - - @Override - public final T fetchOne(String fieldName, Class type) { - return getDelegate().fetchOne(fieldName, type); - } - - @Override - public final U fetchOne(String fieldName, Converter converter) { - return getDelegate().fetchOne(fieldName, converter); - } - - @Override - public final Object fetchOne(Name fieldName) { - return getDelegate().fetchOne(fieldName); - } - - @Override - public final T fetchOne(Name fieldName, Class type) { - return getDelegate().fetchOne(fieldName, type); - } - - @Override - public final U fetchOne(Name fieldName, Converter converter) { - return getDelegate().fetchOne(fieldName, converter); - } - - @Override - public final R fetchOne() { - return getDelegate().fetchOne(); - } - - @Override - public final E fetchOne(RecordMapper mapper) { - return getDelegate().fetchOne(mapper); - } - - @Override - public final Map fetchOneMap() { - return getDelegate().fetchOneMap(); - } - - @Override - public final Object[] fetchOneArray() { - return getDelegate().fetchOneArray(); - } - - @Override - public final E fetchOneInto(Class type) { - return getDelegate().fetchOneInto(type); - } - - @Override - public final Z fetchOneInto(Table table) { - return getDelegate().fetchOneInto(table); - } - - @Override - public final T fetchSingle(Field field) { - return getDelegate().fetchSingle(field); - } - - @Override - public final T fetchSingle(Field field, Class type) { - return getDelegate().fetchSingle(field, type); - } - - @Override - public final U fetchSingle(Field field, Converter converter) { - return getDelegate().fetchSingle(field, converter); - } - - @Override - public final Object fetchSingle(int fieldIndex) { - return getDelegate().fetchSingle(fieldIndex); - } - - @Override - public final T fetchSingle(int fieldIndex, Class type) { - return getDelegate().fetchSingle(fieldIndex, type); - } - - @Override - public final U fetchSingle(int fieldIndex, Converter converter) { - return getDelegate().fetchSingle(fieldIndex, converter); - } - - @Override - public final Object fetchSingle(String fieldName) { - return getDelegate().fetchSingle(fieldName); - } - - @Override - public final T fetchSingle(String fieldName, Class type) { - return getDelegate().fetchSingle(fieldName, type); - } - - @Override - public final U fetchSingle(String fieldName, Converter converter) { - return getDelegate().fetchSingle(fieldName, converter); - } - - @Override - public final Object fetchSingle(Name fieldName) { - return getDelegate().fetchSingle(fieldName); - } - - @Override - public final T fetchSingle(Name fieldName, Class type) { - return getDelegate().fetchSingle(fieldName, type); - } - - @Override - public final U fetchSingle(Name fieldName, Converter converter) { - return getDelegate().fetchSingle(fieldName, converter); - } - - @Override - public final R fetchSingle() { - return getDelegate().fetchSingle(); - } - - @Override - public final E fetchSingle(RecordMapper mapper) { - return getDelegate().fetchSingle(mapper); - } - - @Override - public final Map fetchSingleMap() { - return getDelegate().fetchSingleMap(); - } - - @Override - public final Object[] fetchSingleArray() { - return getDelegate().fetchSingleArray(); - } - - @Override - public final E fetchSingleInto(Class type) { - return getDelegate().fetchSingleInto(type); - } - - @Override - public final Z fetchSingleInto(Table table) { - return getDelegate().fetchSingleInto(table); - } - - - @Override - public final Optional fetchOptional(Field field) { - return getDelegate().fetchOptional(field); - } - - @Override - public final Optional fetchOptional(Field field, Class type) { - return getDelegate().fetchOptional(field, type); - } - - @Override - public final Optional fetchOptional(Field field, Converter converter) { - return getDelegate().fetchOptional(field, converter); - } - - @Override - public final Optional fetchOptional(int fieldIndex) { - return getDelegate().fetchOptional(fieldIndex); - } - - @Override - public final Optional fetchOptional(int fieldIndex, Class type) { - return getDelegate().fetchOptional(fieldIndex, type); - } - - @Override - public final Optional fetchOptional(int fieldIndex, Converter converter) { - return getDelegate().fetchOptional(fieldIndex, converter); - } - - @Override - public final Optional fetchOptional(String fieldName) { - return getDelegate().fetchOptional(fieldName); - } - - @Override - public final Optional fetchOptional(String fieldName, Class type) { - return getDelegate().fetchOptional(fieldName, type); - } - - @Override - public final Optional fetchOptional(String fieldName, Converter converter) { - return getDelegate().fetchOptional(fieldName, converter); - } - - @Override - public final Optional fetchOptional(Name fieldName) { - return getDelegate().fetchOptional(fieldName); - } - - @Override - public final Optional fetchOptional(Name fieldName, Class type) { - return getDelegate().fetchOptional(fieldName, type); - } - - @Override - public final Optional fetchOptional(Name fieldName, Converter converter) { - return getDelegate().fetchOptional(fieldName, converter); - } - - @Override - public final Optional fetchOptional() { - return getDelegate().fetchOptional(); - } - - @Override - public final Optional fetchOptional(RecordMapper mapper) { - return getDelegate().fetchOptional(mapper); - } - - @Override - public final Optional> fetchOptionalMap() { - return getDelegate().fetchOptionalMap(); - } - - @Override - public final Optional fetchOptionalArray() { - return getDelegate().fetchOptionalArray(); - } - - @Override - public final Optional fetchOptionalInto(Class type) { - return getDelegate().fetchOptionalInto(type); - } - - @Override - public final Optional fetchOptionalInto(Table table) { - return getDelegate().fetchOptionalInto(table); - } - - - @Override - public final T fetchAny(Field field) { - return getDelegate().fetchAny(field); - } - - @Override - public final T fetchAny(Field field, Class type) { - return getDelegate().fetchAny(field, type); - } - - @Override - public final U fetchAny(Field field, Converter converter) { - return getDelegate().fetchAny(field, converter); - } - - @Override - public final Object fetchAny(int fieldIndex) { - return getDelegate().fetchAny(fieldIndex); - } - - @Override - public final T fetchAny(int fieldIndex, Class type) { - return getDelegate().fetchAny(fieldIndex, type); - } - - @Override - public final U fetchAny(int fieldIndex, Converter converter) { - return getDelegate().fetchAny(fieldIndex, converter); - } - - @Override - public final Object fetchAny(String fieldName) { - return getDelegate().fetchAny(fieldName); - } - - @Override - public final T fetchAny(String fieldName, Class type) { - return getDelegate().fetchAny(fieldName, type); - } - - @Override - public final U fetchAny(String fieldName, Converter converter) { - return getDelegate().fetchAny(fieldName, converter); - } - - @Override - public final Object fetchAny(Name fieldName) { - return getDelegate().fetchAny(fieldName); - } - - @Override - public final T fetchAny(Name fieldName, Class type) { - return getDelegate().fetchAny(fieldName, type); - } - - @Override - public final U fetchAny(Name fieldName, Converter converter) { - return getDelegate().fetchAny(fieldName, converter); - } - - @Override - public final R fetchAny() { - return getDelegate().fetchAny(); - } - - @Override - public final E fetchAny(RecordMapper mapper) { - return getDelegate().fetchAny(mapper); - } - - @Override - public final Map fetchAnyMap() { - return getDelegate().fetchAnyMap(); - } - - @Override - public final Object[] fetchAnyArray() { - return getDelegate().fetchAnyArray(); - } - - @Override - public final E fetchAnyInto(Class type) { - return getDelegate().fetchAnyInto(type); - } - - @Override - public final Z fetchAnyInto(Table table) { - return getDelegate().fetchAnyInto(table); - } - - @Override - public final Map fetchMap(Field key) { - return getDelegate().fetchMap(key); - } - - @Override - public final Map fetchMap(int keyFieldIndex) { - return getDelegate().fetchMap(keyFieldIndex); - } - - @Override - public final Map fetchMap(String keyFieldName) { - return getDelegate().fetchMap(keyFieldName); - } - - @Override - public final Map fetchMap(Name keyFieldName) { - return getDelegate().fetchMap(keyFieldName); - } - - @Override - public final Map fetchMap(Field key, Field value) { - return getDelegate().fetchMap(key, value); - } - - @Override - public final Map fetchMap(int keyFieldIndex, int valueFieldIndex) { - return getDelegate().fetchMap(keyFieldIndex, valueFieldIndex); - } - - @Override - public final Map fetchMap(String keyFieldName, String valueFieldName) { - return getDelegate().fetchMap(keyFieldName, valueFieldName); - } - - @Override - public final Map fetchMap(Name keyFieldName, Name valueFieldName) { - return getDelegate().fetchMap(keyFieldName, valueFieldName); - } - - @Override - public final Map fetchMap(Field key, Class type) { - return getDelegate().fetchMap(key, type); - } - - @Override - public final Map fetchMap(int keyFieldIndex, Class type) { - return getDelegate().fetchMap(keyFieldIndex, type); - } - - @Override - public final Map fetchMap(String keyFieldName, Class type) { - return getDelegate().fetchMap(keyFieldName, type); - } - - @Override - public final Map fetchMap(Name keyFieldName, Class type) { - return getDelegate().fetchMap(keyFieldName, type); - } - - @Override - public final Map fetchMap(Field key, RecordMapper mapper) { - return getDelegate().fetchMap(key, mapper); - } - - @Override - public final Map fetchMap(int keyFieldIndex, RecordMapper mapper) { - return getDelegate().fetchMap(keyFieldIndex, mapper); - } - - @Override - public final Map fetchMap(String keyFieldName, RecordMapper mapper) { - return getDelegate().fetchMap(keyFieldName, mapper); - } - - @Override - public final Map fetchMap(Name keyFieldName, RecordMapper mapper) { - return getDelegate().fetchMap(keyFieldName, mapper); - } - - @Override - public final Map fetchMap(Field[] keys) { - return getDelegate().fetchMap(keys); - } - - @Override - public final Map fetchMap(int[] keyFieldIndexes) { - return getDelegate().fetchMap(keyFieldIndexes); - } - - @Override - public final Map fetchMap(String[] keyFieldNames) { - return getDelegate().fetchMap(keyFieldNames); - } - - @Override - public final Map fetchMap(Name[] keyFieldNames) { - return getDelegate().fetchMap(keyFieldNames); - } - - @Override - public final Map fetchMap(Field[] keys, Field[] values) { - return getDelegate().fetchMap(keys, values); - } - - @Override - public final Map fetchMap(int[] keyFieldIndexes, int[] valueFieldIndexes) { - return getDelegate().fetchMap(keyFieldIndexes, valueFieldIndexes); - } - - @Override - public final Map fetchMap(String[] keyFieldNames, String[] valueFieldNames) { - return getDelegate().fetchMap(keyFieldNames, valueFieldNames); - } - - @Override - public final Map fetchMap(Name[] keyFieldNames, Name[] valueFieldNames) { - return getDelegate().fetchMap(keyFieldNames, valueFieldNames); - } - - @Override - public final Map, E> fetchMap(Field[] keys, Class type) { - return getDelegate().fetchMap(keys, type); - } - - @Override - public final Map, E> fetchMap(int[] keyFieldIndexes, Class type) { - return getDelegate().fetchMap(keyFieldIndexes, type); - } - - @Override - public final Map, E> fetchMap(String[] keyFieldNames, Class type) { - return getDelegate().fetchMap(keyFieldNames, type); - } - - @Override - public final Map, E> fetchMap(Name[] keyFieldNames, Class type) { - return getDelegate().fetchMap(keyFieldNames, type); - } - - @Override - public final Map, E> fetchMap(Field[] keys, RecordMapper mapper) { - return getDelegate().fetchMap(keys, mapper); - } - - @Override - public final Map, E> fetchMap(int[] keyFieldIndexes, RecordMapper mapper) { - return getDelegate().fetchMap(keyFieldIndexes, mapper); - } - - @Override - public final Map, E> fetchMap(String[] keyFieldNames, RecordMapper mapper) { - return getDelegate().fetchMap(keyFieldNames, mapper); - } - - @Override - public final Map, E> fetchMap(Name[] keyFieldNames, RecordMapper mapper) { - return getDelegate().fetchMap(keyFieldNames, mapper); - } - - @Override - public final Map fetchMap(Class keyType) { - return getDelegate().fetchMap(keyType); - } - - @Override - public final Map fetchMap(Class keyType, Class valueType) { - return getDelegate().fetchMap(keyType, valueType); - } - - @Override - public final Map fetchMap(Class keyType, RecordMapper valueMapper) { - return getDelegate().fetchMap(keyType, valueMapper); - } - - @Override - public final Map fetchMap(RecordMapper keyMapper) { - return getDelegate().fetchMap(keyMapper); - } - - @Override - public final Map fetchMap(RecordMapper keyMapper, Class valueType) { - return getDelegate().fetchMap(keyMapper, valueType); - } - - @Override - public final Map fetchMap(RecordMapper keyMapper, RecordMapper valueMapper) { - return getDelegate().fetchMap(keyMapper, valueMapper); - } - - @Override - public final Map fetchMap(Table table) { - return getDelegate().fetchMap(table); - } - - @Override - public final Map fetchMap(Table keyTable, Table valueTable) { - return getDelegate().fetchMap(keyTable, valueTable); - } - - @Override - public final Map fetchMap(Table table, Class type) { - return getDelegate().fetchMap(table, type); - } - - @Override - public final Map fetchMap(Table table, RecordMapper mapper) { - return getDelegate().fetchMap(table, mapper); - } - - @Override - public final List> fetchMaps() { - return getDelegate().fetchMaps(); - } - - @Override - public final Map> fetchGroups(Field key) { - return getDelegate().fetchGroups(key); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex) { - return getDelegate().fetchGroups(keyFieldIndex); - } - - @Override - public final Map> fetchGroups(String keyFieldName) { - return getDelegate().fetchGroups(keyFieldName); - } - - @Override - public final Map> fetchGroups(Name keyFieldName) { - return getDelegate().fetchGroups(keyFieldName); - } - - @Override - public final Map> fetchGroups(Field key, Field value) { - return getDelegate().fetchGroups(key, value); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex, int valueFieldIndex) { - return getDelegate().fetchGroups(keyFieldIndex, valueFieldIndex); - } - - @Override - public final Map> fetchGroups(String keyFieldName, String valueFieldName) { - return getDelegate().fetchGroups(keyFieldName, valueFieldName); - } - - @Override - public final Map> fetchGroups(Name keyFieldName, Name valueFieldName) { - return getDelegate().fetchGroups(keyFieldName, valueFieldName); - } - - @Override - public final Map> fetchGroups(Field key, Class type) { - return getDelegate().fetchGroups(key, type); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex, Class type) { - return getDelegate().fetchGroups(keyFieldIndex, type); - } - - @Override - public final Map> fetchGroups(String keyFieldName, Class type) { - return getDelegate().fetchGroups(keyFieldName, type); - } - - @Override - public final Map> fetchGroups(Name keyFieldName, Class type) { - return getDelegate().fetchGroups(keyFieldName, type); - } - - @Override - public final Map> fetchGroups(Field key, RecordMapper mapper) { - return getDelegate().fetchGroups(key, mapper); - } - - @Override - public final Map> fetchGroups(int keyFieldIndex, RecordMapper mapper) { - return getDelegate().fetchGroups(keyFieldIndex, mapper); - } - - @Override - public final Map> fetchGroups(String keyFieldName, RecordMapper mapper) { - return getDelegate().fetchGroups(keyFieldName, mapper); - } - - @Override - public final Map> fetchGroups(Name keyFieldName, RecordMapper mapper) { - return getDelegate().fetchGroups(keyFieldName, mapper); - } - - @Override - public final Map> fetchGroups(Field[] keys) { - return getDelegate().fetchGroups(keys); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes) { - return getDelegate().fetchGroups(keyFieldIndexes); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames) { - return getDelegate().fetchGroups(keyFieldNames); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames) { - return getDelegate().fetchGroups(keyFieldNames); - } - - @Override - public final Map> fetchGroups(Field[] keys, Field[] values) { - return getDelegate().fetchGroups(keys, values); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes, int[] valueFieldIndexes) { - return getDelegate().fetchGroups(keyFieldIndexes, valueFieldIndexes); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames, String[] valueFieldNames) { - return getDelegate().fetchGroups(keyFieldNames, valueFieldNames); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames, Name[] valueFieldNames) { - return getDelegate().fetchGroups(keyFieldNames, valueFieldNames); - } - - @Override - public final Map> fetchGroups(Field[] keys, Class type) { - return getDelegate().fetchGroups(keys, type); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes, Class type) { - return getDelegate().fetchGroups(keyFieldIndexes, type); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames, Class type) { - return getDelegate().fetchGroups(keyFieldNames, type); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames, Class type) { - return getDelegate().fetchGroups(keyFieldNames, type); - } - - @Override - public final Map> fetchGroups(Field[] keys, RecordMapper mapper) { - return getDelegate().fetchGroups(keys, mapper); - } - - @Override - public final Map> fetchGroups(int[] keyFieldIndexes, RecordMapper mapper) { - return getDelegate().fetchGroups(keyFieldIndexes, mapper); - } - - @Override - public final Map> fetchGroups(String[] keyFieldNames, RecordMapper mapper) { - return getDelegate().fetchGroups(keyFieldNames, mapper); - } - - @Override - public final Map> fetchGroups(Name[] keyFieldNames, RecordMapper mapper) { - return getDelegate().fetchGroups(keyFieldNames, mapper); - } - - @Override - public final Map> fetchGroups(Class keyType) { - return getDelegate().fetchGroups(keyType); - } - - @Override - public final Map> fetchGroups(Class keyType, Class valueType) { - return getDelegate().fetchGroups(keyType, valueType); - } - - @Override - public final Map> fetchGroups(Class keyType, RecordMapper valueMapper) { - return getDelegate().fetchGroups(keyType, valueMapper); - } - - @Override - public final Map> fetchGroups(RecordMapper keyMapper) { - return getDelegate().fetchGroups(keyMapper); - } - - @Override - public final Map> fetchGroups(RecordMapper keyMapper, Class valueType) { - return getDelegate().fetchGroups(keyMapper, valueType); - } - - @Override - public final Map> fetchGroups(RecordMapper keyMapper, RecordMapper valueMapper) { - return getDelegate().fetchGroups(keyMapper, valueMapper); - } - - @Override - public final Map> fetchGroups(Table table) { - return getDelegate().fetchGroups(table); - } - - @Override - public final Map> fetchGroups(Table keyTable, Table valueTable) { - return getDelegate().fetchGroups(keyTable, valueTable); - } - - @Override - public final Map> fetchGroups(Table table, Class type) { - return getDelegate().fetchGroups(table, type); - } - - @Override - public final Map> fetchGroups(Table table, RecordMapper mapper) { - return getDelegate().fetchGroups(table, mapper); - } - - @Override - public final Object[][] fetchArrays() { - return getDelegate().fetchArrays(); - } - - @Override - public final R[] fetchArray() { - return getDelegate().fetchArray(); - } - - @Override - public final Object[] fetchArray(int fieldIndex) { - return getDelegate().fetchArray(fieldIndex); - } - - @Override - public final T[] fetchArray(int fieldIndex, Class type) { - return getDelegate().fetchArray(fieldIndex, type); - } - - @Override - public final U[] fetchArray(int fieldIndex, Converter converter) { - return getDelegate().fetchArray(fieldIndex, converter); - } - - @Override - public final Object[] fetchArray(String fieldName) { - return getDelegate().fetchArray(fieldName); - } - - @Override - public final T[] fetchArray(String fieldName, Class type) { - return getDelegate().fetchArray(fieldName, type); - } - - @Override - public final U[] fetchArray(String fieldName, Converter converter) { - return getDelegate().fetchArray(fieldName, converter); - } - - @Override - public final Object[] fetchArray(Name fieldName) { - return getDelegate().fetchArray(fieldName); - } - - @Override - public final T[] fetchArray(Name fieldName, Class type) { - return getDelegate().fetchArray(fieldName, type); - } - - @Override - public final U[] fetchArray(Name fieldName, Converter converter) { - return getDelegate().fetchArray(fieldName, converter); - } - - @Override - public final T[] fetchArray(Field field) { - return getDelegate().fetchArray(field); - } - - @Override - public final T[] fetchArray(Field field, Class type) { - return getDelegate().fetchArray(field, type); - } - - @Override - public final U[] fetchArray(Field field, Converter converter) { - return getDelegate().fetchArray(field, converter); - } - - @Override - public final Set fetchSet(RecordMapper mapper) { - return getDelegate().fetchSet(mapper); - } - - @Override - public final Set fetchSet(int fieldIndex) { - return getDelegate().fetchSet(fieldIndex); - } - - @Override - public final Set fetchSet(int fieldIndex, Class type) { - return getDelegate().fetchSet(fieldIndex, type); - } - - @Override - public final Set fetchSet(int fieldIndex, Converter converter) { - return getDelegate().fetchSet(fieldIndex, converter); - } - - @Override - public final Set fetchSet(String fieldName) { - return getDelegate().fetchSet(fieldName); - } - - @Override - public final Set fetchSet(String fieldName, Class type) { - return getDelegate().fetchSet(fieldName, type); - } - - @Override - public final Set fetchSet(String fieldName, Converter converter) { - return getDelegate().fetchSet(fieldName, converter); - } - - @Override - public final Set fetchSet(Name fieldName) { - return getDelegate().fetchSet(fieldName); - } - - @Override - public final Set fetchSet(Name fieldName, Class type) { - return getDelegate().fetchSet(fieldName, type); - } - - @Override - public final Set fetchSet(Name fieldName, Converter converter) { - return getDelegate().fetchSet(fieldName, converter); - } - - @Override - public final Set fetchSet(Field field) { - return getDelegate().fetchSet(field); - } - - @Override - public final Set fetchSet(Field field, Class type) { - return getDelegate().fetchSet(field, type); - } - - @Override - public final Set fetchSet(Field field, Converter converter) { - return getDelegate().fetchSet(field, converter); - } - - @Override - public final List fetchInto(Class type) { - return getDelegate().fetchInto(type); - } - - @Override - public final Result fetchInto(Table table) { - return getDelegate().fetchInto(table); - } - - @Override - public final > H fetchInto(H handler) { - return getDelegate().fetchInto(handler); - } - - @Override - public final List fetch(RecordMapper mapper) { - return getDelegate().fetch(mapper); - } - - - @Override - public final CompletionStage> fetchAsync() { - return getDelegate().fetchAsync(); - } - - @Override - public final CompletionStage> fetchAsync(Executor executor) { - return getDelegate().fetchAsync(executor); - } - - @Override public final Table asTable() { return getDelegate().asTable(); diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index e9e501b3e3..a4ce671677 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -3168,7 +3168,7 @@ final class Tools { if (select instanceof SelectQueryImpl) return (SelectQueryImpl) select; else if (select instanceof AbstractDelegatingQuery) - return ((AbstractDelegatingQuery>) select).getDelegate(); + return ((AbstractDelegatingQuery>) select).getDelegate(); else return null; } diff --git a/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java b/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java index 3ea3f58c9b..85ee76ce99 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UpdateImpl.java @@ -123,7 +123,7 @@ import org.jooq.UpdateWhereStep; */ @SuppressWarnings({ "rawtypes", "unchecked" }) final class UpdateImpl - extends AbstractDelegatingRowCountQuery> + extends AbstractDelegatingRowCountQuery> implements // Cascading interface implementations for Update behaviour @@ -866,17 +866,4 @@ final class UpdateImpl getDelegate().execute(); return returningResult ? (Result) getDelegate().getResult() : getDelegate().getReturnedRecords(); } - - @Override - public final R fetchOne() { - getDelegate().execute(); - return filterOne(returningResult ? (Result) getDelegate().getResult() : getDelegate().getReturnedRecords()); - } - - - @Override - public final Optional fetchOptional() { - return Optional.ofNullable(fetchOne()); - } - }