diff --git a/pom.xml b/pom.xml index a224577db..2b484f525 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 pom import diff --git a/samples/spring-data-jdbc/googlesql/pom.xml b/samples/spring-data-jdbc/googlesql/pom.xml index aabd49f4e..0574cd98d 100644 --- a/samples/spring-data-jdbc/googlesql/pom.xml +++ b/samples/spring-data-jdbc/googlesql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 import pom diff --git a/samples/spring-data-jdbc/postgresql/pom.xml b/samples/spring-data-jdbc/postgresql/pom.xml index e3f847410..a13e1d3a6 100644 --- a/samples/spring-data-jdbc/postgresql/pom.xml +++ b/samples/spring-data-jdbc/postgresql/pom.xml @@ -30,7 +30,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 import pom diff --git a/samples/spring-data-mybatis/googlesql/pom.xml b/samples/spring-data-mybatis/googlesql/pom.xml index 68641aef0..aed7d10ca 100644 --- a/samples/spring-data-mybatis/googlesql/pom.xml +++ b/samples/spring-data-mybatis/googlesql/pom.xml @@ -35,7 +35,7 @@ com.google.cloud google-cloud-spanner-bom - 6.97.1 + 6.98.0 import pom diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java deleted file mode 100644 index 756007190..000000000 --- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcConnectionUrlTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * 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 - * - * http://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 com.google.cloud.spanner.jdbc; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import com.google.cloud.spanner.connection.AbstractMockServerTest; -import com.google.spanner.v1.BatchCreateSessionsRequest; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.experimental.runners.Enclosed; -import org.junit.runner.RunWith; - -@RunWith(Enclosed.class) -public class JdbcConnectionUrlTest { - - public static class ConnectionMinSessionsTest extends AbstractMockServerTest { - @AfterClass - public static void reset() { - mockSpanner.reset(); - } - - protected String getBaseUrl() { - return super.getBaseUrl() + ";minSessions=1"; - } - - @Test - public void testMinSessions() throws InterruptedException, TimeoutException, SQLException { - try (Connection connection = createJdbcConnection()) { - mockSpanner.waitForRequestsToContain( - input -> - input instanceof BatchCreateSessionsRequest - && ((BatchCreateSessionsRequest) input).getSessionCount() == 1, - 5000L); - } - } - } - - public static class ConnectionMaxSessionsTest extends AbstractMockServerTest { - - @AfterClass - public static void reset() { - mockSpanner.reset(); - } - - protected String getBaseUrl() { - return super.getBaseUrl() + ";minSessions=0;maxSessions=1"; - } - - @Test - public void testMaxSessions() - throws InterruptedException, TimeoutException, ExecutionException, SQLException { - ExecutorService executor1 = Executors.newSingleThreadExecutor(); - ExecutorService executor2 = Executors.newSingleThreadExecutor(); - - try (Connection connection1 = createJdbcConnection(); - Connection connection2 = createJdbcConnection()) { - final CountDownLatch latch = new CountDownLatch(1); - Future fut1 = - executor1.submit( - () -> { - assertTrue(latch.await(5L, TimeUnit.SECONDS)); - connection1.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); - connection1.commit(); - return null; - }); - Future fut2 = - executor2.submit( - () -> { - latch.countDown(); - connection2.createStatement().executeUpdate(INSERT_STATEMENT.getSql()); - connection2.commit(); - return null; - }); - // Wait until both finishes. - fut1.get(5L, TimeUnit.SECONDS); - fut2.get(5L, TimeUnit.SECONDS); - } finally { - executor1.shutdown(); - executor2.shutdown(); - } - assertEquals(1, mockSpanner.countRequestsOfType(BatchCreateSessionsRequest.class)); - BatchCreateSessionsRequest request = - mockSpanner.getRequestsOfType(BatchCreateSessionsRequest.class).get(0); - assertEquals(1, request.getSessionCount()); - } - } -} diff --git a/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java b/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java index c337f64cf..147d76b31 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/JdbcGrpcErrorTest.java @@ -85,9 +85,10 @@ public class JdbcGrpcErrorTest { private static MockSpannerServiceImpl mockSpanner; private static Server server; - // FAILED_PRECONDITION is chosen as the test error code as it should never be retryable. + // INVALID_ARGUMENT is chosen as the test error code as it should never be retryable, and it does + // not overlap with the 'are multiplexed sessions supported?' check. private final Exception serverException = - Status.FAILED_PRECONDITION.withDescription("test exception").asRuntimeException(); + Status.INVALID_ARGUMENT.withDescription("test exception").asRuntimeException(); @BeforeClass public static void startStaticServer() throws IOException { @@ -152,7 +153,7 @@ private Connection createConnection() throws SQLException { @Test public void autocommitBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { // This triggers a retry with an explicit BeginTransaction RPC. mockSpanner.abortNextStatement(); @@ -160,7 +161,7 @@ public void autocommitBeginTransaction() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -168,14 +169,14 @@ public void autocommitBeginTransaction() throws SQLException { @Test public void autocommitBeginPDMLTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -183,7 +184,7 @@ public void autocommitBeginPDMLTransaction() throws SQLException { @Test public void transactionalBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); // This triggers a retry with an explicit BeginTransaction RPC. @@ -192,7 +193,7 @@ public void transactionalBeginTransaction() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -200,7 +201,7 @@ public void transactionalBeginTransaction() throws SQLException { @Test public void readOnlyBeginTransaction() throws SQLException { mockSpanner.setBeginTransactionExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); @@ -208,20 +209,21 @@ public void readOnlyBeginTransaction() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void autocommitExecuteSql() throws SQLException { - mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -235,28 +237,29 @@ public void autocommitPDMLExecuteSql() throws SQLException { } mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.createStatement().execute("SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'"); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void transactionalExecuteSql() throws SQLException { - mockSpanner.setExecuteSqlExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setExecuteSqlExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -264,14 +267,14 @@ public void transactionalExecuteSql() throws SQLException { @Test public void autocommitExecuteBatchDml() throws SQLException { mockSpanner.setExecuteBatchDmlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { try (java.sql.Statement statement = connection.createStatement()) { statement.addBatch(UPDATE_STATEMENT.getSql()); statement.addBatch(UPDATE_STATEMENT.getSql()); JdbcSqlExceptionImpl sqlException = assertThrows(JdbcSqlExceptionImpl.class, statement::executeBatch); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -280,7 +283,7 @@ public void autocommitExecuteBatchDml() throws SQLException { @Test public void transactionalExecuteBatchDml() throws SQLException { mockSpanner.setExecuteBatchDmlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); try (java.sql.Statement statement = connection.createStatement()) { @@ -288,7 +291,7 @@ public void transactionalExecuteBatchDml() throws SQLException { statement.addBatch(UPDATE_STATEMENT.getSql()); JdbcSqlExceptionImpl sqlException = assertThrows(JdbcSqlExceptionImpl.class, statement::executeBatch); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -296,26 +299,26 @@ public void transactionalExecuteBatchDml() throws SQLException { @Test public void autocommitCommit() throws SQLException { - mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void transactionalCommit() throws SQLException { - mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCommitExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); JdbcSqlExceptionImpl sqlException = assertThrows(JdbcSqlExceptionImpl.class, connection::commit); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -324,7 +327,7 @@ public void transactionalCommit() throws SQLException { public void autocommitRollback() throws SQLException { // The JDBC driver should throw the exception of the SQL statement and ignore any errors from // the rollback() method. - mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( @@ -340,7 +343,7 @@ public void autocommitRollback() throws SQLException { public void transactionalRollback() throws SQLException { // Rollback exceptions are ignored by the client library and not propagated to the JDBC driver. // This method will therefore not throw any errors. - mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setRollbackExecutionTime(SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql()); @@ -357,13 +360,13 @@ public void autocommitExecuteStreamingSql() throws SQLException { } mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -371,14 +374,14 @@ public void autocommitExecuteStreamingSql() throws SQLException { @Test public void transactionalExecuteStreamingSql() throws SQLException { mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @@ -386,7 +389,7 @@ public void transactionalExecuteStreamingSql() throws SQLException { @Test public void readOnlyExecuteStreamingSql() throws SQLException { mockSpanner.setExecuteStreamingSqlExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); @@ -394,43 +397,44 @@ public void readOnlyExecuteStreamingSql() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void autocommitCreateSession() throws SQLException { - mockSpanner.setBatchCreateSessionsExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCreateSessionExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void transactionalCreateSession() throws SQLException { - mockSpanner.setBatchCreateSessionsExecutionTime( - SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCreateSessionExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); JdbcSqlExceptionImpl sqlException = assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeUpdate(UPDATE_STATEMENT.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } @Test public void readOnlyCreateSession() throws SQLException { - mockSpanner.setCreateSessionExecutionTime(SimulatedExecutionTime.ofException(serverException)); + mockSpanner.setCreateSessionExecutionTime( + SimulatedExecutionTime.ofStickyException(serverException)); try (java.sql.Connection connection = createConnection()) { connection.setAutoCommit(false); connection.setReadOnly(true); @@ -438,7 +442,7 @@ public void readOnlyCreateSession() throws SQLException { assertThrows( JdbcSqlExceptionImpl.class, () -> connection.createStatement().executeQuery(SELECT1.getSql())); - assertEquals(Code.FAILED_PRECONDITION, sqlException.getCode()); + assertEquals(Code.INVALID_ARGUMENT, sqlException.getCode()); assertTrue(sqlException.getMessage(), sqlException.getMessage().contains("test exception")); } } diff --git a/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java b/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java index 9fc6a89dd..57b79a026 100644 --- a/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java +++ b/src/test/java/com/google/cloud/spanner/jdbc/MultiplexedSessionsMockServerTest.java @@ -137,7 +137,7 @@ public void testUsesMultiplexedSessionForQueryInReadOnlyTransaction() throws SQL } @Test - public void testUsesRegularSessionForDmlInAutoCommit() throws SQLException { + public void testUsesMultiplexedSessionForDmlInAutoCommit() throws SQLException { try (Connection connection = createJdbcConnection()) { assertTrue(connection.getAutoCommit()); assertEquals(1, connection.createStatement().executeUpdate(INSERT_SQL)); @@ -154,11 +154,11 @@ public void testUsesRegularSessionForDmlInAutoCommit() throws SQLException { String sessionId = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSession(); Session session = MockServerHelper.getSession(mockSpanner, sessionId); assertNotNull(session); - assertFalse(session.getMultiplexed()); + assertTrue(session.getMultiplexed()); } @Test - public void testUsesRegularSessionForQueryInTransaction() throws SQLException { + public void testUsesMultiplexedSessionForQueryInTransaction() throws SQLException { try (Connection connection = createJdbcConnection()) { connection.setAutoCommit(false); assertFalse(connection.getAutoCommit()); @@ -183,7 +183,7 @@ public void testUsesRegularSessionForQueryInTransaction() throws SQLException { String sessionId = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getSession(); Session session = MockServerHelper.getSession(mockSpanner, sessionId); assertNotNull(session); - assertFalse(session.getMultiplexed()); + assertTrue(session.getMultiplexed()); } @Test