Skip to content

Instantly share code, notes, and snippets.

@tadman
Created April 15, 2011 20:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tadman/922367 to your computer and use it in GitHub Desktop.
Save tadman/922367 to your computer and use it in GitHub Desktop.
FreeTDS Configuration Monkeypatch
module ActiveRecord
class Base
def self.sqlserver_connection(config) #:nodoc:
config = config.dup.symbolize_keys!
config.reverse_merge! :mode => :dblib, :host => 'localhost', :username => 'sa', :password => ''
mode = config[:mode].to_s.downcase.underscore.to_sym
case mode
when :dblib
# <monkeypatch>
# raise ArgumentError, 'Missing :dataserver configuration.' unless config.has_key?(:dataserver)
# </monkeypatch>
require_library_or_gem 'tiny_tds'
warn("TinyTds v0.4.3 or higher required. Using #{TinyTds::VERSION}") unless TinyTds::Client.instance_methods.map(&:to_s).include?("active?")
when :odbc
raise ArgumentError, 'Missing :dsn configuration.' unless config.has_key?(:dsn)
if RUBY_VERSION < '1.9'
require_library_or_gem 'odbc'
else
begin
# TODO: [ODBC] Change this to 'odbc_utf8'
require_library_or_gem 'odbc'
rescue LoadError
require_library_or_gem 'odbc'
end
end unless ['::ODBC','::ODBC_UTF8','::ODBC_NONE'].any? { |odbc_ns| odbc_ns.constantize rescue nil }
require 'active_record/connection_adapters/sqlserver/core_ext/odbc'
when :adonet
require 'System.Data'
raise ArgumentError, 'Missing :database configuration.' unless config.has_key?(:database)
else
raise ArgumentError, "Unknown connection mode in #{config.inspect}."
end
ConnectionAdapters::SQLServerAdapter.new(logger,config.merge(:mode=>mode))
end
end
module ConnectionAdapters
class SQLServerAdapter < AbstractAdapter
def connect
config = @connection_options
@connection = case @connection_options[:mode]
when :dblib
appname = config[:appname] || Rails.application.class.name.split('::').first rescue nil
login_timeout = config[:login_timeout].present? ? config[:login_timeout].to_i : nil
timeout = config[:timeout].present? ? config[:timeout].to_i/1000 : nil
encoding = config[:encoding].present? ? config[:encoding] : nil
# <monkeypatch>
_config = {
:username => config[:username],
:password => config[:password],
:database => config[:database],
:appname => appname,
:login_timeout => login_timeout,
:timeout => timeout,
:encoding => encoding,
:azure => config[:azure]
}
if (config[:dataserver])
_config[:dataserver] = config[:dataserver]
elsif (config[:host])
_config[:host] = config[:host]
end
TinyTds::Client.new(_config).tap do |client|
if config[:azure]
client.execute("SET ANSI_NULLS ON").do
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
client.execute("SET ANSI_NULL_DFLT_ON ON").do
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
client.execute("SET ANSI_PADDING ON").do
client.execute("SET QUOTED_IDENTIFIER ON")
client.execute("SET ANSI_WARNINGS ON").do
else
client.execute("SET ANSI_DEFAULTS ON").do
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
end
# </monkeypatch>
end
when :odbc
odbc = ['::ODBC','::ODBC_UTF8','::ODBC_NONE'].detect{ |odbc_ns| odbc_ns.constantize rescue nil }.constantize
if config[:dsn].include?(';')
driver = odbc::Driver.new.tap do |d|
d.name = config[:dsn_name] || 'Driver1'
d.attrs = config[:dsn].split(';').map{ |atr| atr.split('=') }.reject{ |kv| kv.size != 2 }.inject({}){ |h,kv| k,v = kv ; h[k] = v ; h }
end
odbc::Database.new.drvconnect(driver)
else
odbc.connect config[:dsn], config[:username], config[:password]
end.tap do |c|
if c.respond_to?(:use_time)
c.use_time = true
c.use_utc = ActiveRecord::Base.default_timezone == :utc
@connection_supports_native_types = true
end
end
when :adonet
System::Data::SqlClient::SqlConnection.new.tap do |connection|
connection.connection_string = System::Data::SqlClient::SqlConnectionStringBuilder.new.tap do |cs|
if config[:integrated_security]
cs.integrated_security = true
else
cs.user_i_d = config[:username]
cs.password = config[:password]
end
cs.add 'Server', config[:host].to_clr_string
cs.initial_catalog = config[:database]
cs.multiple_active_result_sets = false
cs.pooling = false
end.to_s
connection.open
end
end
rescue
raise unless @auto_connecting
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment