Skip to content

Commit e54a6e1

Browse files
committed
HHH-18463 Add AzureDialect and determine SQL Server version based on compatibility level
1 parent 5550c20 commit e54a6e1

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

hibernate-core/src/main/java/org/hibernate/cfg/DialectSpecificSettings.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ public interface DialectSpecificSettings {
6767
*/
6868
public static final String COCKROACH_VERSION_STRING = "hibernate.dialect.cockroach.version_string";
6969

70+
/**
71+
* Specifies the compatibility level of the SQL Server database as returned by {@code select compatibility_level from sys.databases}.
72+
* The number has three digits, the first two digits are the major version, the last digit is the minor version.
73+
*/
74+
public static final String SQL_SERVER_COMPATIBILITY_LEVEL = "hibernate.dialect.sqlserver.compatibility_level";
75+
7076
/**
7177
* Specifies the LOB prefetch size. LOBs larger than this value will be read into memory as the HANA JDBC driver closes
7278
* the LOB when the result set is closed.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.dialect;
8+
9+
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
10+
11+
/**
12+
* A {@linkplain Dialect SQL dialect} for Azure SQL Server.
13+
*/
14+
public class AzureSQLServerDialect extends SQLServerDialect {
15+
16+
public AzureSQLServerDialect() {
17+
// Azure SQL Server always is the latest version, so default to a high number
18+
super( DatabaseVersion.make( Integer.MAX_VALUE ) );
19+
}
20+
21+
public AzureSQLServerDialect(DialectResolutionInfo info) {
22+
this();
23+
registerKeywords( info );
24+
}
25+
}

hibernate-core/src/main/java/org/hibernate/dialect/SQLServerDialect.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package org.hibernate.dialect;
88

99
import java.sql.DatabaseMetaData;
10+
import java.sql.ResultSet;
1011
import java.sql.SQLException;
1112
import java.sql.Types;
1213
import java.time.temporal.ChronoField;
@@ -40,6 +41,7 @@
4041
import org.hibernate.dialect.unique.AlterTableUniqueIndexDelegate;
4142
import org.hibernate.dialect.unique.UniqueDelegate;
4243
import org.hibernate.engine.jdbc.Size;
44+
import org.hibernate.engine.jdbc.dialect.spi.BasicSQLExceptionConverter;
4345
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
4446
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
4547
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
@@ -52,6 +54,7 @@
5254
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
5355
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
5456
import org.hibernate.internal.util.JdbcExceptionHelper;
57+
import org.hibernate.internal.util.config.ConfigurationHelper;
5558
import org.hibernate.mapping.Column;
5659
import org.hibernate.persister.entity.mutation.EntityMutationTarget;
5760
import org.hibernate.procedure.internal.SQLServerCallableStatementSupport;
@@ -89,6 +92,7 @@
8992

9093
import jakarta.persistence.TemporalType;
9194

95+
import static org.hibernate.cfg.DialectSpecificSettings.SQL_SERVER_COMPATIBILITY_LEVEL;
9296
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
9397
import static org.hibernate.query.sqm.TemporalUnit.NANOSECOND;
9498
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER;
@@ -174,8 +178,36 @@ public SQLServerDialect(DatabaseVersion version) {
174178
}
175179

176180
public SQLServerDialect(DialectResolutionInfo info) {
177-
super(info);
178-
exporter = createSequenceExporter(info);
181+
this( determineDatabaseVersion( info ) );
182+
registerKeywords( info );
183+
}
184+
185+
private static DatabaseVersion determineDatabaseVersion(DialectResolutionInfo info) {
186+
final Integer compatibilityLevel = getCompatibilityLevel( info );
187+
if ( compatibilityLevel != null ) {
188+
final int majorVersion = compatibilityLevel / 10;
189+
final int minorVersion = compatibilityLevel % 10;
190+
return DatabaseVersion.make( majorVersion, minorVersion );
191+
}
192+
return info.makeCopyOrDefault( MINIMUM_VERSION );
193+
}
194+
195+
private static Integer getCompatibilityLevel(DialectResolutionInfo info) {
196+
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
197+
if ( databaseMetaData != null ) {
198+
try ( java.sql.Statement statement = databaseMetaData.getConnection().createStatement() ) {
199+
final ResultSet rs = statement.executeQuery( "SELECT compatibility_level FROM sys.databases where name = db_name();" );
200+
if ( rs.next() ) {
201+
return rs.getInt( 1 );
202+
}
203+
}
204+
catch (SQLException e) {
205+
throw BasicSQLExceptionConverter.INSTANCE.convert( e );
206+
}
207+
}
208+
209+
// default to the dialect-specific configuration setting
210+
return ConfigurationHelper.getInteger( SQL_SERVER_COMPATIBILITY_LEVEL, info.getConfigurationValues() );
179211
}
180212

181213
private StandardSequenceExporter createSequenceExporter(DatabaseVersion version) {

0 commit comments

Comments
 (0)