1+ require 'active_record'
12require 'active_record/connection_adapters/abstract_adapter'
2- require_library_or_gem 'odbc' unless defined? ( ODBC )
3- require File . dirname ( __FILE__ ) +'/sqlserver_adapter/core_ext/odbc'
43require 'active_record/connection_adapters/sqlserver_adapter/core_ext/active_record'
54require 'base64'
65
@@ -9,12 +8,22 @@ module ActiveRecord
98 class Base
109
1110 def self . sqlserver_connection ( config ) #:nodoc:
12- config . symbolize_keys!
13- username = config [ :username ] ? config [ :username ] . to_s : 'sa'
14- password = config [ :password ] ? config [ :password ] . to_s : ''
15- raise ArgumentError , "Missing DSN. Argument ':dsn' must be set in order for this adapter to work." unless config . has_key? ( :dsn )
16- dsn = config [ :dsn ]
17- ConnectionAdapters ::SQLServerAdapter . new ( logger , [ dsn , username , password ] )
11+ config = config . dup . symbolize_keys!
12+ config . reverse_merge! :mode => :odbc , :host => 'localhost' , :username => 'sa' , :password => ''
13+ mode = config [ :mode ] . to_s . downcase . underscore . to_sym
14+ case mode
15+ when :odbc
16+ require_library_or_gem 'odbc' unless defined? ( ODBC )
17+ require 'active_record/connection_adapters/sqlserver_adapter/core_ext/odbc'
18+ raise ArgumentError , 'Missing :dsn configuration.' unless config . has_key? ( :dsn )
19+ config = config . slice :dsn , :username , :password
20+ when :ado
21+ raise NotImplementedError , 'Please use version 2.3.1 of the adapter for ADO connections. Future versions may support ADO.NET.'
22+ raise ArgumentError , 'Missing :database configuration.' unless config . has_key? ( :database )
23+ else
24+ raise ArgumentError , "Unknown connection mode in #{ config . inspect } ."
25+ end
26+ ConnectionAdapters ::SQLServerAdapter . new ( logger , config . merge ( :mode => mode ) )
1827 end
1928
2029 protected
@@ -138,28 +147,30 @@ def simplified_datetime
138147
139148 end #SQLServerColumn
140149
141- # In ODBC mode, the adapter requires the ODBC support in the DBI module which requires
142- # the Ruby ODBC module. Ruby ODBC 0.996 was used in development and testing,
143- # and it is available at http://www.ch-werner.de/rubyodbc/
150+ # In ODBC mode, the adapter requires Ruby ODBC and requires that you specify
151+ # a :dsn option. Ruby ODBC is available at http://www.ch-werner.de/rubyodbc/
144152 #
145153 # Options:
146154 #
147155 # * <tt>:username</tt> -- Defaults to sa.
148- # * <tt>:password</tt> -- Defaults to empty string.
149- # * <tt>:dsn</tt> -- Defaults to nothing.
156+ # * <tt>:password</tt> -- Defaults to blank string.
157+ # * <tt>:dsn</tt> -- An ODBC DSN. (required)
150158 #
151159 class SQLServerAdapter < AbstractAdapter
152160
153- ADAPTER_NAME = 'SQLServer' . freeze
154- VERSION = '2.4-mmi' . freeze
155- DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s +(\d {4})/
156- SUPPORTED_VERSIONS = [ 2000 , 2005 , 2008 ] . freeze
157- LIMITABLE_TYPES = [ 'string' , 'integer' , 'float' , 'char' , 'nchar' , 'varchar' , 'nvarchar' ] . freeze
158-
159- LOST_CONNECTION_EXCEPTIONS = [ ODBC ::Error ] #[DBI::DatabaseError, DBI::InterfaceError]
160- LOST_CONNECTION_MESSAGES = [
161- 'Invalid handle'
162- ]
161+ ADAPTER_NAME = 'SQLServer' . freeze
162+ VERSION = '2.3.2' . freeze
163+ DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s +(\d {4})/
164+ SUPPORTED_VERSIONS = [ 2000 , 2005 , 2008 ] . freeze
165+ LIMITABLE_TYPES = [ 'string' , 'integer' , 'float' , 'char' , 'nchar' , 'varchar' , 'nvarchar' ] . freeze
166+ LOST_CONNECTION_EXCEPTIONS = {
167+ :odbc => [ 'ODBC::Error' ] ,
168+ :ado => [ ]
169+ }
170+ LOST_CONNECTION_MESSAGES = {
171+ :odbc => [ /link failure/ , /server failed/ , /connection was already closed/ , /invalid handle/i ] ,
172+ :ado => [ ]
173+ }
163174
164175 cattr_accessor :native_text_database_type , :native_binary_database_type , :native_string_database_type ,
165176 :log_info_schema_queries , :enable_default_unicode_types , :auto_connect
@@ -172,8 +183,8 @@ def type_limitable?(type)
172183
173184 end
174185
175- def initialize ( logger , connection_options )
176- @connection_options = connection_options
186+ def initialize ( logger , config )
187+ @connection_options = config
177188 connect
178189 super ( raw_connection , logger )
179190 initialize_sqlserver_caches
@@ -317,7 +328,7 @@ def disable_referential_integrity(&block)
317328 def active?
318329 raw_connection . run ( "SELECT 1" ) . drop
319330 true
320- rescue *LOST_CONNECTION_EXCEPTIONS
331+ rescue *lost_connection_exceptions
321332 false
322333 end
323334
@@ -737,22 +748,35 @@ def remove_database_connections_and_rollback(name)
737748 # CONNECTION MANAGEMENT ====================================#
738749
739750 def connect
740- dsn , username , password = @connection_options
741- @connection = ODBC . connect ( dsn , username , password )
742- configure_connection
751+ config = @connection_options
752+ @connection = case connection_mode
753+ when :odbc
754+ ODBC . connect config [ :dsn ] , config [ :username ] , config [ :password ]
755+ when :ado
756+
757+ end
743758 rescue
744759 raise unless @auto_connecting
745760 end
746761
747- def configure_connection
748- # raw_connection['AutoCommit'] = true
762+ def connection_mode
763+ @connection_options [ :mode ]
764+ end
765+
766+ def lost_connection_exceptions
767+ exceptions = LOST_CONNECTION_EXCEPTIONS [ connection_mode ]
768+ @lost_connection_exceptions ||= exceptions ? exceptions . map ( &:constantize ) : [ ]
769+ end
770+
771+ def lost_connection_messages
772+ LOST_CONNECTION_MESSAGES [ connection_mode ]
749773 end
750774
751775 def with_auto_reconnect
752776 begin
753777 yield
754- rescue *LOST_CONNECTION_EXCEPTIONS => e
755- if LOST_CONNECTION_MESSAGES . any? { |lcm | e . message =~ Regexp . new ( lcm , Regexp :: IGNORECASE ) }
778+ rescue *lost_connection_exceptions => e
779+ if lost_connection_messages . any? { |lcm | e . message =~ lcm }
756780 retry if auto_reconnected?
757781 end
758782 raise
@@ -831,7 +855,6 @@ def raw_select(sql, name = nil)
831855 results = handle_as_array ( handle )
832856 rows = results . inject ( [ ] ) do |rows , row |
833857 row . each_with_index do |value , i |
834- # DEPRECATED in DBI 0.4.0 and above. Remove when 0.2.2 and lower is no longer supported.
835858 if value . is_a? ODBC ::TimeStamp
836859 row [ i ] = value . to_sqlserver_string
837860 end
0 commit comments