Skip to content

Commit efb106e

Browse files
committed
QUARKUS-3363 - Disable JDBC Metadata Defaults in quarkus
Handle Hibernate's `DialectSpecificSettings` as supported Quarkus settings
1 parent 46aa8b3 commit efb106e

File tree

10 files changed

+196
-149
lines changed

10 files changed

+196
-149
lines changed

docs/src/main/asciidoc/_attributes.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
:quickstarts-tree-url: ${quickstarts-base-url}/tree/main
5353
// .
5454
:hibernate-orm-docs-url: https://docs.jboss.org/hibernate/orm/{hibernate-orm-version-major-minor}/userguide/html_single/Hibernate_User_Guide.html
55+
:hibernate-orm-javadocs-url: https://docs.jboss.org/hibernate/orm/{hibernate-orm-version-major-minor}/javadocs/
5556
:hibernate-orm-dialect-docs-url: https://docs.jboss.org/hibernate/orm/{hibernate-orm-version-major-minor}/dialect/dialect.html
5657
:hibernate-search-docs-url: https://docs.jboss.org/hibernate/search/{hibernate-search-version-major-minor}/reference/en-US/html_single/
5758
// .

extensions/datasource/common/src/main/java/io/quarkus/datasource/common/runtime/DatabaseKind.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public static boolean is(String value, String mainName) {
9797
private DatabaseKind() {
9898
}
9999

100-
private enum SupportedDatabaseKind {
100+
public enum SupportedDatabaseKind {
101101
DB2(DatabaseKind.DB2),
102102
DERBY(DatabaseKind.DERBY),
103103
H2(DatabaseKind.H2),

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/CockroachDialectConfig.java

Lines changed: 0 additions & 25 deletions
This file was deleted.

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HANADialectConfig.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmConfigPersistenceUnit.java

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ interface HibernateOrmConfigPersistenceUnitDialect {
310310
*
311311
* E.g. `MyISAM` or `InnoDB` for MySQL.
312312
*
313-
* @deprecated Use {@code mysql.}{@linkplain MySQLDialectConfig#storageEngine storage-engine} instead
313+
* @deprecated Use {@code mysql.}{@linkplain MySQLDialectConfig#storageEngine storage-engine}
314+
* or {@code mariadb.}{@linkplain MySQLDialectConfig#storageEngine storage-engine} instead
314315
*
315316
* @asciidoclet
316317
*/
@@ -319,43 +320,30 @@ interface HibernateOrmConfigPersistenceUnitDialect {
319320
Optional<String> storageEngine();
320321

321322
/**
322-
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.CockroachDialect}
323+
* Configuration specific to Hibernate's Dialect for MariaDB
323324
*/
324-
CockroachDialectConfig cockroach();
325+
MySQLDialectConfig mariadb();
325326

326327
/**
327-
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.HANADialect}
328-
*/
329-
HANADialectConfig hana();
330-
331-
/**
332-
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.MySQLDialect}
328+
* Configuration specific to Hibernate's Dialect for MySQL
333329
*/
334330
MySQLDialectConfig mysql();
335331

336332
/**
337-
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.OracleDialect}
333+
* Configuration specific to Hibernate's Dialect for Oracle
338334
*/
339335
OracleDialectConfig oracle();
340336

341337
/**
342-
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.SQLServerDialect}
343-
*/
344-
SqlServerDialectConfig sqlserver();
345-
346-
/**
347-
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.SybaseDialect}
338+
* Configuration specific to Hibernate's Dialect for Microsoft SQLServer
348339
*/
349-
SybaseDialectConfig sybase();
340+
SqlServerDialectConfig mssql();
350341

351342
default boolean isAnyPropertySet() {
352343
return dialect().isPresent() || storageEngine().isPresent()
353-
|| cockroach().isAnyPropertySet()
354-
|| hana().isAnyPropertySet()
355344
|| mysql().isAnyPropertySet()
356345
|| oracle().isAnyPropertySet()
357-
|| sqlserver().isAnyPropertySet()
358-
|| sybase().isAnyPropertySet();
346+
|| mssql().isAnyPropertySet();
359347
}
360348
}
361349

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java

Lines changed: 165 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
import javax.xml.namespace.QName;
4545

46+
import io.quarkus.datasource.common.runtime.DatabaseKind.SupportedDatabaseKind;
4647
import jakarta.enterprise.context.ApplicationScoped;
4748
import jakarta.enterprise.inject.Default;
4849
import jakarta.persistence.SharedCacheMode;
@@ -1209,49 +1210,179 @@ private static void handleDialectSpecificSettings(
12091210
Optional<String> dbKind,
12101211
Optional<String> dialect) {
12111212

1212-
// todo : do we want dbKind/dialect aware handling for all of these settings (i.e. isMySQLOrMariaDB)?
1213-
// if so, we need to reorganize this code a bit
1213+
final Optional<SupportedDatabaseKind> databaseKind = determineDatabaseKind( dbKind, dialect);
12141214

1215-
final Optional<String> storageEngine = dialectConfig.mysql().storageEngine()
1216-
.or(() -> dialectConfig.storageEngine().or(Optional::empty));
1217-
if (isMySQLOrMariaDB(dbKind, dialect)) {
1218-
if (storageEngine.isPresent()) {
1219-
storageEngineCollector.add(storageEngine.get());
1220-
systemProperties.produce(new SystemPropertyBuildItem(AvailableSettings.STORAGE_ENGINE, storageEngine.get()));
1215+
handleStorageEngine( databaseKind, persistenceUnitName, dialectConfig, storageEngineCollector,
1216+
puPropertiesCollector, systemProperties );
1217+
1218+
if ( dialectConfig.mariadb().bytesPerCharacter().isPresent()
1219+
|| dialectConfig.mariadb().noBackslashEscapes().isPresent() ) {
1220+
if ( databaseKind.isPresent() && databaseKind.get() != SupportedDatabaseKind.MARIADB ) {
1221+
LOG.warnf( "MariaDB specific settings being ignored because the database is not MariaDB." );
12211222
}
1222-
applyOptionalIntegerSetting(dialectConfig.mysql().bytesPerCharacter(), MYSQL_BYTES_PER_CHARACTER,
1223-
puPropertiesCollector);
1224-
applyOptionalBooleanSetting(dialectConfig.mysql().noBackslashEscapes(), MYSQL_NO_BACKSLASH_ESCAPES,
1225-
puPropertiesCollector);
1226-
} else {
1227-
if (storageEngine.isPresent()) {
1228-
LOG.warnf("The storage engine set through configuration property '%1$s' is being ignored"
1229-
+ " because the database is neither MySQL nor MariaDB.",
1230-
HibernateOrmRuntimeConfig.puPropertyKey(persistenceUnitName, "dialect.storage-engine"));
1223+
else {
1224+
applyOptionalIntegerSetting(dialectConfig.mariadb().bytesPerCharacter(), MYSQL_BYTES_PER_CHARACTER,
1225+
puPropertiesCollector);
1226+
applyOptionalBooleanSetting(dialectConfig.mariadb().noBackslashEscapes(), MYSQL_NO_BACKSLASH_ESCAPES,
1227+
puPropertiesCollector);
1228+
}
1229+
}
1230+
1231+
if ( dialectConfig.mysql().bytesPerCharacter().isPresent()
1232+
|| dialectConfig.mysql().noBackslashEscapes().isPresent() ) {
1233+
if ( databaseKind.isPresent() && databaseKind.get() != SupportedDatabaseKind.MYSQL ) {
1234+
LOG.warnf( "MariaDB specific settings being ignored because the database is not MySQL." );
1235+
}
1236+
else {
1237+
applyOptionalIntegerSetting(dialectConfig.mysql().bytesPerCharacter(), MYSQL_BYTES_PER_CHARACTER,
1238+
puPropertiesCollector);
1239+
applyOptionalBooleanSetting(dialectConfig.mysql().noBackslashEscapes(), MYSQL_NO_BACKSLASH_ESCAPES,
1240+
puPropertiesCollector);
1241+
}
1242+
}
1243+
1244+
if ( dialectConfig.oracle().isAnyPropertySet() ) {
1245+
if ( databaseKind.isPresent() && databaseKind.get() != SupportedDatabaseKind.ORACLE ) {
1246+
LOG.warnf( "Oracle specific settings being ignored because the database is not Oracle." );
1247+
}
1248+
else {
1249+
applyOptionalBooleanSetting(dialectConfig.oracle().applicationContinuity(), ORACLE_APPLICATION_CONTINUITY,
1250+
puPropertiesCollector);
1251+
applyOptionalBooleanSetting(dialectConfig.oracle().autonomous(), ORACLE_AUTONOMOUS_DATABASE,
1252+
puPropertiesCollector);
1253+
applyOptionalBooleanSetting(dialectConfig.oracle().extended(), ORACLE_EXTENDED_STRING_SIZE,
1254+
puPropertiesCollector);
1255+
}
1256+
}
1257+
1258+
if ( dialectConfig.mssql().isAnyPropertySet() ) {
1259+
if ( databaseKind.isPresent() && databaseKind.get() != SupportedDatabaseKind.MSSQL ) {
1260+
LOG.warnf( "SQL Server specific settings being ignored because the database is not SQL Server." );
12311261
}
1262+
else {
1263+
applyOptionalStringSetting( dialectConfig.mssql().compatibilityLevel(), SQL_SERVER_COMPATIBILITY_LEVEL,
1264+
puPropertiesCollector);
1265+
}
1266+
}
1267+
}
1268+
1269+
private static Optional<SupportedDatabaseKind> determineDatabaseKind(Optional<String> dbKind, Optional<String> dialect) {
1270+
if ( dbKind.isPresent() ) {
1271+
final String databaseKindName = DatabaseKind.normalize( dbKind.get() );
1272+
final SupportedDatabaseKind resolved = determineDatabaseKind( databaseKindName );
1273+
if ( resolved != null ) {
1274+
return Optional.of( resolved );
1275+
}
1276+
}
1277+
1278+
if ( dialect.isPresent() ) {
1279+
String lowercaseDialect = dialect.get().toLowerCase(Locale.ROOT);
1280+
final SupportedDatabaseKind resolved = determineDatabaseKind( lowercaseDialect );
1281+
if ( resolved != null ) {
1282+
return Optional.of( resolved );
1283+
}
1284+
}
1285+
1286+
return Optional.empty();
1287+
}
1288+
1289+
private static SupportedDatabaseKind determineDatabaseKind(String name) {
1290+
if ( name.contains( "db2" ) ) {
1291+
return SupportedDatabaseKind.DB2;
1292+
}
1293+
if ( name.contains( "derby" ) ) {
1294+
return SupportedDatabaseKind.DERBY;
1295+
}
1296+
if ( name.contains( "h2" ) ) {
1297+
return SupportedDatabaseKind.H2;
1298+
}
1299+
if ( name.contains( "mariadb" ) ) {
1300+
return SupportedDatabaseKind.MARIADB;
1301+
}
1302+
if ( name.contains( "mssql" ) || name.contains( "sqlserver" ) ) {
1303+
return SupportedDatabaseKind.MSSQL;
1304+
}
1305+
if ( name.contains( "mysql" ) ) {
1306+
return SupportedDatabaseKind.MYSQL;
1307+
}
1308+
if ( name.contains( "oracle" ) ) {
1309+
return SupportedDatabaseKind.ORACLE;
1310+
}
1311+
if ( name.contains( "postgresql" ) ) {
1312+
return SupportedDatabaseKind.POSTGRESQL;
1313+
}
1314+
1315+
return null;
1316+
}
12321317

1233-
applyOptionalStringSetting(dialectConfig.cockroach().versionString(), COCKROACH_VERSION_STRING,
1234-
puPropertiesCollector);
1318+
private static void handleStorageEngine(
1319+
Optional<SupportedDatabaseKind> supportedDatabaseKind,
1320+
String persistenceUnitName,
1321+
HibernateOrmConfigPersistenceUnit.HibernateOrmConfigPersistenceUnitDialect dialectConfig,
1322+
Set<String> storageEngineCollector,
1323+
BiConsumer<String, String> puPropertiesCollector,
1324+
BuildProducer<SystemPropertyBuildItem> systemProperties) {
12351325

1236-
applyOptionalIntegerSetting(dialectConfig.hana().maxLobPrefetchSize(), HANA_MAX_LOB_PREFETCH_SIZE,
1237-
puPropertiesCollector);
1326+
final String topLevelStorageEngine = dialectConfig.storageEngine().orElse( null );
12381327

1239-
applyOptionalIntegerSetting(dialectConfig.mysql().bytesPerCharacter(), MYSQL_BYTES_PER_CHARACTER,
1240-
puPropertiesCollector);
1241-
applyOptionalBooleanSetting(dialectConfig.mysql().noBackslashEscapes(), MYSQL_NO_BACKSLASH_ESCAPES,
1242-
puPropertiesCollector);
1328+
if ( topLevelStorageEngine != null ) {
1329+
// NOTE: this top-level storage-engine setting is deprecated - log a warning
1330+
LOG.warnf(
1331+
"The storage engine set through configuration property '%1$s' is no longer supported; "
1332+
+ "use '%1$s' or '%1$s' instead, depending on the database.",
1333+
HibernateOrmRuntimeConfig.puPropertyKey( persistenceUnitName, "dialect.mariadb.storage-engine" ),
1334+
HibernateOrmRuntimeConfig.puPropertyKey( persistenceUnitName, "dialect.mysql.storage-engine" )
1335+
);
1336+
}
12431337

1244-
applyOptionalBooleanSetting(dialectConfig.oracle().applicationContinuity(), ORACLE_APPLICATION_CONTINUITY,
1245-
puPropertiesCollector);
1246-
applyOptionalBooleanSetting(dialectConfig.oracle().autonomous(), ORACLE_AUTONOMOUS_DATABASE,
1247-
puPropertiesCollector);
1248-
applyOptionalBooleanSetting(dialectConfig.oracle().extended(), ORACLE_EXTENDED_STRING_SIZE,
1249-
puPropertiesCollector);
1338+
// if we know this is mariadb and any non-mariadb settings are set, ...
1339+
// todo : what? log a warning? exception?
12501340

1251-
applyOptionalStringSetting(dialectConfig.sqlserver().compatibilityLevel(), SQL_SERVER_COMPATIBILITY_LEVEL,
1252-
puPropertiesCollector);
1341+
final String mariaDbStorageEngine = dialectConfig.mariadb().storageEngine().orElse( topLevelStorageEngine );
1342+
final String mysqlDbStorageEngine = dialectConfig.mysql().storageEngine().orElse( topLevelStorageEngine );
1343+
if ( supportedDatabaseKind.isPresent() && supportedDatabaseKind.get() == SupportedDatabaseKind.MARIADB ) {
1344+
if ( mariaDbStorageEngine != null ) {
1345+
storageEngineCollector.add(mariaDbStorageEngine);
1346+
systemProperties.produce(new SystemPropertyBuildItem(AvailableSettings.STORAGE_ENGINE, mariaDbStorageEngine));
1347+
}
1348+
}
1349+
else if ( supportedDatabaseKind.isPresent() && supportedDatabaseKind.get() == SupportedDatabaseKind.MYSQL ) {
1350+
if ( mysqlDbStorageEngine != null ) {
1351+
storageEngineCollector.add(mysqlDbStorageEngine);
1352+
systemProperties.produce(new SystemPropertyBuildItem(AvailableSettings.STORAGE_ENGINE, mysqlDbStorageEngine));
1353+
}
1354+
}
1355+
else {
1356+
final String storageEngine;
1357+
final String storageEngineSource;
1358+
if ( topLevelStorageEngine != null ) {
1359+
storageEngine = topLevelStorageEngine;
1360+
storageEngineSource = HibernateOrmRuntimeConfig.puPropertyKey(persistenceUnitName, "dialect.storage-engine");
1361+
}
1362+
else if ( mariaDbStorageEngine != null ) {
1363+
storageEngine = mariaDbStorageEngine;
1364+
storageEngineSource = HibernateOrmRuntimeConfig.puPropertyKey(persistenceUnitName, "dialect.mariadb.storage-engine");
1365+
}
1366+
else if ( mysqlDbStorageEngine != null ) {
1367+
storageEngine = mysqlDbStorageEngine;
1368+
storageEngineSource = HibernateOrmRuntimeConfig.puPropertyKey(persistenceUnitName, "dialect.mysql.storage-engine");
1369+
}
1370+
else {
1371+
storageEngine = null;
1372+
storageEngineSource = null;
1373+
}
12531374

1254-
applyOptionalBooleanSetting(dialectConfig.sybase().ansinull(), SYBASE_ANSI_NULL, puPropertiesCollector);
1375+
if ( storageEngine != null ) {
1376+
if ( supportedDatabaseKind.isPresent() ) {
1377+
LOG.warnf(
1378+
"The storage engine set through configuration property '%1$s', is being ignored"
1379+
+ " because the database is neither MySQL nor MariaDB.",
1380+
storageEngineSource);
1381+
}
1382+
else {
1383+
systemProperties.produce(new SystemPropertyBuildItem(AvailableSettings.STORAGE_ENGINE, storageEngine));
1384+
}
1385+
}
12551386
}
12561387
}
12571388

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/MySQLDialectConfig.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,28 @@
88
import io.smallrye.config.WithConverter;
99

1010
/**
11-
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.MySQLDialect},
12-
* though may also affect other dialects such as {@linkplain org.hibernate.dialect.MariaDBDialect}.
13-
*
14-
* @author Steve Ebersole
11+
* Configuration specific to the Hibernate ORM {@linkplain org.hibernate.dialect.MySQLDialect}
12+
* and {@linkplain org.hibernate.dialect.MariaDBDialect}.
1513
*/
1614
@ConfigGroup
1715
public interface MySQLDialectConfig {
1816
/**
1917
* Specifies the bytes per character to use based on the database's configured
2018
* <a href="https://dev.mysql.com/doc/refman/8.0/en/charset-charsets.html">charset</a>.
2119
*
22-
* @see org.hibernate.cfg.DialectSpecificSettings#MYSQL_BYTES_PER_CHARACTER
20+
* See link:{hibernate-orm-javadocs-url}/org/hibernate/cfg/DialectSpecificSettings.html#MYSQL_BYTES_PER_CHARACTER[MYSQL_BYTES_PER_CHARACTER]
21+
*
22+
* @asciidoctor
2323
*/
2424
@ConfigDocDefault("4")
2525
Optional<Integer> bytesPerCharacter();
2626

2727
/**
2828
* Specifies whether the {@code NO_BACKSLASH_ESCAPES} sql mode is enabled.
2929
*
30-
* @see org.hibernate.cfg.DialectSpecificSettings#MYSQL_NO_BACKSLASH_ESCAPES
30+
* See link:{hibernate-orm-javadocs-url}/org/hibernate/cfg/DialectSpecificSettings.html#MYSQL_NO_BACKSLASH_ESCAPES[MYSQL_NO_BACKSLASH_ESCAPES]
31+
*
32+
* @asciidoctor
3133
*/
3234
@ConfigDocDefault("false")
3335
Optional<Boolean> noBackslashEscapes();

0 commit comments

Comments
 (0)