Merge remote-tracking branch 'upstream/main' into wip/6.0

This commit is contained in:
Andrea Boriero 2021-06-15 11:50:01 +02:00
commit 105f91e910
21 changed files with 348 additions and 257 deletions

View File

@ -275,7 +275,7 @@ Please report your mapping that causes the problem to us so we can examine the d
+ +
The default value is `false` which means Hibernate will use an algorithm to determine if the insert can be delayed or if the insert should be performed immediately. The default value is `false` which means Hibernate will use an algorithm to determine if the insert can be delayed or if the insert should be performed immediately.
`*hibernate.id.sequence.increment_size_mismatch_strategy*` (e.g. `LOG`, `FIX` or `EXCEPTION` (default value)):: `*hibernate.id.sequence.increment_size_mismatch_strategy*` (e.g. `LOG`, `FIX`, `NONE` or `EXCEPTION` (default value))::
This setting defines the `org.hibernate.id.SequenceMismatchStrategy` used when This setting defines the `org.hibernate.id.SequenceMismatchStrategy` used when
Hibernate detects a mismatch between a sequence configuration in an entity mapping Hibernate detects a mismatch between a sequence configuration in an entity mapping
and its database sequence object counterpart. and its database sequence object counterpart.

View File

@ -1389,6 +1389,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
this.scrollableResultSetsEnabled = enabled; this.scrollableResultSetsEnabled = enabled;
} }
@Deprecated
public void enableResultSetWrappingSupport(boolean enabled) { public void enableResultSetWrappingSupport(boolean enabled) {
this.wrapResultSetsEnabled = enabled; this.wrapResultSetsEnabled = enabled;
} }

View File

