Skip to content

Commit 00c839a

Browse files
committed
[Rails3] Use new WrappedDatabaseException classes and implement translate_exception. Also create our own LostConnection exception and use this for auto reconnecting logic.
1 parent 0b48b17 commit 00c839a

File tree

4 files changed

+55
-23
lines changed

4 files changed

+55
-23
lines changed

activerecord-sqlserver-adapter.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
2020
"lib/active_record/connection_adapters/sqlserver_adapter/core_ext/odbc.rb",
2121
"lib/active_record/connection_adapters/sqlserver/database_limits.rb",
2222
"lib/active_record/connection_adapters/sqlserver/database_statements.rb",
23+
"lib/active_record/connection_adapters/sqlserver/errors.rb",
2324
"lib/active_record/connection_adapters/sqlserver/schema_statements.rb",
2425
"lib/active_record/connection_adapters/sqlserver/quoting.rb" ]
2526
s.test_files = [
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
module ActiveRecord
2+
3+
class LostConnection < WrappedDatabaseException
4+
end
5+
6+
module ConnectionAdapters
7+
module Sqlserver
8+
module Errors
9+
10+
LOST_CONNECTION_EXCEPTIONS = {
11+
:odbc => ['ODBC::Error'],
12+
:adonet => ['TypeError','System::Data::SqlClient::SqlException']
13+
}.freeze
14+
15+
LOST_CONNECTION_MESSAGES = {
16+
:odbc => [/link failure/, /server failed/, /connection was already closed/, /invalid handle/i],
17+
:adonet => [/current state is closed/, /network-related/]
18+
}.freeze
19+
20+
21+
def lost_connection_exceptions
22+
exceptions = LOST_CONNECTION_EXCEPTIONS[connection_mode]
23+
@lost_connection_exceptions ||= exceptions ? exceptions.map(&:constantize) : []
24+
end
25+
26+
def lost_connection_messages
27+
LOST_CONNECTION_MESSAGES[connection_mode]
28+
end
29+
30+
end
31+
end
32+
end
33+
end

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'active_record/connection_adapters/sqlserver/core_ext/active_record'
44
require 'active_record/connection_adapters/sqlserver/database_limits'
55
require 'active_record/connection_adapters/sqlserver/database_statements'
6+
require 'active_record/connection_adapters/sqlserver/errors'
67
require 'active_record/connection_adapters/sqlserver/schema_statements'
78
require 'active_record/connection_adapters/sqlserver/quoting'
89
require 'active_support/core_ext/kernel/requires'
@@ -165,19 +166,12 @@ class SQLServerAdapter < AbstractAdapter
165166
include Sqlserver::DatabaseStatements
166167
include Sqlserver::SchemaStatements
167168
include Sqlserver::DatabaseLimits
169+
include Sqlserver::Errors
168170

169171
ADAPTER_NAME = 'SQLServer'.freeze
170-
VERSION = '3.0.0.beta1'.freeze
172+
VERSION = '3.0.0.beta.1'.freeze
171173
DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
172174
SUPPORTED_VERSIONS = [2000,2005,2008].freeze
173-
LOST_CONNECTION_EXCEPTIONS = {
174-
:odbc => ['ODBC::Error'],
175-
:adonet => ['TypeError','System::Data::SqlClient::SqlException']
176-
}
177-
LOST_CONNECTION_MESSAGES = {
178-
:odbc => [/link failure/, /server failed/, /connection was already closed/, /invalid handle/i],
179-
:adonet => [/current state is closed/, /network-related/]
180-
}
181175

182176
cattr_accessor :native_text_database_type, :native_binary_database_type, :native_string_database_type,
183177
:log_info_schema_queries, :enable_default_unicode_types, :auto_connect
@@ -331,6 +325,21 @@ def native_binary_database_type
331325

332326
protected
333327

328+
# === Abstract Adapter (Misc Support) =========================== #
329+
330+
def translate_exception(e, message)
331+
case message
332+
when /cannot insert duplicate key .* with unique index/i
333+
RecordNotUnique.new(message,e)
334+
when /conflicted with the foreign key constraint/i
335+
InvalidForeignKey.new(message,e)
336+
when *lost_connection_messages
337+
LostConnection.new(message,e)
338+
else
339+
super
340+
end
341+
end
342+
334343
# === SQLServer Specific (Connection Management) ================ #
335344

336345
def connect
@@ -369,22 +378,11 @@ def remove_database_connections_and_rollback(database=nil)
369378
end if block_given?
370379
end
371380

372-
def lost_connection_exceptions
373-
exceptions = LOST_CONNECTION_EXCEPTIONS[connection_mode]
374-
@lost_connection_exceptions ||= exceptions ? exceptions.map(&:constantize) : []
375-
end
376-
377-
def lost_connection_messages
378-
LOST_CONNECTION_MESSAGES[connection_mode]
379-
end
380-
381381
def with_auto_reconnect
382382
begin
383383
yield
384-
rescue *lost_connection_exceptions => e
385-
if lost_connection_messages.any? { |lcm| e.message =~ lcm }
386-
retry if auto_reconnected?
387-
end
384+
rescue Exception => e
385+
retry if translate_exception(e,e.message).is_a?(LostConnection) && auto_reconnected?
388386
raise
389387
end
390388
end

test/cases/connection_test_sqlserver.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def setup
106106
should 'not auto reconnect when setting is off' do
107107
with_auto_connect(false) do
108108
@connection.disconnect!
109-
assert_raise(ActiveRecord::StatementInvalid) { Topic.count }
109+
assert_raise(ActiveRecord::LostConnection) { Topic.count }
110110
end
111111
end
112112

0 commit comments

Comments
 (0)