From 1e5a72f1f827dbfbd7921ed320514fc99c2c7a3f Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 4 Aug 2023 15:50:00 +0200 Subject: [PATCH] Provide nested cause if datasource fails to provide DatabaseDriver Closes gh-34728 --- .../boot/jdbc/DatabaseDriver.java | 2 ++ ...formPlaceholderDatabaseDriverResolver.java | 14 +++++++++++--- ...laceholderDatabaseDriverResolverTests.java | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java index f99188e9e1..57c15839fc 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DatabaseDriver.java @@ -328,7 +328,9 @@ public enum DatabaseDriver { * @param dataSource data source to inspect * @return the database driver of {@link #UNKNOWN} if not found * @since 2.6.0 + * @deprecated since 2.7.15 for removal in 3.3.0 with no replacement */ + @Deprecated public static DatabaseDriver fromDataSource(DataSource dataSource) { try { String productName = JdbcUtils.commonDatabaseName( diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolver.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolver.java index 67fb0edb15..bd1121b49d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolver.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.boot.jdbc.init; +import java.sql.DatabaseMetaData; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -26,6 +27,7 @@ import java.util.function.Supplier; import javax.sql.DataSource; import org.springframework.boot.jdbc.DatabaseDriver; +import org.springframework.jdbc.support.JdbcUtils; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -89,7 +91,6 @@ public class PlatformPlaceholderDatabaseDriverResolver { * @param dataSource the DataSource from which the {@link DatabaseDriver} is derived * @param values the values in which placeholders are resolved * @return the values with their placeholders resolved - * @see DatabaseDriver#fromDataSource(DataSource) */ public List resolveAll(DataSource dataSource, String... values) { Assert.notNull(dataSource, "DataSource must not be null"); @@ -134,7 +135,14 @@ public class PlatformPlaceholderDatabaseDriverResolver { } DatabaseDriver getDatabaseDriver(DataSource dataSource) { - return DatabaseDriver.fromDataSource(dataSource); + try { + String productName = JdbcUtils.commonDatabaseName( + JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductName)); + return DatabaseDriver.fromProductName(productName); + } + catch (Exception ex) { + throw new IllegalStateException("Failed to determine DatabaseDriver", ex); + } } } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolverTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolverTests.java index 0cbea0e61a..3bd44b62b3 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolverTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/init/PlatformPlaceholderDatabaseDriverResolverTests.java @@ -29,6 +29,7 @@ import org.springframework.boot.jdbc.DatabaseDriver; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.mock; /** @@ -68,6 +69,24 @@ class PlatformPlaceholderDatabaseDriverResolverTests { .containsExactly("schema.sql"); } + @Test + void resolveAllWithDataSourceWhenValueDoesNotContainPlaceholderShouldNotInteractWithDataSource() { + DataSource dataSource = mock(DataSource.class); + new PlatformPlaceholderDatabaseDriverResolver().resolveAll(mock(DataSource.class), "schema.sql"); + then(dataSource).shouldHaveNoInteractions(); + } + + @Test + void resolveAllWithFailingDataSourceWhenValuesContainPlaceholdersShouldThrowNestedCause() throws SQLException { + DataSource dataSource = mock(DataSource.class); + given(dataSource.getConnection()).willThrow(new IllegalStateException("Test: invalid password")); + assertThatIllegalStateException() + .isThrownBy(() -> new PlatformPlaceholderDatabaseDriverResolver().resolveAll(dataSource, "schema.sql", + "schema-@@platform@@.sql", "data-@@platform@@.sql")) + .withMessage("Failed to determine DatabaseDriver") + .withStackTraceContaining("Test: invalid password"); + } + @Test void resolveAllWithDataSourceWhenValuesContainPlaceholdersShouldReturnValuesWithPlaceholdersReplaced() throws SQLException {