@ -220,6 +220,10 @@ public interface SessionFactoryOptions extends QueryEngineOptions {
boolean isScrollableResultSetsEnabled(); boolean isScrollableResultSetsEnabled();
/**
* @deprecated (since 5.5) Scheduled for removal in 6.0 as ResultSet wrapping is no longer needed
*/
@Deprecated
boolean isWrapResultSetsEnabled(); boolean isWrapResultSetsEnabled();
boolean isGetGeneratedKeysEnabled(); boolean isGetGeneratedKeysEnabled();

View File

@ -1236,7 +1236,10 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
/** /**
* Enable wrapping of JDBC result sets in order to speed up column name lookups for * Enable wrapping of JDBC result sets in order to speed up column name lookups for
* broken JDBC drivers * broken JDBC drivers
*
* @deprecated (since 5.5) Scheduled for removal in 6.0 as ResultSet wrapping is no longer needed
*/ */
@Deprecated
String WRAP_RESULT_SETS = "hibernate.jdbc.wrap_result_sets"; String WRAP_RESULT_SETS = "hibernate.jdbc.wrap_result_sets";
/** /**
@ -2552,8 +2555,9 @@ public interface AvailableSettings extends org.hibernate.jpa.AvailableSettings {
* and its database sequence object counterpart. * and its database sequence object counterpart.
* </p> * </p>
* Possible values are {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION}, * Possible values are {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION},
* {@link org.hibernate.id.SequenceMismatchStrategy#LOG}, and * {@link org.hibernate.id.SequenceMismatchStrategy#LOG},
* {@link org.hibernate.id.SequenceMismatchStrategy#FIX}. * {@link org.hibernate.id.SequenceMismatchStrategy#FIX}
* and {@link org.hibernate.id.SequenceMismatchStrategy#NONE}.
* </p> * </p>
* The default value is given by the {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION}, * The default value is given by the {@link org.hibernate.id.SequenceMismatchStrategy#EXCEPTION},
* meaning that an Exception is thrown when detecting such a conflict. * meaning that an Exception is thrown when detecting such a conflict.

View File

@ -67,6 +67,7 @@ public class Oracle12LimitHandler extends AbstractLimitHandler {
if ( !hasMaxRows ) { if ( !hasMaxRows ) {
return sql; return sql;
} }
sql = sql.trim();
return processSql( return processSql(
sql, sql,
@ -106,7 +107,6 @@ public class Oracle12LimitHandler extends AbstractLimitHandler {
useMaxForLimit = false; useMaxForLimit = false;
supportOffset = true; supportOffset = true;
sql = normalizeStatement( sql );
final int offsetFetchLength; final int offsetFetchLength;
final String offsetFetchString; final String offsetFetchString;
if ( hasFirstRow ) { if ( hasFirstRow ) {
@ -125,8 +125,6 @@ public class Oracle12LimitHandler extends AbstractLimitHandler {
useMaxForLimit = true; useMaxForLimit = true;
supportOffset = false; supportOffset = false;
sql = normalizeStatement( sql );
String forUpdateClause = null; String forUpdateClause = null;
boolean isForUpdate = false; boolean isForUpdate = false;
if ( forUpdateIndex > -1 ) { if ( forUpdateIndex > -1 ) {
@ -167,10 +165,6 @@ public class Oracle12LimitHandler extends AbstractLimitHandler {
return pagingSelect.toString(); return pagingSelect.toString();
} }
private String normalizeStatement(String sql) {
return sql.trim().replaceAll( "\\s+", " " );
}
private int getForUpdateIndex(String sql) { private int getForUpdateIndex(String sql) {
final int forUpdateLastIndex = sql.toLowerCase( Locale.ROOT ).lastIndexOf( "for update" ); final int forUpdateLastIndex = sql.toLowerCase( Locale.ROOT ).lastIndexOf( "for update" );
// We need to recognize cases like : select a from t where b = 'for update'; // We need to recognize cases like : select a from t where b = 'for update';

View File

@ -6,21 +6,25 @@
*/ */
package org.hibernate.engine.jdbc.env.internal; package org.hibernate.engine.jdbc.env.internal;
import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.hibernate.HibernateException;
import org.hibernate.boot.model.source.internal.hbm.CommaSeparatedStringHelper; import org.hibernate.boot.model.source.internal.hbm.CommaSeparatedStringHelper;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport; import org.hibernate.engine.jdbc.cursor.internal.StandardRefCursorSupport;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.env.spi.SQLStateType; import org.hibernate.engine.jdbc.env.spi.SQLStateType;
import org.hibernate.engine.jdbc.spi.TypeInfo; import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.SequenceInformation; import org.hibernate.tool.schema.extract.spi.SequenceInformation;
/** /**
@ -29,7 +33,9 @@ import org.hibernate.tool.schema.extract.spi.SequenceInformation;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData { public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
private final JdbcEnvironment jdbcEnvironment; private final JdbcEnvironment jdbcEnvironment;
private final JdbcConnectionAccess connectionAccess;
private final String connectionCatalogName; private final String connectionCatalogName;
private final String connectionSchemaName; private final String connectionSchemaName;
@ -42,18 +48,19 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
private final boolean supportsDataDefinitionInTransaction; private final boolean supportsDataDefinitionInTransaction;
private final boolean doesDataDefinitionCauseTransactionCommit; private final boolean doesDataDefinitionCauseTransactionCommit;
private final SQLStateType sqlStateType; private final SQLStateType sqlStateType;
private final boolean lobLocatorUpdateCopy; private final boolean jdbcMetadataAccessible;
private final Set<String> extraKeywords;
private final LinkedHashSet<TypeInfo> typeInfoSet; //Lazily initialized: loading all sequence information upfront has been
private final List<SequenceInformation> sequenceInformationList; //shown to be too slow in some cases. In this way we only load it
//when there is actual need for these details.
private List<SequenceInformation> sequenceInformationList;
private ExtractedDatabaseMetaDataImpl( private ExtractedDatabaseMetaDataImpl(
JdbcEnvironment jdbcEnvironment, JdbcEnvironment jdbcEnvironment,
JdbcConnectionAccess connectionAccess,
String connectionCatalogName, String connectionCatalogName,
String connectionSchemaName, String connectionSchemaName,
Set<String> extraKeywords,
LinkedHashSet<TypeInfo> typeInfoSet,
boolean supportsRefCursors, boolean supportsRefCursors,
boolean supportsNamedParameters, boolean supportsNamedParameters,
boolean supportsScrollableResults, boolean supportsScrollableResults,
@ -62,20 +69,11 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
boolean supportsDataDefinitionInTransaction, boolean supportsDataDefinitionInTransaction,
boolean doesDataDefinitionCauseTransactionCommit, boolean doesDataDefinitionCauseTransactionCommit,
SQLStateType sqlStateType, SQLStateType sqlStateType,
boolean lobLocatorUpdateCopy, boolean jdbcMetadataIsAccessible) {
List<SequenceInformation> sequenceInformationList) {
this.jdbcEnvironment = jdbcEnvironment; this.jdbcEnvironment = jdbcEnvironment;
this.connectionAccess = connectionAccess;
this.connectionCatalogName = connectionCatalogName; this.connectionCatalogName = connectionCatalogName;
this.connectionSchemaName = connectionSchemaName; this.connectionSchemaName = connectionSchemaName;
this.extraKeywords = extraKeywords != null
? extraKeywords
: Collections.emptySet();
this.typeInfoSet = typeInfoSet != null
? typeInfoSet
: new LinkedHashSet<>();
this.supportsRefCursors = supportsRefCursors; this.supportsRefCursors = supportsRefCursors;
this.supportsNamedParameters = supportsNamedParameters; this.supportsNamedParameters = supportsNamedParameters;
this.supportsScrollableResults = supportsScrollableResults; this.supportsScrollableResults = supportsScrollableResults;
@ -84,8 +82,7 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction; this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction;
this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit; this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit;
this.sqlStateType = sqlStateType; this.sqlStateType = sqlStateType;
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy; this.jdbcMetadataAccessible = jdbcMetadataIsAccessible;
this.sequenceInformationList = sequenceInformationList;
} }
@Override @Override
@ -128,21 +125,11 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
return doesDataDefinitionCauseTransactionCommit; return doesDataDefinitionCauseTransactionCommit;
} }
@Override
public Set<String> getExtraKeywords() {
return extraKeywords;
}
@Override @Override
public SQLStateType getSqlStateType() { public SQLStateType getSqlStateType() {
return sqlStateType; return sqlStateType;
} }
@Override
public boolean doesLobLocatorUpdateCopy() {
return lobLocatorUpdateCopy;
}
@Override @Override
public String getConnectionCatalogName() { public String getConnectionCatalogName() {
return connectionCatalogName; return connectionCatalogName;
@ -154,24 +141,30 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
} }
@Override @Override
public LinkedHashSet<TypeInfo> getTypeInfoSet() { public synchronized List<SequenceInformation> getSequenceInformationList() {
return typeInfoSet; if ( jdbcMetadataAccessible ) {
} //Loading the sequence information can take a while on large databases,
//even minutes in some cases.
@Override //We trigger this lazily as only certain combinations of configurations,
public List<SequenceInformation> getSequenceInformationList() { //mappings and used features actually trigger any use of such details.
return sequenceInformationList; if ( sequenceInformationList == null ) {
sequenceInformationList = sequenceInformationList();
}
return sequenceInformationList;
}
else {
return Collections.emptyList();
}
} }
public static class Builder { public static class Builder {
private final JdbcEnvironment jdbcEnvironment; private final JdbcEnvironment jdbcEnvironment;
private final boolean jdbcMetadataIsAccessible;
private final JdbcConnectionAccess connectionAccess;
private String connectionSchemaName; private String connectionSchemaName;
private String connectionCatalogName; private String connectionCatalogName;
private Set<String> extraKeywords;
private LinkedHashSet<TypeInfo> typeInfoSet;
private boolean supportsRefCursors; private boolean supportsRefCursors;
private boolean supportsNamedParameters; private boolean supportsNamedParameters;
private boolean supportsScrollableResults; private boolean supportsScrollableResults;
@ -180,11 +173,11 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
private boolean supportsDataDefinitionInTransaction; private boolean supportsDataDefinitionInTransaction;
private boolean doesDataDefinitionCauseTransactionCommit; private boolean doesDataDefinitionCauseTransactionCommit;
private SQLStateType sqlStateType; private SQLStateType sqlStateType;
private boolean lobLocatorUpdateCopy;
private List<SequenceInformation> sequenceInformationList = Collections.emptyList();
public Builder(JdbcEnvironment jdbcEnvironment) { public Builder(JdbcEnvironment jdbcEnvironment, boolean jdbcMetadataIsAccessible, JdbcConnectionAccess connectionAccess) {
this.jdbcEnvironment = jdbcEnvironment; this.jdbcEnvironment = jdbcEnvironment;
this.jdbcMetadataIsAccessible = jdbcMetadataIsAccessible;
this.connectionAccess = connectionAccess;
} }
public Builder apply(DatabaseMetaData databaseMetaData) throws SQLException { public Builder apply(DatabaseMetaData databaseMetaData) throws SQLException {
@ -197,16 +190,7 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
supportsBatchUpdates = databaseMetaData.supportsBatchUpdates(); supportsBatchUpdates = databaseMetaData.supportsBatchUpdates();
supportsDataDefinitionInTransaction = !databaseMetaData.dataDefinitionIgnoredInTransactions(); supportsDataDefinitionInTransaction = !databaseMetaData.dataDefinitionIgnoredInTransactions();
doesDataDefinitionCauseTransactionCommit = databaseMetaData.dataDefinitionCausesTransactionCommit(); doesDataDefinitionCauseTransactionCommit = databaseMetaData.dataDefinitionCausesTransactionCommit();
extraKeywords = parseKeywords( databaseMetaData.getSQLKeywords() );
sqlStateType = SQLStateType.interpretReportedSQLStateType( databaseMetaData.getSQLStateType() ); sqlStateType = SQLStateType.interpretReportedSQLStateType( databaseMetaData.getSQLStateType() );
try {
lobLocatorUpdateCopy = databaseMetaData.locatorsUpdateCopy();
}
catch (SQLException sql) {
//ignore, the database might not support this at all
}
typeInfoSet = new LinkedHashSet<>();
typeInfoSet.addAll( TypeInfo.extractTypeInfo( databaseMetaData ) );
return this; return this;
} }
@ -224,42 +208,6 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
return this; return this;
} }
public Builder setExtraKeywords(Set<String> extraKeywords) {
if ( this.extraKeywords == null ) {
this.extraKeywords = extraKeywords;
}
else {
this.extraKeywords.addAll( extraKeywords );
}
return this;
}
public Builder addExtraKeyword(String keyword) {
if ( this.extraKeywords == null ) {
this.extraKeywords = new HashSet<>();
}
this.extraKeywords.add( keyword );
return this;
}
public Builder setTypeInfoSet(LinkedHashSet<TypeInfo> typeInfoSet) {
if ( this.typeInfoSet == null ) {
this.typeInfoSet = typeInfoSet;
}
else {
this.typeInfoSet.addAll( typeInfoSet );
}
return this;
}
public Builder addTypeInfo(TypeInfo typeInfo) {
if ( this.typeInfoSet == null ) {
this.typeInfoSet = new LinkedHashSet<>();
}
typeInfoSet.add( typeInfo );
return this;
}
public Builder setSupportsRefCursors(boolean supportsRefCursors) { public Builder setSupportsRefCursors(boolean supportsRefCursors) {
this.supportsRefCursors = supportsRefCursors; this.supportsRefCursors = supportsRefCursors;
return this; return this;
@ -300,23 +248,12 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
return this; return this;
} }
public Builder setLobLocatorUpdateCopy(boolean lobLocatorUpdateCopy) {
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy;
return this;
}
public Builder setSequenceInformationList(List<SequenceInformation> sequenceInformationList) {
this.sequenceInformationList = sequenceInformationList;
return this;
}
public ExtractedDatabaseMetaDataImpl build() { public ExtractedDatabaseMetaDataImpl build() {
return new ExtractedDatabaseMetaDataImpl( return new ExtractedDatabaseMetaDataImpl(
jdbcEnvironment, jdbcEnvironment,
connectionAccess,
connectionCatalogName, connectionCatalogName,
connectionSchemaName, connectionSchemaName,
extraKeywords,
typeInfoSet,
supportsRefCursors, supportsRefCursors,
supportsNamedParameters, supportsNamedParameters,
supportsScrollableResults, supportsScrollableResults,
@ -325,9 +262,54 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData
supportsDataDefinitionInTransaction, supportsDataDefinitionInTransaction,
doesDataDefinitionCauseTransactionCommit, doesDataDefinitionCauseTransactionCommit,
sqlStateType, sqlStateType,
lobLocatorUpdateCopy, jdbcMetadataIsAccessible
sequenceInformationList
); );
} }
} }
/**
* Get the sequence information List from the database.
*
* @return sequence information List
*/
private List<SequenceInformation> sequenceInformationList() {
final JdbcEnvironment jdbcEnvironment = this.jdbcEnvironment;
final Dialect dialect = this.jdbcEnvironment.getDialect();
Connection connection = null;
try {
connection = connectionAccess.obtainConnection();
final Connection c = connection;
Iterable<SequenceInformation> sequenceInformationIterable = dialect
.getSequenceInformationExtractor()
.extractMetadata( new ExtractionContext.EmptyExtractionContext() {
@Override
public Connection getJdbcConnection() {
return c;
}
@Override
public JdbcEnvironment getJdbcEnvironment() {
return jdbcEnvironment;
}
}
);
return StreamSupport.stream( sequenceInformationIterable.spliterator(), false )
.collect( Collectors.toList() );
}
catch (SQLException e) {
throw new HibernateException( "Could not fetch the SequenceInformation from the database", e );
}
finally {
if ( connection != null ) {
try {
connectionAccess.releaseConnection( connection );
}
catch (SQLException throwables) {
//ignored
}
}
}
}
} }

