From 7439aacd7b93d3f40015ea41744ce2d71c23ebb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 14 Oct 2023 20:56:45 +0200 Subject: [PATCH] fix: accept statements with only comments (#1122) Some drivers send a statement containing only a comment in order to ping the server. These statements would return an error on PGAdapter. This would cause the newest pgx driver to fail with a 'driver: bad connection' error. --- .../statements/BackendConnection.java | 2 +- .../JdbcSimpleModeMockServerTest.java | 24 +++++++++++++++++++ .../statements/BackendConnectionTest.java | 6 +++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java b/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java index 5d898bd20..5752080fd 100644 --- a/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java +++ b/src/main/java/com/google/cloud/spanner/pgadapter/statements/BackendConnection.java @@ -277,7 +277,7 @@ void execute() { // Ignore the statement as it is a no-op to execute COMMIT/ROLLBACK when we are not in a // transaction. TODO: Return a warning. result.set(NO_RESULT); - } else if (statement.getSql().isEmpty()) { + } else if (parsedStatement.getSqlWithoutComments().isEmpty()) { result.set(NO_RESULT); } else if (parsedStatement.isDdl()) { if (analyze) { diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java index ded38fe62..94484c6f0 100644 --- a/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java +++ b/src/test/java/com/google/cloud/spanner/pgadapter/JdbcSimpleModeMockServerTest.java @@ -243,6 +243,30 @@ public void testEmptyStatement() throws SQLException { assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); } + @Test + public void testEmptyStatementWithSemiColon() throws SQLException { + String sql = ";"; + + try (Connection connection = DriverManager.getConnection(createUrl())) { + assertFalse(connection.createStatement().execute(sql)); + } + + // An empty statement is not sent to Spanner. + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + + @Test + public void testPing() throws SQLException { + String sql = "-- ping"; + + try (Connection connection = DriverManager.getConnection(createUrl())) { + assertFalse(connection.createStatement().execute(sql)); + } + + // An empty statement is not sent to Spanner. + assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + } + @Test public void testInvalidDml() throws SQLException { try (Connection connection = DriverManager.getConnection(createUrl())) { diff --git a/src/test/java/com/google/cloud/spanner/pgadapter/statements/BackendConnectionTest.java b/src/test/java/com/google/cloud/spanner/pgadapter/statements/BackendConnectionTest.java index 4e4320da0..083fbfb1e 100644 --- a/src/test/java/com/google/cloud/spanner/pgadapter/statements/BackendConnectionTest.java +++ b/src/test/java/com/google/cloud/spanner/pgadapter/statements/BackendConnectionTest.java @@ -391,8 +391,9 @@ public void testQueryResult() { @Test public void testGeneralException() { Connection connection = mock(Connection.class); - ParsedStatement parsedStatement = mock(ParsedStatement.class); Statement statement = Statement.of("select foo from bar"); + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); RuntimeException error = new RuntimeException("test error"); when(connection.execute(statement)).thenThrow(error); @@ -416,8 +417,9 @@ public void testGeneralException() { @Test public void testCancelledException() { Connection connection = mock(Connection.class); - ParsedStatement parsedStatement = mock(ParsedStatement.class); Statement statement = Statement.of("select foo from bar"); + ParsedStatement parsedStatement = mock(ParsedStatement.class); + when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); SpannerException error = SpannerExceptionFactory.newSpannerException(ErrorCode.CANCELLED, "query cancelled"); when(connection.execute(statement)).thenThrow(error);