diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java
new file mode 100644
index 0000000000..a24691981b
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java
@@ -0,0 +1,3141 @@
+/**
+ * Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
+ * All rights reserved.
+ *
+ * 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.Boolean.FALSE;
+import static java.util.Arrays.asList;
+// ...
+import static org.jooq.SQLDialect.CUBRID;
+import static org.jooq.SQLDialect.MARIADB;
+import static org.jooq.SQLDialect.MYSQL;
+import static org.jooq.conf.BackslashEscaping.DEFAULT;
+import static org.jooq.conf.BackslashEscaping.ON;
+import static org.jooq.conf.ParamType.INLINED;
+import static org.jooq.conf.ParamType.NAMED;
+import static org.jooq.conf.ParamType.NAMED_OR_INLINED;
+import static org.jooq.conf.SettingsTools.getBackslashEscaping;
+import static org.jooq.conf.SettingsTools.reflectionCaching;
+import static org.jooq.conf.SettingsTools.updatablePrimaryKeys;
+import static org.jooq.impl.DDLStatementType.CREATE_INDEX;
+import static org.jooq.impl.DDLStatementType.CREATE_SEQUENCE;
+import static org.jooq.impl.DDLStatementType.CREATE_TABLE;
+import static org.jooq.impl.DDLStatementType.CREATE_VIEW;
+import static org.jooq.impl.DDLStatementType.DROP_INDEX;
+import static org.jooq.impl.DDLStatementType.DROP_SEQUENCE;
+import static org.jooq.impl.DDLStatementType.DROP_TABLE;
+import static org.jooq.impl.DDLStatementType.DROP_VIEW;
+import static org.jooq.impl.DSL.concat;
+import static org.jooq.impl.DSL.escape;
+import static org.jooq.impl.DSL.getDataType;
+import static org.jooq.impl.DSL.name;
+import static org.jooq.impl.DSL.nullSafe;
+import static org.jooq.impl.DSL.val;
+import static org.jooq.impl.DefaultExecuteContext.localConnection;
+import static org.jooq.impl.Identifiers.QUOTES;
+import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER;
+import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER_ESCAPED;
+import static org.jooq.impl.Identifiers.QUOTE_START_DELIMITER;
+import static org.jooq.tools.reflect.Reflect.accessible;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinPool.ManagedBlocker;
+import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+// ...
+import org.jooq.Attachable;
+import org.jooq.AttachableInternal;
+import org.jooq.BindContext;
+import org.jooq.Catalog;
+import org.jooq.Clause;
+import org.jooq.Condition;
+import org.jooq.Configuration;
+import org.jooq.Context;
+import org.jooq.Cursor;
+import org.jooq.DSLContext;
+import org.jooq.DataType;
+import org.jooq.ExecuteContext;
+import org.jooq.ExecuteListener;
+import org.jooq.Field;
+import org.jooq.Name;
+import org.jooq.Param;
+import org.jooq.QueryPart;
+import org.jooq.Record;
+import org.jooq.RecordType;
+import org.jooq.RenderContext;
+import org.jooq.RenderContext.CastMode;
+import org.jooq.Result;
+import org.jooq.Results;
+import org.jooq.Row;
+import org.jooq.SQLDialect;
+import org.jooq.Schema;
+import org.jooq.SelectField;
+import org.jooq.Table;
+import org.jooq.UDT;
+import org.jooq.UDTRecord;
+import org.jooq.UpdatableRecord;
+import org.jooq.conf.BackslashEscaping;
+import org.jooq.conf.Settings;
+import org.jooq.exception.DataAccessException;
+import org.jooq.exception.TooManyRowsException;
+import org.jooq.impl.Tools.Cache.CachedOperation;
+import org.jooq.tools.JooqLogger;
+import org.jooq.tools.StringUtils;
+import org.jooq.tools.jdbc.JDBCUtils;
+import org.jooq.tools.reflect.Reflect;
+import org.jooq.types.UByte;
+import org.jooq.types.UInteger;
+import org.jooq.types.ULong;
+import org.jooq.types.UShort;
+
+/**
+ * General internal jOOQ utilities
+ *
+ * @author Lukas Eder
+ */
+final class Tools {
+
+ static final JooqLogger log = JooqLogger.getLogger(Tools.class);
+
+ // ------------------------------------------------------------------------
+ // Some constants for use with Context.data()
+ // ------------------------------------------------------------------------
+
+ enum DataKey {
+
+ /**
+ * [#1537] This constant is used internally by jOOQ to omit the RETURNING
+ * clause in {@link DSLContext#batchStore(UpdatableRecord...)} calls for
+ * {@link SQLDialect#POSTGRES}.
+ */
+ DATA_OMIT_RETURNING_CLAUSE,
+
+ /**
+ * [#1905] This constant is used internally by jOOQ to indicate to
+ * subqueries that they're being rendered in the context of a row value
+ * expression predicate.
+ *
+ * This is particularly useful for H2, which pretends that ARRAYs and RVEs
+ * are the same
+ */
+ DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY,
+
+ /**
+ * [#1296] This constant is used internally by jOOQ to indicate that
+ * {@link ResultSet} rows must be locked to emulate a
+ * FOR UPDATE clause.
+ */
+ DATA_LOCK_ROWS_FOR_UPDATE,
+
+ /**
+ * [#1520] Count the number of bind values, and potentially enforce a static
+ * statement.
+ */
+ DATA_COUNT_BIND_VALUES,
+
+ /**
+ * [#1520] Enforce executing static statements.
+ *
+ * Some SQL dialects support only a limited amount of bind variables. This
+ * flag is set when static statements have too many bind variables. Known
+ * values are:
+ *
+ *
{@link SQLDialect#ASE} : 2000
+ *
{@link SQLDialect#INGRES} : 1024
+ *
{@link SQLDialect#SQLITE} : 999
+ *
{@link SQLDialect#SQLSERVER} : 2100
+ *
+ */
+ DATA_FORCE_STATIC_STATEMENT,
+
+ /**
+ * [#2665] Omit the emission of clause events by {@link QueryPart}s.
+ *
+ * Some {@link QueryPart}s may contain further {@link QueryPart}s for whom
+ * {@link Clause} emission should be avoided. For example
+ * {@link Clause#FIELD_REFERENCE} may contain a
+ * {@link Clause#TABLE_REFERENCE}.
+ */
+ DATA_OMIT_CLAUSE_EVENT_EMISSION,
+
+ /**
+ * [#2665] Wrap derived tables in parentheses.
+ *
+ * Before allowing for hooking into the SQL transformation SPI, new
+ * {@link RenderContext} instances could be created to "try" to render a
+ * given SQL subclause before inserting it into the real SQL string. This
+ * practice should no longer be pursued, as such "sub-renderers" will emit /
+ * divert {@link Clause} events.
+ */
+ DATA_WRAP_DERIVED_TABLES_IN_PARENTHESES,
+
+ /**
+ * [#2790] A locally scoped data map.
+ *
+ * Sometimes, it is useful to have some information only available while
+ * visiting QueryParts in the same context of the current subquery, e.g.
+ * when communicating between SELECT and WINDOW clauses, as is required to
+ * emulate #531.
+ */
+ DATA_LOCALLY_SCOPED_DATA_MAP,
+
+ /**
+ * [#531] The local window definitions.
+ *
+ * The window definitions declared in the WINDOW clause are
+ * needed in the SELECT clause when emulating them by inlining
+ * window specifications.
+ */
+ DATA_WINDOW_DEFINITIONS,
+
+
+
+
+
+
+
+
+
+
+
+ /**
+ * [#1629] The {@link Connection#getAutoCommit()} flag value before starting
+ * a new transaction.
+ */
+ DATA_DEFAULT_TRANSACTION_PROVIDER_AUTOCOMMIT,
+
+ /**
+ * [#1629] The {@link Connection#getAutoCommit()} flag value before starting
+ * a new transaction.
+ */
+ DATA_DEFAULT_TRANSACTION_PROVIDER_SAVEPOINTS,
+
+ /**
+ * [#1629] The {@link DefaultConnectionProvider} instance to be used during
+ * the transaction.
+ */
+ DATA_DEFAULT_TRANSACTION_PROVIDER_CONNECTION,
+
+ /**
+ * [#2080] When emulating OFFSET pagination in certain databases, synthetic
+ * aliases are generated that must be referenced also in
+ * ORDER BY clauses, in lieu of their corresponding original
+ * aliases.
+ */
+ DATA_OVERRIDE_ALIASES_IN_ORDER_BY,
+
+ /**
+ * [#2080] When emulating OFFSET pagination in certain databases, synthetic
+ * aliases are generated that must be referenced also in
+ * ORDER BY clauses, in lieu of their corresponding original
+ * aliases.
+ */
+ DATA_UNALIAS_ALIASES_IN_ORDER_BY,
+
+ /**
+ * [#3381] The table to be used for the {@link Clause#SELECT_INTO} clause.
+ */
+ DATA_SELECT_INTO_TABLE,
+
+ /**
+ * [#3381] Omit the {@link Clause#SELECT_INTO}, as it is being emulated.
+ */
+ DATA_OMIT_INTO_CLAUSE,
+
+ /**
+ * [#1658] Specify whether the trailing LIMIT clause needs to be rendered.
+ */
+ DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE,
+
+ /**
+ * [#3886] Whether a list has already been indented.
+ */
+ DATA_LIST_ALREADY_INDENTED,
+
+ /**
+ * [#3338] [#5086] Whether a constraint is being referenced (rather than
+ * declared).
+ */
+ DATA_CONSTRAINT_REFERENCE,
+
+ /**
+ * [#1206] Whether to collect Semi / Anti JOIN.
+ */
+ DATA_COLLECT_SEMI_ANTI_JOIN,
+
+ /**
+ * [#1206] The collected Semi / Anti JOIN predicates.
+ */
+ DATA_COLLECTED_SEMI_ANTI_JOIN,
+ }
+
+ /**
+ * [#2965] These are {@link ConcurrentHashMap}s containing caches for
+ * reflection information.
+ *
+ * new String() is used to allow for synchronizing on these
+ * objects.
+ */
+ static final String DATA_REFLECTION_CACHE_GET_ANNOTATED_GETTER = new String("org.jooq.configuration.reflection-cache.get-annotated-getter");
+ static final String DATA_REFLECTION_CACHE_GET_ANNOTATED_MEMBERS = new String("org.jooq.configuration.reflection-cache.get-annotated-members");
+ static final String DATA_REFLECTION_CACHE_GET_ANNOTATED_SETTERS = new String("org.jooq.configuration.reflection-cache.get-annotated-setters");
+ static final String DATA_REFLECTION_CACHE_GET_MATCHING_GETTER = new String("org.jooq.configuration.reflection-cache.get-matching-getter");
+ static final String DATA_REFLECTION_CACHE_GET_MATCHING_MEMBERS = new String("org.jooq.configuration.reflection-cache.get-matching-members");
+ static final String DATA_REFLECTION_CACHE_GET_MATCHING_SETTERS = new String("org.jooq.configuration.reflection-cache.get-matching-setters");
+ static final String DATA_REFLECTION_CACHE_HAS_COLUMN_ANNOTATIONS = new String("org.jooq.configuration.reflection-cache.has-column-annotations");
+
+ // ------------------------------------------------------------------------
+ // Other constants
+ // ------------------------------------------------------------------------
+
+ /**
+ * The default escape character for [a] LIKE [b] ESCAPE [...]
+ * clauses.
+ */
+ static final char ESCAPE = '!';
+
+ /**
+ * Indicating whether JPA (javax.persistence) is on the
+ * classpath.
+ */
+ private static Boolean isJPAAvailable;
+
+ /**
+ * [#3696] The maximum number of consumed exceptions in
+ * {@link #consumeExceptions(Configuration, PreparedStatement, SQLException)}
+ * helps prevent infinite loops and {@link OutOfMemoryError}.
+ */
+ private static int maxConsumedExceptions = 256;
+ private static int maxConsumedResults = 65536;
+
+ /**
+ * A pattern for the dash line syntax
+ */
+ private static final Pattern DASH_PATTERN = Pattern.compile("(-+)");
+
+ /**
+ * A pattern for the dash line syntax
+ */
+ private static final Pattern PLUS_PATTERN = Pattern.compile("\\+(-+)(?=\\+)");
+
+ /**
+ * All characters that are matched by Java's interpretation of \s.
+ *
+ * For a more accurate set of whitespaces, refer to
+ * http://stackoverflow.com/a/4731164/521799. In the event of SQL
+ * processing, it is probably safe to ignore most of those alternative
+ * Unicode whitespaces.
+ */
+ private static final String WHITESPACE = " \t\n\u000B\f\r";
+
+ /**
+ * Acceptable prefixes for JDBC escape syntax.
+ */
+ private static final String[] JDBC_ESCAPE_PREFIXES = {
+ "{fn ",
+ "{d ",
+ "{t ",
+ "{ts "
+ };
+
+ // ------------------------------------------------------------------------
+ // XXX: Record constructors and related methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Turn a {@link Result} into a list of {@link Row}
+ */
+ static final List rows(Result> result) {
+ List rows = new ArrayList();
+
+ for (Record record : result)
+ rows.add(record.valuesRow());
+
+ return rows;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /**
+ * Create a new record
+ */
+ static final RecordDelegate newRecord(boolean fetched, Class type) {
+ return newRecord(fetched, type, null);
+ }
+
+ /**
+ * Create a new record
+ */
+ static final RecordDelegate newRecord(boolean fetched, Class type, Field>[] fields) {
+ return newRecord(fetched, type, fields, null);
+ }
+
+ /**
+ * Create a new record
+ */
+ static final RecordDelegate newRecord(boolean fetched, Table type) {
+ return newRecord(fetched, type, null);
+ }
+
+ /**
+ * Create a new record
+ */
+ @SuppressWarnings("unchecked")
+ static final RecordDelegate newRecord(boolean fetched, Table type, Configuration configuration) {
+ return (RecordDelegate) newRecord(fetched, type.getRecordType(), type.fields(), configuration);
+ }
+
+ /**
+ * Create a new UDT record
+ */
+ static final > RecordDelegate newRecord(boolean fetched, UDT type) {
+ return newRecord(fetched, type, null);
+ }
+
+ /**
+ * Create a new UDT record
+ */
+ static final > RecordDelegate newRecord(boolean fetched, UDT type, Configuration configuration) {
+ return newRecord(fetched, type.getRecordType(), type.fields(), configuration);
+ }
+
+ /**
+ * Create a new record.
+ */
+ static final RecordDelegate newRecord(boolean fetched, Class type, Field>[] fields, Configuration configuration) {
+ return newRecord(fetched, recordFactory(type, fields), configuration);
+ }
+
+ /**
+ * Create a new record.
+ */
+ static final RecordDelegate newRecord(boolean fetched, RecordFactory factory, Configuration configuration) {
+ try {
+ R record = factory.newInstance();
+
+ // [#3300] Records that were fetched from the database
+ if (record instanceof AbstractRecord)
+ ((AbstractRecord) record).fetched = fetched;
+
+ return new RecordDelegate(configuration, record);
+ }
+ catch (Exception e) {
+ throw new IllegalStateException("Could not construct new record", e);
+ }
+ }
+
+ /**
+ * Create a new record factory.
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ static final RecordFactory recordFactory(final Class type, final Field>[] fields) {
+
+ // An ad-hoc type resulting from a JOIN or arbitrary SELECT
+ if (type == RecordImpl.class || type == Record.class) {
+ final RowImpl row = new RowImpl(fields);
+
+ return new RecordFactory() {
+ @Override
+ public R newInstance() {
+ return (R) new RecordImpl(row);
+ }
+ };
+ }
+
+ // Any generated record
+ else {
+ try {
+
+ // [#919] Allow for accessing non-public constructors
+ final Constructor constructor = Reflect.accessible(type.getDeclaredConstructor());
+
+ return new RecordFactory() {
+ @Override
+ public R newInstance() {
+ try {
+ return constructor.newInstance();
+ }
+ catch (Exception e) {
+ throw new IllegalStateException("Could not construct new record", e);
+ }
+ }
+ };
+ }
+ catch (Exception e) {
+ throw new IllegalStateException("Could not construct new record", e);
+ }
+ }
+ }
+
+ /**
+ * [#2700] [#3582] If a POJO attribute is NULL, but the column is NOT NULL
+ * then we should let the database apply DEFAULT values
+ */
+ static final void resetChangedOnNotNull(Record record) {
+ int size = record.size();
+
+ for (int i = 0; i < size; i++)
+ if (record.get(i) == null)
+ if (!record.field(i).getDataType().nullable())
+ record.changed(i, false);
+ }
+
+ /**
+ * Extract the configuration from an attachable.
+ */
+ static final Configuration getConfiguration(Attachable attachable) {
+ if (attachable instanceof AttachableInternal) {
+ return ((AttachableInternal) attachable).configuration();
+ }
+
+ return null;
+ }
+
+ /**
+ * Get an attachable's configuration or a new {@link DefaultConfiguration}
+ * if null.
+ */
+ static final Configuration configuration(Attachable attachable) {
+ return configuration(attachable instanceof AttachableInternal
+ ? ((AttachableInternal) attachable).configuration()
+ : null);
+ }
+
+ /**
+ * Get a configuration or a new {@link DefaultConfiguration} if
+ * null.
+ */
+ static final Configuration configuration(Configuration configuration) {
+ return configuration != null ? configuration : new DefaultConfiguration();
+ }
+
+ /**
+ * Get a configuration's settings or default settings if the configuration
+ * is null.
+ */
+ static final Settings settings(Attachable attachable) {
+ return configuration(attachable).settings();
+ }
+
+ /**
+ * Get a configuration's settings or default settings if the configuration
+ * is null.
+ */
+ static final Settings settings(Configuration configuration) {
+ return configuration(configuration).settings();
+ }
+
+ static final boolean attachRecords(Configuration configuration) {
+ if (configuration != null) {
+ Settings settings = configuration.settings();
+
+ if (settings != null) {
+ return !FALSE.equals(settings.isAttachRecords());
+ }
+ }
+
+ return true;
+ }
+
+ static final Field>[] fieldArray(Collection extends Field>> fields) {
+ return fields == null ? null : fields.toArray(new Field[0]);
+ }
+
+ // ------------------------------------------------------------------------
+ // XXX: Data-type related methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Useful conversion method
+ */
+ static final Class>[] types(Field>[] fields) {
+ return types(dataTypes(fields));
+ }
+
+ /**
+ * Useful conversion method
+ */
+ static final Class>[] types(DataType>[] types) {
+ if (types == null)
+ return null;
+
+ Class>[] result = new Class>[types.length];
+
+ for (int i = 0; i < types.length; i++) {
+ if (types[i] != null) {
+ result[i] = types[i].getType();
+ }
+ else {
+ result[i] = Object.class;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Useful conversion method
+ */
+ static final Class>[] types(Object[] values) {
+ if (values == null)
+ return null;
+
+ Class>[] result = new Class>[values.length];
+
+ for (int i = 0; i < values.length; i++) {
+ if (values[i] instanceof Field>) {
+ result[i] = ((Field>) values[i]).getType();
+ }
+ else if (values[i] != null) {
+ result[i] = values[i].getClass();
+ }
+ else {
+ result[i] = Object.class;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Useful conversion method
+ */
+ static final DataType>[] dataTypes(Field>[] fields) {
+ if (fields == null)
+ return null;
+
+ DataType>[] result = new DataType>[fields.length];
+
+ for (int i = 0; i < fields.length; i++) {
+ if (fields[i] != null) {
+ result[i] = fields[i].getDataType();
+ }
+ else {
+ result[i] = getDataType(Object.class);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Useful conversion method
+ */
+ static final DataType>[] dataTypes(Class>[] types) {
+ if (types == null)
+ return null;
+
+ DataType>[] result = new DataType>[types.length];
+
+ for (int i = 0; i < types.length; i++) {
+ if (types[i] != null) {
+ result[i] = getDataType(types[i]);
+ }
+ else {
+ result[i] = getDataType(Object.class);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Useful conversion method
+ */
+ static final DataType>[] dataTypes(Object[] values) {
+ return dataTypes(types(values));
+ }
+
+ // ------------------------------------------------------------------------
+ // XXX: General utility methods
+ // ------------------------------------------------------------------------
+
+ static final String[] fieldNames(int length) {
+ String[] result = new String[length];
+
+ for (int i = 0; i < length; i++)
+ result[i] = "v" + i;
+
+ return result;
+ }
+
+ static final String[] fieldNames(Field>[] fields) {
+ String[] result = new String[fields.length];
+
+ for (int i = 0; i < fields.length; i++)
+ result[i] = fields[i].getName();
+
+ return result;
+ }
+
+ static final Field>[] fields(int length) {
+ Field>[] result = new Field[length];
+ String[] names = fieldNames(length);
+
+ for (int i = 0; i < length; i++)
+ result[i] = DSL.field(name(names[i]));
+
+ return result;
+ }
+
+ static final Field>[] aliasedFields(Field>[] fields, String[] aliases) {
+ Field>[] result = new Field[fields.length];
+
+ for (int i = 0; i < fields.length; i++)
+ result[i] = fields[i].as(aliases[i]);
+
+ return result;
+ }
+
+ static final Field>[] fieldsByName(String[] fieldNames) {
+ return fieldsByName(null, fieldNames);
+ }
+
+ static final Field>[] fieldsByName(String tableName, String[] fieldNames) {
+ Field>[] result = new Field[fieldNames.length];
+
+ for (int i = 0; i < fieldNames.length; i++)
+ if (tableName == null)
+ result[i] = DSL.field(name(fieldNames[i]));
+ else
+ result[i] = DSL.field(name(tableName, fieldNames[i]));
+
+ return result;
+ }
+
+ static final Field>[] fieldsByName(Name[] names) {
+ Field>[] result = new Field[names.length];
+
+ for (int i = 0; i < names.length; i++)
+ result[i] = DSL.field(names[i]);
+
+ return result;
+ }
+
+ static final Name[] names(String[] names) {
+ Name[] result = new Name[names.length];
+
+ for (int i = 0; i < names.length; i++)
+ result[i] = DSL.name(names[i]);
+
+ return result;
+ }
+
+ private static final IllegalArgumentException fieldExpected(Object value) {
+ return new IllegalArgumentException("Cannot interpret argument of type " + value.getClass() + " as a Field: " + value);
+ }
+
+ /**
+ * Be sure that a given object is a field.
+ *
+ * @param value The argument object
+ * @return The argument object itself, if it is a {@link Field}, or a bind
+ * value created from the argument object.
+ */
+ @SuppressWarnings("unchecked")
+ static final Field field(T value) {
+
+ // Fields can be mixed with constant values
+ if (value instanceof Field>) {
+ return (Field) value;
+ }
+
+ // [#4771] Any other QueryPart type is not supported here
+ else if (value instanceof QueryPart) {
+ throw fieldExpected(value);
+ }
+ else {
+ return val(value);
+ }
+ }
+
+ // The following overloads help performance by avoiding runtime data type lookups
+ // ------------------------------------------------------------------------------
+
+ static final Param field(byte value) {
+ return val((Object) value, SQLDataType.TINYINT);
+ }
+
+ static final Param field(Byte value) {
+ return val((Object) value, SQLDataType.TINYINT);
+ }
+
+ static final Param field(UByte value) {
+ return val((Object) value, SQLDataType.TINYINTUNSIGNED);
+ }
+
+ static final Param field(short value) {
+ return val((Object) value, SQLDataType.SMALLINT);
+ }
+
+ static final Param field(Short value) {
+ return val((Object) value, SQLDataType.SMALLINT);
+ }
+
+ static final Param field(UShort value) {
+ return val((Object) value, SQLDataType.SMALLINTUNSIGNED);
+ }
+
+ static final Param field(int value) {
+ return val((Object) value, SQLDataType.INTEGER);
+ }
+
+ static final Param field(Integer value) {
+ return val((Object) value, SQLDataType.INTEGER);
+ }
+
+ static final Param field(UInteger value) {
+ return val((Object) value, SQLDataType.INTEGERUNSIGNED);
+ }
+
+ static final Param field(long value) {
+ return val((Object) value, SQLDataType.BIGINT);
+ }
+
+ static final Param field(Long value) {
+ return val((Object) value, SQLDataType.BIGINT);
+ }
+
+ static final Param field(ULong value) {
+ return val((Object) value, SQLDataType.BIGINTUNSIGNED);
+ }
+
+ static final Param field(float value) {
+ return val((Object) value, SQLDataType.REAL);
+ }
+
+ static final Param field(Float value) {
+ return val((Object) value, SQLDataType.REAL);
+ }
+
+ static final Param field(double value) {
+ return val((Object) value, SQLDataType.DOUBLE);
+ }
+
+ static final Param field(Double value) {
+ return val((Object) value, SQLDataType.DOUBLE);
+ }
+
+ static final Param field(boolean value) {
+ return val((Object) value, SQLDataType.BOOLEAN);
+ }
+
+ static final Param field(Boolean value) {
+ return val((Object) value, SQLDataType.BOOLEAN);
+ }
+
+ static final Param field(BigDecimal value) {
+ return val((Object) value, SQLDataType.DECIMAL);
+ }
+
+ static final Param field(BigInteger value) {
+ return val((Object) value, SQLDataType.DECIMAL_INTEGER);
+ }
+
+ static final Param field(byte[] value) {
+ return val((Object) value, SQLDataType.VARBINARY);
+ }
+
+ static final Param field(String value) {
+ return val((Object) value, SQLDataType.VARCHAR);
+ }
+
+ static final Param field(Date value) {
+ return val((Object) value, SQLDataType.DATE);
+ }
+
+ static final Param