View File

@ -6,17 +6,8 @@
*/ */
package org.hibernate.engine.jdbc.env.internal; package org.hibernate.engine.jdbc.env.internal;
import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.registry.selector.spi.StrategySelector;
@ -24,6 +15,7 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder; import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
@ -33,7 +25,6 @@ import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameFormatter; import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameFormatter;
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver; import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.TypeInfo;
import org.hibernate.exception.internal.SQLExceptionTypeDelegate; import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
import org.hibernate.exception.internal.SQLStateConversionDelegate; import org.hibernate.exception.internal.SQLStateConversionDelegate;
import org.hibernate.exception.internal.StandardSQLExceptionConverter; import org.hibernate.exception.internal.StandardSQLExceptionConverter;
@ -41,8 +32,6 @@ import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.sql.ast.SqlAstTranslatorFactory; import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory; import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -64,7 +53,6 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
private final QualifiedObjectNameFormatter qualifiedObjectNameFormatter; private final QualifiedObjectNameFormatter qualifiedObjectNameFormatter;
private final LobCreatorBuilderImpl lobCreatorBuilder; private final LobCreatorBuilderImpl lobCreatorBuilder;
private final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<>();
private final NameQualifierSupport nameQualifierSupport; private final NameQualifierSupport nameQualifierSupport;
/** /**
@ -73,7 +61,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
* @param serviceRegistry The service registry * @param serviceRegistry The service registry
* @param dialect The resolved dialect. * @param dialect The resolved dialect.
*/ */
public JdbcEnvironmentImpl(final ServiceRegistryImplementor serviceRegistry, Dialect dialect) { public JdbcEnvironmentImpl(final ServiceRegistryImplementor serviceRegistry, final Dialect dialect) {
this.dialect = dialect; this.dialect = dialect;
this.sqlAstTranslatorFactory = resolveSqlAstTranslatorFactory( dialect ); this.sqlAstTranslatorFactory = resolveSqlAstTranslatorFactory( dialect );
@ -97,7 +85,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
identifierHelperBuilder.setNameQualifierSupport( nameQualifierSupport ); identifierHelperBuilder.setNameQualifierSupport( nameQualifierSupport );
IdentifierHelper identifierHelper = null; IdentifierHelper identifierHelper = null;
ExtractedDatabaseMetaDataImpl.Builder dbMetaDataBuilder = new ExtractedDatabaseMetaDataImpl.Builder( this ); ExtractedDatabaseMetaDataImpl.Builder dbMetaDataBuilder = new ExtractedDatabaseMetaDataImpl.Builder( this, false, null );
try { try {
identifierHelper = dialect.buildIdentifierHelper( identifierHelperBuilder, null ); identifierHelper = dialect.buildIdentifierHelper( identifierHelperBuilder, null );
dbMetaDataBuilder.setSupportsNamedParameters( dialect.supportsNamedParameters( null ) ); dbMetaDataBuilder.setSupportsNamedParameters( dialect.supportsNamedParameters( null ) );
@ -169,8 +157,12 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
* Constructor form used from testing * Constructor form used from testing
* *
* @param dialect The dialect * @param dialect The dialect
* @param jdbcConnectionAccess
*/ */
public JdbcEnvironmentImpl(DatabaseMetaData databaseMetaData, Dialect dialect) throws SQLException { public JdbcEnvironmentImpl(
DatabaseMetaData databaseMetaData,
Dialect dialect,
JdbcConnectionAccess jdbcConnectionAccess) throws SQLException {
this.dialect = dialect; this.dialect = dialect;
this.sqlAstTranslatorFactory = resolveSqlAstTranslatorFactory( dialect ); this.sqlAstTranslatorFactory = resolveSqlAstTranslatorFactory( dialect );
@ -198,10 +190,9 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
} }
this.identifierHelper = identifierHelper; this.identifierHelper = identifierHelper;
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ) this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this, true, jdbcConnectionAccess )
.apply( databaseMetaData ) .apply( databaseMetaData )
.setSupportsNamedParameters( databaseMetaData.supportsNamedParameters() ) .setSupportsNamedParameters( databaseMetaData.supportsNamedParameters() )
.setSequenceInformationList( sequenceInformationList( databaseMetaData.getConnection() ) )
.build(); .build();
this.currentCatalog = null; this.currentCatalog = null;
@ -233,6 +224,20 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
} }
} }
/**
* @deprecated currently used by Hibernate Reactive
* This version of the constructor should handle the case in which we do actually have the option to access the DatabaseMetaData,
* but since Hibernate Reactive is currently not making use of it we take a shortcut.
*/
@Deprecated
public JdbcEnvironmentImpl(
ServiceRegistryImplementor serviceRegistry,
Dialect dialect,
DatabaseMetaData databaseMetaData
/*JdbcConnectionAccess jdbcConnectionAccess*/) throws SQLException {
this(serviceRegistry, dialect);
}
/** /**
* The main constructor form. Builds a JdbcEnvironment using the available DatabaseMetaData * The main constructor form. Builds a JdbcEnvironment using the available DatabaseMetaData
* *
@ -245,7 +250,8 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
public JdbcEnvironmentImpl( public JdbcEnvironmentImpl(
ServiceRegistryImplementor serviceRegistry, ServiceRegistryImplementor serviceRegistry,
Dialect dialect, Dialect dialect,
DatabaseMetaData databaseMetaData) throws SQLException { DatabaseMetaData databaseMetaData,
JdbcConnectionAccess jdbcConnectionAccess) throws SQLException {
this.dialect = dialect; this.dialect = dialect;
this.sqlAstTranslatorFactory = resolveSqlAstTranslatorFactory( dialect ); this.sqlAstTranslatorFactory = resolveSqlAstTranslatorFactory( dialect );
@ -279,11 +285,10 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
} }
this.identifierHelper = identifierHelper; this.identifierHelper = identifierHelper;
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this ) this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl.Builder( this, true, jdbcConnectionAccess )
.apply( databaseMetaData ) .apply( databaseMetaData )
.setConnectionSchemaName( determineCurrentSchemaName( databaseMetaData, serviceRegistry, dialect ) ) .setConnectionSchemaName( determineCurrentSchemaName( databaseMetaData, serviceRegistry, dialect ) )
.setSupportsNamedParameters( dialect.supportsNamedParameters( databaseMetaData ) ) .setSupportsNamedParameters( dialect.supportsNamedParameters( databaseMetaData ) )
.setSequenceInformationList( sequenceInformationList( databaseMetaData.getConnection() ) )
.build(); .build();
// and that current-catalog and current-schema happen after it // and that current-catalog and current-schema happen after it
@ -295,8 +300,6 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
databaseMetaData databaseMetaData
); );
this.typeInfoSet.addAll( TypeInfo.extractTypeInfo( databaseMetaData ) );
this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder( this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(
dialect, dialect,
cfgService.getSettings(), cfgService.getSettings(),
@ -309,7 +312,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
private String determineCurrentSchemaName( private String determineCurrentSchemaName(
DatabaseMetaData databaseMetaData, DatabaseMetaData databaseMetaData,
ServiceRegistry serviceRegistry, ServiceRegistry serviceRegistry,
Dialect dialect) throws SQLException { Dialect dialect) {
final SchemaNameResolver schemaNameResolver; final SchemaNameResolver schemaNameResolver;
final Object setting = serviceRegistry.getService( ConfigurationService.class ).getSettings().get( final Object setting = serviceRegistry.getService( ConfigurationService.class ).getSettings().get(
@ -344,14 +347,6 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
return new SqlExceptionHelper( sqlExceptionConverter, logWarnings ); return new SqlExceptionHelper( sqlExceptionConverter, logWarnings );
} }
private Set<String> buildMergedReservedWords(Dialect dialect, DatabaseMetaData dbmd) throws SQLException {
Set<String> reservedWords = new HashSet<>();
reservedWords.addAll( dialect.getKeywords() );
// todo : do we need to explicitly handle SQL:2003 keywords?
Collections.addAll( reservedWords, dbmd.getSQLKeywords().split( "," ) );
return reservedWords;
}
@Override @Override
public Dialect getDialect() { public Dialect getDialect() {
return dialect; return dialect;
@ -402,47 +397,4 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
return lobCreatorBuilder; return lobCreatorBuilder;
} }
@Override
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
for ( TypeInfo typeInfo : typeInfoSet ) {
if ( typeInfo.getJdbcTypeCode() == jdbcTypeCode ) {
return typeInfo;
}
}
return null;
}
/**
* Get the sequence information List from the database.
*
* @param connection database connection
* @return sequence information List
*/
private List<SequenceInformation> sequenceInformationList(final Connection connection) {
try {
Iterable<SequenceInformation> sequenceInformationIterable = dialect
.getSequenceInformationExtractor()
.extractMetadata( new ExtractionContext.EmptyExtractionContext() {
@Override
public Connection getJdbcConnection() {
return connection;
}
@Override
public JdbcEnvironment getJdbcEnvironment() {
return JdbcEnvironmentImpl.this;
}
}
);
return StreamSupport.stream( sequenceInformationIterable.spliterator(), false )
.collect( Collectors.toList() );
}
catch (SQLException e) {
log.error( "Could not fetch the SequenceInformation from the database", e );
}
return Collections.emptyList();
}
} }

