activerecord-sqlserver-adapter 3.1.1 → 3.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG +253 -63
- data/VERSION +1 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +0 -7
- data/lib/active_record/connection_adapters/sqlserver/core_ext/database_statements.rb +97 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +41 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/relation.rb +19 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +169 -61
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +3 -0
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +12 -4
- data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +85 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +102 -123
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +69 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +25 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +67 -0
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +32 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +185 -122
- data/lib/arel/visitors/sqlserver.rb +32 -9
- metadata +46 -63
- data/README.rdoc +0 -176
- data/lib/active_record/connection_adapters/sqlserver/version.rb +0 -11
@@ -1,29 +1,35 @@
|
|
1
|
+
require 'base64'
|
1
2
|
require 'arel/visitors/sqlserver'
|
2
3
|
require 'active_record'
|
4
|
+
require 'active_record/base'
|
5
|
+
require 'active_support/concern'
|
6
|
+
require 'active_support/core_ext/string'
|
3
7
|
require 'active_record/connection_adapters/abstract_adapter'
|
4
8
|
require 'active_record/connection_adapters/sqlserver/core_ext/active_record'
|
9
|
+
require 'active_record/connection_adapters/sqlserver/core_ext/database_statements'
|
10
|
+
require 'active_record/connection_adapters/sqlserver/core_ext/explain'
|
11
|
+
require 'active_record/connection_adapters/sqlserver/core_ext/explain_subscriber'
|
12
|
+
require 'active_record/connection_adapters/sqlserver/core_ext/relation'
|
5
13
|
require 'active_record/connection_adapters/sqlserver/database_limits'
|
6
14
|
require 'active_record/connection_adapters/sqlserver/database_statements'
|
7
15
|
require 'active_record/connection_adapters/sqlserver/errors'
|
16
|
+
require 'active_record/connection_adapters/sqlserver/schema_cache'
|
8
17
|
require 'active_record/connection_adapters/sqlserver/schema_statements'
|
18
|
+
require 'active_record/connection_adapters/sqlserver/showplan'
|
9
19
|
require 'active_record/connection_adapters/sqlserver/quoting'
|
10
|
-
require 'active_record/connection_adapters/sqlserver/
|
11
|
-
require 'active_support/core_ext/kernel/requires'
|
12
|
-
require 'active_support/core_ext/string'
|
13
|
-
require 'base64'
|
20
|
+
require 'active_record/connection_adapters/sqlserver/utils'
|
14
21
|
|
15
22
|
module ActiveRecord
|
16
|
-
|
23
|
+
|
17
24
|
class Base
|
18
|
-
|
25
|
+
|
19
26
|
def self.sqlserver_connection(config) #:nodoc:
|
20
27
|
config = config.symbolize_keys
|
21
|
-
config.reverse_merge! :mode => :dblib
|
28
|
+
config.reverse_merge! :mode => :dblib
|
22
29
|
mode = config[:mode].to_s.downcase.underscore.to_sym
|
23
30
|
case mode
|
24
31
|
when :dblib
|
25
32
|
require 'tiny_tds'
|
26
|
-
warn("TinyTds v0.4.3 or higher required. Using #{TinyTds::VERSION}") unless TinyTds::Client.instance_methods.map(&:to_s).include?("active?")
|
27
33
|
when :odbc
|
28
34
|
raise ArgumentError, 'Missing :dsn configuration.' unless config.has_key?(:dsn)
|
29
35
|
require 'odbc'
|
@@ -31,75 +37,79 @@ module ActiveRecord
|
|
31
37
|
else
|
32
38
|
raise ArgumentError, "Unknown connection mode in #{config.inspect}."
|
33
39
|
end
|
34
|
-
ConnectionAdapters::SQLServerAdapter.new(logger,config.merge(:mode=>mode))
|
40
|
+
ConnectionAdapters::SQLServerAdapter.new(nil, logger, nil, config.merge(:mode=>mode))
|
35
41
|
end
|
36
|
-
|
42
|
+
|
37
43
|
protected
|
38
|
-
|
44
|
+
|
39
45
|
def self.did_retry_sqlserver_connection(connection,count)
|
40
46
|
logger.info "CONNECTION RETRY: #{connection.class.name} retry ##{count}."
|
41
47
|
end
|
42
|
-
|
48
|
+
|
43
49
|
def self.did_lose_sqlserver_connection(connection)
|
44
50
|
logger.info "CONNECTION LOST: #{connection.class.name}"
|
45
51
|
end
|
46
|
-
|
52
|
+
|
47
53
|
end
|
48
|
-
|
54
|
+
|
49
55
|
module ConnectionAdapters
|
50
|
-
|
56
|
+
|
51
57
|
class SQLServerColumn < Column
|
52
58
|
|
53
59
|
def initialize(name, default, sql_type = nil, null = true, sqlserver_options = {})
|
54
60
|
@sqlserver_options = sqlserver_options.symbolize_keys
|
55
61
|
super(name, default, sql_type, null)
|
56
|
-
@primary = @sqlserver_options[:is_identity]
|
62
|
+
@primary = @sqlserver_options[:is_identity] || @sqlserver_options[:is_primary]
|
57
63
|
end
|
58
|
-
|
64
|
+
|
59
65
|
class << self
|
60
|
-
|
66
|
+
|
61
67
|
def string_to_binary(value)
|
62
68
|
"0x#{value.unpack("H*")[0]}"
|
63
69
|
end
|
64
|
-
|
70
|
+
|
65
71
|
def binary_to_string(value)
|
66
72
|
value =~ /[^[:xdigit:]]/ ? value : [value].pack('H*')
|
67
73
|
end
|
68
|
-
|
74
|
+
|
69
75
|
end
|
70
|
-
|
76
|
+
|
71
77
|
def is_identity?
|
72
78
|
@sqlserver_options[:is_identity]
|
73
79
|
end
|
74
|
-
|
80
|
+
|
81
|
+
def is_primary?
|
82
|
+
@sqlserver_options[:is_primary]
|
83
|
+
end
|
84
|
+
|
75
85
|
def is_utf8?
|
76
86
|
!!(@sql_type =~ /nvarchar|ntext|nchar/i)
|
77
87
|
end
|
78
|
-
|
88
|
+
|
79
89
|
def is_integer?
|
80
90
|
!!(@sql_type =~ /int/i)
|
81
91
|
end
|
82
|
-
|
92
|
+
|
83
93
|
def is_real?
|
84
94
|
!!(@sql_type =~ /real/i)
|
85
95
|
end
|
86
|
-
|
96
|
+
|
87
97
|
def sql_type_for_statement
|
88
98
|
if is_integer? || is_real?
|
89
|
-
sql_type.sub(/\(\d
|
99
|
+
sql_type.sub(/\((\d+)?\)/,'')
|
90
100
|
else
|
91
101
|
sql_type
|
92
102
|
end
|
93
103
|
end
|
94
|
-
|
104
|
+
|
95
105
|
def default_function
|
96
106
|
@sqlserver_options[:default_function]
|
97
107
|
end
|
98
|
-
|
108
|
+
|
99
109
|
def table_name
|
100
110
|
@sqlserver_options[:table_name]
|
101
111
|
end
|
102
|
-
|
112
|
+
|
103
113
|
def table_klass
|
104
114
|
@table_klass ||= begin
|
105
115
|
table_name.classify.constantize
|
@@ -108,14 +118,14 @@ module ActiveRecord
|
|
108
118
|
end
|
109
119
|
(@table_klass && @table_klass < ActiveRecord::Base) ? @table_klass : nil
|
110
120
|
end
|
111
|
-
|
121
|
+
|
112
122
|
def database_year
|
113
123
|
@sqlserver_options[:database_year]
|
114
124
|
end
|
115
|
-
|
116
|
-
|
125
|
+
|
126
|
+
|
117
127
|
private
|
118
|
-
|
128
|
+
|
119
129
|
def extract_limit(sql_type)
|
120
130
|
case sql_type
|
121
131
|
when /^smallint/i
|
@@ -130,7 +140,7 @@ module ActiveRecord
|
|
130
140
|
super
|
131
141
|
end
|
132
142
|
end
|
133
|
-
|
143
|
+
|
134
144
|
def simplified_type(field_type)
|
135
145
|
case field_type
|
136
146
|
when /real/i then :float
|
@@ -144,7 +154,7 @@ module ActiveRecord
|
|
144
154
|
else super
|
145
155
|
end
|
146
156
|
end
|
147
|
-
|
157
|
+
|
148
158
|
def simplified_datetime
|
149
159
|
if database_year >= 2008
|
150
160
|
:datetime
|
@@ -156,47 +166,50 @@ module ActiveRecord
|
|
156
166
|
:datetime
|
157
167
|
end
|
158
168
|
end
|
159
|
-
|
169
|
+
|
160
170
|
end #class SQLServerColumn
|
161
|
-
|
171
|
+
|
162
172
|
class SQLServerAdapter < AbstractAdapter
|
163
|
-
|
173
|
+
|
164
174
|
include Sqlserver::Quoting
|
165
175
|
include Sqlserver::DatabaseStatements
|
176
|
+
include Sqlserver::Showplan
|
166
177
|
include Sqlserver::SchemaStatements
|
167
178
|
include Sqlserver::DatabaseLimits
|
168
179
|
include Sqlserver::Errors
|
169
|
-
|
170
|
-
|
180
|
+
|
181
|
+
VERSION = File.read(File.expand_path("../../../../VERSION",__FILE__)).strip
|
171
182
|
ADAPTER_NAME = 'SQLServer'.freeze
|
172
183
|
DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+"?(\d{4}|\w+)"?/
|
173
|
-
SUPPORTED_VERSIONS = [2005,2008,2010,2011]
|
174
|
-
|
175
|
-
attr_reader :database_version, :database_year
|
176
|
-
|
184
|
+
SUPPORTED_VERSIONS = [2005,2008,2010,2011,2012,2014,2016,2017]
|
185
|
+
|
186
|
+
attr_reader :database_version, :database_year, :spid, :product_level, :product_version, :edition
|
187
|
+
|
177
188
|
cattr_accessor :native_text_database_type, :native_binary_database_type, :native_string_database_type,
|
178
|
-
:
|
179
|
-
:cs_equality_operator, :lowercase_schema_reflection, :auto_connect_duration
|
180
|
-
|
189
|
+
:enable_default_unicode_types, :auto_connect, :retry_deadlock_victim,
|
190
|
+
:cs_equality_operator, :lowercase_schema_reflection, :auto_connect_duration,
|
191
|
+
:showplan_option
|
192
|
+
|
181
193
|
self.enable_default_unicode_types = true
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
def initialize(logger,config)
|
194
|
+
|
195
|
+
|
196
|
+
def initialize(connection, logger, pool, config)
|
197
|
+
super(connection, logger, pool)
|
198
|
+
# AbstractAdapter Responsibility
|
199
|
+
@schema_cache = Sqlserver::SchemaCache.new self
|
200
|
+
@visitor = Arel::Visitors::SQLServer.new self
|
201
|
+
# Our Responsibility
|
202
|
+
@config = config
|
192
203
|
@connection_options = config
|
193
204
|
connect
|
194
|
-
|
195
|
-
@database_version = info_schema_query { select_value('SELECT @@version') }
|
205
|
+
@database_version = select_value 'SELECT @@version', 'SCHEMA'
|
196
206
|
@database_year = begin
|
197
|
-
if @database_version =~ /
|
207
|
+
if @database_version =~ /Azure/i
|
198
208
|
@sqlserver_azure = true
|
199
|
-
@database_version.match(/\s(
|
209
|
+
@database_version.match(/\s-\s([0-9.]+)/)[1]
|
210
|
+
year = 2016
|
211
|
+
elsif @database_version =~ /vNext/i
|
212
|
+
year = 2016
|
200
213
|
else
|
201
214
|
year = DATABASE_VERSION_REGEXP.match(@database_version)[1]
|
202
215
|
year == "Denali" ? 2011 : year.to_i
|
@@ -204,49 +217,63 @@ module ActiveRecord
|
|
204
217
|
rescue
|
205
218
|
0
|
206
219
|
end
|
220
|
+
@product_level = select_value "SELECT CAST(SERVERPROPERTY('productlevel') AS VARCHAR(128))", 'SCHEMA'
|
221
|
+
@product_version = select_value "SELECT CAST(SERVERPROPERTY('productversion') AS VARCHAR(128))", 'SCHEMA'
|
222
|
+
@edition = select_value "SELECT CAST(SERVERPROPERTY('edition') AS VARCHAR(128))", 'SCHEMA'
|
207
223
|
initialize_dateformatter
|
208
|
-
initialize_sqlserver_caches
|
209
224
|
use_database
|
210
|
-
unless SUPPORTED_VERSIONS.include?(@database_year)
|
225
|
+
unless (@sqlserver_azure == true || SUPPORTED_VERSIONS.include?(@database_year))
|
211
226
|
raise NotImplementedError, "Currently, only #{SUPPORTED_VERSIONS.to_sentence} are supported. We got back #{@database_version}."
|
212
227
|
end
|
213
228
|
end
|
214
|
-
|
229
|
+
|
215
230
|
# === Abstract Adapter ========================================== #
|
216
|
-
|
231
|
+
|
217
232
|
def adapter_name
|
218
233
|
ADAPTER_NAME
|
219
234
|
end
|
220
|
-
|
235
|
+
|
221
236
|
def supports_migrations?
|
222
237
|
true
|
223
238
|
end
|
224
|
-
|
239
|
+
|
225
240
|
def supports_primary_key?
|
226
241
|
true
|
227
242
|
end
|
228
|
-
|
243
|
+
|
229
244
|
def supports_count_distinct?
|
230
245
|
true
|
231
246
|
end
|
232
|
-
|
247
|
+
|
233
248
|
def supports_ddl_transactions?
|
234
249
|
true
|
235
250
|
end
|
236
|
-
|
251
|
+
|
252
|
+
def supports_bulk_alter?
|
253
|
+
false
|
254
|
+
end
|
255
|
+
|
237
256
|
def supports_savepoints?
|
238
257
|
true
|
239
258
|
end
|
240
|
-
|
259
|
+
|
260
|
+
def supports_index_sort_order?
|
261
|
+
true
|
262
|
+
end
|
263
|
+
|
264
|
+
def supports_explain?
|
265
|
+
true
|
266
|
+
end
|
267
|
+
|
241
268
|
def disable_referential_integrity
|
242
269
|
do_execute "EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'"
|
243
270
|
yield
|
244
271
|
ensure
|
245
272
|
do_execute "EXEC sp_MSforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL'"
|
246
273
|
end
|
247
|
-
|
274
|
+
|
248
275
|
# === Abstract Adapter (Connection Management) ================== #
|
249
|
-
|
276
|
+
|
250
277
|
def active?
|
251
278
|
case @connection_options[:mode]
|
252
279
|
when :dblib
|
@@ -265,6 +292,7 @@ module ActiveRecord
|
|
265
292
|
end
|
266
293
|
|
267
294
|
def disconnect!
|
295
|
+
@spid = nil
|
268
296
|
case @connection_options[:mode]
|
269
297
|
when :dblib
|
270
298
|
@connection.close rescue nil
|
@@ -272,123 +300,130 @@ module ActiveRecord
|
|
272
300
|
@connection.disconnect rescue nil
|
273
301
|
end
|
274
302
|
end
|
275
|
-
|
303
|
+
|
276
304
|
def reset!
|
277
305
|
remove_database_connections_and_rollback { }
|
278
306
|
end
|
279
|
-
|
280
|
-
def clear_cache!
|
281
|
-
initialize_sqlserver_caches
|
282
|
-
end
|
283
|
-
|
307
|
+
|
284
308
|
# === Abstract Adapter (Misc Support) =========================== #
|
285
|
-
|
309
|
+
|
286
310
|
def pk_and_sequence_for(table_name)
|
287
311
|
idcol = identity_column(table_name)
|
288
312
|
idcol ? [idcol.name,nil] : nil
|
289
313
|
end
|
290
314
|
|
291
315
|
def primary_key(table_name)
|
292
|
-
identity_column(table_name).try(:name)
|
316
|
+
identity_column(table_name).try(:name) || schema_cache.columns[table_name].detect(&:is_primary?).try(:name)
|
293
317
|
end
|
294
|
-
|
318
|
+
|
295
319
|
# === SQLServer Specific (DB Reflection) ======================== #
|
296
|
-
|
320
|
+
|
297
321
|
def sqlserver?
|
298
322
|
true
|
299
323
|
end
|
300
|
-
|
324
|
+
|
301
325
|
def sqlserver_2005?
|
302
326
|
@database_year == 2005
|
303
327
|
end
|
304
|
-
|
328
|
+
|
305
329
|
def sqlserver_2008?
|
306
330
|
@database_year == 2008
|
307
331
|
end
|
308
|
-
|
332
|
+
|
309
333
|
def sqlserver_2011?
|
310
334
|
@database_year == 2011
|
311
335
|
end
|
312
|
-
|
336
|
+
|
337
|
+
def sqlserver_2012?
|
338
|
+
@database_year == 2012
|
339
|
+
end
|
340
|
+
|
313
341
|
def sqlserver_azure?
|
314
342
|
@sqlserver_azure
|
315
343
|
end
|
316
|
-
|
344
|
+
|
317
345
|
def version
|
318
346
|
self.class::VERSION
|
319
347
|
end
|
320
|
-
|
348
|
+
|
321
349
|
def inspect
|
322
|
-
"#<#{self.class} version: #{version}, year: #{@database_year}, connection_options: #{@connection_options.inspect}>"
|
350
|
+
"#<#{self.class} version: #{version}, year: #{@database_year}, product_level: #{@product_level.inspect}, product_version: #{@product_version.inspect}, edition: #{@edition.inspect}, connection_options: #{@connection_options.inspect}>"
|
323
351
|
end
|
324
|
-
|
352
|
+
|
325
353
|
def auto_connect
|
326
354
|
@@auto_connect.is_a?(FalseClass) ? false : true
|
327
355
|
end
|
328
|
-
|
356
|
+
|
329
357
|
def auto_connect_duration
|
330
358
|
@@auto_connect_duration ||= 10
|
331
359
|
end
|
332
|
-
|
360
|
+
|
361
|
+
def retry_deadlock_victim
|
362
|
+
@@retry_deadlock_victim.is_a?(FalseClass) ? false : true
|
363
|
+
end
|
364
|
+
alias :retry_deadlock_victim? :retry_deadlock_victim
|
365
|
+
|
333
366
|
def native_string_database_type
|
334
|
-
@@native_string_database_type || (enable_default_unicode_types ? 'nvarchar' : 'varchar')
|
367
|
+
@@native_string_database_type || (enable_default_unicode_types ? 'nvarchar' : 'varchar')
|
335
368
|
end
|
336
|
-
|
369
|
+
|
337
370
|
def native_text_database_type
|
338
371
|
@@native_text_database_type || enable_default_unicode_types ? 'nvarchar(max)' : 'varchar(max)'
|
339
372
|
end
|
340
|
-
|
373
|
+
|
341
374
|
def native_time_database_type
|
342
375
|
sqlserver_2005? ? 'datetime' : 'time'
|
343
376
|
end
|
344
|
-
|
377
|
+
|
345
378
|
def native_date_database_type
|
346
379
|
sqlserver_2005? ? 'datetime' : 'date'
|
347
380
|
end
|
348
|
-
|
381
|
+
|
349
382
|
def native_binary_database_type
|
350
383
|
@@native_binary_database_type || 'varbinary(max)'
|
351
384
|
end
|
352
|
-
|
385
|
+
|
353
386
|
def cs_equality_operator
|
354
387
|
@@cs_equality_operator || 'COLLATE Latin1_General_CS_AS_WS'
|
355
388
|
end
|
356
|
-
|
357
|
-
|
389
|
+
|
358
390
|
protected
|
359
|
-
|
391
|
+
|
360
392
|
# === Abstract Adapter (Misc Support) =========================== #
|
361
|
-
|
393
|
+
|
362
394
|
def translate_exception(e, message)
|
363
395
|
case message
|
364
|
-
when /cannot insert duplicate key .* with unique index/i
|
396
|
+
when /(cannot insert duplicate key .* with unique index) | (violation of unique key constraint)/i
|
365
397
|
RecordNotUnique.new(message,e)
|
366
398
|
when /conflicted with the foreign key constraint/i
|
367
399
|
InvalidForeignKey.new(message,e)
|
400
|
+
when /has been chosen as the deadlock victim/i
|
401
|
+
DeadlockVictim.new(message,e)
|
368
402
|
when *lost_connection_messages
|
369
403
|
LostConnection.new(message,e)
|
370
404
|
else
|
371
405
|
super
|
372
406
|
end
|
373
407
|
end
|
374
|
-
|
408
|
+
|
375
409
|
# === SQLServer Specific (Connection Management) ================ #
|
376
|
-
|
410
|
+
|
377
411
|
def connect
|
378
412
|
config = @connection_options
|
379
|
-
@connection = case
|
413
|
+
@connection = case config[:mode]
|
380
414
|
when :dblib
|
381
|
-
appname = config[:appname] || Rails.application.class.name.split('::').first rescue nil
|
415
|
+
appname = config[:appname] || configure_application_name || Rails.application.class.name.split('::').first rescue nil
|
382
416
|
login_timeout = config[:login_timeout].present? ? config[:login_timeout].to_i : nil
|
383
417
|
timeout = config[:timeout].present? ? config[:timeout].to_i/1000 : nil
|
384
418
|
encoding = config[:encoding].present? ? config[:encoding] : nil
|
385
|
-
TinyTds::Client.new({
|
419
|
+
TinyTds::Client.new({
|
386
420
|
:dataserver => config[:dataserver],
|
387
421
|
:host => config[:host],
|
388
422
|
:port => config[:port],
|
389
423
|
:username => config[:username],
|
390
424
|
:password => config[:password],
|
391
425
|
:database => config[:database],
|
426
|
+
:tds_version => config[:tds_version],
|
392
427
|
:appname => appname,
|
393
428
|
:login_timeout => login_timeout,
|
394
429
|
:timeout => timeout,
|
@@ -408,6 +443,8 @@ module ActiveRecord
|
|
408
443
|
client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
|
409
444
|
client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
|
410
445
|
end
|
446
|
+
client.execute("SET TEXTSIZE 2147483647").do
|
447
|
+
client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
|
411
448
|
end
|
412
449
|
when :odbc
|
413
450
|
if config[:dsn].include?(';')
|
@@ -418,7 +455,7 @@ module ActiveRecord
|
|
418
455
|
ODBC::Database.new.drvconnect(driver)
|
419
456
|
else
|
420
457
|
ODBC.connect config[:dsn], config[:username], config[:password]
|
421
|
-
end.tap do |c|
|
458
|
+
end.tap do |c|
|
422
459
|
begin
|
423
460
|
c.use_time = true
|
424
461
|
c.use_utc = ActiveRecord::Base.default_timezone == :utc
|
@@ -427,19 +464,34 @@ module ActiveRecord
|
|
427
464
|
end
|
428
465
|
end
|
429
466
|
end
|
467
|
+
@spid = _raw_select("SELECT @@SPID", :fetch => :rows).first.first
|
468
|
+
configure_connection
|
430
469
|
rescue
|
431
470
|
raise unless @auto_connecting
|
432
471
|
end
|
433
|
-
|
472
|
+
|
473
|
+
# Override this method so every connection can be configured to your needs.
|
474
|
+
# For example:
|
475
|
+
# raw_connection_do "SET TEXTSIZE #{64.megabytes}"
|
476
|
+
# raw_connection_do "SET CONCAT_NULL_YIELDS_NULL ON"
|
477
|
+
def configure_connection
|
478
|
+
end
|
479
|
+
|
480
|
+
# Override this method so every connection can have a unique name. Max 30 characters. Used by TinyTDS only.
|
481
|
+
# For example:
|
482
|
+
# "myapp_#{$$}_#{Thread.current.object_id}".to(29)
|
483
|
+
def configure_application_name
|
484
|
+
end
|
485
|
+
|
434
486
|
def initialize_dateformatter
|
435
|
-
@database_dateformat =
|
487
|
+
@database_dateformat = user_options_dateformat
|
436
488
|
a, b, c = @database_dateformat.each_char.to_a
|
437
489
|
[a,b,c].each { |f| f.upcase! if f == 'y' }
|
438
490
|
dateformat = "%#{a}-%#{b}-%#{c}"
|
439
491
|
::Date::DATE_FORMATS[:_sqlserver_dateformat] = dateformat
|
440
492
|
::Time::DATE_FORMATS[:_sqlserver_dateformat] = dateformat
|
441
493
|
end
|
442
|
-
|
494
|
+
|
443
495
|
def remove_database_connections_and_rollback(database=nil)
|
444
496
|
database ||= current_database
|
445
497
|
do_execute "ALTER DATABASE #{quote_table_name(database)} SET SINGLE_USER WITH ROLLBACK IMMEDIATE"
|
@@ -449,24 +501,35 @@ module ActiveRecord
|
|
449
501
|
do_execute "ALTER DATABASE #{quote_table_name(database)} SET MULTI_USER"
|
450
502
|
end if block_given?
|
451
503
|
end
|
452
|
-
|
453
|
-
def
|
504
|
+
|
505
|
+
def with_sqlserver_error_handling
|
454
506
|
begin
|
455
507
|
yield
|
456
508
|
rescue Exception => e
|
457
|
-
|
509
|
+
case translate_exception(e,e.message)
|
510
|
+
when LostConnection; retry if auto_reconnected?
|
511
|
+
when DeadlockVictim; retry if retry_deadlock_victim? && open_transactions == 0
|
512
|
+
end
|
458
513
|
raise
|
459
514
|
end
|
460
515
|
end
|
461
|
-
|
516
|
+
|
517
|
+
def disable_auto_reconnect
|
518
|
+
old_auto_connect, self.class.auto_connect = self.class.auto_connect, false
|
519
|
+
yield
|
520
|
+
ensure
|
521
|
+
self.class.auto_connect = old_auto_connect
|
522
|
+
end
|
523
|
+
|
462
524
|
def auto_reconnected?
|
463
525
|
return false unless auto_connect
|
464
526
|
@auto_connecting = true
|
465
527
|
count = 0
|
466
528
|
while count <= (auto_connect_duration / 2)
|
467
|
-
|
529
|
+
result = reconnect!
|
468
530
|
ActiveRecord::Base.did_retry_sqlserver_connection(self,count)
|
469
|
-
return true if
|
531
|
+
return true if result
|
532
|
+
sleep 2** count
|
470
533
|
count += 1
|
471
534
|
end
|
472
535
|
ActiveRecord::Base.did_lose_sqlserver_connection(self)
|
@@ -474,10 +537,10 @@ module ActiveRecord
|
|
474
537
|
ensure
|
475
538
|
@auto_connecting = false
|
476
539
|
end
|
477
|
-
|
540
|
+
|
478
541
|
end #class SQLServerAdapter < AbstractAdapter
|
479
|
-
|
542
|
+
|
480
543
|
end #module ConnectionAdapters
|
481
|
-
|
544
|
+
|
482
545
|
end #module ActiveRecord
|
483
546
|
|