From 4781ad7dbd3266768e1fa3eb75bbbc4e2d4a331e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 25 May 2023 14:46:27 +0200 Subject: [PATCH] Ensure thatPreferredCursorExecution is the only configuration flag to control cursor preference. [resolves #267] Signed-off-by: Mark Paluch --- .../io/r2dbc/mssql/ConnectionOptions.java | 5 - .../mssql/MssqlConnectionConfiguration.java | 54 +++-- .../io/r2dbc/mssql/SimpleMssqlStatement.java | 25 +- .../io/r2dbc/mssql/MssqlBatchUnitTests.java | 6 +- ...MssqlConnectionConfigurationUnitTests.java | 224 ++++++++++-------- .../r2dbc/mssql/MssqlConnectionUnitTests.java | 2 +- .../mssql/SimpleMssqlStatementUnitTests.java | 30 +-- .../io/r2dbc/mssql/TestConnectionOptions.java | 29 +++ 8 files changed, 195 insertions(+), 180 deletions(-) create mode 100644 src/test/java/io/r2dbc/mssql/TestConnectionOptions.java diff --git a/src/main/java/io/r2dbc/mssql/ConnectionOptions.java b/src/main/java/io/r2dbc/mssql/ConnectionOptions.java index 468436d5..a051a874 100644 --- a/src/main/java/io/r2dbc/mssql/ConnectionOptions.java +++ b/src/main/java/io/r2dbc/mssql/ConnectionOptions.java @@ -17,7 +17,6 @@ package io.r2dbc.mssql; import io.r2dbc.mssql.codec.Codecs; -import io.r2dbc.mssql.codec.DefaultCodecs; import reactor.util.annotation.Nullable; import java.time.Duration; @@ -38,10 +37,6 @@ class ConnectionOptions { private volatile Duration statementTimeout = Duration.ZERO; - ConnectionOptions() { - this(sql -> false, new DefaultCodecs(), new IndefinitePreparedStatementCache(), true); - } - ConnectionOptions(Predicate preferCursoredExecution, Codecs codecs, PreparedStatementCache preparedStatementCache, boolean sendStringParametersAsUnicode) { this.preferCursoredExecution = preferCursoredExecution; this.codecs = codecs; diff --git a/src/main/java/io/r2dbc/mssql/MssqlConnectionConfiguration.java b/src/main/java/io/r2dbc/mssql/MssqlConnectionConfiguration.java index 59852c61..95e39233 100644 --- a/src/main/java/io/r2dbc/mssql/MssqlConnectionConfiguration.java +++ b/src/main/java/io/r2dbc/mssql/MssqlConnectionConfiguration.java @@ -45,6 +45,7 @@ import java.security.KeyStore; import java.time.Duration; import java.util.Arrays; +import java.util.Locale; import java.util.Optional; import java.util.UUID; import java.util.function.Function; @@ -182,14 +183,14 @@ MssqlConnectionConfiguration withRedirect(Redirect redirect) { } return new MssqlConnectionConfiguration(this.applicationName, this.connectionId, this.connectTimeout, this.database, redirectServerName, hostNameInCertificate, this.lockWaitTimeout, - this.password, - this.preferCursoredExecution, redirect.getPort(), this.sendStringParametersAsUnicode, this.ssl, this.sslContextBuilderCustomizer, - this.sslTunnelSslContextBuilderCustomizer, this.tcpKeepAlive, this.tcpNoDelay, this.trustServerCertificate, this.trustStore, this.trustStoreType, this.trustStorePassword, this.username); + this.password, + this.preferCursoredExecution, redirect.getPort(), this.sendStringParametersAsUnicode, this.ssl, this.sslContextBuilderCustomizer, + this.sslTunnelSslContextBuilderCustomizer, this.tcpKeepAlive, this.tcpNoDelay, this.trustServerCertificate, this.trustStore, this.trustStoreType, this.trustStorePassword, this.username); } ClientConfiguration toClientConfiguration() { return new DefaultClientConfiguration(this.connectTimeout, this.host, this.hostNameInCertificate, this.port, this.ssl, this.sslContextBuilderCustomizer, - this.sslTunnelSslContextBuilderCustomizer, this.tcpKeepAlive, this.tcpNoDelay, this.trustServerCertificate, this.trustStore, this.trustStoreType, this.trustStorePassword); + this.sslTunnelSslContextBuilderCustomizer, this.tcpKeepAlive, this.tcpNoDelay, this.trustServerCertificate, this.trustStore, this.trustStoreType, this.trustStorePassword); } ConnectionOptions toConnectionOptions() { @@ -354,7 +355,7 @@ public static final class Builder { @Nullable private Duration lockWaitTimeout; - private Predicate preferCursoredExecution = sql -> false; + private Predicate preferCursoredExecution = DefaultCursorPreference.INSTANCE; private CharSequence password; @@ -714,11 +715,11 @@ public MssqlConnectionConfiguration build() { } return new MssqlConnectionConfiguration(this.applicationName, this.connectionId, this.connectTimeout, this.database, this.host, this.hostNameInCertificate, this.lockWaitTimeout, - this.password, - this.preferCursoredExecution, this.port, this.sendStringParametersAsUnicode, this.ssl, this.sslContextBuilderCustomizer, - this.sslTunnelSslContextBuilderCustomizer, this.tcpKeepAlive, - this.tcpNoDelay, this.trustServerCertificate, this.trustStore, - this.trustStoreType, this.trustStorePassword, this.username); + this.password, + this.preferCursoredExecution, this.port, this.sendStringParametersAsUnicode, this.ssl, this.sslContextBuilderCustomizer, + this.sslTunnelSslContextBuilderCustomizer, this.tcpKeepAlive, + this.tcpNoDelay, this.trustServerCertificate, this.trustStore, + this.trustStoreType, this.trustStorePassword, this.username); } } @@ -887,12 +888,35 @@ public SslContext getSslContext() throws GeneralSecurityException { private static SslContextBuilder createSslContextBuilder() { SslContextBuilder sslContextBuilder = SslContextBuilder.forClient(); sslContextBuilder.sslProvider( - OpenSsl.isAvailable() ? - io.netty.handler.ssl.SslProvider.OPENSSL : - io.netty.handler.ssl.SslProvider.JDK) - .ciphers(null, IdentityCipherSuiteFilter.INSTANCE) - .applicationProtocolConfig(null); + OpenSsl.isAvailable() ? + io.netty.handler.ssl.SslProvider.OPENSSL : + io.netty.handler.ssl.SslProvider.JDK) + .ciphers(null, IdentityCipherSuiteFilter.INSTANCE) + .applicationProtocolConfig(null); return sslContextBuilder; } + + static class DefaultCursorPreference implements Predicate { + + static final DefaultCursorPreference INSTANCE = new DefaultCursorPreference(); + + @Override + public boolean test(String sql) { + + if (sql.isEmpty()) { + return false; + } + + String lc = sql.trim().toLowerCase(Locale.ENGLISH); + if (lc.contains("for xml") || lc.contains("for json")) { + return false; + } + + char c = sql.charAt(0); + + return (c == 's' || c == 'S') && lc.startsWith("select"); + } + } + } diff --git a/src/main/java/io/r2dbc/mssql/SimpleMssqlStatement.java b/src/main/java/io/r2dbc/mssql/SimpleMssqlStatement.java index 902a4741..c210012e 100644 --- a/src/main/java/io/r2dbc/mssql/SimpleMssqlStatement.java +++ b/src/main/java/io/r2dbc/mssql/SimpleMssqlStatement.java @@ -29,7 +29,6 @@ import reactor.util.Logger; import reactor.util.Loggers; -import java.util.Locale; import java.util.function.Predicate; /** @@ -61,7 +60,7 @@ final class SimpleMssqlStatement extends MssqlStatementSupport implements MssqlS */ SimpleMssqlStatement(Client client, ConnectionOptions connectionOptions, String sql) { - super(connectionOptions.prefersCursors(sql) || prefersCursors(sql)); + super(connectionOptions.prefersCursors(sql)); this.connectionOptions = connectionOptions; Assert.requireNonNull(client, "Client must not be null"); @@ -162,26 +161,4 @@ public SimpleMssqlStatement fetchSize(int fetchSize) { return this; } - /** - * Returns {@code true} if the query is supported by this {@link MssqlStatement}. Cursored execution is supported for {@literal SELECT} queries. - * - * @param sql the query to inspect. - * @return {@code true} if the {@code sql} query is supported. - */ - static boolean prefersCursors(String sql) { - - if (sql.isEmpty()) { - return false; - } - - String lc = sql.trim().toLowerCase(Locale.ENGLISH); - if (lc.contains("for xml") || lc.contains("for json")) { - return false; - } - - char c = sql.charAt(0); - - return (c == 's' || c == 'S') && lc.startsWith("select"); - } - } diff --git a/src/test/java/io/r2dbc/mssql/MssqlBatchUnitTests.java b/src/test/java/io/r2dbc/mssql/MssqlBatchUnitTests.java index d99b53fb..87198754 100644 --- a/src/test/java/io/r2dbc/mssql/MssqlBatchUnitTests.java +++ b/src/test/java/io/r2dbc/mssql/MssqlBatchUnitTests.java @@ -39,7 +39,7 @@ void shouldExecuteSingleBatch() { .thenRespond(DoneToken.create(1)) .build(); - new MssqlBatch(client, new ConnectionOptions()) + new MssqlBatch(client, new TestConnectionOptions()) .add("foo") .execute() .as(StepVerifier::create) @@ -55,7 +55,7 @@ void shouldExecuteMultiBatch() { .thenRespond(DoneToken.create(1), DoneToken.create(1)) .build(); - new MssqlBatch(client, new ConnectionOptions()) + new MssqlBatch(client, new TestConnectionOptions()) .add("foo") .add("bar") .execute() @@ -73,7 +73,7 @@ void shouldFailOnExecution() { "proc", 0)) .build(); - new MssqlBatch(client, new ConnectionOptions()) + new MssqlBatch(client, new TestConnectionOptions()) .add("foo") .execute() .as(StepVerifier::create) diff --git a/src/test/java/io/r2dbc/mssql/MssqlConnectionConfigurationUnitTests.java b/src/test/java/io/r2dbc/mssql/MssqlConnectionConfigurationUnitTests.java index 952dce68..6b7bd2d3 100644 --- a/src/test/java/io/r2dbc/mssql/MssqlConnectionConfigurationUnitTests.java +++ b/src/test/java/io/r2dbc/mssql/MssqlConnectionConfigurationUnitTests.java @@ -19,6 +19,8 @@ import io.r2dbc.mssql.message.tds.Redirect; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.testcontainers.shaded.org.bouncycastle.asn1.x500.X500Name; import org.testcontainers.shaded.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.testcontainers.shaded.org.bouncycastle.cert.X509CertificateHolder; @@ -53,31 +55,31 @@ final class MssqlConnectionConfigurationUnitTests { @Test void builderNoApplicationName() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder().applicationName(null)) - .withMessage("applicationName must not be null"); + .withMessage("applicationName must not be null"); } @Test void builderNoConnectionId() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder().connectionId(null)) - .withMessage("connectionId must not be null"); + .withMessage("connectionId must not be null"); } @Test void builderNoHost() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder().host(null)) - .withMessage("host must not be null"); + .withMessage("host must not be null"); } @Test void builderNoPassword() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder().password(null)) - .withMessage("password must not be null"); + .withMessage("password must not be null"); } @Test void builderNoUsername() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder().username(null)) - .withMessage("username must not be null"); + .withMessage("username must not be null"); } @Test @@ -85,150 +87,150 @@ void configuration() { UUID connectionId = UUID.randomUUID(); Predicate TRUE = s -> true; MssqlConnectionConfiguration configuration = MssqlConnectionConfiguration.builder() - .connectionId(connectionId) - .database("test-database") - .host("test-host") - .password("test-password") - .preferCursoredExecution(TRUE) - .port(100) - .username("test-username") - .sendStringParametersAsUnicode(false) - .build(); + .connectionId(connectionId) + .database("test-database") + .host("test-host") + .password("test-password") + .preferCursoredExecution(TRUE) + .port(100) + .username("test-username") + .sendStringParametersAsUnicode(false) + .build(); assertThat(configuration) - .hasFieldOrPropertyWithValue("connectionId", connectionId) - .hasFieldOrPropertyWithValue("database", "test-database") - .hasFieldOrPropertyWithValue("host", "test-host") - .hasFieldOrPropertyWithValue("password", "test-password") - .hasFieldOrPropertyWithValue("preferCursoredExecution", TRUE) - .hasFieldOrPropertyWithValue("port", 100) - .hasFieldOrPropertyWithValue("username", "test-username") - .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", false); + .hasFieldOrPropertyWithValue("connectionId", connectionId) + .hasFieldOrPropertyWithValue("database", "test-database") + .hasFieldOrPropertyWithValue("host", "test-host") + .hasFieldOrPropertyWithValue("password", "test-password") + .hasFieldOrPropertyWithValue("preferCursoredExecution", TRUE) + .hasFieldOrPropertyWithValue("port", 100) + .hasFieldOrPropertyWithValue("username", "test-username") + .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", false); } @Test void configurationDefaults() { MssqlConnectionConfiguration configuration = MssqlConnectionConfiguration.builder() - .applicationName("r2dbc") - .database("test-database") - .host("test-host") - .password("test-password") - .username("test-username") - .build(); + .applicationName("r2dbc") + .database("test-database") + .host("test-host") + .password("test-password") + .username("test-username") + .build(); assertThat(configuration) - .hasFieldOrPropertyWithValue("applicationName", "r2dbc") - .hasFieldOrPropertyWithValue("database", "test-database") - .hasFieldOrPropertyWithValue("host", "test-host") - .hasFieldOrPropertyWithValue("password", "test-password") - .hasFieldOrPropertyWithValue("port", 1433) - .hasFieldOrPropertyWithValue("username", "test-username") - .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true); + .hasFieldOrPropertyWithValue("applicationName", "r2dbc") + .hasFieldOrPropertyWithValue("database", "test-database") + .hasFieldOrPropertyWithValue("host", "test-host") + .hasFieldOrPropertyWithValue("password", "test-password") + .hasFieldOrPropertyWithValue("port", 1433) + .hasFieldOrPropertyWithValue("username", "test-username") + .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true); } @Test void constructorNoNoHost() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder() - .password("test-password") - .username("test-username") - .build()) - .withMessage("host must not be null"); + .password("test-password") + .username("test-username") + .build()) + .withMessage("host must not be null"); } @Test void constructorNoPassword() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder() - .host("test-host") - .username("test-username") - .build()) - .withMessage("password must not be null"); + .host("test-host") + .username("test-username") + .build()) + .withMessage("password must not be null"); } @Test void constructorNoUsername() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder() - .host("test-host") - .password("test-password") - .build()) - .withMessage("username must not be null"); + .host("test-host") + .password("test-password") + .build()) + .withMessage("username must not be null"); } @Test void constructorNoSslCustomizer() { assertThatIllegalArgumentException().isThrownBy(() -> MssqlConnectionConfiguration.builder() - .sslContextBuilderCustomizer(null) - .build()) - .withMessage("sslContextBuilderCustomizer must not be null"); + .sslContextBuilderCustomizer(null) + .build()) + .withMessage("sslContextBuilderCustomizer must not be null"); } @Test void redirect() { MssqlConnectionConfiguration configuration = MssqlConnectionConfiguration.builder() - .applicationName("r2dbc") - .database("test-database") - .host("test-host") - .password("test-password") - .username("test-username") - .build(); + .applicationName("r2dbc") + .database("test-database") + .host("test-host") + .password("test-password") + .username("test-username") + .build(); MssqlConnectionConfiguration target = configuration.withRedirect(Redirect.create("target", 1234)); assertThat(target) - .hasFieldOrPropertyWithValue("applicationName", "r2dbc") - .hasFieldOrPropertyWithValue("database", "test-database") - .hasFieldOrPropertyWithValue("host", "target") - .hasFieldOrPropertyWithValue("password", "test-password") - .hasFieldOrPropertyWithValue("port", 1234) - .hasFieldOrPropertyWithValue("username", "test-username") - .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true) - .hasFieldOrPropertyWithValue("hostNameInCertificate", "test-host"); + .hasFieldOrPropertyWithValue("applicationName", "r2dbc") + .hasFieldOrPropertyWithValue("database", "test-database") + .hasFieldOrPropertyWithValue("host", "target") + .hasFieldOrPropertyWithValue("password", "test-password") + .hasFieldOrPropertyWithValue("port", 1234) + .hasFieldOrPropertyWithValue("username", "test-username") + .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true) + .hasFieldOrPropertyWithValue("hostNameInCertificate", "test-host"); } @Test void redirectOtherDomain() { MssqlConnectionConfiguration configuration = MssqlConnectionConfiguration.builder() - .applicationName("r2dbc") - .database("test-database") - .host("test-host.windows.net") - .password("test-password") - .username("test-username") - .build(); + .applicationName("r2dbc") + .database("test-database") + .host("test-host.windows.net") + .password("test-password") + .username("test-username") + .build(); MssqlConnectionConfiguration target = configuration.withRedirect(Redirect.create("target.other.domain", 1234)); assertThat(target) - .hasFieldOrPropertyWithValue("applicationName", "r2dbc") - .hasFieldOrPropertyWithValue("database", "test-database") - .hasFieldOrPropertyWithValue("host", "target.other.domain") - .hasFieldOrPropertyWithValue("password", "test-password") - .hasFieldOrPropertyWithValue("port", 1234) - .hasFieldOrPropertyWithValue("username", "test-username") - .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true) - .hasFieldOrPropertyWithValue("hostNameInCertificate", "test-host.windows.net"); + .hasFieldOrPropertyWithValue("applicationName", "r2dbc") + .hasFieldOrPropertyWithValue("database", "test-database") + .hasFieldOrPropertyWithValue("host", "target.other.domain") + .hasFieldOrPropertyWithValue("password", "test-password") + .hasFieldOrPropertyWithValue("port", 1234) + .hasFieldOrPropertyWithValue("username", "test-username") + .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true) + .hasFieldOrPropertyWithValue("hostNameInCertificate", "test-host.windows.net"); } @Test void redirectInDomain() { MssqlConnectionConfiguration configuration = MssqlConnectionConfiguration.builder() - .applicationName("r2dbc") - .database("test-database") - .host("test-host.windows.net") - .password("test-password") - .username("test-username") - .hostNameInCertificate("*.windows.net") - .build(); + .applicationName("r2dbc") + .database("test-database") + .host("test-host.windows.net") + .password("test-password") + .username("test-username") + .hostNameInCertificate("*.windows.net") + .build(); MssqlConnectionConfiguration target = configuration.withRedirect(Redirect.create("worker.target.windows.net", 1234)); assertThat(target) - .hasFieldOrPropertyWithValue("applicationName", "r2dbc") - .hasFieldOrPropertyWithValue("database", "test-database") - .hasFieldOrPropertyWithValue("host", "worker.target.windows.net") - .hasFieldOrPropertyWithValue("password", "test-password") - .hasFieldOrPropertyWithValue("port", 1234) - .hasFieldOrPropertyWithValue("username", "test-username") - .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true) - .hasFieldOrPropertyWithValue("hostNameInCertificate", "*.target.windows.net"); + .hasFieldOrPropertyWithValue("applicationName", "r2dbc") + .hasFieldOrPropertyWithValue("database", "test-database") + .hasFieldOrPropertyWithValue("host", "worker.target.windows.net") + .hasFieldOrPropertyWithValue("password", "test-password") + .hasFieldOrPropertyWithValue("port", 1234) + .hasFieldOrPropertyWithValue("username", "test-username") + .hasFieldOrPropertyWithValue("sendStringParametersAsUnicode", true) + .hasFieldOrPropertyWithValue("hostNameInCertificate", "*.target.windows.net"); } @Test @@ -244,7 +246,7 @@ void configureKeyStore(@TempDir File tempDir) throws Exception { Certificate selfSignedCertificate = selfSign(keypair, "CN=dummy"); KeyStore.Entry entry = new KeyStore.PrivateKeyEntry(keypair.getPrivate(), - new Certificate[]{selfSignedCertificate}); + new Certificate[]{selfSignedCertificate}); keyStore.setEntry("dummy", entry, new KeyStore.PasswordProtection("key-password".toCharArray())); @@ -254,13 +256,13 @@ void configureKeyStore(@TempDir File tempDir) throws Exception { } MssqlConnectionConfiguration configuration = MssqlConnectionConfiguration.builder() - .database("test-database") - .host("test-host.windows.net") - .password("test-password") - .username("test-username") - .trustStore(file) - .trustStorePassword("my-password".toCharArray()) - .build(); + .database("test-database") + .host("test-host.windows.net") + .password("test-password") + .username("test-username") + .trustStore(file) + .trustStorePassword("my-password".toCharArray()) + .build(); MssqlConnectionConfiguration.DefaultClientConfiguration clientConfiguration = (MssqlConnectionConfiguration.DefaultClientConfiguration) configuration.toClientConfiguration(); @@ -271,7 +273,7 @@ void configureKeyStore(@TempDir File tempDir) throws Exception { } private static Certificate selfSign(KeyPair keyPair, String subjectDN) - throws Exception { + throws Exception { Date startDate = new Date(); X500Name dnName = new X500Name(subjectDN); @@ -283,16 +285,28 @@ private static Certificate selfSign(KeyPair keyPair, String subjectDN) SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair - .getPublic().getEncoded()); + .getPublic().getEncoded()); X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(dnName, - BigInteger.valueOf(1), startDate, endDate, dnName, subjectPublicKeyInfo); + BigInteger.valueOf(1), startDate, endDate, dnName, subjectPublicKeyInfo); ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(keyPair.getPrivate()); X509CertificateHolder certificateHolder = certificateBuilder.build(contentSigner); return new JcaX509CertificateConverter() - .getCertificate(certificateHolder); + .getCertificate(certificateHolder); + } + + @ParameterizedTest + @ValueSource(strings = {"select", "SELECT", "sElEcT"}) + void shouldAcceptQueries(String query) { + assertThat(MssqlConnectionConfiguration.DefaultCursorPreference.INSTANCE).accepts(query); + } + + @ParameterizedTest + @ValueSource(strings = {" select", "sp_cursor", "INSERT"}) + void shouldRejectQueries(String query) { + assertThat(MssqlConnectionConfiguration.DefaultCursorPreference.INSTANCE).rejects(query); } } diff --git a/src/test/java/io/r2dbc/mssql/MssqlConnectionUnitTests.java b/src/test/java/io/r2dbc/mssql/MssqlConnectionUnitTests.java index 5965c7e8..43ed81d3 100644 --- a/src/test/java/io/r2dbc/mssql/MssqlConnectionUnitTests.java +++ b/src/test/java/io/r2dbc/mssql/MssqlConnectionUnitTests.java @@ -54,7 +54,7 @@ class MssqlConnectionUnitTests { static MssqlConnectionMetadata metadata = new MssqlConnectionMetadata("SQL Server", "1.0"); - static ConnectionOptions conectionOptions = new ConnectionOptions(); + static ConnectionOptions conectionOptions = new TestConnectionOptions(); @Test void shouldBeginTransactionFromInitialState() { diff --git a/src/test/java/io/r2dbc/mssql/SimpleMssqlStatementUnitTests.java b/src/test/java/io/r2dbc/mssql/SimpleMssqlStatementUnitTests.java index 3d6fb04d..68b620df 100644 --- a/src/test/java/io/r2dbc/mssql/SimpleMssqlStatementUnitTests.java +++ b/src/test/java/io/r2dbc/mssql/SimpleMssqlStatementUnitTests.java @@ -24,16 +24,7 @@ import io.r2dbc.mssql.message.TransactionDescriptor; import io.r2dbc.mssql.message.tds.Encode; import io.r2dbc.mssql.message.tds.ServerCharset; -import io.r2dbc.mssql.message.token.Column; -import io.r2dbc.mssql.message.token.ColumnMetadataToken; -import io.r2dbc.mssql.message.token.DataToken; -import io.r2dbc.mssql.message.token.DoneToken; -import io.r2dbc.mssql.message.token.ErrorToken; -import io.r2dbc.mssql.message.token.RowToken; -import io.r2dbc.mssql.message.token.RowTokenFactory; -import io.r2dbc.mssql.message.token.RpcRequest; -import io.r2dbc.mssql.message.token.SqlBatch; -import io.r2dbc.mssql.message.token.Tabular; +import io.r2dbc.mssql.message.token.*; import io.r2dbc.mssql.message.type.Collation; import io.r2dbc.mssql.message.type.LengthStrategy; import io.r2dbc.mssql.message.type.SqlServerType; @@ -42,8 +33,6 @@ import io.r2dbc.spi.R2dbcNonTransientResourceException; import io.r2dbc.spi.Result; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; @@ -61,9 +50,7 @@ import static io.r2dbc.mssql.message.type.TypeInformation.Builder; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; /** * Unit tests for {@link SimpleMssqlStatement}. @@ -79,7 +66,7 @@ class SimpleMssqlStatementUnitTests { createColumn(3, "salary", SqlServerType.MONEY, 8, LengthStrategy.BYTELENTYPE, null)).toArray(new Column[0]); - static final ConnectionOptions OPTIONS = new ConnectionOptions(); + static final ConnectionOptions OPTIONS = new TestConnectionOptions(); @Test void shouldReportNumberOfAffectedRows() { @@ -352,15 +339,4 @@ private static Column createColumn(int index, String name, SqlServerType serverT return new Column(index, name, type, null); } - @ParameterizedTest - @ValueSource(strings = {"select", "SELECT", "sElEcT"}) - void shouldAcceptQueries(String query) { - assertThat(SimpleMssqlStatement.prefersCursors(query)).isTrue(); - } - - @ParameterizedTest - @ValueSource(strings = {" select", "sp_cursor", "INSERT"}) - void shouldRejectQueries(String query) { - assertThat(SimpleMssqlStatement.prefersCursors(query)).isFalse(); - } } diff --git a/src/test/java/io/r2dbc/mssql/TestConnectionOptions.java b/src/test/java/io/r2dbc/mssql/TestConnectionOptions.java new file mode 100644 index 00000000..914aa614 --- /dev/null +++ b/src/test/java/io/r2dbc/mssql/TestConnectionOptions.java @@ -0,0 +1,29 @@ +/* + * Copyright 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. + * 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 io.r2dbc.mssql; + +import io.r2dbc.mssql.codec.DefaultCodecs; + +/** + * @author Mark Paluch + */ +class TestConnectionOptions extends ConnectionOptions { + + TestConnectionOptions() { + super(MssqlConnectionConfiguration.DefaultCursorPreference.INSTANCE, new DefaultCodecs(), new IndefinitePreparedStatementCache(), true); + } +}