HHH-18463 Add AzureDialect and determine SQL Server version based on compatibility level

This commit is contained in:
Christian Beikov 2024-08-07 14:29:55 +02:00
parent 5550c20120
commit e54a6e15b2
3 changed files with 65 additions and 2 deletions

View File

@ -67,6 +67,12 @@ public interface DialectSpecificSettings {
*/
public static final String COCKROACH_VERSION_STRING = "hibernate.dialect.cockroach.version_string";
/**
* Specifies the compatibility level of the SQL Server database as returned by {@code select compatibility_level from sys.databases}.
* The number has three digits, the first two digits are the major version, the last digit is the minor version.
*/
public static final String SQL_SERVER_COMPATIBILITY_LEVEL = "hibernate.dialect.sqlserver.compatibility_level";
/**
* Specifies the LOB prefetch size. LOBs larger than this value will be read into memory as the HANA JDBC driver closes
* the LOB when the result set is closed.

View File

@ -0,0 +1,25 @@
/*
* 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.dialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
/**
* A {@linkplain Dialect SQL dialect} for Azure SQL Server.
*/
public class AzureSQLServerDialect extends SQLServerDialect {
public AzureSQLServerDialect() {
// Azure SQL Server always is the latest version, so default to a high number
super( DatabaseVersion.make( Integer.MAX_VALUE ) );
}
public AzureSQLServerDialect(DialectResolutionInfo info) {
this();
registerKeywords( info );
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.dialect;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.temporal.ChronoField;
@ -40,6 +41,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.unique.AlterTableUniqueIndexDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.dialect.spi.BasicSQLExceptionConverter;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
@ -52,6 +54,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.mapping.Column;
import org.hibernate.persister.entity.mutation.EntityMutationTarget;
import org.hibernate.procedure.internal.SQLServerCallableStatementSupport;
@ -89,6 +92,7 @@ import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
import jakarta.persistence.TemporalType;
import static org.hibernate.cfg.DialectSpecificSettings.SQL_SERVER_COMPATIBILITY_LEVEL;
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
import static org.hibernate.query.sqm.TemporalUnit.NANOSECOND;
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER;
@ -174,8 +178,36 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
}
public SQLServerDialect(DialectResolutionInfo info) {
super(info);
exporter = createSequenceExporter(info);
this( determineDatabaseVersion( info ) );
registerKeywords( info );
}
private static DatabaseVersion determineDatabaseVersion(DialectResolutionInfo info) {
final Integer compatibilityLevel = getCompatibilityLevel( info );
if ( compatibilityLevel != null ) {
final int majorVersion = compatibilityLevel / 10;
final int minorVersion = compatibilityLevel % 10;
return DatabaseVersion.make( majorVersion, minorVersion );
}
return info.makeCopyOrDefault( MINIMUM_VERSION );
}
private static Integer getCompatibilityLevel(DialectResolutionInfo info) {
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
if ( databaseMetaData != null ) {
try ( java.sql.Statement statement = databaseMetaData.getConnection().createStatement() ) {
final ResultSet rs = statement.executeQuery( "SELECT compatibility_level FROM sys.databases where name = db_name();" );
if ( rs.next() ) {
return rs.getInt( 1 );
}
}
catch (SQLException e) {
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
}
}
// default to the dialect-specific configuration setting
return ConfigurationHelper.getInteger( SQL_SERVER_COMPATIBILITY_LEVEL, info.getConfigurationValues() );
}
private StandardSequenceExporter createSequenceExporter(DatabaseVersion version) {