Skip to content

Commit ce0c422

Browse files
authored
perf: use last_statement optimization in autocommit (#1911)
* perf: use last_statement optimization in autocommit Statements that are executed in autocommit mode should use the last_statement optimization. * test: add more tests
1 parent 121ad50 commit ce0c422

File tree

1 file changed

+168
-0
lines changed

1 file changed

+168
-0
lines changed

src/test/java/com/google/cloud/spanner/jdbc/ExecuteMockServerTest.java

+168
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
3939
import com.google.spanner.v1.CommitRequest;
4040
import com.google.spanner.v1.ExecuteBatchDmlRequest;
41+
import com.google.spanner.v1.ExecuteSqlRequest;
4142
import com.google.spanner.v1.ResultSetMetadata;
4243
import com.google.spanner.v1.ResultSetStats;
4344
import com.google.spanner.v1.StructType;
@@ -66,6 +67,8 @@
6667
*/
6768
@RunWith(Parameterized.class)
6869
public class ExecuteMockServerTest extends AbstractMockServerTest {
70+
private static final IllegalStateException REQUEST_NOT_FOUND =
71+
new IllegalStateException("request not found");
6972
private static Dialect currentDialect;
7073

7174
@Parameters(name = "dialect = {0}")
@@ -219,9 +222,27 @@ public void testStatementExecuteQuery() throws SQLException {
219222
try (ResultSet resultSet = statement.executeQuery(query)) {
220223
verifyResultSet(resultSet);
221224
}
225+
ExecuteSqlRequest request =
226+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
227+
.filter(r -> r.getSql().equals(query))
228+
.findAny()
229+
.orElseThrow(() -> REQUEST_NOT_FOUND);
230+
assertTrue(request.getTransaction().hasSingleUse());
231+
assertTrue(request.getTransaction().getSingleUse().hasReadOnly());
232+
assertFalse(request.getLastStatement());
233+
222234
try (ResultSet resultSet = statement.executeQuery(dmlReturning)) {
223235
verifyResultSet(resultSet);
224236
}
237+
request =
238+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
239+
.filter(r -> r.getSql().equals(dmlReturning))
240+
.findAny()
241+
.orElseThrow(() -> REQUEST_NOT_FOUND);
242+
assertTrue(request.getTransaction().hasBegin());
243+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
244+
assertTrue(request.getLastStatement());
245+
225246
try (ResultSet resultSet = statement.executeQuery(clientSideQuery)) {
226247
verifyClientSideResultSet(resultSet);
227248
}
@@ -237,6 +258,15 @@ public void testStatementExecuteUpdate() throws SQLException {
237258
try (Connection connection = createJdbcConnection();
238259
Statement statement = connection.createStatement()) {
239260
assertEquals(1, statement.executeUpdate(dml));
261+
ExecuteSqlRequest request =
262+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
263+
.filter(r -> r.getSql().equals(dml))
264+
.findAny()
265+
.orElseThrow(() -> REQUEST_NOT_FOUND);
266+
assertTrue(request.getTransaction().hasBegin());
267+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
268+
assertTrue(request.getLastStatement());
269+
240270
assertEquals(0, statement.executeUpdate(DDL));
241271

242272
connection.setAutoCommit(false);
@@ -256,6 +286,14 @@ public void testStatementExecuteUpdateReturnGeneratedKeys() throws SQLException
256286
Statement statement = connection.createStatement()) {
257287
// TODO: Add tests for RETURN_GENERATED_KEYS when that is supported.
258288
assertEquals(1, statement.executeUpdate(dml, Statement.NO_GENERATED_KEYS));
289+
ExecuteSqlRequest request =
290+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
291+
.findAny()
292+
.orElseThrow(() -> REQUEST_NOT_FOUND);
293+
assertTrue(request.getTransaction().hasBegin());
294+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
295+
assertTrue(request.getLastStatement());
296+
259297
assertEquals(0, statement.executeUpdate(DDL, Statement.NO_GENERATED_KEYS));
260298
assertEquals(0, statement.executeUpdate(clientSideUpdate, Statement.NO_GENERATED_KEYS));
261299

@@ -271,6 +309,14 @@ public void testStatementExecuteUpdateReturnColumnNames() throws SQLException {
271309
try (Connection connection = createJdbcConnection();
272310
Statement statement = connection.createStatement()) {
273311
assertEquals(1, statement.executeUpdate(dml, new String[] {"id"}));
312+
ExecuteSqlRequest request =
313+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
314+
.findAny()
315+
.orElseThrow(() -> REQUEST_NOT_FOUND);
316+
assertTrue(request.getTransaction().hasBegin());
317+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
318+
assertTrue(request.getLastStatement());
319+
274320
assertEquals(0, statement.executeUpdate(DDL, new String[] {"id"}));
275321
assertEquals(0, statement.executeUpdate(clientSideUpdate, new String[] {"id"}));
276322

@@ -289,6 +335,14 @@ public void testStatementExecuteUpdateReturnColumnIndexes() throws SQLException
289335
try (Connection connection = createJdbcConnection();
290336
Statement statement = connection.createStatement()) {
291337
assertEquals(1, statement.executeUpdate(dml, new int[] {1}));
338+
ExecuteSqlRequest request =
339+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
340+
.findAny()
341+
.orElseThrow(() -> REQUEST_NOT_FOUND);
342+
assertTrue(request.getTransaction().hasBegin());
343+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
344+
assertTrue(request.getLastStatement());
345+
292346
assertEquals(0, statement.executeUpdate(DDL, new int[] {1}));
293347
assertEquals(0, statement.executeUpdate(clientSideUpdate, new int[] {1}));
294348
verifyOverflow(() -> statement.executeUpdate(largeDml, new int[] {1}));
@@ -303,6 +357,14 @@ public void testStatementLargeExecuteUpdate() throws SQLException {
303357
try (Connection connection = createJdbcConnection();
304358
Statement statement = connection.createStatement()) {
305359
assertEquals(1L, statement.executeLargeUpdate(dml));
360+
ExecuteSqlRequest request =
361+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
362+
.findAny()
363+
.orElseThrow(() -> REQUEST_NOT_FOUND);
364+
assertTrue(request.getTransaction().hasBegin());
365+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
366+
assertTrue(request.getLastStatement());
367+
306368
assertEquals(0L, statement.executeLargeUpdate(DDL));
307369
assertEquals(0L, statement.executeLargeUpdate(clientSideUpdate));
308370
assertEquals(LARGE_UPDATE_COUNT, statement.executeLargeUpdate(largeDml));
@@ -318,6 +380,14 @@ public void testStatementExecuteLargeUpdateReturnGeneratedKeys() throws SQLExcep
318380
Statement statement = connection.createStatement()) {
319381
// TODO: Add tests for RETURN_GENERATED_KEYS when that is supported.
320382
assertEquals(1, statement.executeLargeUpdate(dml, Statement.NO_GENERATED_KEYS));
383+
ExecuteSqlRequest request =
384+
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).stream()
385+
.findAny()
386+
.orElseThrow(() -> REQUEST_NOT_FOUND);
387+
assertTrue(request.getTransaction().hasBegin());
388+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
389+
assertTrue(request.getLastStatement());
390+
321391
assertEquals(0, statement.executeLargeUpdate(DDL, Statement.NO_GENERATED_KEYS));
322392
assertEquals(0, statement.executeLargeUpdate(clientSideUpdate, Statement.NO_GENERATED_KEYS));
323393
assertEquals(
@@ -870,4 +940,102 @@ public void testExecuteAutoBatchDml() throws SQLException {
870940
assertEquals(3, request.getStatementsCount());
871941
assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class));
872942
}
943+
944+
@Test
945+
public void testLastStatement_AutoCommit_Query() throws SQLException {
946+
try (Connection connection = createJdbcConnection();
947+
Statement statement = connection.createStatement()) {
948+
//noinspection EmptyTryBlock
949+
try (ResultSet ignore = statement.executeQuery(query)) {}
950+
}
951+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
952+
assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement());
953+
}
954+
955+
@Test
956+
public void testLastStatement_AutoCommit_Dml() throws SQLException {
957+
try (Connection connection = createJdbcConnection();
958+
Statement statement = connection.createStatement()) {
959+
statement.executeUpdate(dml);
960+
}
961+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
962+
assertTrue(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement());
963+
}
964+
965+
@Test
966+
public void testLastStatement_AutoCommit_DmlReturning() throws SQLException {
967+
try (Connection connection = createJdbcConnection();
968+
Statement statement = connection.createStatement()) {
969+
//noinspection EmptyTryBlock
970+
try (ResultSet ignore = statement.executeQuery(dmlReturning)) {}
971+
}
972+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
973+
assertTrue(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement());
974+
}
975+
976+
@Test
977+
public void testLastStatement_AutoCommit_BatchDml() throws SQLException {
978+
try (Connection connection = createJdbcConnection();
979+
Statement statement = connection.createStatement()) {
980+
statement.addBatch(dml);
981+
statement.addBatch(dml);
982+
statement.executeBatch();
983+
}
984+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class));
985+
assertTrue(
986+
mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0).getLastStatements());
987+
}
988+
989+
@Test
990+
public void testLastStatement_Transaction_Query() throws SQLException {
991+
try (Connection connection = createJdbcConnection();
992+
Statement statement = connection.createStatement()) {
993+
connection.setAutoCommit(false);
994+
//noinspection EmptyTryBlock
995+
try (ResultSet ignore = statement.executeQuery(query)) {}
996+
connection.commit();
997+
}
998+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
999+
assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement());
1000+
}
1001+
1002+
@Test
1003+
public void testLastStatement_Transaction_Dml() throws SQLException {
1004+
try (Connection connection = createJdbcConnection();
1005+
Statement statement = connection.createStatement()) {
1006+
connection.setAutoCommit(false);
1007+
statement.executeUpdate(dml);
1008+
connection.commit();
1009+
}
1010+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
1011+
assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement());
1012+
}
1013+
1014+
@Test
1015+
public void testLastStatement_Transaction_DmlReturning() throws SQLException {
1016+
try (Connection connection = createJdbcConnection();
1017+
Statement statement = connection.createStatement()) {
1018+
connection.setAutoCommit(false);
1019+
//noinspection EmptyTryBlock
1020+
try (ResultSet ignore = statement.executeQuery(dmlReturning)) {}
1021+
connection.commit();
1022+
}
1023+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
1024+
assertFalse(mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0).getLastStatement());
1025+
}
1026+
1027+
@Test
1028+
public void testLastStatement_Transaction_BatchDml() throws SQLException {
1029+
try (Connection connection = createJdbcConnection();
1030+
Statement statement = connection.createStatement()) {
1031+
connection.setAutoCommit(false);
1032+
statement.addBatch(dml);
1033+
statement.addBatch(dml);
1034+
statement.executeBatch();
1035+
connection.commit();
1036+
}
1037+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class));
1038+
assertFalse(
1039+
mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0).getLastStatements());
1040+
}
8731041
}

0 commit comments

Comments
 (0)