Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 36f8fb5

Browse files
committed
HHH-19710 Add vector support for SAP HANA Cloud
1 parent af843e0 commit 36f8fb5

File tree

12 files changed

+601
-19
lines changed

12 files changed

+601
-19
lines changed

‎hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HANALegacyDialect.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ private LockingSupport buildLockingSupport() {
216216

217217
@Override
218218
public DatabaseVersion determineDatabaseVersion(DialectResolutionInfo info) {
219-
return HANALegacyServerConfiguration.staticDetermineDatabaseVersion( info );
219+
return HANALegacyServerConfiguration.determineDatabaseVersion( info );
220220
}
221221

222222
// Use column or row tables by default

‎hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HANALegacyServerConfiguration.java

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@
88
import java.sql.ResultSet;
99
import java.sql.SQLException;
1010
import java.sql.Statement;
11+
import java.time.LocalDate;
12+
import java.util.regex.Matcher;
13+
import java.util.regex.Pattern;
1114

1215
import org.hibernate.dialect.DatabaseVersion;
16+
import org.hibernate.dialect.SimpleDatabaseVersion;
1317
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
1418
import org.hibernate.internal.CoreLogging;
1519
import org.hibernate.internal.CoreMessageLogger;
@@ -24,6 +28,7 @@
2428
public class HANALegacyServerConfiguration {
2529

2630
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( HANALegacyServerConfiguration.class );
31+
private static final Pattern CLOUD_VERSION_PATTERN = Pattern.compile( "\\(fa/CE(\\d+)\\.(\\d+)\\)" );
2732
public static final int MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE = 1024;
2833

2934
private final DatabaseVersion fullVersion;
@@ -49,22 +54,39 @@ public int getMaxLobPrefetchSize() {
4954
public static HANALegacyServerConfiguration fromDialectResolutionInfo(DialectResolutionInfo info) {
5055
Integer maxLobPrefetchSize = null;
5156
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
57+
DatabaseVersion databaseVersion = null;
5258
if ( databaseMetaData != null ) {
53-
try (final Statement statement = databaseMetaData.getConnection().createStatement()) {
54-
try ( ResultSet rs = statement.executeQuery(
55-
"SELECT TOP 1 VALUE,MAP(LAYER_NAME,'DEFAULT',1,'SYSTEM',2,'DATABASE',3,4) AS LAYER FROM SYS.M_INIFILE_CONTENTS WHERE FILE_NAME='indexserver.ini' AND SECTION='session' AND KEY='max_lob_prefetch_size' ORDER BY LAYER DESC" ) ) {
56-
// This only works if the current user has the privilege INIFILE ADMIN
57-
if ( rs.next() ) {
58-
maxLobPrefetchSize = rs.getInt( 1 );
59-
}
60-
}
59+
int databaseMajorVersion = -1;
60+
try {
61+
databaseMajorVersion = databaseMetaData.getDatabaseMajorVersion();
6162
}
6263
catch (SQLException e) {
6364
// Ignore
6465
LOG.debug(
65-
"An error occurred while trying to determine the value of the HANA parameter indexserver.ini / session / max_lob_prefetch_size.",
66+
"An error occurred while trying to determine the database version.",
6667
e );
6768
}
69+
70+
if (databaseMajorVersion > 0 && databaseMajorVersion < 4) {
71+
try (final Statement statement = databaseMetaData.getConnection().createStatement()) {
72+
try ( ResultSet rs = statement.executeQuery(
73+
"SELECT TOP 1 VALUE,MAP(LAYER_NAME,'DEFAULT',1,'SYSTEM',2,'DATABASE',3,4) AS LAYER FROM SYS.M_CONFIGURATION_PARAMETER_VALUES WHERE FILE_NAME='indexserver.ini' AND SECTION='session' AND KEY='max_lob_prefetch_size' ORDER BY LAYER DESC" ) ) {
74+
// This only works if the current user has the privilege INIFILE ADMIN
75+
if ( rs.next() ) {
76+
maxLobPrefetchSize = rs.getInt( 1 );
77+
}
78+
}
79+
}
80+
catch (SQLException e) {
81+
// Ignore
82+
LOG.debug(
83+
"An error occurred while trying to determine the value of the HANA parameter indexserver.ini / session / max_lob_prefetch_size.",
84+
e );
85+
}
86+
}
87+
else {
88+
databaseVersion = determineDatabaseVersion( info );
89+
}
6890
}
6991
// default to the dialect-specific configuration settings
7092
if ( maxLobPrefetchSize == null ) {
@@ -74,12 +96,78 @@ public static HANALegacyServerConfiguration fromDialectResolutionInfo(DialectRes
7496
MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE
7597
);
7698
}
77-
return new HANALegacyServerConfiguration( staticDetermineDatabaseVersion( info ), maxLobPrefetchSize );
99+
if ( databaseVersion == null ) {
100+
databaseVersion = staticDetermineDatabaseVersion( info );
101+
}
102+
return new HANALegacyServerConfiguration( databaseVersion, maxLobPrefetchSize );
103+
}
104+
105+
public static DatabaseVersion determineDatabaseVersion(DialectResolutionInfo info) {
106+
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
107+
String databaseVersion = null;
108+
if ( databaseMetaData != null ) {
109+
try (final Statement statement = databaseMetaData.getConnection().createStatement()) {
110+
try (ResultSet rs = statement.executeQuery(
111+
"SELECT VALUE FROM M_SYSTEM_OVERVIEW WHERE NAME='Version'" )) {
112+
// This only works if the current user has the privilege INIFILE ADMIN
113+
if ( rs.next() ) {
114+
databaseVersion = rs.getString( 1 );
115+
}
116+
}
117+
}
118+
catch (SQLException e) {
119+
// Ignore
120+
LOG.debug( "An error occurred while trying to determine the HANA Cloud version.", e );
121+
}
122+
}
123+
return databaseVersion == null
124+
? staticDetermineDatabaseVersion( info )
125+
: determineDatabaseVersion( databaseVersion );
126+
}
127+
128+
public static DatabaseVersion determineDatabaseVersion(String versionString) {
129+
if ( versionString == null ) {
130+
return HANALegacyDialect.DEFAULT_VERSION;
131+
}
132+
final String[] components = StringHelper.split( " ", versionString );
133+
final DatabaseVersion databaseVersion = staticDetermineDatabaseVersion( components[0] );
134+
if ( components.length == 1 || databaseVersion.isBefore( 4 ) ) {
135+
return databaseVersion;
136+
}
137+
else {
138+
// Parse the HANA Cloud version
139+
final Matcher matcher = CLOUD_VERSION_PATTERN.matcher( components[1] );
140+
if ( matcher.matches() ) {
141+
final int year = Integer.parseInt( matcher.group( 1 ) );
142+
final int week = Integer.parseInt( matcher.group( 2 ) );
143+
return new SimpleDatabaseVersion(
144+
databaseVersion.getDatabaseMajorVersion(),
145+
getHanaCloudVersion( LocalDate.of( year, 1, 1 ).plusWeeks( week ) ),
146+
databaseVersion.getDatabaseMicroVersion()
147+
);
148+
}
149+
else {
150+
return databaseVersion;
151+
}
152+
}
153+
}
154+
155+
private static int getHanaCloudVersion(LocalDate date) {
156+
final int quarter = switch (date.getMonth()) {
157+
case JANUARY, FEBRUARY, MARCH -> 1;
158+
case APRIL, MAY, JUNE -> 2;
159+
case JULY, AUGUST, SEPTEMBER -> 3;
160+
case OCTOBER, NOVEMBER, DECEMBER -> 4;
161+
};
162+
return date.getYear() * 10 + quarter;
163+
}
164+
165+
public static DatabaseVersion staticDetermineDatabaseVersion(DialectResolutionInfo info) {
166+
return staticDetermineDatabaseVersion( info.getDatabaseVersion() );
78167
}
79168

80-
static DatabaseVersion staticDetermineDatabaseVersion(DialectResolutionInfoinfo) {
169+
publicstatic DatabaseVersion staticDetermineDatabaseVersion(StringversionString) {
81170
// Parse the version according to https://answers.sap.com/questions/9760991/hana-sps-version-check.html
82-
final String versionString = info.getDatabaseVersion();
83171
int majorVersion = 1;
84172
int minorVersion = 0;
85173
int patchLevel = 0;

‎hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ protected DatabaseVersion getMinimumSupportedVersion() {
217217

218218
@Override
219219
public DatabaseVersion determineDatabaseVersion(DialectResolutionInfo info) {
220-
return HANAServerConfiguration.staticDetermineDatabaseVersion( info );
220+
return HANAServerConfiguration.determineDatabaseVersion( info );
221221
}
222222

223223
// Use column or row tables by default

‎hibernate-core/src/main/java/org/hibernate/dialect/HANAServerConfiguration.java

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import java.sql.ResultSet;
99
import java.sql.SQLException;
1010
import java.sql.Statement;
11+
import java.time.LocalDate;
12+
import java.util.regex.Matcher;
13+
import java.util.regex.Pattern;
1114

1215
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
1316
import org.hibernate.internal.CoreLogging;
@@ -23,6 +26,7 @@
2326
public class HANAServerConfiguration {
2427

2528
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( HANAServerConfiguration.class );
29+
private static final Pattern CLOUD_VERSION_PATTERN = Pattern.compile( "\\(fa/CE(\\d+)\\.(\\d+)\\)" );
2630
public static final int MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE = 1024;
2731

2832
private final DatabaseVersion fullVersion;
@@ -48,6 +52,7 @@ public int getMaxLobPrefetchSize() {
4852
public static HANAServerConfiguration fromDialectResolutionInfo(DialectResolutionInfo info) {
4953
Integer maxLobPrefetchSize = null;
5054
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
55+
DatabaseVersion databaseVersion = null;
5156
if ( databaseMetaData != null ) {
5257
int databaseMajorVersion = -1;
5358
try {
@@ -77,6 +82,9 @@ public static HANAServerConfiguration fromDialectResolutionInfo(DialectResolutio
7782
e );
7883
}
7984
}
85+
else {
86+
databaseVersion = determineDatabaseVersion( info );
87+
}
8088
}
8189
// default to the dialect-specific configuration settings
8290
if ( maxLobPrefetchSize == null ) {
@@ -86,12 +94,78 @@ public static HANAServerConfiguration fromDialectResolutionInfo(DialectResolutio
8694
MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE
8795
);
8896
}
89-
return new HANAServerConfiguration( staticDetermineDatabaseVersion( info ), maxLobPrefetchSize );
97+
if ( databaseVersion == null ) {
98+
databaseVersion = staticDetermineDatabaseVersion( info );
99+
}
100+
return new HANAServerConfiguration( databaseVersion, maxLobPrefetchSize );
101+
}
102+
103+
public static DatabaseVersion determineDatabaseVersion(DialectResolutionInfo info) {
104+
final DatabaseMetaData databaseMetaData = info.getDatabaseMetadata();
105+
String databaseVersion = null;
106+
if ( databaseMetaData != null ) {
107+
try (final Statement statement = databaseMetaData.getConnection().createStatement()) {
108+
try (ResultSet rs = statement.executeQuery(
109+
"SELECT VALUE FROM M_SYSTEM_OVERVIEW WHERE NAME='Version'" )) {
110+
// This only works if the current user has the privilege INIFILE ADMIN
111+
if ( rs.next() ) {
112+
databaseVersion = rs.getString( 1 );
113+
}
114+
}
115+
}
116+
catch (SQLException e) {
117+
// Ignore
118+
LOG.debug( "An error occurred while trying to determine the HANA Cloud version.", e );
119+
}
120+
}
121+
return databaseVersion == null
122+
? staticDetermineDatabaseVersion( info )
123+
: determineDatabaseVersion( databaseVersion );
124+
}
125+
126+
public static DatabaseVersion determineDatabaseVersion(String versionString) {
127+
if ( versionString == null ) {
128+
return HANADialect.MINIMUM_VERSION;
129+
}
130+
final String[] components = StringHelper.split( " ", versionString );
131+
final DatabaseVersion databaseVersion = staticDetermineDatabaseVersion( components[0] );
132+
if ( components.length == 1 || databaseVersion.isBefore( 4 ) ) {
133+
return databaseVersion;
134+
}
135+
else {
136+
// Parse the HANA Cloud version
137+
final Matcher matcher = CLOUD_VERSION_PATTERN.matcher( components[1] );
138+
if ( matcher.matches() ) {
139+
final int year = Integer.parseInt( matcher.group( 1 ) );
140+
final int week = Integer.parseInt( matcher.group( 2 ) );
141+
return new SimpleDatabaseVersion(
142+
databaseVersion.getDatabaseMajorVersion(),
143+
getHanaCloudVersion( LocalDate.of( year, 1, 1 ).plusWeeks( week ) ),
144+
databaseVersion.getDatabaseMicroVersion()
145+
);
146+
}
147+
else {
148+
return databaseVersion;
149+
}
150+
}
151+
}
152+
153+
private static int getHanaCloudVersion(LocalDate date) {
154+
final int quarter = switch (date.getMonth()) {
155+
case JANUARY, FEBRUARY, MARCH -> 1;
156+
case APRIL, MAY, JUNE -> 2;
157+
case JULY, AUGUST, SEPTEMBER -> 3;
158+
case OCTOBER, NOVEMBER, DECEMBER -> 4;
159+
};
160+
return date.getYear() * 10 + quarter;
161+
}
162+
163+
public static DatabaseVersion staticDetermineDatabaseVersion(DialectResolutionInfo info) {
164+
return staticDetermineDatabaseVersion( info.getDatabaseVersion() );
90165
}
91166

92-
static DatabaseVersion staticDetermineDatabaseVersion(DialectResolutionInfoinfo) {
167+
publicstatic DatabaseVersion staticDetermineDatabaseVersion(StringversionString) {
93168
// Parse the version according to https://answers.sap.com/questions/9760991/hana-sps-version-check.html
94-
final String versionString = info.getDatabaseVersion();
95169
int majorVersion = 1;
96170
int minorVersion = 0;
97171
int patchLevel = 0;

‎hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/ArrayJdbcType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public <T> JavaType<T> getJdbcRecommendedJavaTypeMapping(
8181
}
8282
}
8383

84-
private static JavaType<?> elementJavaType(JavaType<?> javaTypeDescriptor) {
84+
protected static JavaType<?> elementJavaType(JavaType<?> javaTypeDescriptor) {
8585
if ( javaTypeDescriptor instanceof ByteArrayJavaType ) {
8686
// Special handling needed for Byte[], because that would conflict with the VARBINARY mapping
8787
return ByteJavaType.INSTANCE;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.orm.test.dialect.unit;
6+
7+
import org.hibernate.dialect.DatabaseVersion;
8+
import org.hibernate.dialect.HANADialect;
9+
import org.hibernate.dialect.HANAServerConfiguration;
10+
import org.hibernate.testing.orm.junit.RequiresDialect;
11+
import org.junit.jupiter.api.Test;
12+
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
import static org.junit.jupiter.api.Assertions.assertNotNull;
15+
16+
@RequiresDialect(HANADialect.class)
17+
public class HANADialectVersionTest {
18+
19+
@Test
20+
public void testStaticVersion() {
21+
// HANA database 2.0 SPS 07
22+
DatabaseVersion dv = HANAServerConfiguration.staticDetermineDatabaseVersion( "2.00.076.00.1705400033" );
23+
assertEquals( 2, dv.getMajor() );
24+
assertEquals( 0, dv.getMinor() );
25+
assertEquals( 76, dv.getMicro() );
26+
27+
// HANA Cloud version QRC 3/2024
28+
dv = HANAServerConfiguration.staticDetermineDatabaseVersion( "4.00.000.00.1730808477" );
29+
assertNotNull( dv );
30+
assertEquals( 4, dv.getMajor() );
31+
assertEquals( 0, dv.getMinor() );
32+
assertEquals( 0, dv.getMicro() );
33+
34+
// HANA Cloud version QRC 2/2025
35+
dv = HANAServerConfiguration.staticDetermineDatabaseVersion( "4.00.000.00.1755603748" );
36+
assertNotNull( dv );
37+
assertEquals( 4, dv.getMajor() );
38+
assertEquals( 0, dv.getMinor() );
39+
assertEquals( 0, dv.getMicro() );
40+
}
41+
42+
@Test
43+
public void testDynamicVersion() {
44+
// HANA database 2.0 SPS 07
45+
DatabaseVersion dv = HANAServerConfiguration.determineDatabaseVersion( "2.00.076.00.1705400033 (fa/hana2sp07)" );
46+
assertEquals( 2, dv.getMajor() );
47+
assertEquals( 0, dv.getMinor() );
48+
assertEquals( 76, dv.getMicro() );
49+
50+
// HANA Cloud version QRC 3/2024
51+
dv = HANAServerConfiguration.determineDatabaseVersion( "4.00.000.00.1730808477 (fa/CE2024.42)" );
52+
assertNotNull( dv );
53+
assertEquals( 4, dv.getMajor() );
54+
assertEquals( 2024_4, dv.getMinor() );
55+
assertEquals( 0, dv.getMicro() );
56+
57+
// HANA Cloud version QRC 2/2025
58+
dv = HANAServerConfiguration.determineDatabaseVersion( "4.00.000.00.1755603748 (fa/CE2025.14)" );
59+
assertNotNull( dv );
60+
assertEquals( 4, dv.getMajor() );
61+
assertEquals( 2025_2, dv.getMinor() );
62+
assertEquals( 0, dv.getMicro() );
63+
}
64+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /