/*
* 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.lang.Boolean.TRUE;
import static java.lang.Character.isJavaIdentifierPart;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.joining;
// ...
// ...
// ...
// ...
// ...
// ...
import static org.jooq.SQLDialect.DERBY;
// ...
import static org.jooq.SQLDialect.FIREBIRD;
import static org.jooq.SQLDialect.H2;
// ...
import static org.jooq.SQLDialect.HSQLDB;
// ...
// ...
// ...
import static org.jooq.SQLDialect.MARIADB;
// ...
import static org.jooq.SQLDialect.MYSQL;
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
// ...
// ...
import static org.jooq.SQLDialect.YUGABYTEDB;
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.RenderDefaultNullability.IMPLICIT_NULL;
import static org.jooq.conf.RenderQuotedNames.EXPLICIT_DEFAULT_QUOTED;
import static org.jooq.conf.SettingsTools.getBackslashEscaping;
import static org.jooq.conf.SettingsTools.updatablePrimaryKeys;
import static org.jooq.conf.ThrowExceptions.THROW_FIRST;
import static org.jooq.conf.ThrowExceptions.THROW_NONE;
import static org.jooq.impl.CacheType.REFLECTION_CACHE_GET_ANNOTATED_GETTER;
import static org.jooq.impl.CacheType.REFLECTION_CACHE_GET_ANNOTATED_MEMBERS;
import static org.jooq.impl.CacheType.REFLECTION_CACHE_GET_ANNOTATED_SETTERS;
import static org.jooq.impl.CacheType.REFLECTION_CACHE_GET_MATCHING_GETTER;
import static org.jooq.impl.CacheType.REFLECTION_CACHE_GET_MATCHING_MEMBERS;
import static org.jooq.impl.CacheType.REFLECTION_CACHE_GET_MATCHING_SETTERS;
import static org.jooq.impl.CacheType.REFLECTION_CACHE_HAS_COLUMN_ANNOTATIONS;
import static org.jooq.impl.DDLStatementType.ALTER_SCHEMA;
import static org.jooq.impl.DDLStatementType.ALTER_TABLE;
import static org.jooq.impl.DDLStatementType.ALTER_VIEW;
import static org.jooq.impl.DDLStatementType.CREATE_DATABASE;
import static org.jooq.impl.DDLStatementType.CREATE_DOMAIN;
import static org.jooq.impl.DDLStatementType.CREATE_INDEX;
import static org.jooq.impl.DDLStatementType.CREATE_SCHEMA;
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_SCHEMA;
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.asterisk;
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.keyword;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.noCondition;
import static org.jooq.impl.DSL.row;
import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.unquotedName;
import static org.jooq.impl.DSL.val;
import static org.jooq.impl.DefaultExecuteContext.localConnection;
import static org.jooq.impl.DefaultParseContext.SUPPORTS_HASH_COMMENT_SYNTAX;
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.impl.Keywords.K_ALWAYS;
import static org.jooq.impl.Keywords.K_AS;
import static org.jooq.impl.Keywords.K_ATOMIC;
import static org.jooq.impl.Keywords.K_AUTOINCREMENT;
import static org.jooq.impl.Keywords.K_AUTO_INCREMENT;
import static org.jooq.impl.Keywords.K_BEGIN;
import static org.jooq.impl.Keywords.K_BEGIN_CATCH;
import static org.jooq.impl.Keywords.K_BEGIN_TRY;
import static org.jooq.impl.Keywords.K_BY;
import static org.jooq.impl.Keywords.K_CHARACTER_SET;
import static org.jooq.impl.Keywords.K_COLLATE;
import static org.jooq.impl.Keywords.K_DECLARE;
import static org.jooq.impl.Keywords.K_DEFAULT;
import static org.jooq.impl.Keywords.K_DO;
import static org.jooq.impl.Keywords.K_ELSE;
import static org.jooq.impl.Keywords.K_ELSIF;
import static org.jooq.impl.Keywords.K_END;
import static org.jooq.impl.Keywords.K_END_CATCH;
import static org.jooq.impl.Keywords.K_END_IF;
import static org.jooq.impl.Keywords.K_END_TRY;
import static org.jooq.impl.Keywords.K_ENUM;
import static org.jooq.impl.Keywords.K_ERROR;
import static org.jooq.impl.Keywords.K_EXCEPTION;
import static org.jooq.impl.Keywords.K_EXEC;
import static org.jooq.impl.Keywords.K_EXECUTE_BLOCK;
import static org.jooq.impl.Keywords.K_EXECUTE_IMMEDIATE;
import static org.jooq.impl.Keywords.K_EXECUTE_STATEMENT;
import static org.jooq.impl.Keywords.K_GENERATED;
import static org.jooq.impl.Keywords.K_IDENTITY;
import static org.jooq.impl.Keywords.K_IF;
import static org.jooq.impl.Keywords.K_INT;
import static org.jooq.impl.Keywords.K_LIKE;
import static org.jooq.impl.Keywords.K_NOT;
import static org.jooq.impl.Keywords.K_NOT_NULL;
import static org.jooq.impl.Keywords.K_NULL;
import static org.jooq.impl.Keywords.K_NVARCHAR;
import static org.jooq.impl.Keywords.K_PERSISTED;
import static org.jooq.impl.Keywords.K_PRIMARY_KEY;
import static org.jooq.impl.Keywords.K_RAISE;
import static org.jooq.impl.Keywords.K_RAISERROR;
import static org.jooq.impl.Keywords.K_SERIAL;
import static org.jooq.impl.Keywords.K_SERIAL4;
import static org.jooq.impl.Keywords.K_SERIAL8;
import static org.jooq.impl.Keywords.K_SQLSTATE;
import static org.jooq.impl.Keywords.K_START_WITH;
import static org.jooq.impl.Keywords.K_STORED;
import static org.jooq.impl.Keywords.K_THEN;
import static org.jooq.impl.Keywords.K_THROW;
import static org.jooq.impl.Keywords.K_VIRTUAL;
import static org.jooq.impl.Keywords.K_WHEN;
import static org.jooq.impl.QOM.GenerationOption.STORED;
import static org.jooq.impl.QOM.GenerationOption.VIRTUAL;
import static org.jooq.impl.SQLDataType.BLOB;
import static org.jooq.impl.SQLDataType.CLOB;
import static org.jooq.impl.SQLDataType.INTEGER;
import static org.jooq.impl.SQLDataType.JSON;
import static org.jooq.impl.SQLDataType.JSONB;
import static org.jooq.impl.SQLDataType.OTHER;
import static org.jooq.impl.SQLDataType.SMALLINT;
import static org.jooq.impl.SQLDataType.VARCHAR;
import static org.jooq.impl.SQLDataType.XML;
import static org.jooq.impl.Tools.DataKey.DATA_BLOCK_NESTING;
import static org.jooq.tools.StringUtils.defaultIfNull;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
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.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinPool.ManagedBlocker;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
import java.util.stream.Stream;
// ...
// ...
import org.jooq.Asterisk;
import org.jooq.Attachable;
import org.jooq.BindContext;
import org.jooq.Catalog;
import org.jooq.Check;
import org.jooq.Clause;
import org.jooq.CommonTableExpression;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.Context;
import org.jooq.Converter;
import org.jooq.ConverterProvider;
import org.jooq.Converters;
import org.jooq.Cursor;
import org.jooq.DSLContext;
import org.jooq.DataType;
import org.jooq.EmbeddableRecord;
import org.jooq.EnumType;
import org.jooq.ExecuteContext;
import org.jooq.ExecuteListener;
import org.jooq.Field;
import org.jooq.FieldOrRow;
import org.jooq.Fields;
import org.jooq.ForeignKey;
import org.jooq.JSON;
import org.jooq.JSONB;
import org.jooq.JSONEntry;
import org.jooq.JoinType;
import org.jooq.Name;
import org.jooq.OrderField;
import org.jooq.Param;
// ...
import org.jooq.QualifiedAsterisk;
import org.jooq.QualifiedRecord;
import org.jooq.Query;
import org.jooq.QueryPart;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.RecordQualifier;
import org.jooq.RenderContext;
import org.jooq.RenderContext.CastMode;
import org.jooq.Result;
import org.jooq.ResultOrRows;
import org.jooq.ResultQuery;
import org.jooq.Results;
import org.jooq.Row;
import org.jooq.SQLDialect;
import org.jooq.Schema;
import org.jooq.SchemaMapping;
import org.jooq.Scope;
import org.jooq.Select;
import org.jooq.SelectFieldOrAsterisk;
import org.jooq.SortField;
import org.jooq.Source;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.TableRecord;
import org.jooq.UDT;
import org.jooq.UpdatableRecord;
import org.jooq.WindowSpecification;
import org.jooq.XML;
import org.jooq.conf.BackslashEscaping;
import org.jooq.conf.NestedCollectionEmulation;
import org.jooq.conf.ParseNameCase;
import org.jooq.conf.RenderDefaultNullability;
import org.jooq.conf.RenderQuotedNames;
import org.jooq.conf.Settings;
import org.jooq.conf.SettingsTools;
import org.jooq.conf.ThrowExceptions;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.DataTypeException;
import org.jooq.exception.DetachedException;
import org.jooq.exception.ExceptionTools;
import org.jooq.exception.MappingException;
import org.jooq.exception.NoDataFoundException;
import org.jooq.exception.TemplatingException;
import org.jooq.exception.TooManyRowsException;
import org.jooq.impl.QOM.GenerationOption;
import org.jooq.impl.ResultsImpl.ResultOrRowsImpl;
import org.jooq.tools.Ints;
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.tools.reflect.ReflectException;
import org.jooq.types.UByte;
import org.jooq.types.UInteger;
import org.jooq.types.ULong;
import org.jooq.types.UShort;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import io.r2dbc.spi.R2dbcException;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
/**
* General internal jOOQ utilities
*
* @author Lukas Eder
*/
final class Tools {
static final JooqLogger log = JooqLogger.getLogger(Tools.class);
// ------------------------------------------------------------------------
// Empty arrays for use with Collection.toArray()
// ------------------------------------------------------------------------
static final byte[] EMPTY_BYTE = {};
static final Catalog[] EMPTY_CATALOG = {};
static final Check>[] EMPTY_CHECK = {};
static final Clause[] EMPTY_CLAUSE = {};
static final Collection>[] EMPTY_COLLECTION = {};
static final CommonTableExpression>[] EMPTY_COMMON_TABLE_EXPRESSION = {};
static final ExecuteListener[] EMPTY_EXECUTE_LISTENER = {};
static final Field>[] EMPTY_FIELD = {};
static final FieldOrRow[] EMPTY_FIELD_OR_ROW = {};
static final int[] EMPTY_INT = {};
static final JSONEntry>[] EMPTY_JSONENTRY = {};
static final Name[] EMPTY_NAME = {};
static final Object[] EMPTY_OBJECT = {};
static final Param>[] EMPTY_PARAM = {};
static final OrderField>[] EMPTY_ORDERFIELD = {};
static final Query[] EMPTY_QUERY = {};
static final QueryPart[] EMPTY_QUERYPART = {};
static final Record[] EMPTY_RECORD = {};
static final Row[] EMPTY_ROW = {};
static final Schema[] EMTPY_SCHEMA = {};
static final SortField>[] EMPTY_SORTFIELD = {};
static final Source[] EMPTY_SOURCE = {};
static final String[] EMPTY_STRING = {};
static final Table>[] EMPTY_TABLE = {};
static final TableField, ?>[] EMPTY_TABLE_FIELD = {};
static final TableRecord>[] EMPTY_TABLE_RECORD = {};
static final UpdatableRecord>[] EMPTY_UPDATABLE_RECORD = {};
// ------------------------------------------------------------------------
// Some constants for use with Context.data()
// ------------------------------------------------------------------------
/**
* Keys for {@link Configuration#data()}, which may be referenced frequently
* and represent a {@code boolean} value and are thus stored in an
* {@link EnumSet} for speedier access.
*/
enum BooleanDataKey {
/**
* [#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,
/**
* [#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#ACCESS} : 768
*
{@link SQLDialect#ASE} : 2000
*
{@link SQLDialect#INGRES} : 1024
*
{@link SQLDialect#ORACLE} : 32767
*
{@link SQLDialect#POSTGRES} : 32767
*
{@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,
/**
* [#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.
*/
DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY,
/**
* [#2744] Currently rendering the data change delta table syntax.
*
* In some dialects, a FINAL TABLE (INSERT ...) clause exists, which
* corresponds to the PostgreSQL INSERT .. RETURNING clause.
*/
DATA_RENDERING_DATA_CHANGE_DELTA_TABLE,
/**
* [#1629] The {@link Connection#getAutoCommit()} flag value before starting
* a new transaction.
*/
DATA_DEFAULT_TRANSACTION_PROVIDER_AUTOCOMMIT,
/**
* [#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.
* [#8898] Oracle doesn't support aliases in RETURNING clauses.
*/
DATA_UNALIAS_ALIASED_EXPRESSIONS,
/**
* [#7139] No data must be selected in the SELECT statement.
*/
DATA_SELECT_NO_DATA,
/**
* [#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,
/**
* [#11486] An INSERT .. SELECT statement.
*/
DATA_INSERT_SELECT,
/**
* [#2995] An INSERT INTO t SELECT statement. Without any
* explicit column list, the SELECT statement must not be
* wrapped in parentheses (which would be interpreted as the column
* list's parentheses).
*/
DATA_INSERT_SELECT_WITHOUT_INSERT_COLUMN_LIST,
/**
* [#3579] [#6431] [#7222] There are nested set operations in the current
* {@link Select} scope.
*/
DATA_NESTED_SET_OPERATIONS,
/**
* [#5191] Whether INSERT RETURNING is being emulated for bulk insertions.
*/
DATA_EMULATE_BULK_INSERT_RETURNING,
/**
* [#9925] In some cases the AS keyword is required for
* aliasing, e.g. XML.
*/
DATA_AS_REQUIRED,
/**
* [#12030] MULTISET conditions need to render the MULTISET emulation
* differently to implement MULTISET semantics (ORDER agnostic)
*/
DATA_MULTISET_CONDITION,
/**
* [#12021] MULTISET content may need to be rendered differently (e.g.
* nested ROW types).
*/
DATA_MULTISET_CONTENT,
/**
* [#12072] In some cases, it's recommended to generate an explicit
* ELSE NULL clause in a CASE expression.
*/
DATA_FORCE_CASE_ELSE_NULL,
/**
* [#12092] Whether the @@group_concat_max_len value has already been
* set.
*/
DATA_GROUP_CONCAT_MAX_LEN_SET,
/**
* [#11543] Whether the @@innodb_lock_wait_timeout value has already
* been set.
*/
DATA_LOCK_WAIT_TIMEOUT_SET
}
/**
* Keys for {@link Configuration#data()}, which may be referenced frequently
* and are thus stored in an {@link EnumMap} for speedier access.
*/
enum DataKey {
/**
* The level of anonymous block nesting, in case we're generating a block.
*/
DATA_BLOCK_NESTING,
/**
* [#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_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,
/**
* [#3381] The table to be used for the {@link Clause#SELECT_INTO} clause.
*/
DATA_SELECT_INTO_TABLE,
/**
* [#1206] The collected Semi / Anti JOIN predicates.
*/
DATA_COLLECTED_SEMI_ANTI_JOIN,
/**
* [#5764] Sometimes, it is necessary to prepend some SQL to the
* generated SQL.
*
* This needs to be done e.g. to emulate inline table valued parameters
* in SQL Server:
*
*
* -- With TVP bind variable:
* SELECT * FROM func (?)
*
* -- Inlining TVP bind variable:
* DECLARE @t TABLE_TYPE;
* INSERT INTO @t VALUES (?),(?),...,(?);
* SELECT * FROM func (@t)
*
*/
DATA_PREPEND_SQL,
/**
* [#12092] Sometimes, it is necessary to append some SQL to the
* generated SQL.
*
* This needs to be done e.g. to make sure the
* MySQL @@group_concat_max_len setting is set to an appropriate value,
* and reset to the previous value again.
*
*
* SET @t = @@group_concat_max_len;
* SET @@group_concat_max_len = 4294967295;
* SELECT group_concat(...);
* SET @@group_concat_max_len = @t;
*
*/
DATA_APPEND_SQL,
/**
* [#6583] The target table on which a DML operation operates on.
*/
DATA_DML_TARGET_TABLE,
/**
* [#8479] There is a WHERE clause to be emulated for ON DUPLICATE KEY
*/
DATA_ON_DUPLICATE_KEY_WHERE,
/**
* [#3607] [#8522] CTEs that need to be added to the top level CTE
* section.
*/
DATA_TOP_LEVEL_CTE,
/**
* [#10540] Aliases to be applied to the current SELECT
* statement.
*/
DATA_SELECT_ALIASES,
/**
* [#8917] An internal schema mapping that overrides any user-defined
* schema mappings.
*/
DATA_SCHEMA_MAPPING,
}
/**
* Keys for {@link Configuration#data()}, which may be referenced very
* infrequently and are thus stored in an ordinary {@link HashMap} for a
* more optimal memory layout.
*/
enum DataExtendedKey {
/**
* [#9017] We've already transformed ROWNUM expressions to LIMIT.
*/
DATA_TRANSFORM_ROWNUM_TO_LIMIT,
/**
* [#1535] [#11851] The window function object that uses a
* {@link WindowSpecification}.
*/
DATA_WINDOW_FUNCTION,
}
// ------------------------------------------------------------------------
// Other constants
// ------------------------------------------------------------------------
/**
* The default escape character for [a] LIKE [b] ESCAPE [...]
* clauses.
*/
static final char ESCAPE = '!';
/**
* A lock for the initialisation of other static members
*/
private static final Object initLock = new Object();
/**
* Indicating whether JPA (jakarta.persistence) is on the
* classpath.
*/
private static volatile JPANamespace jpaNamespace;
/**
* Indicating whether Kotlin (kotlin.*) is on the classpath.
*/
private static volatile Boolean isKotlinAvailable;
private static volatile Reflect ktJvmClassMapping;
private static volatile Reflect ktKClasses;
private static volatile Reflect ktKClass;
private static volatile Reflect ktKTypeParameter;
/**
* [#3696] The maximum number of consumed exceptions in
* {@link #consumeExceptions(Configuration, PreparedStatement, SQLException)}
* helps prevent infinite loops and {@link OutOfMemoryError}.
*/
static int maxConsumedExceptions = 256;
static int maxConsumedResults = 65536;
/**
* A pattern for the dash line syntax
*/
private static final Pattern DASH_PATTERN = Pattern.compile("(-+)");
/**
* A pattern for the pipe line syntax
*/
private static final Pattern PIPE_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 char[] WHITESPACE_CHARACTERS = " \t\n\u000B\f\r".toCharArray();
/**
* Acceptable prefixes for JDBC escape syntax.
*/
private static final char[][] JDBC_ESCAPE_PREFIXES = {
"{fn ".toCharArray(),
"{d ".toCharArray(),
"{t ".toCharArray(),
"{ts ".toCharArray()
};
private static final char[] TOKEN_SINGLE_LINE_COMMENT = { '-', '-' };
private static final char[] TOKEN_SINGLE_LINE_COMMENT_C = { '/', '/' };
private static final char[] TOKEN_HASH = { '#' };
private static final char[] TOKEN_MULTI_LINE_COMMENT_OPEN = { '/', '*' };
private static final char[] TOKEN_MULTI_LINE_COMMENT_CLOSE = { '*', '/' };
private static final char[] TOKEN_APOS = { '\'' };
private static final char[] TOKEN_ESCAPED_APOS = { '\'', '\'' };
/**
* "Suffixes" that are placed behind a "?" character to form an operator,
* rather than a JDBC bind variable. This is particularly useful to prevent
* parsing PostgreSQL operators as bind variables, as can be seen here:
* https://www.postgresql.org/docs/current/static/functions-json.html,
* https://www.postgresql.org/docs/current/static/ltree.html,
* https://www.postgresql.org/docs/current/static/functions-geometry.html.
*
* [#5307] Known PostgreSQL JSON operators:
*
*
?|
*
?&
*
*
* [#7035] Known PostgreSQL LTREE operators:
*
*
? (we cannot handle this one)
*
?@>
*
?<@
*
?~
*
?@
*
*
* [#7037] Known PostgreSQL Geometry operators:
*
*
?#
*
?-
*
?|
*
*/
private static final char[][] NON_BIND_VARIABLE_SUFFIXES = {
{ '?' },
{ '|' },
{ '&' },
{ '@' },
{ '<' },
{ '~' },
{ '#' },
{ '-' }
};
/**
* "Suffixes" that are placed behind a "?" character to form a JDBC bind
* variable, rather than an operator.
*
* [#11442] The above NON_BIND_VARIABLE_SUFFIXES leads to false positives,
* such as "?<>", which is a non-equality operator, not
* an operator on its own.
*/
private static final char[][] BIND_VARIABLE_SUFFIXES = {
{ '<', '>' }
};
/**
* All hexadecimal digits accessible through array index, e.g.
* HEX_DIGITS[15] == 'f'.
*/
private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
private static final byte[] HEX_LOOKUP = {
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
/* 0x40 */ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static final Set REQUIRES_BACKSLASH_ESCAPING = SQLDialect.supportedBy(MARIADB, MYSQL);
static final Set NO_SUPPORT_NULL = SQLDialect.supportedBy(DERBY, FIREBIRD, HSQLDB);
static final Set NO_SUPPORT_BINARY_TYPE_LENGTH = SQLDialect.supportedBy(POSTGRES, YUGABYTEDB);
static final Set NO_SUPPORT_CAST_TYPE_IN_DDL = SQLDialect.supportedBy(MARIADB, MYSQL);
static final Set SUPPORT_NON_BIND_VARIABLE_SUFFIXES = SQLDialect.supportedBy(POSTGRES, YUGABYTEDB);
static final Set SUPPORT_POSTGRES_LITERALS = SQLDialect.supportedBy(POSTGRES, YUGABYTEDB);
static final Set DEFAULT_BEFORE_NULL = SQLDialect.supportedBy(FIREBIRD, HSQLDB);
static final Set NO_SUPPORT_TIMESTAMP_PRECISION = SQLDialect.supportedBy(DERBY);
static final Set DEFAULT_TIMESTAMP_NOT_NULL = SQLDialect.supportedBy(MARIADB);
// ------------------------------------------------------------------------
// XXX: Record constructors and related methods
// ------------------------------------------------------------------------
/**
* Turn a {@link Result} into a list of {@link Row}
*/
static final List rows(Result> result) {
return map(result, r -> r.valuesRow());
}
/**
* 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, AbstractRow fields) {
return newRecord(fetched, type, fields, null);
}
/**
* Create a new {@link Table} or {@link UDT} record.
*/
static final RecordDelegate newRecord(boolean fetched, RecordQualifier type) {
return newRecord(fetched, type, null);
}
/**
* Create a new {@link Table} or {@link UDT} record.
*/
static final RecordDelegate newRecord(boolean fetched, RecordQualifier type, Configuration configuration) {
return newRecord(fetched, type.getRecordType(), (AbstractRow) type.fieldsRow(), configuration);
}
/**
* Create a new record.
*/
static final RecordDelegate newRecord(boolean fetched, Class extends R> type, AbstractRow extends R> fields, Configuration configuration) {
return newRecord(fetched, recordFactory(type, fields), configuration);
}
/**
* Create a new record.
*/
static final RecordDelegate newRecord(boolean fetched, Supplier factory, Configuration configuration) {
return new RecordDelegate<>(configuration, factory, fetched);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
static final AbstractRow row0(FieldsImpl fields) {
switch (fields.size()) {
case 1: return new RowImpl1(fields);
case 2: return new RowImpl2(fields);
case 3: return new RowImpl3(fields);
case 4: return new RowImpl4(fields);
case 5: return new RowImpl5(fields);
case 6: return new RowImpl6(fields);
case 7: return new RowImpl7(fields);
case 8: return new RowImpl8(fields);
case 9: return new RowImpl9(fields);
case 10: return new RowImpl10(fields);
case 11: return new RowImpl11(fields);
case 12: return new RowImpl12(fields);
case 13: return new RowImpl13(fields);
case 14: return new RowImpl14(fields);
case 15: return new RowImpl15(fields);
case 16: return new RowImpl16(fields);
case 17: return new RowImpl17(fields);
case 18: return new RowImpl18(fields);
case 19: return new RowImpl19(fields);
case 20: return new RowImpl20(fields);
case 21: return new RowImpl21(fields);
case 22: return new RowImpl22(fields);
default: return (AbstractRow) new RowImplN(fields);
}
}
static final AbstractRow> row0(Collection extends Field>> fields) {
return row0(fields.toArray(EMPTY_FIELD));
}
static final AbstractRow> row0(Field>... fields) {
return row0(new FieldsImpl<>(fields));
}
static final Class extends AbstractRecord> recordType(int length) {
switch (length) {
case 1: return RecordImpl1.class;
case 2: return RecordImpl2.class;
case 3: return RecordImpl3.class;
case 4: return RecordImpl4.class;
case 5: return RecordImpl5.class;
case 6: return RecordImpl6.class;
case 7: return RecordImpl7.class;
case 8: return RecordImpl8.class;
case 9: return RecordImpl9.class;
case 10: return RecordImpl10.class;
case 11: return RecordImpl11.class;
case 12: return RecordImpl12.class;
case 13: return RecordImpl13.class;
case 14: return RecordImpl14.class;
case 15: return RecordImpl15.class;
case 16: return RecordImpl16.class;
case 17: return RecordImpl17.class;
case 18: return RecordImpl18.class;
case 19: return RecordImpl19.class;
case 20: return RecordImpl20.class;
case 21: return RecordImpl21.class;
case 22: return RecordImpl22.class;
default: return RecordImplN.class;
}
}
/**
* Create a new record factory.
*/
@SuppressWarnings({ "unchecked" })
static final Supplier recordFactory(Class extends R> type, AbstractRow extends R> row) {
// An ad-hoc type resulting from a JOIN or arbitrary SELECT
if (type == AbstractRecord.class || type == Record.class || InternalRecord.class.isAssignableFrom(type)) {
switch (row.size()) {
case 1: return () -> (R) new RecordImpl1<>(row);
case 2: return () -> (R) new RecordImpl2<>(row);
case 3: return () -> (R) new RecordImpl3<>(row);
case 4: return () -> (R) new RecordImpl4<>(row);
case 5: return () -> (R) new RecordImpl5<>(row);
case 6: return () -> (R) new RecordImpl6<>(row);
case 7: return () -> (R) new RecordImpl7<>(row);
case 8: return () -> (R) new RecordImpl8<>(row);
case 9: return () -> (R) new RecordImpl9<>(row);
case 10: return () -> (R) new RecordImpl10<>(row);
case 11: return () -> (R) new RecordImpl11<>(row);
case 12: return () -> (R) new RecordImpl12<>(row);
case 13: return () -> (R) new RecordImpl13<>(row);
case 14: return () -> (R) new RecordImpl14<>(row);
case 15: return () -> (R) new RecordImpl15<>(row);
case 16: return () -> (R) new RecordImpl16<>(row);
case 17: return () -> (R) new RecordImpl17<>(row);
case 18: return () -> (R) new RecordImpl18<>(row);
case 19: return () -> (R) new RecordImpl19<>(row);
case 20: return () -> (R) new RecordImpl20<>(row);
case 21: return () -> (R) new RecordImpl21<>(row);
case 22: return () -> (R) new RecordImpl22<>(row);
default: return () -> (R) new RecordImplN(row);
}
}
// Any generated record
else {
try {
// [#919] Allow for accessing non-public constructors
final Constructor extends R> constructor = Reflect.accessible(type.getDeclaredConstructor());
return () -> {
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);
}
/**
* Get an attachable's configuration or a new {@link DefaultConfiguration}
* if null.
*/
static final Configuration configurationOrThrow(Attachable attachable) {
if (attachable.configuration() == null)
throw new DetachedException("No configuration attached: " + attachable);
else
return configuration(attachable.configuration());
}
/**
* Get an attachable's configuration or a new {@link DefaultConfiguration}
* if null.
*/
static final Configuration configuration(Attachable attachable) {
return configuration(attachable.configuration());
}
/**
* 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 or a new {@link DefaultConfiguration} if
* null.
*/
static final Configuration configuration(Scope scope) {
return configuration(scope != null ? scope.configuration() : null);
}
/**
* Get a converter from a {@link ConverterProvider} or null if
* no converter could be provided.
*/
static final Converter converter(Configuration configuration, T instance, Class tType, Class uType) {
Converter result = configuration(configuration).converterProvider().provide(tType, uType);
if (result == null)
result = CTX.configuration().converterProvider().provide(tType, uType);
// [#11823] [#12208] The new ad-hoc conversion API tries to avoid the Class literal
// meaning there are perfectly reasonable API usages when using MULTISET
// where we can't decide on a converter prior to having an actual result
// type - so, let's try again if we have the result value.
if (result == null && tType == Converters.UnknownType.class)
result = converter(configuration, instance, (Class) (instance == null ? Object.class : instance.getClass()), uType);
return result;
}
/**
* Get a converter from a {@link ConverterProvider} or null if
* no converter could be provided.
*/
static final Converter converterOrFail(Configuration configuration, T instance, Class tType, Class uType) {
Converter result = converter(configuration, instance, tType, uType);
if (result == null)
throw new DataTypeException("No Converter found for types " + tType.getName() + " and " + uType.getName());
return result;
}
/**
* Get a converter from a {@link ConverterProvider}.
*/
static final Converter converterOrFail(Attachable attachable, T instance, Class tType, Class uType) {
return converterOrFail(configuration(attachable), instance, tType, uType);
}
/**
* 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 T attach(Attachable attachable, Configuration configuration, Supplier supplier) {
Configuration previous = attachable.configuration();
try {
attachable.attach(configuration);
return supplier.get();
}
finally {
attachable.attach(previous);
}
}
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(EMPTY_FIELD);
}
// ------------------------------------------------------------------------
// XXX: Data-type related methods
// ------------------------------------------------------------------------
static final DataType>[] dataTypes(Class>[] types) {
return map(types, t -> t != null ? getDataType(t) : getDataType(Object.class), DataType[]::new);
}
// ------------------------------------------------------------------------
// XXX: General utility methods
// ------------------------------------------------------------------------
private static final int FIELD_NAME_CACHE_SIZE = 128;
private static final String[] FIELD_NAME_STRINGS;
private static final Name[] FIELD_NAMES;
static {
FIELD_NAME_STRINGS = IntStream.range(0, FIELD_NAME_CACHE_SIZE).mapToObj(Tools::fieldNameString0).toArray(String[]::new);
FIELD_NAMES = IntStream.range(0, FIELD_NAME_CACHE_SIZE).mapToObj(i -> name(FIELD_NAME_STRINGS[i])).toArray(Name[]::new);
}
static final SortField sortField(OrderField field) {
if (field instanceof SortField)
return (SortField) field;
else if (field instanceof Field)
return ((Field) field).sortDefault();
else
throw new IllegalArgumentException("Field not supported : " + field);
}
static final SortField>[] sortFields(OrderField>[] fields) {
if (fields instanceof SortField[])
return (SortField>[]) fields;
else
return map(fields, o -> sortField(o), SortField[]::new);
}
static final List> sortFields(Collection extends OrderField>> fields) {
return Tools.map(fields, (OrderField> o) -> sortField(o));
}
private static final String fieldNameString0(int index) {
return "v" + index;
}
static final String fieldNameString(int index) {
return index < FIELD_NAME_CACHE_SIZE ? FIELD_NAME_STRINGS[index] : fieldNameString0(index);
}
static final Name fieldName(int index) {
return index < FIELD_NAME_CACHE_SIZE ? FIELD_NAMES[index] : name(fieldNameString0(index));
}
static final Name[] fieldNames(int length) {
Name[] result = new Name[length];
for (int i = 0; i < length; i++)
result[i] = fieldName(i);
return result;
}
static final String[] fieldNameStrings(int length) {
String[] result = new String[length];
for (int i = 0; i < length; i++)
result[i] = fieldNameString(i);
return result;
}
static final Field>[] fields(int length) {
return fields(length, SQLDataType.OTHER);
}
@SuppressWarnings("unchecked")
static final Field[] fields(int length, DataType type) {
Field[] result = new Field[length];
for (int i = 0; i < length; i++)
result[i] = DSL.field(fieldName(i), type);
return result;
}
static final Field unqualified(Field field) {
return DSL.field(field.getUnqualifiedName(), field.getDataType());
}
static final SortField unqualified(SortField field) {
SortFieldImpl i = (SortFieldImpl) field;
return i.transform(unqualified(i.getField()));
}
static final List> unaliasedFields(Collection extends Field>> fields) {
return map(fields, (f, i) -> DSL.field(fieldName(i), f.getDataType()).as(f));
}
static final ReferenceImpl aliasedKey(ForeignKey key, Table child, Table parent) {
// [#10603] [#5050] TODO: Solve aliasing constraints more generically
// [#8762] We can't dereference child.fields() or parent.fields() here yet, because this method is being called by
// the TableImpl constructor, meaning the fields are not initialised yet.
return new ReferenceImpl<>(
child,
key.getQualifiedName(),
Tools.fieldsByName(child, key.getFieldsArray()),
key.getKey(),
Tools.fieldsByName(parent, key.getKeyFieldsArray()),
key.enforced()
);
}
static final List> aliasedFields(Collection extends Field>> fields) {
return map(fields, (f, i) -> f.as(fieldName(i)));
}
static final Field>[] fieldsByName(String[] fieldNames) {
return fieldsByName(null, fieldNames);
}
static final Field>[] fieldsByName(Name tableName, int length) {
Field>[] result = new Field[length];
if (tableName == null)
for (int i = 0; i < length; i++)
result[i] = DSL.field(fieldName(i));
else
for (int i = 0; i < length; i++)
result[i] = DSL.field(name(tableName, fieldName(i)));
return result;
}
@SuppressWarnings("unchecked")
static final TableField[] fieldsByName(Table tableName, Field>[] fieldNames) {
if (tableName == null)
return map(fieldNames, n -> (TableField) DSL.field(n.getUnqualifiedName(), n.getDataType()), TableField[]::new);
else
return map(fieldNames, n -> (TableField) DSL.field(tableName.getQualifiedName().append(n.getUnqualifiedName()), n.getDataType()), TableField[]::new);
}
static final Field>[] fieldsByName(Name tableName, Name[] fieldNames) {
if (tableName == null)
return map(fieldNames, n -> DSL.field(n), Field[]::new);
else
return map(fieldNames, n -> DSL.field(name(tableName, n)), Field[]::new);
}
static final Field>[] fieldsByName(String tableName, String[] fieldNames) {
if (StringUtils.isEmpty(tableName))
return map(fieldNames, n -> DSL.field(name(n)), Field[]::new);
else
return map(fieldNames, n -> DSL.field(name(tableName, n)), Field[]::new);
}
static final Field>[] fieldsByName(Name[] names) {
return map(names, n -> DSL.field(n), Field[]::new);
}
static final Name[] names(String[] names) {
return map(names, n -> DSL.name(n), Name[]::new);
}
static final List names(Collection> names) {
return map(names, n -> n instanceof Name ? (Name) n : DSL.name(String.valueOf(n)));
}
static final List> jsonEntries(Field>[] entries) {
return Tools.map(entries, f -> DSL.jsonEntry(f));
}
private static final IllegalArgumentException fieldExpected(Object value) {
return new IllegalArgumentException("Cannot interpret argument of type " + value.getClass() + " as a Field: " + value);
}
/**
* [#461] [#473] [#2597] [#8234] Some internals need a cast only if necessary.
*/
@SuppressWarnings("unchecked")
static final Field[] castAllIfNeeded(Field>[] fields, Class type) {
Field[] castFields = new Field[fields.length];
for (int i = 0; i < fields.length; i++)
castFields[i] = castIfNeeded(fields[i], type);
return castFields;
}
/**
* [#461] [#473] [#2597] [#8234] Some internals need a cast only if necessary.
*/
@SuppressWarnings("unchecked")
static final Field castIfNeeded(Field> field, Class type) {
if (field.getType().equals(type))
return (Field) field;
else
return field.cast(type);
}
/**
* [#461] [#473] [#2597] [#8234] Some internals need a cast only if necessary.
*/
@SuppressWarnings("unchecked")
static final Field castIfNeeded(Field> field, DataType type) {
if (field.getDataType().equals(type))
return (Field) field;
else
return field.cast(type);
}
/**
* [#461] [#473] [#2597] [#8234] Some internals need a cast only if necessary.
*/
@SuppressWarnings("unchecked")
static final Field castIfNeeded(Field> field, Field type) {
if (field.getDataType().equals(type.getDataType()))
return (Field) field;
else
return field.cast(type);
}
/**
* 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;
// [#6362] [#8220] Single-column selects can be considered fields, too
else if (value instanceof Select && Tools.degree((Select>) value) == 1)
return DSL.field((Select>) 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