Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,21 @@ protected final IRubyObject beginTransaction(final ThreadContext context, final
// NOTE: only reversed order - just to ~ match how Rails does it :
/* if ( connection.getAutoCommit() ) */ connection.setAutoCommit(false);
if ( isolation != null ) setTransactionIsolation(context, connection, isolation);
// pgjdbc's setAutoCommit(false) only flips a client-side flag; the
// wire-level BEGIN is deferred until the next statement is sent
// (QueryExecutorImpl#sendQueryPreamble). Rails 7.1+ lazy transactions
// assume begin_db_transaction opens a server-side transaction once
// materialized, so flush the deferred BEGIN now with a no-op statement
// - pgjdbc prepends BEGIN to it in the same round-trip, matching the
// cost of pg's exec("BEGIN").
Statement statement = null;
try {
statement = connection.createStatement();
statement.execute("SELECT 1");
}
finally {
close(statement);
}
return context.nil;
}

Expand Down
14 changes: 14 additions & 0 deletions test/db/postgresql/transaction_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ def test_supports_savepoints
assert_true ActiveRecord::Base.connection.supports_savepoints?
end

# pgjdbc defers the wire-level BEGIN until the next statement is sent, but
# AR 7.1+ lazy transactions expect begin_db_transaction to actually open a
# server-side transaction (e.g. materialize_transactions), so it must flush
# the deferred BEGIN right away.
def test_begin_db_transaction_opens_transaction_on_the_server
connection = ActiveRecord::Base.connection
assert_equal 'IDLE', connection.jdbc_connection(true).transaction_state.to_s

connection.begin_db_transaction
assert_equal 'OPEN', connection.jdbc_connection(true).transaction_state.to_s
ensure
connection.rollback_db_transaction
end

# @override
def test_releasing_named_savepoints
omit 'savepoins not supported' unless @supports_savepoints
Expand Down
Loading