Skip to content

Commit 5f75187

Browse files
committed
[derby] support getting and setting transaction isolation on a connection
setting it using the JDBC method seems to avoid some probable locking : SQLException: Column 'PARAM1' already exists. SQL State: X0Y68 (likely related to #497 as well)
1 parent 223c3d8 commit 5f75187

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

lib/arjdbc/derby/adapter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def init_connection(jdbc_connection)
109109

110110
def configure_connection
111111
# must be done or SELECT...FOR UPDATE won't work how we expect :
112-
execute("SET ISOLATION = SERIALIZABLE")
112+
@connection.transaction_isolation = :serializable
113113
# if a user name was specified upon connection, the user's name is the
114114
# default schema for the connection, if a schema with that name exists
115115
set_schema(config[:schema]) if config.key?(:schema)

src/java/arjdbc/derby/DerbyRubyJdbcConnection.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,46 @@ protected IRubyObject matchTables(final Ruby runtime,
118118
return super.matchTables(runtime, connection, catalog, schemaPattern, tablePattern, types, checkExistsOnly);
119119
}
120120

121+
@JRubyMethod(name = "transaction_isolation", alias = "get_transaction_isolation")
122+
public IRubyObject get_transaction_isolation(final ThreadContext context) {
123+
return withConnection(context, new Callable<IRubyObject>() {
124+
public IRubyObject call(final Connection connection) throws SQLException {
125+
final int level = connection.getTransactionIsolation();
126+
final String isolationSymbol = formatTransactionIsolationLevel(level);
127+
if ( isolationSymbol == null ) return context.getRuntime().getNil();
128+
return context.getRuntime().newSymbol(isolationSymbol);
129+
}
130+
});
131+
}
132+
133+
@JRubyMethod(name = "transaction_isolation=", alias = "set_transaction_isolation")
134+
public IRubyObject set_transaction_isolation(final ThreadContext context, final IRubyObject isolation) {
135+
return withConnection(context, new Callable<IRubyObject>() {
136+
public IRubyObject call(final Connection connection) throws SQLException {
137+
final int level;
138+
if ( isolation.isNil() ) {
139+
level = connection.getMetaData().getDefaultTransactionIsolation();
140+
}
141+
else {
142+
level = mapTransactionIsolationLevel(isolation);
143+
}
144+
145+
connection.setTransactionIsolation(level);
146+
147+
final String isolationSymbol = formatTransactionIsolationLevel(level);
148+
if ( isolationSymbol == null ) return context.getRuntime().getNil();
149+
return context.getRuntime().newSymbol(isolationSymbol);
150+
}
151+
});
152+
}
153+
154+
public static String formatTransactionIsolationLevel(final int level) {
155+
if ( level == Connection.TRANSACTION_READ_UNCOMMITTED ) return "read_uncommitted"; // 1
156+
if ( level == Connection.TRANSACTION_READ_COMMITTED ) return "read_committed"; // 2
157+
if ( level == Connection.TRANSACTION_REPEATABLE_READ ) return "repeatable_read"; // 4
158+
if ( level == Connection.TRANSACTION_SERIALIZABLE ) return "serializable"; // 8
159+
if ( level == 0 ) return null;
160+
throw new IllegalArgumentException("unexpected transaction isolation level: " + level);
161+
}
162+
121163
}

0 commit comments

Comments
 (0)