View File

@ -149,7 +149,12 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
} }
} }
); );
return new JdbcEnvironmentImpl( registry, dialect, dbmd ); return new JdbcEnvironmentImpl(
registry,
dialect,
dbmd,
jdbcConnectionAccess
);
} }
catch (SQLException e) { catch (SQLException e) {
log.unableToObtainConnectionMetadata( e ); log.unableToObtainConnectionMetadata( e );

View File

@ -44,24 +44,6 @@ public interface ExtractedDatabaseMetaData {
*/ */
String getConnectionSchemaName(); String getConnectionSchemaName();
/**
* Set of type info reported by the driver.
*
* @return The type information obtained from the driver.
*
* @see java.sql.DatabaseMetaData#getTypeInfo()
*/
LinkedHashSet<TypeInfo> getTypeInfoSet();
/**
* Get the list of extra keywords (beyond standard SQL92 keywords) reported by the driver.
*
* @return The extra keywords used by this database.
*
* @see java.sql.DatabaseMetaData#getSQLKeywords()
*/
Set<String> getExtraKeywords();
/** /**
* Does the driver report supporting named parameters? * Does the driver report supporting named parameters?
* *
@ -135,15 +117,6 @@ public interface ExtractedDatabaseMetaData {
*/ */
SQLStateType getSqlStateType(); SQLStateType getSqlStateType();
/**
* Did the driver report that updates to a LOB locator affect a copy of the LOB?
*
* @return True if updates to the state of a LOB locator update only a copy.
*
* @see java.sql.DatabaseMetaData#locatorsUpdateCopy()
*/
boolean doesLobLocatorUpdateCopy();
/** /**
* Retrieve the list of {@code SequenceInformation} objects which describe the underlying database sequences. * Retrieve the list of {@code SequenceInformation} objects which describe the underlying database sequences.
* *

View File

@ -63,6 +63,10 @@ public class IdentifierHelperBuilder {
return; return;
} }
//Important optimisation: skip loading all keywords from the DB when autoQuoteKeywords is disabled
if ( autoQuoteKeywords == false ) {
return;
}
this.reservedWords.addAll( parseKeywords( metaData.getSQLKeywords() ) ); this.reservedWords.addAll( parseKeywords( metaData.getSQLKeywords() ) );
} }
@ -182,6 +186,10 @@ public class IdentifierHelperBuilder {
} }
public void applyReservedWords(Collection<String> words) { public void applyReservedWords(Collection<String> words) {
//No use when autoQuoteKeywords is disabled
if ( autoQuoteKeywords == false ) {
return;
}
this.reservedWords.addAll( words ); this.reservedWords.addAll( words );
} }

View File

@ -93,11 +93,12 @@ public interface JdbcEnvironment extends Service {
LobCreatorBuilder getLobCreatorBuilder(); LobCreatorBuilder getLobCreatorBuilder();
/** /**
* Find type information for the type identified by the given "JDBC type code". * @deprecated This is currently not implemented an will likely be removed
* * (A default method is provided to facilitate removal from implementors)
* @param jdbcTypeCode The JDBC type code.
*
* @return The corresponding type info.
*/ */
TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode); @Deprecated
default TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
throw new UnsupportedOperationException( "Support for getting TypeInfo from jdbcTypeCode has been disabled as it wasn't used. Use org.hibernate.engine.jdbc.spi.TypeInfo.extractTypeInfo as alternative, or report an issue and explain." );
}
} }

View File

@ -32,7 +32,13 @@ public enum SequenceMismatchStrategy {
* When detecting a mismatch, Hibernate tries to fix it by overriding the entity sequence mapping using the one * When detecting a mismatch, Hibernate tries to fix it by overriding the entity sequence mapping using the one
* found in the database. * found in the database.
*/ */
FIX; FIX,
/**
* Don't perform any check. This is useful to speedup bootstrap as it won't query the sequences on the DB,
* at cost of not validating the sequences.
*/
NONE;
/** /**
* Interpret the configured SequenceMismatchStrategy value. * Interpret the configured SequenceMismatchStrategy value.

View File

@ -11,6 +11,7 @@ import java.util.Properties;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.boot.SchemaAutoTooling;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.QualifiedName; import org.hibernate.boot.model.relational.QualifiedName;
@ -200,19 +201,20 @@ public class SequenceStyleGenerator
final boolean isPooledOptimizer = OptimizerFactory.isPooledOptimizer( optimizationStrategy ); final boolean isPooledOptimizer = OptimizerFactory.isPooledOptimizer( optimizationStrategy );
if ( isPooledOptimizer && isPhysicalSequence( jdbcEnvironment, forceTableUse ) ) {
SequenceMismatchStrategy sequenceMismatchStrategy = configurationService.getSetting(
AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY,
SequenceMismatchStrategy::interpret,
SequenceMismatchStrategy.EXCEPTION
);
if ( sequenceMismatchStrategy != SequenceMismatchStrategy.NONE && isPooledOptimizer && isPhysicalSequence( jdbcEnvironment, forceTableUse ) ) {
String databaseSequenceName = sequenceName.getObjectName().getText(); String databaseSequenceName = sequenceName.getObjectName().getText();
Long databaseIncrementValue = getSequenceIncrementValue( jdbcEnvironment, databaseSequenceName ); Long databaseIncrementValue = getSequenceIncrementValue( jdbcEnvironment, databaseSequenceName );
if ( databaseIncrementValue != null && !databaseIncrementValue.equals( (long) incrementSize ) ) { if ( databaseIncrementValue != null && !databaseIncrementValue.equals( (long) incrementSize ) ) {
int dbIncrementValue = databaseIncrementValue.intValue(); int dbIncrementValue = databaseIncrementValue.intValue();
SequenceMismatchStrategy sequenceMismatchStrategy = configurationService.getSetting(
AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY,
SequenceMismatchStrategy::interpret,
SequenceMismatchStrategy.EXCEPTION
);
switch ( sequenceMismatchStrategy ) { switch ( sequenceMismatchStrategy ) {
case EXCEPTION: case EXCEPTION:
throw new MappingException( throw new MappingException(

View File

@ -8,6 +8,7 @@ package org.hibernate.metamodel.internal;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -25,6 +26,7 @@ import org.hibernate.Internal;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.internal.EntityManagerMessageLogger; import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.HEMLogging; import org.hibernate.internal.HEMLogging;
import org.hibernate.internal.log.DeprecationLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;

View File

@ -0,0 +1,67 @@
package org.hibernate.dialect;
import org.hibernate.dialect.pagination.Oracle12LimitHandler;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@TestForIssue( jiraKey = "HHH-14649")
public class Oracle12LimitHandlerTest {
@Test
public void testSqlWithSpace() {
final String sql = "select p.name from Person p where p.id = 1 for update";
final String expected = "select * from ( select p.name from Person p where p.id = 1 ) where rownum <= ? for update";
final QueryParameters queryParameters = getQueryParameters( 0, 5 );
final String processedSql = Oracle12LimitHandler.INSTANCE.processSql( sql, queryParameters );
assertEquals( expected, processedSql );
}
@Test
public void testSqlWithSpaceInsideQuotedString() {
final String sql = "select p.name from Person p where p.name = ' this is a string with spaces ' for update";
final String expected = "select * from ( select p.name from Person p where p.name = ' this is a string with spaces ' ) where rownum <= ? for update";
final QueryParameters queryParameters = getQueryParameters( 0, 5 );
final String processedSql = Oracle12LimitHandler.INSTANCE.processSql( sql, queryParameters );
assertEquals( expected, processedSql );
}
@Test
public void testSqlWithForUpdateInsideQuotedString() {
final String sql = "select a.prop from A a where a.name = 'this is for update '";
final String expected = "select a.prop from A a where a.name = 'this is for update ' fetch first ? rows only";
final QueryParameters queryParameters = getQueryParameters( 0, 5 );
final String processedSql = Oracle12LimitHandler.INSTANCE.processSql( sql, queryParameters );
assertEquals( expected, processedSql );
}
@Test
public void testSqlWithForUpdateInsideAndOutsideQuotedStringA() {
final String sql = "select a.prop from A a where a.name = 'this is for update ' for update";
final String expected = "select * from ( select a.prop from A a where a.name = 'this is for update ' ) where rownum <= ? for update";
final QueryParameters queryParameters = getQueryParameters( 0, 5 );
final String processedSql = Oracle12LimitHandler.INSTANCE.processSql( sql, queryParameters );
assertEquals( expected, processedSql );
}
private QueryParameters getQueryParameters(int firstRow, int maxRow) {
final QueryParameters queryParameters = new QueryParameters();
RowSelection rowSelection = new RowSelection();
rowSelection.setFirstRow( firstRow );
rowSelection.setMaxRows( maxRow );
queryParameters.setRowSelection( rowSelection );
return queryParameters;
}
}

View File

@ -0,0 +1,71 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.engine.jdbc.env.internal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.id.SequenceMismatchStrategy;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
/**
* Verifies that setting {@code AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY} to {@code none}
* is going to skip loading the sequence information from the database.
*/
@TestForIssue( jiraKey = "HHH-14667")
public class SkipLoadingSequenceInformationTest extends BaseCoreFunctionalTestCase {
@Override
protected void configure(Configuration configuration) {
configuration.setProperty( AvailableSettings.SEQUENCE_INCREMENT_SIZE_MISMATCH_STRATEGY, SequenceMismatchStrategy.NONE.name() );
configuration.setProperty( Environment.DIALECT, VetoingDialect.class.getName() );
}
@Entity(name="seqentity")
static class SequencingEntity {
@Id
@GenericGenerator(name = "pooledoptimizer", strategy = "enhanced-sequence",
parameters = {
@org.hibernate.annotations.Parameter(name = "optimizer", value = "pooled"),
@org.hibernate.annotations.Parameter(name = "initial_value", value = "1"),
@org.hibernate.annotations.Parameter(name = "increment_size", value = "2")
}
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pooledoptimizer")
Integer id;
String name;
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{SequencingEntity.class};
}
@Test
public void test() {
// If it's able to boot, we're good.
}
public static class VetoingDialect extends H2Dialect {
@Override
public SequenceInformationExtractor getSequenceInformationExtractor() {
throw new IllegalStateException("Should really not invoke this method in this setup");
}
}
}

View File

@ -38,8 +38,6 @@ public class NoDatabaseMetaDataTest extends BaseUnitTestCase {
assertNull( extractedDatabaseMetaData.getConnectionCatalogName() ); assertNull( extractedDatabaseMetaData.getConnectionCatalogName() );
assertNull( extractedDatabaseMetaData.getConnectionSchemaName() ); assertNull( extractedDatabaseMetaData.getConnectionSchemaName() );
assertTrue( extractedDatabaseMetaData.getTypeInfoSet().isEmpty() );
assertTrue( extractedDatabaseMetaData.getExtraKeywords().isEmpty() );
assertFalse( extractedDatabaseMetaData.supportsNamedParameters() ); assertFalse( extractedDatabaseMetaData.supportsNamedParameters() );
assertFalse( extractedDatabaseMetaData.supportsRefCursors() ); assertFalse( extractedDatabaseMetaData.supportsRefCursors() );
assertFalse( extractedDatabaseMetaData.supportsScrollableResults() ); assertFalse( extractedDatabaseMetaData.supportsScrollableResults() );
@ -48,7 +46,6 @@ public class NoDatabaseMetaDataTest extends BaseUnitTestCase {
assertFalse( extractedDatabaseMetaData.supportsDataDefinitionInTransaction() ); assertFalse( extractedDatabaseMetaData.supportsDataDefinitionInTransaction() );
assertFalse( extractedDatabaseMetaData.doesDataDefinitionCauseTransactionCommit() ); assertFalse( extractedDatabaseMetaData.doesDataDefinitionCauseTransactionCommit() );
assertNull( extractedDatabaseMetaData.getSqlStateType() ); assertNull( extractedDatabaseMetaData.getSqlStateType() );
assertFalse( extractedDatabaseMetaData.doesLobLocatorUpdateCopy() );
StandardServiceRegistryBuilder.destroy( serviceRegistry ); StandardServiceRegistryBuilder.destroy( serviceRegistry );
} }
@ -65,8 +62,6 @@ public class NoDatabaseMetaDataTest extends BaseUnitTestCase {
assertNull( extractedDatabaseMetaData.getConnectionCatalogName() ); assertNull( extractedDatabaseMetaData.getConnectionCatalogName() );
assertNull( extractedDatabaseMetaData.getConnectionSchemaName() ); assertNull( extractedDatabaseMetaData.getConnectionSchemaName() );
assertTrue( extractedDatabaseMetaData.getTypeInfoSet().isEmpty() );
assertTrue( extractedDatabaseMetaData.getExtraKeywords().isEmpty() );
assertTrue( extractedDatabaseMetaData.supportsNamedParameters() ); assertTrue( extractedDatabaseMetaData.supportsNamedParameters() );
assertFalse( extractedDatabaseMetaData.supportsRefCursors() ); assertFalse( extractedDatabaseMetaData.supportsRefCursors() );
assertFalse( extractedDatabaseMetaData.supportsScrollableResults() ); assertFalse( extractedDatabaseMetaData.supportsScrollableResults() );
@ -75,7 +70,6 @@ public class NoDatabaseMetaDataTest extends BaseUnitTestCase {
assertFalse( extractedDatabaseMetaData.supportsDataDefinitionInTransaction() ); assertFalse( extractedDatabaseMetaData.supportsDataDefinitionInTransaction() );
assertFalse( extractedDatabaseMetaData.doesDataDefinitionCauseTransactionCommit() ); assertFalse( extractedDatabaseMetaData.doesDataDefinitionCauseTransactionCommit() );
assertNull( extractedDatabaseMetaData.getSqlStateType() ); assertNull( extractedDatabaseMetaData.getSqlStateType() );
assertFalse( extractedDatabaseMetaData.doesLobLocatorUpdateCopy() );
StandardServiceRegistryBuilder.destroy( serviceRegistry ); StandardServiceRegistryBuilder.destroy( serviceRegistry );
} }

View File

@ -6,19 +6,16 @@
*/ */
package org.hibernate.orm.test.schemafilter; package org.hibernate.orm.test.schemafilter;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.persistence.Entity;
import org.hamcrest.BaseMatcher; import javax.persistence.GeneratedValue;
import org.hamcrest.Description; import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources; import org.hibernate.boot.MetadataSources;
@ -34,22 +31,23 @@ import org.hibernate.tool.schema.internal.SchemaCreatorImpl;
import org.hibernate.tool.schema.internal.SchemaDropperImpl; import org.hibernate.tool.schema.internal.SchemaDropperImpl;
import org.hibernate.tool.schema.spi.SchemaFilter; import org.hibernate.tool.schema.spi.SchemaFilter;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.hibernate.testing.DialectChecks; import org.hamcrest.BaseMatcher;
import org.hibernate.testing.RequiresDialectFeature; import org.hamcrest.Description;
import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
/** /**
* @author Andrea Boriero * @author Andrea Boriero
*/ */
@TestForIssue(jiraKey = "HHH-10937") @TestForIssue(jiraKey = "HHH-10937")
@RequiresDialectFeature(value = {DialectChecks.SupportSchemaCreation.class}) @RequiresDialect(H2Dialect.class)
public class SequenceFilterTest extends BaseUnitTestCase { public class SequenceFilterTest extends BaseUnitTestCase {
private StandardServiceRegistryImpl serviceRegistry; private StandardServiceRegistryImpl serviceRegistry;
private Metadata metadata; private Metadata metadata;
@ -59,6 +57,7 @@ public class SequenceFilterTest extends BaseUnitTestCase {
Map settings = new HashMap(); Map settings = new HashMap();
settings.putAll( Environment.getProperties() ); settings.putAll( Environment.getProperties() );
settings.put( AvailableSettings.DIALECT, H2Dialect.class.getName() ); settings.put( AvailableSettings.DIALECT, H2Dialect.class.getName() );
settings.put( "hibernate.temp.use_jdbc_metadata_defaults", "false" );
settings.put( AvailableSettings.FORMAT_SQL, false ); settings.put( AvailableSettings.FORMAT_SQL, false );
this.serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( settings ); this.serviceRegistry = ServiceRegistryBuilder.buildServiceRegistry( settings );

View File

@ -22,6 +22,7 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.SQLServer2012Dialect; import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl; import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
@ -82,15 +83,16 @@ public class SQLServerDialectSequenceInformationTest extends BaseUnitTestCase {
ssrb.applySettings( Collections.singletonMap( AvailableSettings.URL, newUrl ) ); ssrb.applySettings( Collections.singletonMap( AvailableSettings.URL, newUrl ) );
StandardServiceRegistry ssr = ssrb.build(); StandardServiceRegistry ssr = ssrb.build();
try ( Connection connection = ssr.getService( JdbcServices.class ) final JdbcConnectionAccess bootstrapJdbcConnectionAccess = ssr.getService( JdbcServices.class )
.getBootstrapJdbcConnectionAccess() .getBootstrapJdbcConnectionAccess();
.obtainConnection() ) {
try ( Connection connection = bootstrapJdbcConnectionAccess.obtainConnection() ) {
try (Statement statement = connection.createStatement()) { try (Statement statement = connection.createStatement()) {
statement.execute( "CREATE SEQUENCE ITEM_SEQ START WITH 100 INCREMENT BY 10" ); statement.execute( "CREATE SEQUENCE ITEM_SEQ START WITH 100 INCREMENT BY 10" );
} }
JdbcEnvironment jdbcEnvironment = new JdbcEnvironmentImpl( connection.getMetaData(), dialect ); JdbcEnvironment jdbcEnvironment = new JdbcEnvironmentImpl( connection.getMetaData(), dialect, bootstrapJdbcConnectionAccess );
Iterable<SequenceInformation> sequenceInformations = SequenceInformationExtractorLegacyImpl.INSTANCE.extractMetadata( Iterable<SequenceInformation> sequenceInformations = SequenceInformationExtractorLegacyImpl.INSTANCE.extractMetadata(
new ExtractionContext.EmptyExtractionContext() { new ExtractionContext.EmptyExtractionContext() {
@Override @Override

View File

@ -93,6 +93,30 @@ public class OraclePaginationWithLocksTest {
); );
} }
@Test
public void testNativeQueryWithSpaces(SessionFactoryScope scope) {
scope.inTransaction( session -> {
final List<Person> people = session.createNativeQuery(
"select p.name from Person p where p.id = 1 for update" )
.setMaxResults( 10 )
.list();
} );
scope.inTransaction( session -> {
Person p = new Person();
p.setName( " this is a string with spaces " );
session.persist( p );
} );
scope.inTransaction( session -> {
final List<Person> people = session.createNativeQuery(
"select p.name from Person p where p.name = ' this is a string with spaces ' for update" )
.setMaxResults( 10 )
.list();
assertEquals( 1, people.size() );
} );
}
@Test @Test
public void testCriteriaQuery(SessionFactoryScope scope) { public void testCriteriaQuery(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(

View File

@ -56,10 +56,11 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices, ServiceRegistr
dialect = ConnectionProviderBuilder.getCorrespondingDialect(); dialect = ConnectionProviderBuilder.getCorrespondingDialect();
connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease ); connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease );
sqlStatementLogger = new SqlStatementLogger( true, false, false ); sqlStatementLogger = new SqlStatementLogger( true, false, false );
this.jdbcConnectionAccess = new JdbcConnectionAccessImpl( connectionProvider );
Connection jdbcConnection = connectionProvider.getConnection(); Connection jdbcConnection = connectionProvider.getConnection();
try { try {
jdbcEnvironment = new JdbcEnvironmentImpl( jdbcConnection.getMetaData(), dialect ); jdbcEnvironment = new JdbcEnvironmentImpl( jdbcConnection.getMetaData(), dialect, jdbcConnectionAccess );
} }
finally { finally {
try { try {
@ -69,7 +70,6 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices, ServiceRegistr
} }
} }
this.jdbcConnectionAccess = new JdbcConnectionAccessImpl( connectionProvider );
} }
public void release() { public void release() {