Skip to content

Commit

Permalink
chore: use existing transaction for analyze in batch (#2737)
Browse files Browse the repository at this point in the history
DML batches in a transaction are allowed to execute analyzeUpdate.
PGAdapter should use this transaction instead of creating a separate
transaction in such cases to reduce the number of round-trips.
  • Loading branch information
olavloite authored Jan 10, 2025
1 parent fa81272 commit 8f0361d
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ StatementResult analyzeOrExecute(Statement statement) {
// We handle one very specific use case here to prevent unnecessary problems: If the user
// has started a DML batch and is then analyzing an update statement (probably a prepared
// statement), then we use a separate transaction for that.
if (spannerConnection.isDmlBatchActive()) {
if (spannerConnection.isDmlBatchActive() && !spannerConnection.isInTransaction()) {
final Statement statementToAnalyze = statement;
resultSet =
spannerConnection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.google.spanner.v1.CommitRequest;
import com.google.spanner.v1.ExecuteSqlRequest;
import com.google.spanner.v1.ExecuteSqlRequest.QueryMode;
import com.google.spanner.v1.ResultSetStats;
import com.google.spanner.v1.RollbackRequest;
import com.google.spanner.v1.TypeCode;
import io.grpc.Status;
Expand Down Expand Up @@ -873,4 +874,36 @@ public void testImplicitBatchOfClientSideStatements() throws SQLException {
}
}
}

@Test
public void testPrepareInDmlBatch() throws SQLException {
String sql = "insert into test (id, value) values ($1, $2)";
mockSpanner.putStatementResult(
StatementResult.query(
com.google.cloud.spanner.Statement.of(sql),
com.google.spanner.v1.ResultSet.newBuilder()
.setMetadata(
createParameterTypesMetadata(ImmutableList.of(TypeCode.INT64, TypeCode.STRING)))
.setStats(ResultSetStats.getDefaultInstance())
.build()));
mockSpanner.putStatementResult(
StatementResult.update(
com.google.cloud.spanner.Statement.newBuilder(sql)
.bind("p1")
.to(1L)
.bind("p2")
.to("one")
.build(),
1L));

try (Connection connection = DriverManager.getConnection(createUrl());
Statement statement = connection.createStatement()) {
statement.execute("begin");
statement.execute("start batch dml");
statement.execute("prepare foo as insert into test (id, value) values ($1, $2)");
statement.execute("execute foo (1, 'one')");
statement.execute("run batch");
statement.execute("commit");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,34 @@ public void testBatchDml() throws Exception {
assertEquals(2, request.getStatementsCount());
}

@Test
public void testBatchDmlInTransaction() throws Exception {
String sql = "insert into my_table (id, value) values ($1, $2)";
mockSpanner.putStatementResult(
StatementResult.query(
Statement.of(sql),
ResultSet.newBuilder()
.setMetadata(
createParameterTypesMetadata(ImmutableList.of(TypeCode.INT64, TypeCode.STRING)))
.setStats(ResultSetStats.getDefaultInstance())
.build()));
mockSpanner.putStatementResult(
StatementResult.update(
Statement.newBuilder(sql).bind("p1").to(1L).bind("p2").to("One").build(), 1L));
mockSpanner.putStatementResult(
StatementResult.update(
Statement.newBuilder(sql).bind("p1").to(2L).bind("p2").to("Two").build(), 1L));

String actualOutput = execute("batch_dml_in_transaction");
String expectedOutput = "Inserted two rows\n";
assertEquals(expectedOutput, actualOutput);

assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class));
ExecuteBatchDmlRequest request =
mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0);
assertEquals(2, request.getStatementsCount());
}

@Test
public void testBatchDdl() throws Exception {
addDdlResponseToSpannerAdmin();
Expand Down
17 changes: 17 additions & 0 deletions src/test/php/pdo/pdo_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,23 @@ function batch_dml($dsn): void
$connection = null;
}

function batch_dml_in_transaction($dsn): void
{
$connection = new PDO($dsn);
$connection->beginTransaction();
$connection->exec("START BATCH DML");
$statement = $connection->prepare("insert into my_table (id, value) values (:id, :value)");
$statement->execute(["id" => 1, "value" => "One"]);
$statement->execute(["id" => 2, "value" => "Two"]);
$connection->exec("RUN BATCH");
$connection->commit();

print("Inserted two rows\n");

$statement = null;
$connection = null;
}

function batch_ddl($dsn): void
{
$connection = new PDO($dsn);
Expand Down

0 comments on commit 8f0361d

Please sign in to comment.