1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
# frozen-string-literal: true
module Sequel
module JDBC
module Transactions
def freeze
supports_savepoints?
super
end
# Check the JDBC DatabaseMetaData for savepoint support
def supports_savepoints?
return @supports_savepoints if defined?(@supports_savepoints)
@supports_savepoints = synchronize{|c| c.getMetaData.supports_savepoints}
end
# Check the JDBC DatabaseMetaData for support for serializable isolation,
# since that's the value most people will use.
def supports_transaction_isolation_levels?
synchronize{|conn| conn.getMetaData.supportsTransactionIsolationLevel(JavaSQL::Connection::TRANSACTION_SERIALIZABLE)}
end
private
JDBC_TRANSACTION_ISOLATION_LEVELS = {:uncommitted=>JavaSQL::Connection::TRANSACTION_READ_UNCOMMITTED,
:committed=>JavaSQL::Connection::TRANSACTION_READ_COMMITTED,
:repeatable=>JavaSQL::Connection::TRANSACTION_REPEATABLE_READ,
:serializable=>JavaSQL::Connection::TRANSACTION_SERIALIZABLE}.freeze
# Set the transaction isolation level on the given connection using
# the JDBC API.
def set_transaction_isolation(conn, opts)
level = opts.fetch(:isolation, transaction_isolation_level)
if (jdbc_level = JDBC_TRANSACTION_ISOLATION_LEVELS[level]) &&
conn.getMetaData.supportsTransactionIsolationLevel(jdbc_level)
_trans(conn)[:original_jdbc_isolation_level] = conn.getTransactionIsolation
log_connection_yield("Transaction.isolation_level = #{level}", conn){conn.setTransactionIsolation(jdbc_level)}
end
end
# Most JDBC drivers that support savepoints support releasing them.
def supports_releasing_savepoints?
true
end
# JDBC savepoint object for the current savepoint for the connection.
def savepoint_obj(conn)
_trans(conn)[:savepoints][-1][:obj]
end
# Use JDBC connection's setAutoCommit to false to start transactions
def begin_transaction(conn, opts=OPTS)
if in_savepoint?(conn)
_trans(conn)[:savepoints][-1][:obj] = log_connection_yield('Transaction.savepoint', conn){conn.set_savepoint}
else
log_connection_yield('Transaction.begin', conn){conn.setAutoCommit(false)}
set_transaction_isolation(conn, opts)
end
end
# Use JDBC connection's commit method to commit transactions
def commit_transaction(conn, opts=OPTS)
if in_savepoint?(conn)
if supports_releasing_savepoints?
log_connection_yield('Transaction.release_savepoint', conn){conn.release_savepoint(savepoint_obj(conn))}
end
else
log_connection_yield('Transaction.commit', conn){conn.commit}
end
end
# Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
def remove_transaction(conn, committed)
if jdbc_level = _trans(conn)[:original_jdbc_isolation_level]
log_connection_yield("Transaction.restore_isolation_level", conn){conn.setTransactionIsolation(jdbc_level)}
end
unless in_savepoint?(conn)
conn.setAutoCommit(true)
end
ensure
super
end
# Use JDBC connection's rollback method to rollback transactions
def rollback_transaction(conn, opts=OPTS)
if in_savepoint?(conn)
log_connection_yield('Transaction.rollback_savepoint', conn){conn.rollback(savepoint_obj(conn))}
else
log_connection_yield('Transaction.rollback', conn){conn.rollback}
end
end
end
end
end
|