From e1955c3014c61600c9dd294630394158cea01798 Mon Sep 17 00:00:00 2001 From: Joe Rafaniello Date: Thu, 17 Nov 2011 16:01:20 -0500 Subject: [PATCH] Handle statements that cannot be retried on a new database connection by not reconnecting. For example, retrying commit_db_transaction on a new connection would result in: The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.: COMMIT TRANSACTION --- .../sqlserver/database_statements.rb | 6 +-- .../connection_adapters/sqlserver_adapter.rb | 7 ++++ test/cases/connection_test_sqlserver.rb | 39 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/lib/active_record/connection_adapters/sqlserver/database_statements.rb b/lib/active_record/connection_adapters/sqlserver/database_statements.rb index 5013a8079..c00a20a05 100644 --- a/lib/active_record/connection_adapters/sqlserver/database_statements.rb +++ b/lib/active_record/connection_adapters/sqlserver/database_statements.rb @@ -50,7 +50,7 @@ def begin_db_transaction end def commit_db_transaction - do_execute "COMMIT TRANSACTION" + disable_auto_reconnect { do_execute "COMMIT TRANSACTION" } end def rollback_db_transaction @@ -58,14 +58,14 @@ def rollback_db_transaction end def create_savepoint - do_execute "SAVE TRANSACTION #{current_savepoint_name}" + disable_auto_reconnect { do_execute "SAVE TRANSACTION #{current_savepoint_name}" } end def release_savepoint end def rollback_to_savepoint - do_execute "ROLLBACK TRANSACTION #{current_savepoint_name}" + disable_auto_reconnect { do_execute "ROLLBACK TRANSACTION #{current_savepoint_name}" } end def add_limit_offset!(sql, options) diff --git a/lib/active_record/connection_adapters/sqlserver_adapter.rb b/lib/active_record/connection_adapters/sqlserver_adapter.rb index b2a1fbd2c..9aef15562 100644 --- a/lib/active_record/connection_adapters/sqlserver_adapter.rb +++ b/lib/active_record/connection_adapters/sqlserver_adapter.rb @@ -477,6 +477,13 @@ def with_auto_reconnect end end + def disable_auto_reconnect + old_auto_connect, self.class.auto_connect = self.class.auto_connect, false + yield + ensure + self.class.auto_connect = old_auto_connect + end + def auto_reconnected? return false unless auto_connect @auto_connecting = true diff --git a/test/cases/connection_test_sqlserver.rb b/test/cases/connection_test_sqlserver.rb index cf7030ab8..f4b437847 100644 --- a/test/cases/connection_test_sqlserver.rb +++ b/test/cases/connection_test_sqlserver.rb @@ -115,6 +115,45 @@ def setup end end + context 'testing #disable_auto_reconnect' do + should 'when auto reconnect setting is on' do + with_auto_connect(true) do + @connection.send(:disable_auto_reconnect) do + assert !@connection.class.auto_connect + end + assert @connection.class.auto_connect + end + end + + should 'when auto reconnect setting is off' do + with_auto_connect(false) do + @connection.send(:disable_auto_reconnect) do + assert !@connection.class.auto_connect + end + assert !@connection.class.auto_connect + end + end + end + + should 'not auto reconnect on commit transaction' do + @connection.disconnect! + assert_raise(ActiveRecord::LostConnection) { @connection.commit_db_transaction } + end + + should 'gracefully ignore lost connections on rollback transaction' do + @connection.disconnect! + assert_nothing_raised { @connection.rollback_db_transaction } + end + + should 'not auto reconnect on create savepoint' do + @connection.disconnect! + assert_raise(ActiveRecord::LostConnection) { @connection.create_savepoint } + end + + should 'not auto reconnect on rollback to savepoint ' do + @connection.disconnect! + assert_raise(ActiveRecord::LostConnection) { @connection.rollback_to_savepoint } + end end