diff --git a/pom.xml b/pom.xml index ad15c2b..208b26a 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ 0.8.5.RELEASE 7.1.2.jre8-preview 2.5.4 - Arabba-SR12 + Borca-BUILD-SNAPSHOT 1.0.3 4.1.63.Final @@ -224,7 +224,7 @@ - io.r2dbc + org.postgresql r2dbc-postgresql true @@ -241,12 +241,6 @@ test - - dev.miku - r2dbc-mysql - test - - org.mariadb r2dbc-mariadb diff --git a/src/test/java/org/springframework/data/r2dbc/connectionfactory/init/H2DatabasePopulatorIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/connectionfactory/init/H2DatabasePopulatorIntegrationTests.java index 94ceb76..18867db 100644 --- a/src/test/java/org/springframework/data/r2dbc/connectionfactory/init/H2DatabasePopulatorIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/connectionfactory/init/H2DatabasePopulatorIntegrationTests.java @@ -23,6 +23,8 @@ import java.util.UUID; import org.junit.jupiter.api.Test; +import org.springframework.core.io.Resource; + /** * Integration tests for {@link DatabasePopulator} using H2. * @@ -40,6 +42,10 @@ class H2DatabasePopulatorIntegrationTests extends AbstractDatabaseInitialization return this.connectionFactory; } + Resource usersSchema() { + return resource("users-schema-h2.sql"); + } + @Test void shouldRunScript() { diff --git a/src/test/java/org/springframework/data/r2dbc/core/MariaDbDatabaseClientIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/core/MariaDbDatabaseClientIntegrationTests.java index 96e62db..f65d43f 100644 --- a/src/test/java/org/springframework/data/r2dbc/core/MariaDbDatabaseClientIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/core/MariaDbDatabaseClientIntegrationTests.java @@ -27,6 +27,7 @@ import java.util.UUID; import javax.sql.DataSource; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -146,6 +147,11 @@ public class MariaDbDatabaseClientIntegrationTests extends AbstractDatabaseClien .verifyComplete(); } + @Override + @Test + @Disabled + public void insertTypedObjectWithBinary() {} + @Table("boolean_mapping") @Data static class BooleanMapping { diff --git a/src/test/java/org/springframework/data/r2dbc/core/MySqlDatabaseClientIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/core/MySqlDatabaseClientIntegrationTests.java deleted file mode 100644 index 8662160..0000000 --- a/src/test/java/org/springframework/data/r2dbc/core/MySqlDatabaseClientIntegrationTests.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2019-2021 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.r2dbc.core; - -import static org.assertj.core.api.Assertions.*; - -import io.r2dbc.spi.ConnectionFactory; -import lombok.Data; -import reactor.test.StepVerifier; - -import java.util.Arrays; -import java.util.Collections; -import java.util.UUID; - -import javax.sql.DataSource; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.dao.DataAccessException; -import org.springframework.data.annotation.Id; -import org.springframework.data.convert.ReadingConverter; -import org.springframework.data.convert.WritingConverter; -import org.springframework.data.r2dbc.dialect.MySqlDialect; -import org.springframework.data.r2dbc.testing.ExternalDatabase; -import org.springframework.data.r2dbc.testing.MySqlTestSupport; -import org.springframework.data.relational.core.mapping.Table; -import org.springframework.data.relational.core.query.Criteria; -import org.springframework.jdbc.core.JdbcTemplate; - -/** - * Integration tests for {@link DatabaseClient} against MySQL. - * - * @author Mark Paluch - * @author Mingyuan Wu - */ -public class MySqlDatabaseClientIntegrationTests extends AbstractDatabaseClientIntegrationTests { - - @RegisterExtension public static final ExternalDatabase database = MySqlTestSupport.database(); - - @Override - protected DataSource createDataSource() { - return MySqlTestSupport.createDataSource(database); - } - - @Override - protected ConnectionFactory createConnectionFactory() { - return MySqlTestSupport.createConnectionFactory(database); - } - - @Override - protected String getCreateTableStatement() { - return MySqlTestSupport.CREATE_TABLE_LEGOSET; - } - - @Test // gh-166 - public void considersBuiltInConverters() { - - ConnectionFactory connectionFactory = createConnectionFactory(); - JdbcTemplate jdbc = createJdbcTemplate(createDataSource()); - - try { - jdbc.execute("DROP TABLE boolean_mapping"); - } catch (DataAccessException e) {} - jdbc.execute("CREATE TABLE boolean_mapping (id int, flag1 TINYINT, flag2 TINYINT)"); - - BooleanMapping mapping = new BooleanMapping(); - mapping.setId(42); - mapping.setFlag1(true); - - DatabaseClient databaseClient = DatabaseClient.create(connectionFactory); - - databaseClient.insert().into(BooleanMapping.class).using(mapping).then() // - .as(StepVerifier::create) // - .verifyComplete(); - - databaseClient.select().from(BooleanMapping.class).fetch().first() // - .as(StepVerifier::create) // - .consumeNextWith(actual -> assertThat(actual.isFlag1()).isTrue()) // - .verifyComplete(); - } - - @Test // gh-305 - public void shouldApplyCustomConverters() { - - ConnectionFactory connectionFactory = createConnectionFactory(); - JdbcTemplate jdbc = createJdbcTemplate(createDataSource()); - ReactiveDataAccessStrategy strategy = new DefaultReactiveDataAccessStrategy(MySqlDialect.INSTANCE, - Arrays.asList(UuidToStringConverter.INSTANCE, StringToUuidConverter.INSTANCE)); - - try { - jdbc.execute("DROP TABLE uuid_type"); - } catch (DataAccessException e) {} - jdbc.execute("CREATE TABLE uuid_type (id varchar(255), uuid_value varchar(255))"); - - UuidType uuidType = new UuidType(); - uuidType.setId(UUID.randomUUID()); - uuidType.setUuidValue(UUID.randomUUID()); - - DatabaseClient databaseClient = DatabaseClient.builder().connectionFactory(connectionFactory) - .dataAccessStrategy(strategy).build(); - - databaseClient.insert().into(UuidType.class).using(uuidType).then() // - .as(StepVerifier::create) // - .verifyComplete(); - - databaseClient.select().from(UuidType.class).matching(Criteria.where("id").is(uuidType.getId())) // - .fetch().first() // - .as(StepVerifier::create) // - .consumeNextWith(actual -> assertThat(actual.getUuidValue()).isEqualTo(uuidType.getUuidValue())) // - .verifyComplete(); - - uuidType.setUuidValue(null); - databaseClient.update().table(UuidType.class).using(uuidType).then() // - .as(StepVerifier::create) // - .verifyComplete(); - - databaseClient.execute("SELECT * FROM uuid_type WHERE id = ?") // - .bind(0, uuidType.getId()) // - .as(UuidType.class) // - .fetch().first() // - .as(StepVerifier::create) // - .consumeNextWith(actual -> assertThat(actual.getUuidValue()).isNull()) // - .verifyComplete(); - - databaseClient.execute("SELECT * FROM uuid_type WHERE id in (:ids)") // - .bind("ids", Collections.singleton(uuidType.getId())) // - .as(UuidType.class) // - .fetch().first() // - .as(StepVerifier::create) // - .consumeNextWith(actual -> assertThat(actual.getUuidValue()).isNull()) // - .verifyComplete(); - } - - @Table("boolean_mapping") - @Data - static class BooleanMapping { - - int id; - boolean flag1; - boolean flag2; - } - - @Table("uuid_type") - @Data - static class UuidType { - - @Id UUID id; - UUID uuidValue; - } - - @WritingConverter - enum UuidToStringConverter implements Converter { - INSTANCE; - - @Override - public String convert(UUID uuid) { - return uuid.toString(); - } - } - - @ReadingConverter - enum StringToUuidConverter implements Converter { - INSTANCE; - - @Override - public UUID convert(String value) { - return UUID.fromString(value); - } - } - -} diff --git a/src/test/java/org/springframework/data/r2dbc/core/MySqlTransactionalDatabaseClientIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/core/MySqlTransactionalDatabaseClientIntegrationTests.java deleted file mode 100644 index b26b48f..0000000 --- a/src/test/java/org/springframework/data/r2dbc/core/MySqlTransactionalDatabaseClientIntegrationTests.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2019-2021 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.r2dbc.core; - -import io.r2dbc.spi.ConnectionFactory; -import reactor.core.publisher.Mono; - -import java.time.Duration; - -import javax.sql.DataSource; - -import org.junit.jupiter.api.extension.RegisterExtension; - -import org.springframework.data.r2dbc.testing.ExternalDatabase; -import org.springframework.data.r2dbc.testing.MySqlTestSupport; -import org.springframework.r2dbc.core.DatabaseClient; - -/** - * Transactional integration tests for {@link DatabaseClient} against MySQL. - * - * @author Mark Paluch - */ -public class MySqlTransactionalDatabaseClientIntegrationTests - extends AbstractTransactionalDatabaseClientIntegrationTests { - - @RegisterExtension public static final ExternalDatabase database = MySqlTestSupport.database(); - - @Override - protected DataSource createDataSource() { - return MySqlTestSupport.createDataSource(database); - } - - @Override - protected ConnectionFactory createConnectionFactory() { - return MySqlTestSupport.createConnectionFactory(database); - } - - @Override - protected String getCreateTableStatement() { - return MySqlTestSupport.CREATE_TABLE_LEGOSET; - } - - @Override - protected Mono prepareForTransaction(DatabaseClient client) { - - /* - * We have to execute a sql statement first. - * Otherwise MySql don't have a transaction id. - * And we need to delay emitting the result so that MySql has time to write the transaction id, which is done in - * batches every now and then. - * @see: https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-internal-data.html - */ - return client.sql(getInsertIntoLegosetStatement()) // - .bind(0, 42055) // - .bind(1, "SCHAUFELRADBAGGER") // - .bindNull(2, Integer.class) // - .fetch().rowsUpdated() // - .delayElement(Duration.ofMillis(50)) // - .then(); - } - - @Override - protected String getCurrentTransactionIdStatement() { - return "SELECT tx.trx_id FROM information_schema.innodb_trx tx WHERE tx.trx_mysql_thread_id = connection_id()"; - } -} diff --git a/src/test/java/org/springframework/data/r2dbc/dialect/DialectResolverUnitTests.java b/src/test/java/org/springframework/data/r2dbc/dialect/DialectResolverUnitTests.java index 278ef51..8453408 100644 --- a/src/test/java/org/springframework/data/r2dbc/dialect/DialectResolverUnitTests.java +++ b/src/test/java/org/springframework/data/r2dbc/dialect/DialectResolverUnitTests.java @@ -2,8 +2,6 @@ package org.springframework.data.r2dbc.dialect; import static org.assertj.core.api.Assertions.*; -import dev.miku.r2dbc.mysql.MySqlConnectionConfiguration; -import dev.miku.r2dbc.mysql.MySqlConnectionFactory; import io.r2dbc.h2.H2ConnectionConfiguration; import io.r2dbc.h2.H2ConnectionFactory; import io.r2dbc.mssql.MssqlConnectionConfiguration; @@ -40,13 +38,10 @@ public class DialectResolverUnitTests { MssqlConnectionFactory mssql = new MssqlConnectionFactory(MssqlConnectionConfiguration.builder().host("localhost") .database("foo").username("bar").password("password").build()); H2ConnectionFactory h2 = new H2ConnectionFactory(H2ConnectionConfiguration.builder().inMemory("mem").build()); - MySqlConnectionFactory mysql = MySqlConnectionFactory - .from(MySqlConnectionConfiguration.builder().host("localhost").username("mysql").build()); assertThat(DialectResolver.getDialect(postgres)).isEqualTo(PostgresDialect.INSTANCE); assertThat(DialectResolver.getDialect(mssql)).isEqualTo(SqlServerDialect.INSTANCE); assertThat(DialectResolver.getDialect(h2)).isEqualTo(H2Dialect.INSTANCE); - assertThat(DialectResolver.getDialect(mysql)).isEqualTo(MySqlDialect.INSTANCE); } @Test // gh-20, gh-104 diff --git a/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java index f5bae17..a4d6acd 100644 --- a/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java @@ -24,6 +24,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.Value; import reactor.core.publisher.Flux; +import reactor.core.publisher.Hooks; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -60,6 +61,10 @@ import org.springframework.transaction.reactive.TransactionalOperator; */ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcIntegrationTestSupport { + static { + Hooks.onOperatorDebug(); + } + @Autowired private LegoSetRepository repository; @Autowired private ConnectionFactory connectionFactory; protected JdbcTemplate jdbc; diff --git a/src/test/java/org/springframework/data/r2dbc/repository/MySqlR2dbcRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/MySqlR2dbcRepositoryIntegrationTests.java deleted file mode 100644 index fe79851..0000000 --- a/src/test/java/org/springframework/data/r2dbc/repository/MySqlR2dbcRepositoryIntegrationTests.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2019-2021 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.r2dbc.repository; - -import io.r2dbc.spi.ConnectionFactory; -import lombok.AllArgsConstructor; -import lombok.Data; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import java.time.LocalDateTime; - -import javax.sql.DataSource; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan.Filter; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.FilterType; -import org.springframework.dao.DataAccessException; -import org.springframework.data.annotation.Id; -import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration; -import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories; -import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory; -import org.springframework.data.r2dbc.testing.ExternalDatabase; -import org.springframework.data.r2dbc.testing.MySqlTestSupport; -import org.springframework.data.repository.reactive.ReactiveCrudRepository; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -/** - * Integration tests for {@link LegoSetRepository} using {@link R2dbcRepositoryFactory} against MySQL. - * - * @author Mark Paluch - */ -@ExtendWith(SpringExtension.class) -@ContextConfiguration -public class MySqlR2dbcRepositoryIntegrationTests extends AbstractR2dbcRepositoryIntegrationTests { - - @RegisterExtension public static final ExternalDatabase database = MySqlTestSupport.database(); - - @Autowired DateTestsRepository dateTestsRepository; - - @Configuration - @EnableR2dbcRepositories(considerNestedRepositories = true, - includeFilters = { @Filter(classes = MySqlLegoSetRepository.class, type = FilterType.ASSIGNABLE_TYPE), - @Filter(classes = DateTestsRepository.class, type = FilterType.ASSIGNABLE_TYPE) }) - static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration { - - @Bean - @Override - public ConnectionFactory connectionFactory() { - return MySqlTestSupport.createConnectionFactory(database); - } - } - - @Override - protected DataSource createDataSource() { - return MySqlTestSupport.createDataSource(database); - } - - @Override - protected ConnectionFactory createConnectionFactory() { - return MySqlTestSupport.createConnectionFactory(database); - } - - @Override - protected String getCreateTableStatement() { - return MySqlTestSupport.CREATE_TABLE_LEGOSET_WITH_ID_GENERATION; - } - - @Override - protected Class getRepositoryInterfaceType() { - return MySqlLegoSetRepository.class; - } - - @Test - public void shouldUserJsr310Types() { - - JdbcTemplate jdbcTemplate = createJdbcTemplate(createDataSource()); - - try { - jdbcTemplate.execute("DROP TABLE date_tests"); - } catch (DataAccessException e) {} - - jdbcTemplate.execute("CREATE TABLE date_tests (id int, created_timestamp TIMESTAMP, created_date datetime);"); - - dateTestsRepository.save(new DateTests(null, LocalDateTime.now(), LocalDateTime.now())).as(StepVerifier::create) - .expectNextCount(1).verifyComplete(); - } - - @Data - @AllArgsConstructor - static class DateTests { - @Id Integer id; - LocalDateTime createdTimestamp; - LocalDateTime createdDate; - } - - interface MySqlLegoSetRepository extends LegoSetRepository { - - @Override - @Query("SELECT name FROM legoset") - Flux findAsProjection(); - - @Override - @Query("SELECT * FROM legoset WHERE manual = :manual") - Mono findByManual(int manual); - - @Override - @Query("SELECT id FROM legoset") - Flux findAllIds(); - } - - interface DateTestsRepository extends ReactiveCrudRepository { - - } -} diff --git a/src/test/java/org/springframework/data/r2dbc/repository/MySqlR2dbcRepositoryWithMixedCaseNamesIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/MySqlR2dbcRepositoryWithMixedCaseNamesIntegrationTests.java deleted file mode 100644 index b8f4b14..0000000 --- a/src/test/java/org/springframework/data/r2dbc/repository/MySqlR2dbcRepositoryWithMixedCaseNamesIntegrationTests.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2021 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.r2dbc.repository; - -import io.r2dbc.spi.ConnectionFactory; - -import java.util.Optional; - -import javax.sql.DataSource; - -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan.Filter; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.FilterType; -import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration; -import org.springframework.data.r2dbc.convert.R2dbcCustomConversions; -import org.springframework.data.r2dbc.mapping.R2dbcMappingContext; -import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories; -import org.springframework.data.r2dbc.testing.ExternalDatabase; -import org.springframework.data.r2dbc.testing.MySqlTestSupport; -import org.springframework.data.relational.core.mapping.NamingStrategy; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -/** - * Integration tests for {@link LegoSetRepository} with table and column names that contain upper and lower case - * characters against MySql. - * - * @author Jens Schauder - */ -@ExtendWith(SpringExtension.class) -@ContextConfiguration -public class MySqlR2dbcRepositoryWithMixedCaseNamesIntegrationTests - extends AbstractR2dbcRepositoryWithMixedCaseNamesIntegrationTests { - - @RegisterExtension public static final ExternalDatabase database = MySqlTestSupport.database(); - - @Configuration - @EnableR2dbcRepositories(considerNestedRepositories = true, - includeFilters = @Filter(classes = { LegoSetRepository.class }, type = FilterType.ASSIGNABLE_TYPE)) - static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration { - - @Bean - @Override - public ConnectionFactory connectionFactory() { - return MySqlTestSupport.createConnectionFactory(database); - } - - @Override - public R2dbcMappingContext r2dbcMappingContext(Optional namingStrategy, - R2dbcCustomConversions r2dbcCustomConversions) { - - R2dbcMappingContext r2dbcMappingContext = super.r2dbcMappingContext(namingStrategy, r2dbcCustomConversions); - r2dbcMappingContext.setForceQuote(true); - - return r2dbcMappingContext; - } - } - - @Override - protected DataSource createDataSource() { - return MySqlTestSupport.createDataSource(database); - } - - @Override - protected ConnectionFactory createConnectionFactory() { - return MySqlTestSupport.createConnectionFactory(database); - } - - @Override - protected String getCreateTableStatement() { - return MySqlTestSupport.CREATE_TABLE_LEGOSET_WITH_MIXED_CASE_NAMES; - } - - @Override - protected String getDropTableStatement() { - return MySqlTestSupport.DROP_TABLE_LEGOSET_WITH_MIXED_CASE_NAMES; - } -} diff --git a/src/test/java/org/springframework/data/r2dbc/testing/MySqlTestSupport.java b/src/test/java/org/springframework/data/r2dbc/testing/MySqlTestSupport.java deleted file mode 100644 index 24896d9..0000000 --- a/src/test/java/org/springframework/data/r2dbc/testing/MySqlTestSupport.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2019-2021 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.r2dbc.testing; - -import dev.miku.r2dbc.mysql.MySqlConnectionFactoryProvider; -import io.r2dbc.spi.ConnectionFactory; -import io.r2dbc.spi.ConnectionFactoryOptions; - -import java.util.function.Supplier; -import java.util.stream.Stream; - -import javax.sql.DataSource; - -import org.springframework.data.r2dbc.testing.ExternalDatabase.ProvidedDatabase; - -import org.testcontainers.containers.MySQLContainer; - -import com.mysql.cj.jdbc.MysqlDataSource; - -/** - * Utility class for testing against MySQL. - * - * @author Mark Paluch - * @author Bogdan Ilchyshyn - * @author Jens Schauder - */ -public class MySqlTestSupport { - - private static ExternalDatabase testContainerDatabase; - - public static String CREATE_TABLE_LEGOSET = "CREATE TABLE legoset (\n" // - + " id integer PRIMARY KEY,\n" // - + " version integer NULL,\n" // - + " name varchar(255) NOT NULL,\n" // - + " manual integer NULL\n," // - + " cert varbinary(255) NULL\n" // - + ") ENGINE=InnoDB;"; - - public static String CREATE_TABLE_LEGOSET_WITH_ID_GENERATION = "CREATE TABLE legoset (\n" // - + " id integer AUTO_INCREMENT PRIMARY KEY,\n" // - + " version integer NULL,\n" // - + " name varchar(255) NOT NULL,\n" // - + " flag boolean NULL,\n" // - + " manual integer NULL\n" // - + ") ENGINE=InnoDB;"; - - - public static final String CREATE_TABLE_LEGOSET_WITH_MIXED_CASE_NAMES = "CREATE TABLE `LegoSet` (\n" // - + " `Id` integer AUTO_INCREMENT PRIMARY KEY,\n" // - + " `Name` varchar(255) NOT NULL,\n" // - + " `Manual` integer NULL\n" // - + ") ENGINE=InnoDB;"; - - public static final String DROP_TABLE_LEGOSET_WITH_MIXED_CASE_NAMES = "DROP TABLE LegoSet"; - /** - * Returns a database either hosted locally or running inside Docker. - * - * @return information about the database. Guaranteed to be not {@literal null}. - */ - public static ExternalDatabase database() { - - if (Boolean.getBoolean("spring.data.r2dbc.test.preferLocalDatabase")) { - - return getFirstWorkingDatabase( // - MySqlTestSupport::local, // - MySqlTestSupport::testContainer // - ); - } else { - - return getFirstWorkingDatabase( // - MySqlTestSupport::testContainer, // - MySqlTestSupport::local // - ); - } - } - - @SafeVarargs - private static ExternalDatabase getFirstWorkingDatabase(Supplier... suppliers) { - - return Stream.of(suppliers).map(Supplier::get) // - .filter(ExternalDatabase::checkValidity) // - .findFirst() // - .orElse(ExternalDatabase.unavailable()); - } - - /** - * Returns a locally provided database. - */ - private static ExternalDatabase local() { - - return ProvidedDatabase.builder() // - .hostname("localhost") // - .port(3306) // - .database("mysql") // - .username("root") // - .password("my-secret-pw") // - .jdbcUrl("jdbc:mysql://localhost:3306/mysql?allowPublicKeyRetrieval=true") // - .build(); - } - - /** - * Returns a database provided via Testcontainers. - */ - private static ExternalDatabase testContainer() { - - if (testContainerDatabase == null) { - - try { - MySQLContainer container = new MySQLContainer("mysql:8.0.24"); - container.start(); - - testContainerDatabase = ProvidedDatabase.builder(container) // - .database(container.getDatabaseName()) // - .username("root") // - .build(); - } catch (IllegalStateException ise) { - // docker not available. - testContainerDatabase = ExternalDatabase.unavailable(); - } - } - - return testContainerDatabase; - } - - /** - * Creates a new R2DBC MySQL {@link ConnectionFactory} configured from the {@link ExternalDatabase}. - */ - public static ConnectionFactory createConnectionFactory(ExternalDatabase database) { - - ConnectionFactoryOptions options = ConnectionUtils.createOptions("mysql", database); - return new MySqlConnectionFactoryProvider().create(options); - } - - /** - * Creates a new {@link DataSource} configured from the {@link ExternalDatabase}. - */ - public static DataSource createDataSource(ExternalDatabase database) { - - MysqlDataSource dataSource = new MysqlDataSource(); - - dataSource.setUser(database.getUsername()); - dataSource.setPassword(database.getPassword()); - dataSource.setURL(database.getJdbcUrl() + "?useSSL=false&allowPublicKeyRetrieval=true"); - - return dataSource; - } -} diff --git a/src/test/java/org/springframework/data/r2dbc/testing/StatementRecorder.java b/src/test/java/org/springframework/data/r2dbc/testing/StatementRecorder.java index 4661837..abe098c 100644 --- a/src/test/java/org/springframework/data/r2dbc/testing/StatementRecorder.java +++ b/src/test/java/org/springframework/data/r2dbc/testing/StatementRecorder.java @@ -23,10 +23,12 @@ import io.r2dbc.spi.ConnectionMetadata; import io.r2dbc.spi.IsolationLevel; import io.r2dbc.spi.Result; import io.r2dbc.spi.Statement; +import io.r2dbc.spi.TransactionDefinition; import io.r2dbc.spi.ValidationDepth; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; @@ -156,11 +158,17 @@ public class StatementRecorder implements ConnectionFactory { } class RecorderConnection implements Connection { + @Override public Publisher beginTransaction() { return createStatement("BEGIN").execute().then(); } + @Override + public Publisher beginTransaction(TransactionDefinition definition) { + return createStatement("BEGIN " + definition).execute().then(); + } + @Override public Publisher close() { return createStatement("CLOSE").execute().then(); @@ -238,6 +246,16 @@ public class StatementRecorder implements ConnectionFactory { return createStatement("SET AUTOCOMMIT " + autoCommit).execute().then(); } + @Override + public Publisher setLockWaitTimeout(Duration timeout) { + return createStatement("SET LOCK WAIT TIMEOUT " + timeout).execute().then(); + } + + @Override + public Publisher setStatementTimeout(Duration timeout) { + return createStatement("SET STATEMENT TIMEOUT " + timeout).execute().then(); + } + @Override public Publisher setTransactionIsolationLevel(IsolationLevel isolationLevel) { return createStatement("SET TRANSACTION ISOLATION LEVEL " + isolationLevel.asSql()).execute().then(); @@ -307,6 +325,16 @@ public class StatementRecorder implements ConnectionFactory { public Flux execute() { return Flux.fromIterable(results).doOnSubscribe(subscription -> executedStatements.add(this)); } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer(); + sb.append(getClass().getSimpleName()); + sb.append(" [sql='").append(sql).append('\''); + sb.append(", bindings=").append(bindings); + sb.append(']'); + return sb.toString(); + } } } diff --git a/src/test/resources/org/springframework/data/r2dbc/connectionfactory/init/users-schema-h2.sql b/src/test/resources/org/springframework/data/r2dbc/connectionfactory/init/users-schema-h2.sql new file mode 100644 index 0000000..8bfe302 --- /dev/null +++ b/src/test/resources/org/springframework/data/r2dbc/connectionfactory/init/users-schema-h2.sql @@ -0,0 +1,8 @@ +DROP TABLE users IF EXISTS; + +CREATE TABLE users +( + id INTEGER NOT NULL AUTO_INCREMENT, + first_name VARCHAR(50) NOT NULL, + last_name VARCHAR(50) NOT NULL +);