Skip to content

Commit 3142f18

Browse files
Fix getTransactionIsolationLevel for read-only and read-write
1 parent c6eeaf0 commit 3142f18

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

src/main/java/oracle/r2dbc/impl/OracleConnectionImpl.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,16 @@ public Publisher<Void> setStatementTimeout(Duration timeout) {
643643
* <p>
644644
* Implements the R2DBC SPI method by returning the isolation level set for
645645
* the database session of this {@code Connection}, if the session is not
646-
* currently in a transaction. If the session is in a transaction, then the
647-
* isolation level of that transaction is returned.
646+
* currently in a transaction.
647+
* </p><p>
648+
* If the session is in a transaction, and an isolation level was
649+
* explicitly specified via {@link TransactionDefinition#ISOLATION_LEVEL},
650+
* then the isolation level of that transaction is returned. If the current
651+
* transaction is read-only, then {@link IsolationLevel#SERIALIZABLE} is
652+
* returned as read-only transactions have the same behavior as if the
653+
* SERIALIZABLE isolation level. Otherwise, if no isolation level was
654+
* explicitly set, then the current transaction should have the isolation
655+
* level set for the database session.
648656
* </p>
649657
* @throws IllegalStateException If this {@code Connection} is closed
650658
*/
@@ -659,10 +667,11 @@ public IsolationLevel getTransactionIsolationLevel() {
659667
IsolationLevel currentIsolationLevel =
660668
currentTransaction.getAttribute(ISOLATION_LEVEL);
661669

662-
if (currentIsolationLevel == null)
663-
return isolationLevel;
664-
else
665-
return currentIsolationLevel;
670+
return currentIsolationLevel != null
671+
? currentIsolationLevel
672+
: Boolean.TRUE == currentTransaction.getAttribute(READ_ONLY)
673+
? SERIALIZABLE
674+
: isolationLevel;
666675
}
667676
}
668677

src/test/java/oracle/r2dbc/impl/OracleConnectionImplTest.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,14 @@ public void testBeginTransactionReadOnly() {
241241
awaitUpdate(1, sessionB.createStatement(
242242
"INSERT INTO testBeginTransactionReadOnly VALUES ('b')"));
243243

244-
// Begin a READ ONLY transaction with sessionA and expect a query result
245-
// having only the committed row, and not the uncomitted row
244+
// Begin a READ ONLY transaction with sessionA. Expect
245+
// getTransactionIsolationLevel to return SERIALIZABLE as read-only
246+
// transactions have the same behavior. Expect a query result
247+
// having only the committed row, and not the uncommitted row
246248
awaitNone(sessionA.commitTransaction());
247249
awaitNone(sessionA.beginTransaction(transactionDefinition(Map.of(
248250
READ_ONLY, true))));
251+
assertEquals(SERIALIZABLE, sessionA.getTransactionIsolationLevel());
249252
awaitQuery(List.of("a"), row -> row.get(0, String.class),
250253
sessionA.createStatement(
251254
"SELECT value FROM testBeginTransactionReadOnly"));
@@ -288,6 +291,12 @@ public void testBeginTransactionReadWrite() {
288291
verifyReadCommittedIsolation(connection, () ->
289292
connection.beginTransaction(transactionDefinition(Map.of(
290293
READ_ONLY, false))));
294+
295+
// Expect read write transactions to have the session's isolation level
296+
awaitNone(connection.setTransactionIsolationLevel(SERIALIZABLE));
297+
verifySerializableIsolation(connection, () ->
298+
connection.beginTransaction(transactionDefinition(Map.of(
299+
READ_ONLY, false))));
291300
}
292301
finally {
293302
tryAwaitNone(connection.close());
@@ -367,6 +376,7 @@ private static void verifyReadCommittedIsolation(
367376
sessionA.isAutoCommit(),
368377
"Unexpected return value from isAutoCommit() after" +
369378
" beginTransaction()");
379+
assertEquals(READ_COMMITTED, sessionA.getTransactionIsolationLevel());
370380
awaitUpdate(1, sessionA.createStatement(
371381
"INSERT INTO verifyReadCommittedIsolation VALUES ('A')"));
372382

@@ -455,6 +465,7 @@ private static void verifySerializableIsolation(
455465
sessionA.isAutoCommit(),
456466
"Unexpected return value from isAutoCommit() after" +
457467
" beginTransaction()");
468+
assertEquals(SERIALIZABLE, sessionA.getTransactionIsolationLevel());
458469
awaitUpdate(1, sessionA.createStatement(
459470
"INSERT INTO verifySerializableIsolation VALUES ('A')"));
460471

@@ -1018,7 +1029,25 @@ public void testGetTransactionIsolationLevel() {
10181029
"Unexpected return value of getTransactionIsolationLevel() for a" +
10191030
" newly created connection");
10201031

1021-
// TODO: Verify serializable
1032+
1033+
// Begin a transaction with a different level that what was passed to
1034+
// setTransactionIsolationLevel. Expect the getter to return the level
1035+
// of the current transaction
1036+
awaitNone(connection.beginTransaction(SERIALIZABLE));
1037+
assertEquals(SERIALIZABLE, connection.getTransactionIsolationLevel());
1038+
1039+
// End the transaction and expect the getter to return the setter value
1040+
awaitNone(connection.commitTransaction());
1041+
assertEquals(READ_COMMITTED, connection.getTransactionIsolationLevel());
1042+
1043+
// Set the level and expect the getter to return it
1044+
awaitNone(connection.setTransactionIsolationLevel(SERIALIZABLE));
1045+
assertEquals(SERIALIZABLE, connection.getTransactionIsolationLevel());
1046+
1047+
// Begin a READ ONLY transaction, expect the READ COMMITTED ISOLATION
1048+
// level.
1049+
//TODO
1050+
10221051
}
10231052
finally {
10241053
tryAwaitNone(connection.close());

0 commit comments

Comments
 (0)