Skip to content

Commit fef6c98

Browse files
aidanharanAidan Haran
and
Aidan Haran
authored
Refactored to use new_client connection pattern (#917)
Co-authored-by: Aidan Haran <aharan@fusioneer.com>
1 parent 6855ef8 commit fef6c98

File tree

3 files changed

+91
-82
lines changed

3 files changed

+91
-82
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#### Changed
2121

22-
- ...
22+
- [#917](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/917) Refactored to use new_client connection pattern
2323

2424
#### Added
2525

lib/active_record/connection_adapters/sqlserver_adapter.rb

Lines changed: 81 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,73 @@ class SQLServerAdapter < AbstractAdapter
5959
self.use_output_inserted = true
6060
self.exclude_output_inserted_table_names = Concurrent::Map.new { false }
6161

62-
def initialize(connection, logger = nil, config = {})
62+
class << self
63+
def new_client(config)
64+
case config[:mode]
65+
when :dblib
66+
require "tiny_tds"
67+
dblib_connect(config)
68+
else
69+
raise ArgumentError, "Unknown connection mode in #{config.inspect}."
70+
end
71+
end
72+
73+
def dblib_connect(config)
74+
TinyTds::Client.new(
75+
dataserver: config[:dataserver],
76+
host: config[:host],
77+
port: config[:port],
78+
username: config[:username],
79+
password: config[:password],
80+
database: config[:database],
81+
tds_version: config[:tds_version] || "7.3",
82+
appname: config_appname(config),
83+
login_timeout: config_login_timeout(config),
84+
timeout: config_timeout(config),
85+
encoding: config_encoding(config),
86+
azure: config[:azure],
87+
contained: config[:contained]
88+
).tap do |client|
89+
if config[:azure]
90+
client.execute("SET ANSI_NULLS ON").do
91+
client.execute("SET ANSI_NULL_DFLT_ON ON").do
92+
client.execute("SET ANSI_PADDING ON").do
93+
client.execute("SET ANSI_WARNINGS ON").do
94+
else
95+
client.execute("SET ANSI_DEFAULTS ON").do
96+
end
97+
client.execute("SET QUOTED_IDENTIFIER ON").do
98+
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
99+
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
100+
client.execute("SET TEXTSIZE 2147483647").do
101+
client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
102+
end
103+
rescue TinyTds::Error => e
104+
raise ActiveRecord::NoDatabaseError if e.message.match(/database .* does not exist/i)
105+
raise e
106+
end
107+
108+
def config_appname(config)
109+
config[:appname] || configure_application_name || Rails.application.class.name.split("::").first rescue nil
110+
end
111+
112+
def config_login_timeout(config)
113+
config[:login_timeout].present? ? config[:login_timeout].to_i : nil
114+
end
115+
116+
def config_timeout(config)
117+
config[:timeout].present? ? config[:timeout].to_i / 1000 : nil
118+
end
119+
120+
def config_encoding(config)
121+
config[:encoding].present? ? config[:encoding] : nil
122+
end
123+
end
124+
125+
def initialize(connection, logger, _connection_options, config)
63126
super(connection, logger, config)
64-
# Our Responsibility
65127
@connection_options = config
66-
connect
67-
initialize_dateformatter
68-
use_database
128+
configure_connection
69129
end
70130

71131
# === Abstract Adapter ========================================== #
@@ -226,6 +286,14 @@ def reset!
226286
do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
227287
end
228288

289+
def configure_connection
290+
@spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
291+
@version_year = version_year
292+
293+
initialize_dateformatter
294+
use_database
295+
end
296+
229297
# === Abstract Adapter (Misc Support) =========================== #
230298

231299
def tables_with_referential_integrity
@@ -408,78 +476,18 @@ def translate_exception(e, message:, sql:, binds:)
408476

409477
# === SQLServer Specific (Connection Management) ================ #
410478

411-
def connect
412-
config = @connection_options
413-
@connection = case config[:mode]
414-
when :dblib
415-
dblib_connect(config)
416-
end
417-
@spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
418-
@version_year = version_year
419-
configure_connection
420-
end
421-
422479
def connection_errors
423480
@connection_errors ||= [].tap do |errors|
424481
errors << TinyTds::Error if defined?(TinyTds::Error)
425482
end
426483
end
427484

428-
def dblib_connect(config)
429-
TinyTds::Client.new(
430-
dataserver: config[:dataserver],
431-
host: config[:host],
432-
port: config[:port],
433-
username: config[:username],
434-
password: config[:password],
435-
database: config[:database],
436-
tds_version: config[:tds_version] || "7.3",
437-
appname: config_appname(config),
438-
login_timeout: config_login_timeout(config),
439-
timeout: config_timeout(config),
440-
encoding: config_encoding(config),
441-
azure: config[:azure],
442-
contained: config[:contained]
443-
).tap do |client|
444-
if config[:azure]
445-
client.execute("SET ANSI_NULLS ON").do
446-
client.execute("SET ANSI_NULL_DFLT_ON ON").do
447-
client.execute("SET ANSI_PADDING ON").do
448-
client.execute("SET ANSI_WARNINGS ON").do
449-
else
450-
client.execute("SET ANSI_DEFAULTS ON").do
451-
end
452-
client.execute("SET QUOTED_IDENTIFIER ON").do
453-
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
454-
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
455-
client.execute("SET TEXTSIZE 2147483647").do
456-
client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
457-
end
458-
end
459-
460-
def config_appname(config)
461-
config[:appname] || configure_application_name || Rails.application.class.name.split("::").first rescue nil
462-
end
463-
464-
def config_login_timeout(config)
465-
config[:login_timeout].present? ? config[:login_timeout].to_i : nil
466-
end
467-
468-
def config_timeout(config)
469-
config[:timeout].present? ? config[:timeout].to_i / 1000 : nil
470-
end
471-
472-
def config_encoding(config)
473-
config[:encoding].present? ? config[:encoding] : nil
474-
end
475-
476-
def configure_connection; end
477-
478485
def configure_application_name; end
479486

480487
def initialize_dateformatter
481488
@database_dateformat = user_options_dateformat
482489
a, b, c = @database_dateformat.each_char.to_a
490+
483491
[a, b, c].each { |f| f.upcase! if f == "y" }
484492
dateformat = "%#{a}-%#{b}-%#{c}"
485493
::Date::DATE_FORMATS[:_sqlserver_dateformat] = dateformat
@@ -502,6 +510,13 @@ def version_year
502510
def sqlserver_version
503511
@sqlserver_version ||= _raw_select("SELECT @@version", fetch: :rows).first.first.to_s
504512
end
513+
514+
private
515+
516+
def connect
517+
@connection = self.class.new_client(@connection_options)
518+
configure_connection
519+
end
505520
end
506521
end
507522
end

lib/active_record/sqlserver_base.rb

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,15 @@ module ActiveRecord
44
module ConnectionHandling
55
def sqlserver_connection(config) #:nodoc:
66
config = config.symbolize_keys
7-
config.reverse_merge! mode: :dblib
8-
mode = config[:mode].to_s.downcase.underscore.to_sym
9-
case mode
10-
when :dblib
11-
require "tiny_tds"
12-
else
13-
raise ArgumentError, "Unknown connection mode in #{config.inspect}."
14-
end
15-
ConnectionAdapters::SQLServerAdapter.new(nil, nil, config.merge(mode: mode))
16-
rescue TinyTds::Error => e
17-
if e.message.match(/database .* does not exist/i)
18-
raise ActiveRecord::NoDatabaseError
19-
else
20-
raise
21-
end
7+
config.reverse_merge!(mode: :dblib)
8+
config[:mode] = config[:mode].to_s.downcase.underscore.to_sym
9+
10+
ConnectionAdapters::SQLServerAdapter.new(
11+
ConnectionAdapters::SQLServerAdapter.new_client(config),
12+
logger,
13+
nil,
14+
config
15+
)
2216
end
2317
end
2418
end

0 commit comments

Comments
 (0)