/* * 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 org.jooq.SQLDialect.CUBRID; import static org.jooq.SQLDialect.DERBY; import static org.jooq.SQLDialect.FIREBIRD; 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.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.reflectionCaching; 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.DDLStatementType.ALTER_INDEX; import static org.jooq.impl.DDLStatementType.ALTER_SCHEMA; import static org.jooq.impl.DDLStatementType.ALTER_SEQUENCE; 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.jsonEntry; import static org.jooq.impl.DSL.keyword; import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.row; import static org.jooq.impl.DSL.select; 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.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_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_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_BY_DEFAULT_AS_IDENTITY; 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_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_THEN; import static org.jooq.impl.Keywords.K_THROW; import static org.jooq.impl.Keywords.K_WHEN; import static org.jooq.impl.ParserContext.SUPPORTS_HASH_COMMENT_SYNTAX; import static org.jooq.impl.SQLDataType.BLOB; import static org.jooq.impl.SQLDataType.CLOB; 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.VARCHAR; import static org.jooq.impl.SQLDataType.XML; import static org.jooq.impl.Tools.DataCacheKey.DATA_REFLECTION_CACHE_GET_ANNOTATED_GETTER; import static org.jooq.impl.Tools.DataCacheKey.DATA_REFLECTION_CACHE_GET_ANNOTATED_MEMBERS; import static org.jooq.impl.Tools.DataCacheKey.DATA_REFLECTION_CACHE_GET_ANNOTATED_SETTERS; import static org.jooq.impl.Tools.DataCacheKey.DATA_REFLECTION_CACHE_GET_MATCHING_GETTER; import static org.jooq.impl.Tools.DataCacheKey.DATA_REFLECTION_CACHE_GET_MATCHING_MEMBERS; import static org.jooq.impl.Tools.DataCacheKey.DATA_REFLECTION_CACHE_GET_MATCHING_SETTERS; import static org.jooq.impl.Tools.DataCacheKey.DATA_REFLECTION_CACHE_HAS_COLUMN_ANNOTATIONS; import static org.jooq.impl.Tools.DataKey.DATA_BLOCK_NESTING; import static org.jooq.tools.StringUtils.defaultIfNull; import java.io.Serializable; 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.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.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.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.ForeignKey; import org.jooq.JSON; import org.jooq.JSONB; import org.jooq.JSONEntry; import org.jooq.Name; import org.jooq.OrderField; import org.jooq.Param; // ... import org.jooq.QualifiedAsterisk; import org.jooq.Query; import org.jooq.QueryPart; import org.jooq.Record; import org.jooq.Record1; import org.jooq.RecordType; import org.jooq.RenderContext; import org.jooq.RenderContext.CastMode; import org.jooq.Result; import org.jooq.ResultOrRows; import org.jooq.Results; import org.jooq.Row; import org.jooq.SQLDialect; import org.jooq.Schema; import org.jooq.Scope; import org.jooq.Select; import org.jooq.SelectFieldOrAsterisk; import org.jooq.SortField; import org.jooq.Table; import org.jooq.TableField; import org.jooq.TableRecord; import org.jooq.UDT; import org.jooq.UDTRecord; import org.jooq.UpdatableRecord; import org.jooq.XML; import org.jooq.conf.BackslashEscaping; 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.MappingException; import org.jooq.exception.NoDataFoundException; import org.jooq.exception.TemplatingException; import org.jooq.exception.TooManyRowsException; 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; /** * 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 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 String[] EMPTY_STRING = {}; static final Table>[] EMPTY_TABLE = {}; 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: *
* 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,
/**
* [#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,
/**
* [#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,
/**
* [#1535] We're currently generating the window specification of a
* window function that requires an ORDER BY clause.
*/
DATA_WINDOW_FUNCTION_REQUIRES_ORDER_BY,
/**
* [#9925] In some cases the AS keyword is required for aliasing, e.g. XML.
*/
DATA_AS_REQUIRED
}
/**
* 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: *
*
*/
DATA_PREPEND_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
* -- With TVP bind variable:
* SELECT * FROM func (?)
*
* -- Inlining TVP bind variable:
* DECLARE @t TABLE_TYPE;
* INSERT INTO @t VALUES (?),(?),...,(?);
* SELECT * FROM func (@t)
* SELECT
* statement.
*/
DATA_SELECT_ALIASES
}
/**
* 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
}
/**
* [#2965] These are {@link ConcurrentHashMap}s containing caches for
* reflection information.
*
* new String() is used to allow for synchronizing on these
* objects.
*/
enum DataCacheKey {
DATA_REFLECTION_CACHE_GET_ANNOTATED_GETTER("org.jooq.configuration.reflection-cache.get-annotated-getter"),
DATA_REFLECTION_CACHE_GET_ANNOTATED_MEMBERS("org.jooq.configuration.reflection-cache.get-annotated-members"),
DATA_REFLECTION_CACHE_GET_ANNOTATED_SETTERS("org.jooq.configuration.reflection-cache.get-annotated-setters"),
DATA_REFLECTION_CACHE_GET_MATCHING_GETTER("org.jooq.configuration.reflection-cache.get-matching-getter"),
DATA_REFLECTION_CACHE_GET_MATCHING_MEMBERS("org.jooq.configuration.reflection-cache.get-matching-members"),
DATA_REFLECTION_CACHE_GET_MATCHING_SETTERS("org.jooq.configuration.reflection-cache.get-matching-setters"),
DATA_REFLECTION_CACHE_HAS_COLUMN_ANNOTATIONS("org.jooq.configuration.reflection-cache.has-column-annotations"),
DATA_CACHE_RECORD_MAPPERS("org.jooq.configuration.cache.record-mappers");
final String key;
DataCacheKey(String key) {
this.key = key;
}
}
// ------------------------------------------------------------------------
// 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 (javax.persistence) is on the
* classpath.
*/
private static volatile Boolean isJPAAvailable;
/**
* 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 maxForceSettingsAttempts = 16;
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: *
* [#7037] Known PostgreSQL Geometry operators: *
HEX_DIGITS[15] == 'f'.
*/
private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
private static final Setnull.
*/
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 null if
* no converter could be provided.
*/
static final 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