mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-28 06:49:09 +00:00
some cleanups in OracleDialect
This commit is contained in:
parent
81851dc985
commit
33fec62a56
@ -48,7 +48,6 @@
|
|||||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||||
import org.hibernate.boot.model.relational.Sequence;
|
import org.hibernate.boot.model.relational.Sequence;
|
||||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.dialect.aggregate.AggregateSupport;
|
import org.hibernate.dialect.aggregate.AggregateSupport;
|
||||||
import org.hibernate.dialect.aggregate.AggregateSupportImpl;
|
import org.hibernate.dialect.aggregate.AggregateSupportImpl;
|
||||||
import org.hibernate.dialect.function.CastFunction;
|
import org.hibernate.dialect.function.CastFunction;
|
||||||
@ -192,6 +191,9 @@
|
|||||||
|
|
||||||
import static java.lang.Math.ceil;
|
import static java.lang.Math.ceil;
|
||||||
import static java.lang.Math.log;
|
import static java.lang.Math.log;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.NON_CONTEXTUAL_LOB_CREATION;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.STATEMENT_BATCH_SIZE;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.USE_GET_GENERATED_KEYS;
|
||||||
import static org.hibernate.internal.util.StringHelper.parseCommaSeparatedString;
|
import static org.hibernate.internal.util.StringHelper.parseCommaSeparatedString;
|
||||||
import static org.hibernate.type.SqlTypes.ARRAY;
|
import static org.hibernate.type.SqlTypes.ARRAY;
|
||||||
import static org.hibernate.type.SqlTypes.BIGINT;
|
import static org.hibernate.type.SqlTypes.BIGINT;
|
||||||
@ -345,11 +347,11 @@ protected void checkVersion() {
|
|||||||
* Set appropriate default values for configuration properties.
|
* Set appropriate default values for configuration properties.
|
||||||
*/
|
*/
|
||||||
protected void initDefaultProperties() {
|
protected void initDefaultProperties() {
|
||||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE,
|
getDefaultProperties().setProperty( STATEMENT_BATCH_SIZE,
|
||||||
Integer.toString( getDefaultStatementBatchSize() ) );
|
Integer.toString( getDefaultStatementBatchSize() ) );
|
||||||
getDefaultProperties().setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION,
|
getDefaultProperties().setProperty( NON_CONTEXTUAL_LOB_CREATION,
|
||||||
Boolean.toString( getDefaultNonContextualLobCreation() ) );
|
Boolean.toString( getDefaultNonContextualLobCreation() ) );
|
||||||
getDefaultProperties().setProperty( Environment.USE_GET_GENERATED_KEYS,
|
getDefaultProperties().setProperty( USE_GET_GENERATED_KEYS,
|
||||||
Boolean.toString( getDefaultUseGetGeneratedKeys() ) );
|
Boolean.toString( getDefaultUseGetGeneratedKeys() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1388,7 +1390,7 @@ public final Properties getDefaultProperties() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The default value to use for the configuration property
|
* The default value to use for the configuration property
|
||||||
* {@value Environment#STATEMENT_BATCH_SIZE}.
|
* {@value org.hibernate.cfg.Environment#STATEMENT_BATCH_SIZE}.
|
||||||
*/
|
*/
|
||||||
public int getDefaultStatementBatchSize() {
|
public int getDefaultStatementBatchSize() {
|
||||||
return 1;
|
return 1;
|
||||||
@ -1396,7 +1398,7 @@ public int getDefaultStatementBatchSize() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The default value to use for the configuration property
|
* The default value to use for the configuration property
|
||||||
* {@value Environment#NON_CONTEXTUAL_LOB_CREATION}.
|
* {@value org.hibernate.cfg.Environment#NON_CONTEXTUAL_LOB_CREATION}.
|
||||||
*/
|
*/
|
||||||
public boolean getDefaultNonContextualLobCreation() {
|
public boolean getDefaultNonContextualLobCreation() {
|
||||||
return false;
|
return false;
|
||||||
@ -1404,7 +1406,7 @@ public boolean getDefaultNonContextualLobCreation() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The default value to use for the configuration property
|
* The default value to use for the configuration property
|
||||||
* {@value Environment#USE_GET_GENERATED_KEYS}.
|
* {@value org.hibernate.cfg.Environment#USE_GET_GENERATED_KEYS}.
|
||||||
*/
|
*/
|
||||||
public boolean getDefaultUseGetGeneratedKeys() {
|
public boolean getDefaultUseGetGeneratedKeys() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -11,14 +11,12 @@
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.QueryTimeoutException;
|
import org.hibernate.QueryTimeoutException;
|
||||||
import org.hibernate.boot.model.TypeContributions;
|
import org.hibernate.boot.model.TypeContributions;
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.dialect.aggregate.AggregateSupport;
|
import org.hibernate.dialect.aggregate.AggregateSupport;
|
||||||
import org.hibernate.dialect.aggregate.OracleAggregateSupport;
|
import org.hibernate.dialect.aggregate.OracleAggregateSupport;
|
||||||
import org.hibernate.dialect.function.CommonFunctionFactory;
|
import org.hibernate.dialect.function.CommonFunctionFactory;
|
||||||
@ -47,7 +45,6 @@
|
|||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||||
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
||||||
@ -91,7 +88,10 @@
|
|||||||
|
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
|
|
||||||
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.BATCH_VERSIONED_DATA;
|
||||||
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
|
||||||
|
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||||
import static org.hibernate.query.sqm.TemporalUnit.DAY;
|
import static org.hibernate.query.sqm.TemporalUnit.DAY;
|
||||||
import static org.hibernate.query.sqm.TemporalUnit.HOUR;
|
import static org.hibernate.query.sqm.TemporalUnit.HOUR;
|
||||||
import static org.hibernate.query.sqm.TemporalUnit.MINUTE;
|
import static org.hibernate.query.sqm.TemporalUnit.MINUTE;
|
||||||
@ -128,11 +128,14 @@
|
|||||||
*/
|
*/
|
||||||
public class OracleDialect extends Dialect {
|
public class OracleDialect extends Dialect {
|
||||||
|
|
||||||
private static final Pattern DISTINCT_KEYWORD_PATTERN = Pattern.compile( "\\bdistinct\\b" );
|
private static final Pattern DISTINCT_KEYWORD_PATTERN = Pattern.compile( "\\bdistinct\\b", CASE_INSENSITIVE );
|
||||||
private static final Pattern GROUP_BY_KEYWORD_PATTERN = Pattern.compile( "\\bgroup\\sby\\b" );
|
private static final Pattern GROUP_BY_KEYWORD_PATTERN = Pattern.compile( "\\bgroup\\s+by\\b", CASE_INSENSITIVE );
|
||||||
private static final Pattern ORDER_BY_KEYWORD_PATTERN = Pattern.compile( "\\border\\sby\\b" );
|
private static final Pattern ORDER_BY_KEYWORD_PATTERN = Pattern.compile( "\\border\\s+by\\b", CASE_INSENSITIVE );
|
||||||
private static final Pattern UNION_KEYWORD_PATTERN = Pattern.compile( "\\bunion\\b" );
|
private static final Pattern UNION_KEYWORD_PATTERN = Pattern.compile( "\\bunion\\b", CASE_INSENSITIVE );
|
||||||
private static final Pattern SQL_STATEMENT_TYPE_PATTERN = Pattern.compile("^(?:/\\*.*?\\*/)?\\s*(select|insert|update|delete)\\s+.*?", Pattern.CASE_INSENSITIVE);
|
|
||||||
|
private static final Pattern SQL_STATEMENT_TYPE_PATTERN =
|
||||||
|
Pattern.compile( "^(?:/\\*.*?\\*/)?\\s*(select|insert|update|delete)\\s+.*?", CASE_INSENSITIVE );
|
||||||
|
|
||||||
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
|
private static final int PARAM_LIST_SIZE_LIMIT = 1000;
|
||||||
|
|
||||||
public static final String PREFER_LONG_RAW = "hibernate.dialect.oracle.prefer_long_raw";
|
public static final String PREFER_LONG_RAW = "hibernate.dialect.oracle.prefer_long_raw";
|
||||||
@ -683,7 +686,8 @@ public TimeZoneSupport getTimeZoneSupport() {
|
|||||||
@Override
|
@Override
|
||||||
protected void initDefaultProperties() {
|
protected void initDefaultProperties() {
|
||||||
super.initDefaultProperties();
|
super.initDefaultProperties();
|
||||||
getDefaultProperties().setProperty( Environment.BATCH_VERSIONED_DATA, Boolean.toString( getVersion().isSameOrAfter( 12 ) ) );
|
getDefaultProperties().setProperty( BATCH_VERSIONED_DATA,
|
||||||
|
Boolean.toString( getVersion().isSameOrAfter( 12 ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1066,50 +1070,35 @@ public String getTemporaryTableCreateOptions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For Oracle, the FOR UPDATE clause cannot be applied when using ORDER BY, DISTINCT or views.
|
* The {@code FOR UPDATE} clause cannot be applied when using {@code ORDER BY}, {@code DISTINCT} or views.
|
||||||
*
|
*
|
||||||
* @see <a href="https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#SQLRF01702">Oracle FOR UPDATE restrictions</a>
|
* @see <a href="https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/SELECT.html">Oracle FOR UPDATE restrictions</a>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean useFollowOnLocking(String sql, QueryOptions queryOptions) {
|
public boolean useFollowOnLocking(String sql, QueryOptions queryOptions) {
|
||||||
if ( StringHelper.isEmpty( sql ) || queryOptions == null ) {
|
if ( isEmpty( sql ) || queryOptions == null ) {
|
||||||
|
// ugh, used by DialectFeatureChecks (gotta be a better way)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sql = sql.toLowerCase( Locale.ROOT );
|
|
||||||
|
|
||||||
return DISTINCT_KEYWORD_PATTERN.matcher( sql ).find()
|
return DISTINCT_KEYWORD_PATTERN.matcher( sql ).find()
|
||||||
|| GROUP_BY_KEYWORD_PATTERN.matcher( sql ).find()
|
|| GROUP_BY_KEYWORD_PATTERN.matcher( sql ).find()
|
||||||
|| UNION_KEYWORD_PATTERN.matcher( sql ).find()
|
|| UNION_KEYWORD_PATTERN.matcher( sql ).find()
|
||||||
|| (
|
|| ORDER_BY_KEYWORD_PATTERN.matcher( sql ).find() && queryOptions.hasLimit()
|
||||||
queryOptions.hasLimit()
|
|| queryOptions.hasLimit() && queryOptions.getLimit().getFirstRow() != null;
|
||||||
&& (
|
|
||||||
ORDER_BY_KEYWORD_PATTERN.matcher( sql ).find()
|
|
||||||
|| queryOptions.getLimit().getFirstRow() != null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getQueryHintString(String sql, String hints) {
|
public String getQueryHintString(String sql, String hints) {
|
||||||
String statementType = statementType(sql);
|
final String statementType = statementType( sql );
|
||||||
|
final int start = sql.indexOf( statementType );
|
||||||
final int pos = sql.indexOf( statementType );
|
if ( start < 0 ) {
|
||||||
if ( pos > -1 ) {
|
return sql;
|
||||||
final StringBuilder buffer = new StringBuilder( sql.length() + hints.length() + 8 );
|
}
|
||||||
if ( pos > 0 ) {
|
else {
|
||||||
buffer.append( sql, 0, pos );
|
int end = start + statementType.length();
|
||||||
}
|
return sql.substring( 0, end ) + " /*+ " + hints + " */" + sql.substring( end );
|
||||||
buffer
|
|
||||||
.append( statementType )
|
|
||||||
.append( " /*+ " )
|
|
||||||
.append( hints )
|
|
||||||
.append( " */" )
|
|
||||||
.append( sql.substring( pos + statementType.length() ) );
|
|
||||||
sql = buffer.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sql;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1147,13 +1136,13 @@ public boolean supportsPartitionBy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String statementType(String sql) {
|
private String statementType(String sql) {
|
||||||
Matcher matcher = SQL_STATEMENT_TYPE_PATTERN.matcher( sql );
|
final Matcher matcher = SQL_STATEMENT_TYPE_PATTERN.matcher( sql );
|
||||||
|
|
||||||
if ( matcher.matches() && matcher.groupCount() == 1 ) {
|
if ( matcher.matches() && matcher.groupCount() == 1 ) {
|
||||||
return matcher.group(1);
|
return matcher.group(1);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
throw new IllegalArgumentException( "Can't determine SQL statement type for statement: " + sql );
|
throw new IllegalArgumentException( "Can't determine SQL statement type for statement: " + sql );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -18,7 +18,7 @@ public enum JdbcLockStrategy {
|
|||||||
*/
|
*/
|
||||||
AUTO,
|
AUTO,
|
||||||
/**
|
/**
|
||||||
* Use follow on locking.
|
* Use follow-on locking.
|
||||||
*/
|
*/
|
||||||
FOLLOW_ON,
|
FOLLOW_ON,
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
||||||
import org.hibernate.engine.spi.SessionEventListenerManager;
|
import org.hibernate.engine.spi.SessionEventListenerManager;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.query.spi.Limit;
|
import org.hibernate.query.spi.Limit;
|
||||||
@ -92,20 +91,11 @@ public DeferredResultSetAccess(
|
|||||||
}
|
}
|
||||||
|
|
||||||
final LockOptions lockOptions = queryOptions.getLockOptions();
|
final LockOptions lockOptions = queryOptions.getLockOptions();
|
||||||
boolean followOnLocking = false;
|
final JdbcLockStrategy jdbcLockStrategy = jdbcSelect.getLockStrategy();
|
||||||
if ( lockOptions != null && !lockOptions.isEmpty() && jdbcSelect.getLockStrategy() != JdbcLockStrategy.NONE ) {
|
if ( jdbcLockStrategy != JdbcLockStrategy.NONE
|
||||||
switch ( jdbcSelect.getLockStrategy() ) {
|
&& lockOptions != null && !lockOptions.isEmpty() ) {
|
||||||
case FOLLOW_ON:
|
usesFollowOnLocking = useFollowOnLocking( jdbcLockStrategy, sql, queryOptions, lockOptions, dialect );
|
||||||
followOnLocking = true;
|
if ( usesFollowOnLocking ) {
|
||||||
break;
|
|
||||||
case AUTO:
|
|
||||||
if ( lockOptions.getFollowOnLocking() == null && dialect.useFollowOnLocking( sql, queryOptions )
|
|
||||||
|| Boolean.TRUE.equals( lockOptions.getFollowOnLocking() ) ) {
|
|
||||||
followOnLocking = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( followOnLocking ) {
|
|
||||||
final LockMode lockMode = determineFollowOnLockMode( lockOptions );
|
final LockMode lockMode = determineFollowOnLockMode( lockOptions );
|
||||||
if ( lockMode != LockMode.UPGRADE_SKIPLOCKED ) {
|
if ( lockMode != LockMode.UPGRADE_SKIPLOCKED ) {
|
||||||
// Dialect prefers to perform locking in a separate step
|
// Dialect prefers to perform locking in a separate step
|
||||||
@ -131,7 +121,9 @@ public DeferredResultSetAccess(
|
|||||||
sql = dialect.applyLocksToSql( sql, lockOptions, Collections.emptyMap() );
|
sql = dialect.applyLocksToSql( sql, lockOptions, Collections.emptyMap() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
usesFollowOnLocking = followOnLocking;
|
else {
|
||||||
|
usesFollowOnLocking = false;
|
||||||
|
}
|
||||||
finalSql = dialect.addSqlHintOrComment(
|
finalSql = dialect.addSqlHintOrComment(
|
||||||
sql,
|
sql,
|
||||||
queryOptions,
|
queryOptions,
|
||||||
@ -140,6 +132,24 @@ public DeferredResultSetAccess(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean useFollowOnLocking(
|
||||||
|
JdbcLockStrategy jdbcLockStrategy,
|
||||||
|
String sql,
|
||||||
|
QueryOptions queryOptions,
|
||||||
|
LockOptions lockOptions,
|
||||||
|
Dialect dialect) {
|
||||||
|
switch ( jdbcLockStrategy ) {
|
||||||
|
case FOLLOW_ON:
|
||||||
|
return true;
|
||||||
|
case AUTO:
|
||||||
|
return lockOptions.getFollowOnLocking() == null
|
||||||
|
? dialect.useFollowOnLocking( sql, queryOptions )
|
||||||
|
: lockOptions.getFollowOnLocking();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public LimitHandler getLimitHandler() {
|
public LimitHandler getLimitHandler() {
|
||||||
return limitHandler;
|
return limitHandler;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user