GH-804 - Polishing.
Actively reject attempts to use a dedicated schema with SQL Server. Prevent schema reset being executed if no schema is used. Properly report exception during database name detection. Original pull request: GH-808.
This commit is contained in:
@@ -67,8 +67,9 @@ class DatabaseSchemaInitializer implements InitializingBean {
|
|||||||
|
|
||||||
var initialSchema = connection.getSchema();
|
var initialSchema = connection.getSchema();
|
||||||
var schemaName = properties.getSchema();
|
var schemaName = properties.getSchema();
|
||||||
|
var useSchema = schemaName != null && !schemaName.isEmpty();
|
||||||
|
|
||||||
if (schemaName != null && !schemaName.isEmpty()) { // A schema name has been specified.
|
if (useSchema) { // A schema name has been specified.
|
||||||
|
|
||||||
if (eventPublicationTableExists(schemaName)) {
|
if (eventPublicationTableExists(schemaName)) {
|
||||||
return;
|
return;
|
||||||
@@ -82,7 +83,7 @@ class DatabaseSchemaInitializer implements InitializingBean {
|
|||||||
new ResourceDatabasePopulator(locator.getSchemaResource(databaseType)).execute(dataSource);
|
new ResourceDatabasePopulator(locator.getSchemaResource(databaseType)).execute(dataSource);
|
||||||
|
|
||||||
// Return to the initial schema.
|
// Return to the initial schema.
|
||||||
if (initialSchema != null) {
|
if (initialSchema != null && useSchema) {
|
||||||
jdbcOperations.execute(databaseType.getSetSchemaSql(initialSchema));
|
jdbcOperations.execute(databaseType.getSetSchemaSql(initialSchema));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,11 +43,16 @@ enum DatabaseType {
|
|||||||
UUID databaseToUUID(Object id) {
|
UUID databaseToUUID(Object id) {
|
||||||
return UUID.fromString(id.toString());
|
return UUID.fromString(id.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isSchemaSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
POSTGRES("postgresql", "PostgreSQL"),
|
POSTGRES("postgresql", "PostgreSQL"),
|
||||||
|
|
||||||
MSSQL("sqlserver", "Microsoft SQL Server"){
|
MSSQL("sqlserver", "Microsoft SQL Server") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Object uuidToDatabase(UUID id) {
|
Object uuidToDatabase(UUID id) {
|
||||||
@@ -58,6 +63,11 @@ enum DatabaseType {
|
|||||||
UUID databaseToUUID(Object id) {
|
UUID databaseToUUID(Object id) {
|
||||||
return UUID.fromString(id.toString());
|
return UUID.fromString(id.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isSchemaSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static final String SCHEMA_NOT_SUPPORTED = "Setting the schema name not supported on MySQL!";
|
static final String SCHEMA_NOT_SUPPORTED = "Setting the schema name not supported on MySQL!";
|
||||||
@@ -92,14 +102,21 @@ enum DatabaseType {
|
|||||||
return "/schema-" + value + ".sql";
|
return "/schema-" + value + ".sql";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isSchemaSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
String getSetSchemaSql(String schema) {
|
String getSetSchemaSql(String schema) {
|
||||||
|
|
||||||
|
if (!isSchemaSupported()) {
|
||||||
|
throw new IllegalArgumentException(SCHEMA_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
|
||||||
return switch (this) {
|
return switch (this) {
|
||||||
|
|
||||||
case MYSQL -> throw new IllegalArgumentException(SCHEMA_NOT_SUPPORTED);
|
|
||||||
case H2, HSQLDB -> "SET SCHEMA " + schema;
|
case H2, HSQLDB -> "SET SCHEMA " + schema;
|
||||||
case POSTGRES -> "SET search_path TO " + schema;
|
case POSTGRES -> "SET search_path TO " + schema;
|
||||||
case MSSQL -> ""; // No equivalent schema-switching command in MSSQL
|
default -> throw new IllegalArgumentException(SCHEMA_NOT_SUPPORTED);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class JdbcConfigurationProperties {
|
|||||||
|
|
||||||
void verify(DatabaseType databaseType) {
|
void verify(DatabaseType databaseType) {
|
||||||
|
|
||||||
if (schema != null && databaseType.equals(DatabaseType.MYSQL)) {
|
if (schema != null && !databaseType.isSchemaSupported()) {
|
||||||
throw new IllegalStateException(DatabaseType.SCHEMA_NOT_SUPPORTED);
|
throw new IllegalStateException(DatabaseType.SCHEMA_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,9 @@ class JdbcEventPublicationAutoConfiguration implements EventPublicationConfigura
|
|||||||
var metadata = JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductName);
|
var metadata = JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductName);
|
||||||
name = JdbcUtils.commonDatabaseName(metadata);
|
name = JdbcUtils.commonDatabaseName(metadata);
|
||||||
|
|
||||||
} catch (Exception o_O) {}
|
} catch (Exception o_O) {
|
||||||
|
throw new RuntimeException(o_O);
|
||||||
|
}
|
||||||
|
|
||||||
return name == null ? "UNKNOWN" : name;
|
return name == null ? "UNKNOWN" : name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ CREATE TABLE EVENT_PUBLICATION
|
|||||||
COMPLETION_DATE DATETIME2(6) NULL,
|
COMPLETION_DATE DATETIME2(6) NULL,
|
||||||
PRIMARY KEY (ID),
|
PRIMARY KEY (ID),
|
||||||
INDEX EVENT_PUBLICATION_BY_COMPLETION_DATE_IDX (COMPLETION_DATE)
|
INDEX EVENT_PUBLICATION_BY_COMPLETION_DATE_IDX (COMPLETION_DATE)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,11 +44,18 @@ class DatabaseSchemaInitializerUnitTests {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(strings = { "", "test" })
|
@ValueSource(strings = { "", "test" })
|
||||||
void rejectsExplicitSchemaNameForMySql(String schema) {
|
void rejectsExplicitSchemaNameForMySql(String schema) {
|
||||||
assertThatIllegalStateException().isThrownBy(() -> createInitializer(withSchema(schema)));
|
assertThatIllegalStateException().isThrownBy(() -> createInitializer(withSchema(schema), DatabaseType.MYSQL));
|
||||||
}
|
}
|
||||||
|
|
||||||
private DatabaseSchemaInitializer createInitializer(JdbcConfigurationProperties properties) {
|
// GH-804
|
||||||
return new DatabaseSchemaInitializer(dataSource, resourceLoader, DatabaseType.MYSQL, jdbcTemplate, properties);
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = { "", "test" })
|
||||||
|
void rejectsExplicitSchemaNameForMSSql(String schema) {
|
||||||
|
assertThatIllegalStateException().isThrownBy(() -> createInitializer(withSchema(schema), DatabaseType.MSSQL));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DatabaseSchemaInitializer createInitializer(JdbcConfigurationProperties properties, DatabaseType type) {
|
||||||
|
return new DatabaseSchemaInitializer(dataSource, resourceLoader, type, jdbcTemplate, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JdbcConfigurationProperties withSchema(String schema) {
|
private static JdbcConfigurationProperties withSchema(String schema) {
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.junit.jupiter.api.Nested;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
|
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
|
||||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.jdbc.core.JdbcOperations;
|
import org.springframework.jdbc.core.JdbcOperations;
|
||||||
import org.springframework.modulith.events.core.EventSerializer;
|
import org.springframework.modulith.events.core.EventSerializer;
|
||||||
@@ -46,6 +45,7 @@ import org.springframework.modulith.events.support.CompletionMode;
|
|||||||
import org.springframework.modulith.testapp.TestApplication;
|
import org.springframework.modulith.testapp.TestApplication;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -454,11 +454,9 @@ class JdbcEventPublicationRepositoryIntegrationTests {
|
|||||||
class PostgresWithDeleteCompletion extends WithDeleteCompletion {}
|
class PostgresWithDeleteCompletion extends WithDeleteCompletion {}
|
||||||
|
|
||||||
// MSSQL
|
// MSSQL
|
||||||
@WithMssql
|
|
||||||
class MssqlWithNoDefinedSchemaName extends WithNoDefinedSchemaName {}
|
|
||||||
|
|
||||||
@WithMssql
|
@WithMssql
|
||||||
class MssqlWithEmptySchemaName extends WithEmptySchemaName {}
|
class MssqlWithNoDefinedSchemaName extends WithNoDefinedSchemaName {}
|
||||||
|
|
||||||
@WithMssql
|
@WithMssql
|
||||||
class MssqlWithDeleteCompletion extends WithDeleteCompletion {}
|
class MssqlWithDeleteCompletion extends WithDeleteCompletion {}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
spring.datasource.url=jdbc:tc:sqlserver:2022-latest:///events;encrypt=false;TC_ACCEPT_LICENSE=accept
|
spring.datasource.url=jdbc:tc:sqlserver:2022-latest:///events;encrypt=false
|
||||||
spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver
|
spring.datasource.driverClassName=org.testcontainers.jdbc.ContainerDatabaseDriver
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
mcr.microsoft.com/mssql/server:2022-latest
|
||||||
Reference in New Issue
Block a user