HHH-18669 - resolve the driver name from the connection metadata, in case it wasn't explicitly set and access to the database metadata is allowed

Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
Jan Schatteman 2024-10-07 22:59:34 +02:00 committed by Jan Schatteman
parent 3b40e53c4b
commit bcac1e3299
4 changed files with 70 additions and 6 deletions

View File

@ -6,10 +6,11 @@ package org.hibernate.agroal.internal;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.DatabaseMetaData;
import javax.sql.DataSource;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.sql.DataSource;
import org.hibernate.HibernateException;
import org.hibernate.cfg.AgroalSettings;
@ -33,6 +34,7 @@ import io.agroal.api.security.NamePrincipal;
import io.agroal.api.security.SimplePassword;
import static org.hibernate.cfg.AgroalSettings.AGROAL_CONFIG_PREFIX;
import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess;
/**
* ConnectionProvider based on Agroal connection pool
@ -61,6 +63,7 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl
public static final String CONFIG_PREFIX = AGROAL_CONFIG_PREFIX + ".";
private static final long serialVersionUID = 1L;
private AgroalDataSource agroalDataSource = null;
private boolean isMetadataAccessAllowed = true;
// --- Configurable
@ -89,6 +92,8 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl
@Override
public void configure(Map<String, Object> props) throws HibernateException {
isMetadataAccessAllowed = allowJdbcMetadataAccess( props );
ConnectionInfoLogger.INSTANCE.configureConnectionPool( "Agroal" );
try {
AgroalPropertiesReader agroalProperties = new AgroalPropertiesReader( CONFIG_PREFIX )
@ -136,9 +141,12 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl
final AgroalConnectionPoolConfiguration acpc = agroalDataSource.getConfiguration().connectionPoolConfiguration();
final AgroalConnectionFactoryConfiguration acfc = acpc.connectionFactoryConfiguration();
return new DatabaseConnectionInfoImpl(
acfc.jdbcUrl(),
acfc.connectionProviderClass().toString(),
// Attempt to resolve the driver name from the dialect, in case it wasn't explicitly set and access to
// the database metadata is allowed
acfc.connectionProviderClass() != null ? acfc.connectionProviderClass().toString() : extractDriverNameFromMetadata(),
dialect.getVersion(),
Boolean.toString( acfc.autoCommit() ),
acfc.jdbcTransactionIsolation() != null
@ -149,6 +157,19 @@ public class AgroalConnectionProvider implements ConnectionProvider, Configurabl
);
}
private String extractDriverNameFromMetadata() {
if (isMetadataAccessAllowed) {
try ( Connection conn = getConnection() ) {
DatabaseMetaData dbmd = conn.getMetaData();
return dbmd.getDriverName();
}
catch (SQLException e) {
// Do nothing
}
}
return null;
}
@Override
public boolean isUnwrappableAs(Class<?> unwrapType) {
return ConnectionProvider.class.equals( unwrapType )

View File

@ -216,7 +216,7 @@ public class JdbcEnvironmentInitiator implements StandardServiceInitiator<JdbcEn
*
* @see JdbcSettings#ALLOW_METADATA_ON_BOOT
*/
private static boolean allowJdbcMetadataAccess(Map<String, Object> configurationValues) {
public static boolean allowJdbcMetadataAccess(Map<String, Object> configurationValues) {
final Boolean allow = getBooleanWrapper( ALLOW_METADATA_ON_BOOT, configurationValues, null );
if ( allow != null ) {
return allow;

View File

@ -5,9 +5,10 @@
package org.hibernate.hikaricp.internal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;
import javax.sql.DataSource;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
@ -15,6 +16,7 @@ import org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo;
import org.hibernate.internal.log.ConnectionInfoLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable;
@ -22,6 +24,8 @@ import org.hibernate.service.spi.Stoppable;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess;
/**
* HikariCP Connection provider for Hibernate.
*
@ -31,6 +35,7 @@ import com.zaxxer.hikari.HikariDataSource;
public class HikariCPConnectionProvider implements ConnectionProvider, Configurable, Stoppable {
private static final long serialVersionUID = -9131625057941275711L;
private boolean isMetadataAccessAllowed = true;
/**
* HikariCP configuration.
@ -49,6 +54,8 @@ public class HikariCPConnectionProvider implements ConnectionProvider, Configura
@Override
public void configure(Map<String, Object> props) throws HibernateException {
try {
isMetadataAccessAllowed = allowJdbcMetadataAccess( props );
ConnectionInfoLogger.INSTANCE.configureConnectionPool( "HikariCP" );
hcfg = HikariConfigurationUtil.loadConfiguration( props );
@ -83,7 +90,9 @@ public class HikariCPConnectionProvider implements ConnectionProvider, Configura
public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
return new DatabaseConnectionInfoImpl(
hcfg.getJdbcUrl(),
hcfg.getDriverClassName(),
// Attempt to resolve the driver name from the dialect, in case it wasn't explicitly set and access to
// the database metadata is allowed
!StringHelper.isBlank( hcfg.getDriverClassName() ) ? hcfg.getDriverClassName() : extractDriverNameFromMetadata(),
dialect.getVersion(),
Boolean.toString( hcfg.isAutoCommit() ),
hcfg.getTransactionIsolation(),
@ -92,6 +101,19 @@ public class HikariCPConnectionProvider implements ConnectionProvider, Configura
);
}
private String extractDriverNameFromMetadata() {
if (isMetadataAccessAllowed) {
try ( Connection conn = getConnection() ) {
DatabaseMetaData dbmd = conn.getMetaData();
return dbmd.getDriverName();
}
catch (SQLException e) {
// Do nothing
}
}
return null;
}
@Override
public boolean isUnwrappableAs(Class<?> unwrapType) {
return ConnectionProvider.class.equals( unwrapType )

View File

@ -5,6 +5,7 @@
package org.hibernate.vibur.internal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
@ -14,6 +15,7 @@ import org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo;
import org.hibernate.internal.log.ConnectionInfoLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable;
@ -26,6 +28,7 @@ import static org.hibernate.cfg.AvailableSettings.ISOLATION;
import static org.hibernate.cfg.AvailableSettings.PASS;
import static org.hibernate.cfg.AvailableSettings.URL;
import static org.hibernate.cfg.AvailableSettings.USER;
import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess;
/**
* <p>ViburDBCP connection provider for Hibernate integration.
@ -57,9 +60,12 @@ public class ViburDBCPConnectionProvider implements ConnectionProvider, Configur
private static final String VIBUR_PREFIX = VIBUR_CONFIG_PREFIX + ".";
private ViburDBCPDataSource dataSource = null;
private boolean isMetadataAccessAllowed = true;
@Override
public void configure(Map<String, Object> configurationValues) {
isMetadataAccessAllowed = allowJdbcMetadataAccess( configurationValues );
ConnectionInfoLogger.INSTANCE.configureConnectionPool( "Vibur" );
dataSource = new ViburDBCPDataSource( transform( configurationValues ) );
@ -94,7 +100,9 @@ public class ViburDBCPConnectionProvider implements ConnectionProvider, Configur
public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
return new DatabaseConnectionInfoImpl(
dataSource.getJdbcUrl(),
dataSource.getDriverClassName(),
// Attempt to resolve the driver name from the dialect, in case it wasn't explicitly set and access to
// the database metadata is allowed
!StringHelper.isBlank( dataSource.getDriverClassName() ) ? dataSource.getDriverClassName() : extractDriverNameFromMetadata(),
dialect.getVersion(),
String.valueOf( dataSource.getDefaultAutoCommit() ),
dataSource.getDefaultTransactionIsolation(),
@ -103,6 +111,19 @@ public class ViburDBCPConnectionProvider implements ConnectionProvider, Configur
);
}
private String extractDriverNameFromMetadata() {
if (isMetadataAccessAllowed) {
try ( Connection conn = getConnection() ) {
DatabaseMetaData dbmd = conn.getMetaData();
return dbmd.getDriverName();
}
catch (SQLException e) {
// Do nothing
}
}
return null;
}
@Override
public boolean isUnwrappableAs(Class<?> unwrapType) {
return ConnectionProvider.class.equals( unwrapType )