Skip to content

Commit b382999

Browse files
authored
fix: set transaction isolation level had no effect (#3718)
The `set transaction isolation level` SQL statement was accepted by a connection, but did not actually set the isolation level.
1 parent 79bbf78 commit b382999

File tree

3 files changed

+66
-2
lines changed

3 files changed

+66
-2
lines changed

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java

+21
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,27 @@ public void setTransactionMode(TransactionMode transactionMode) {
859859
this.unitOfWorkType = UnitOfWorkType.of(transactionMode);
860860
}
861861

862+
IsolationLevel getTransactionIsolationLevel() {
863+
ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
864+
ConnectionPreconditions.checkState(!isDdlBatchActive(), "This connection is in a DDL batch");
865+
ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction");
866+
return this.transactionIsolationLevel;
867+
}
868+
869+
void setTransactionIsolationLevel(IsolationLevel isolationLevel) {
870+
Preconditions.checkNotNull(isolationLevel);
871+
ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
872+
ConnectionPreconditions.checkState(
873+
!isBatchActive(), "Cannot set transaction isolation level while in a batch");
874+
ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction");
875+
ConnectionPreconditions.checkState(
876+
!isTransactionStarted(),
877+
"The transaction isolation level cannot be set after the transaction has started");
878+
879+
this.transactionBeginMarked = true;
880+
this.transactionIsolationLevel = isolationLevel;
881+
}
882+
862883
@Override
863884
public String getTransactionTag() {
864885
ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java

+5
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,11 @@ public StatementResult statementSetTransactionMode(TransactionMode mode) {
490490

491491
@Override
492492
public StatementResult statementSetPgTransactionMode(PgTransactionMode transactionMode) {
493+
if (transactionMode.getIsolationLevel() != null) {
494+
getConnection()
495+
.setTransactionIsolationLevel(
496+
transactionMode.getIsolationLevel().getSpannerIsolationLevel());
497+
}
493498
if (transactionMode.getAccessMode() != null) {
494499
switch (transactionMode.getAccessMode()) {
495500
case READ_ONLY_TRANSACTION:

google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TransactionMockServerTest.java

+40-2
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,13 @@ public void testBatchDml() {
122122
}
123123

124124
@Test
125-
public void testTransactionIsolationLevel() {
125+
public void testBeginTransactionIsolationLevel() {
126+
SpannerPool.closeSpannerPool();
126127
for (Dialect dialect : new Dialect[] {Dialect.POSTGRESQL, Dialect.GOOGLE_STANDARD_SQL}) {
127128
mockSpanner.putStatementResult(
128129
MockSpannerServiceImpl.StatementResult.detectDialectResult(dialect));
129130

130-
try (Connection connection = createConnection()) {
131+
try (Connection connection = super.createConnection()) {
131132
for (IsolationLevel isolationLevel :
132133
new IsolationLevel[] {IsolationLevel.REPEATABLE_READ, IsolationLevel.SERIALIZABLE}) {
133134
for (boolean useSql : new boolean[] {true, false}) {
@@ -158,4 +159,41 @@ public void testTransactionIsolationLevel() {
158159
SpannerPool.closeSpannerPool();
159160
}
160161
}
162+
163+
@Test
164+
public void testSetTransactionIsolationLevel() {
165+
SpannerPool.closeSpannerPool();
166+
mockSpanner.putStatementResult(
167+
MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.POSTGRESQL));
168+
169+
try (Connection connection = super.createConnection()) {
170+
for (boolean autocommit : new boolean[] {true, false}) {
171+
connection.setAutocommit(autocommit);
172+
173+
for (IsolationLevel isolationLevel :
174+
new IsolationLevel[] {IsolationLevel.REPEATABLE_READ, IsolationLevel.SERIALIZABLE}) {
175+
// Manually start a transaction if autocommit is enabled.
176+
if (autocommit) {
177+
connection.execute(Statement.of("begin"));
178+
}
179+
connection.execute(
180+
Statement.of(
181+
"set transaction isolation level " + isolationLevel.name().replace("_", " ")));
182+
connection.executeUpdate(INSERT_STATEMENT);
183+
connection.commit();
184+
185+
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
186+
ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
187+
assertTrue(request.getTransaction().hasBegin());
188+
assertTrue(request.getTransaction().getBegin().hasReadWrite());
189+
assertEquals(isolationLevel, request.getTransaction().getBegin().getIsolationLevel());
190+
assertFalse(request.getLastStatement());
191+
assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class));
192+
193+
mockSpanner.clearRequests();
194+
}
195+
}
196+
}
197+
SpannerPool.closeSpannerPool();
198+
}
161199
}

0 commit comments

Comments
 (0)