Skip to content

Commit

Permalink
feat: allow DML batches in transactions to execute analyzeUpdate (#3114)
Browse files Browse the repository at this point in the history
Executing analyzeUpdate in a DML Batch inside a transaction should
be possible, as the parent transaction can be used for that.
  • Loading branch information
olavloite authored May 23, 2024
1 parent dfd9c4b commit dee7cda
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,6 @@ private Void endUnitOfWorkSpan() {
return null;
}

abstract boolean isSingleUse();

/**
* Returns a descriptive name for the type of transaction / unit of work. This is used in error
* messages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public String toString() {
}

@Override
boolean isSingleUse() {
public boolean isSingleUse() {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private DdlBatch(Builder builder) {
}

@Override
boolean isSingleUse() {
public boolean isSingleUse() {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ static Builder newBuilder() {

private DmlBatch(Builder builder) {
super(builder);
this.transaction = builder.transaction;
this.transaction = Preconditions.checkNotNull(builder.transaction);
this.statementTag = builder.statementTag;
}

@Override
boolean isSingleUse() {
public boolean isSingleUse() {
return false;
}

Expand Down Expand Up @@ -174,8 +174,11 @@ public ApiFuture<Long> executeUpdateAsync(
@Override
public ApiFuture<ResultSet> analyzeUpdateAsync(
CallType callType, ParsedStatement update, AnalyzeMode analyzeMode, UpdateOption... options) {
throw SpannerExceptionFactory.newSpannerException(
ErrorCode.FAILED_PRECONDITION, "Analyzing updates is not allowed for DML batches.");
if (transaction.isSingleUse()) {
throw SpannerExceptionFactory.newSpannerException(
ErrorCode.FAILED_PRECONDITION, "Analyzing updates is not allowed for DML batches.");
}
return transaction.analyzeUpdateAsync(callType, update, analyzeMode, options);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private SingleUseTransaction(Builder builder) {
}

@Override
boolean isSingleUse() {
public boolean isSingleUse() {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ public boolean isActive() {
/** @return <code>true</code> if this unit of work is still active. */
boolean isActive();

/** Returns true if this transaction can only be used for a single statement. */
boolean isSingleUse();

/**
* Commits the changes in this unit of work to the database. For read-only transactions, this only
* closes the {@link ReadContext}. This method will throw a {@link SpannerException} if called for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,9 @@ public void testAnalyzeUpdateStatementDdlBatch() {
}

@Test
public void testAnalyzeUpdateDmlBatch() {
public void testAnalyzeUpdateDmlBatch_AutoCommit() {
try (Connection connection = createConnection()) {
connection.setAutocommit(true);
connection.startBatchDml();

SpannerException exception =
Expand All @@ -371,8 +372,23 @@ public void testAnalyzeUpdateDmlBatch() {
}

@Test
public void testAnalyzeUpdateStatementDmlBatch() {
public void testAnalyzeUpdateDmlBatch_Transactional() {
try (Connection connection = createConnection()) {
connection.setAutocommit(false);
connection.startBatchDml();

assertNotNull(connection.analyzeUpdate(PLAN_UPDATE, QueryAnalyzeMode.PLAN));
assertEquals(-1L, connection.executeUpdate(INSERT_STATEMENT));
connection.runBatch();

assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
}
}

@Test
public void testAnalyzeUpdateStatementDmlBatch_AutoCommit() {
try (Connection connection = createConnection()) {
connection.setAutocommit(true);
connection.startBatchDml();

SpannerException exception =
Expand All @@ -385,4 +401,18 @@ public void testAnalyzeUpdateStatementDmlBatch() {
assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
}

@Test
public void testAnalyzeUpdateStatementDmlBatch_Transactional() {
try (Connection connection = createConnection()) {
connection.setAutocommit(false);
connection.startBatchDml();

connection.analyzeUpdateStatement(PLAN_UPDATE, QueryAnalyzeMode.PLAN);
assertEquals(-1L, connection.executeUpdate(INSERT_STATEMENT));
connection.runBatch();

assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
}
}
}

0 comments on commit dee7cda

Please sign in to comment.