activerecord-sqlserver-adapter 3.0.0 → 3.0.1
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.
- data/CHANGELOG +6 -1
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +65 -35
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +9 -7
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +27 -21
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +32 -24
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -203,11 +203,11 @@ module ActiveRecord
|
|
203
203
|
end
|
204
204
|
|
205
205
|
def raw_connection_do(sql)
|
206
|
-
case
|
206
|
+
case @connection_options[:mode]
|
207
207
|
when :odbc
|
208
|
-
|
208
|
+
@connection.do(sql)
|
209
209
|
else :adonet
|
210
|
-
|
210
|
+
@connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_non_query
|
211
211
|
end
|
212
212
|
end
|
213
213
|
|
@@ -226,17 +226,17 @@ module ActiveRecord
|
|
226
226
|
|
227
227
|
def raw_connection_run(sql)
|
228
228
|
with_auto_reconnect do
|
229
|
-
case
|
229
|
+
case @connection_options[:mode]
|
230
230
|
when :odbc
|
231
|
-
block_given? ?
|
231
|
+
block_given? ? @connection.run_block(sql) { |handle| yield(handle) } : @connection.run(sql)
|
232
232
|
else :adonet
|
233
|
-
|
233
|
+
@connection.create_command.tap{ |cmd| cmd.command_text = sql }.execute_reader
|
234
234
|
end
|
235
235
|
end
|
236
236
|
end
|
237
237
|
|
238
238
|
def handle_more_results?(handle)
|
239
|
-
case
|
239
|
+
case @connection_options[:mode]
|
240
240
|
when :odbc
|
241
241
|
handle.more_results
|
242
242
|
when :adonet
|
@@ -245,7 +245,7 @@ module ActiveRecord
|
|
245
245
|
end
|
246
246
|
|
247
247
|
def handle_to_names_and_values(handle, options={})
|
248
|
-
case
|
248
|
+
case @connection_options[:mode]
|
249
249
|
when :odbc
|
250
250
|
handle_to_names_and_values_odbc(handle, options)
|
251
251
|
when :adonet
|
@@ -254,29 +254,40 @@ module ActiveRecord
|
|
254
254
|
end
|
255
255
|
|
256
256
|
def handle_to_names_and_values_odbc(handle, options={})
|
257
|
+
@connection.use_utc = ActiveRecord::Base.default_timezone == :utc if @connection_supports_native_types
|
257
258
|
case options[:fetch]
|
258
259
|
when :all, :one
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
names = handle.columns(true).map{ |c| c.name }
|
266
|
-
names_and_values = []
|
267
|
-
rows.each do |row|
|
268
|
-
h = {}
|
269
|
-
i = 0
|
270
|
-
while i < row.size
|
271
|
-
v = row[i]
|
272
|
-
h[names[i]] = v.respond_to?(:to_sqlserver_string) ? v.to_sqlserver_string : v
|
273
|
-
i += 1
|
260
|
+
if @connection_supports_native_types
|
261
|
+
if options[:fetch] == :all
|
262
|
+
handle.each_hash || []
|
263
|
+
else
|
264
|
+
row = handle.fetch_hash
|
265
|
+
rows = row ? [row] : [[]]
|
274
266
|
end
|
275
|
-
|
267
|
+
else
|
268
|
+
rows = if options[:fetch] == :all
|
269
|
+
handle.fetch_all || []
|
270
|
+
else
|
271
|
+
row = handle.fetch
|
272
|
+
row ? [row] : [[]]
|
273
|
+
end
|
274
|
+
names = handle.columns(true).map{ |c| c.name }
|
275
|
+
names_and_values = []
|
276
|
+
rows.each do |row|
|
277
|
+
h = {}
|
278
|
+
i = 0
|
279
|
+
while i < row.size
|
280
|
+
v = row[i]
|
281
|
+
h[names[i]] = v.respond_to?(:to_sqlserver_string) ? v.to_sqlserver_string : v
|
282
|
+
i += 1
|
283
|
+
end
|
284
|
+
names_and_values << h
|
285
|
+
end
|
286
|
+
names_and_values
|
276
287
|
end
|
277
|
-
names_and_values
|
278
288
|
when :rows
|
279
289
|
rows = handle.fetch_all || []
|
290
|
+
return rows if @connection_supports_native_types
|
280
291
|
rows.each do |row|
|
281
292
|
i = 0
|
282
293
|
while i < row.size
|
@@ -291,36 +302,55 @@ module ActiveRecord
|
|
291
302
|
|
292
303
|
def handle_to_names_and_values_adonet(handle, options={})
|
293
304
|
if handle.has_rows
|
294
|
-
|
305
|
+
names = []
|
295
306
|
rows = []
|
296
|
-
fields_named =
|
307
|
+
fields_named = options[:fetch] == :rows
|
308
|
+
one_row_only = options[:fetch] == :one
|
297
309
|
while handle.read
|
298
310
|
row = []
|
299
311
|
handle.visible_field_count.times do |row_index|
|
300
312
|
value = handle.get_value(row_index)
|
301
|
-
value =
|
313
|
+
value = case value
|
314
|
+
when System::String
|
302
315
|
value.to_s
|
303
|
-
|
316
|
+
when System::DBNull
|
304
317
|
nil
|
305
|
-
|
306
|
-
value.to_string("yyyy-MM-dd HH:
|
318
|
+
when System::DateTime
|
319
|
+
value.to_string("yyyy-MM-dd HH:mm:ss.fff").to_s
|
320
|
+
when @@array_of_bytes ||= System::Array[System::Byte]
|
321
|
+
String.new(value)
|
307
322
|
else
|
308
323
|
value
|
309
324
|
end
|
310
325
|
row << value
|
311
|
-
|
326
|
+
names << handle.get_name(row_index).to_s unless fields_named
|
327
|
+
break if one_row_only
|
312
328
|
end
|
313
329
|
rows << row
|
314
330
|
fields_named = true
|
315
331
|
end
|
316
332
|
else
|
317
|
-
|
333
|
+
rows = []
|
334
|
+
end
|
335
|
+
if options[:fetch] != :rows
|
336
|
+
names_and_values = []
|
337
|
+
rows.each do |row|
|
338
|
+
h = {}
|
339
|
+
i = 0
|
340
|
+
while i < row.size
|
341
|
+
h[names[i]] = row[i]
|
342
|
+
i += 1
|
343
|
+
end
|
344
|
+
names_and_values << h
|
345
|
+
end
|
346
|
+
names_and_values
|
347
|
+
else
|
348
|
+
rows
|
318
349
|
end
|
319
|
-
[fields,rows]
|
320
350
|
end
|
321
351
|
|
322
352
|
def finish_statement_handle(handle)
|
323
|
-
case
|
353
|
+
case @connection_options[:mode]
|
324
354
|
when :odbc
|
325
355
|
handle.drop if handle && handle.respond_to?(:drop) && !handle.finished?
|
326
356
|
when :adonet
|
@@ -19,12 +19,12 @@ module ActiveRecord
|
|
19
19
|
|
20
20
|
|
21
21
|
def lost_connection_exceptions
|
22
|
-
exceptions = LOST_CONNECTION_EXCEPTIONS[
|
22
|
+
exceptions = LOST_CONNECTION_EXCEPTIONS[@connection_options[:mode]]
|
23
23
|
@lost_connection_exceptions ||= exceptions ? exceptions.map{ |e| e.constantize rescue nil }.compact : []
|
24
24
|
end
|
25
25
|
|
26
26
|
def lost_connection_messages
|
27
|
-
LOST_CONNECTION_MESSAGES[
|
27
|
+
LOST_CONNECTION_MESSAGES[@connection_options[:mode]]
|
28
28
|
end
|
29
29
|
|
30
30
|
end
|
@@ -3,6 +3,8 @@ module ActiveRecord
|
|
3
3
|
module Sqlserver
|
4
4
|
module Quoting
|
5
5
|
|
6
|
+
QUOTED_TRUE, QUOTED_FALSE = '1', '0'
|
7
|
+
|
6
8
|
def quote(value, column = nil)
|
7
9
|
case value
|
8
10
|
when String, ActiveSupport::Multibyte::Chars
|
@@ -22,21 +24,21 @@ module ActiveRecord
|
|
22
24
|
string.to_s.gsub(/\'/, "''")
|
23
25
|
end
|
24
26
|
|
25
|
-
def quote_column_name(
|
26
|
-
|
27
|
+
def quote_column_name(name)
|
28
|
+
@sqlserver_quoted_column_and_table_names[name] ||=
|
29
|
+
name.to_s.split('.').map{ |n| n =~ /^\[.*\]$/ ? n : "[#{n}]" }.join('.')
|
27
30
|
end
|
28
31
|
|
29
|
-
def quote_table_name(
|
30
|
-
|
31
|
-
quote_column_name(table_name)
|
32
|
+
def quote_table_name(name)
|
33
|
+
quote_column_name(name)
|
32
34
|
end
|
33
35
|
|
34
36
|
def quoted_true
|
35
|
-
|
37
|
+
QUOTED_TRUE
|
36
38
|
end
|
37
39
|
|
38
40
|
def quoted_false
|
39
|
-
|
41
|
+
QUOTED_FALSE
|
40
42
|
end
|
41
43
|
|
42
44
|
def quoted_date(value)
|
@@ -4,27 +4,7 @@ module ActiveRecord
|
|
4
4
|
module SchemaStatements
|
5
5
|
|
6
6
|
def native_database_types
|
7
|
-
|
8
|
-
:primary_key => "int NOT NULL IDENTITY(1,1) PRIMARY KEY",
|
9
|
-
:string => { :name => native_string_database_type, :limit => 255 },
|
10
|
-
:text => { :name => native_text_database_type },
|
11
|
-
:integer => { :name => "int", :limit => 4 },
|
12
|
-
:float => { :name => "float", :limit => 8 },
|
13
|
-
:decimal => { :name => "decimal" },
|
14
|
-
:datetime => { :name => "datetime" },
|
15
|
-
:timestamp => { :name => "datetime" },
|
16
|
-
:time => { :name => native_time_database_type },
|
17
|
-
:date => { :name => native_date_database_type },
|
18
|
-
:binary => { :name => native_binary_database_type },
|
19
|
-
:boolean => { :name => "bit"},
|
20
|
-
# These are custom types that may move somewhere else for good schema_dumper.rb hacking to output them.
|
21
|
-
:char => { :name => 'char' },
|
22
|
-
:varchar_max => { :name => 'varchar(max)' },
|
23
|
-
:nchar => { :name => "nchar" },
|
24
|
-
:nvarchar => { :name => "nvarchar", :limit => 255 },
|
25
|
-
:nvarchar_max => { :name => "nvarchar(max)" },
|
26
|
-
:ntext => { :name => "ntext" }
|
27
|
-
}
|
7
|
+
ActiveRecord::ConnectionAdapters::SQLServerAdapter::NATIVE_DATABASE_TYPES
|
28
8
|
end
|
29
9
|
|
30
10
|
def tables(name = nil)
|
@@ -167,6 +147,31 @@ module ActiveRecord
|
|
167
147
|
|
168
148
|
# === SQLServer Specific ======================================== #
|
169
149
|
|
150
|
+
def initialize_native_database_types
|
151
|
+
return if defined?(ActiveRecord::ConnectionAdapters::SQLServerAdapter::NATIVE_DATABASE_TYPES)
|
152
|
+
ActiveRecord::ConnectionAdapters::SQLServerAdapter.const_set(:NATIVE_DATABASE_TYPES,{
|
153
|
+
:primary_key => "int NOT NULL IDENTITY(1,1) PRIMARY KEY",
|
154
|
+
:string => { :name => native_string_database_type, :limit => 255 },
|
155
|
+
:text => { :name => native_text_database_type },
|
156
|
+
:integer => { :name => "int", :limit => 4 },
|
157
|
+
:float => { :name => "float", :limit => 8 },
|
158
|
+
:decimal => { :name => "decimal" },
|
159
|
+
:datetime => { :name => "datetime" },
|
160
|
+
:timestamp => { :name => "datetime" },
|
161
|
+
:time => { :name => native_time_database_type },
|
162
|
+
:date => { :name => native_date_database_type },
|
163
|
+
:binary => { :name => native_binary_database_type },
|
164
|
+
:boolean => { :name => "bit"},
|
165
|
+
# These are custom types that may move somewhere else for good schema_dumper.rb hacking to output them.
|
166
|
+
:char => { :name => 'char' },
|
167
|
+
:varchar_max => { :name => 'varchar(max)' },
|
168
|
+
:nchar => { :name => "nchar" },
|
169
|
+
:nvarchar => { :name => "nvarchar", :limit => 255 },
|
170
|
+
:nvarchar_max => { :name => "nvarchar(max)" },
|
171
|
+
:ntext => { :name => "ntext" }
|
172
|
+
})
|
173
|
+
end
|
174
|
+
|
170
175
|
def column_definitions(table_name)
|
171
176
|
db_name = unqualify_db_name(table_name)
|
172
177
|
db_name_with_period = "#{db_name}." if db_name
|
@@ -330,6 +335,7 @@ module ActiveRecord
|
|
330
335
|
@sqlserver_columns_cache = {} if reset_columns
|
331
336
|
@sqlserver_views_cache = nil
|
332
337
|
@sqlserver_view_information_cache = {}
|
338
|
+
@sqlserver_quoted_column_and_table_names = {}
|
333
339
|
end
|
334
340
|
|
335
341
|
# === SQLServer Specific (Identity Inserts) ===================== #
|
@@ -102,7 +102,7 @@ module ActiveRecord
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def is_utf8?
|
105
|
-
sql_type =~ /nvarchar|ntext|nchar/i
|
105
|
+
@sql_type =~ /nvarchar|ntext|nchar/i
|
106
106
|
end
|
107
107
|
|
108
108
|
def default_function
|
@@ -181,10 +181,13 @@ module ActiveRecord
|
|
181
181
|
include Sqlserver::Errors
|
182
182
|
|
183
183
|
ADAPTER_NAME = 'SQLServer'.freeze
|
184
|
-
VERSION = '3.0.
|
184
|
+
VERSION = '3.0.1'.freeze
|
185
185
|
DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
|
186
186
|
SUPPORTED_VERSIONS = [2005,2008].freeze
|
187
187
|
|
188
|
+
attr_reader :database_version, :database_year,
|
189
|
+
:connection_supports_native_types
|
190
|
+
|
188
191
|
cattr_accessor :native_text_database_type, :native_binary_database_type, :native_string_database_type,
|
189
192
|
:log_info_schema_queries, :enable_default_unicode_types, :auto_connect,
|
190
193
|
:cs_equality_operator
|
@@ -192,10 +195,13 @@ module ActiveRecord
|
|
192
195
|
def initialize(logger,config)
|
193
196
|
@connection_options = config
|
194
197
|
connect
|
195
|
-
super(
|
198
|
+
super(@connection, logger)
|
199
|
+
@database_version = info_schema_query { select_value('SELECT @@version') }
|
200
|
+
@database_year = DATABASE_VERSION_REGEXP.match(@database_version)[1].to_i rescue 0
|
201
|
+
initialize_native_database_types
|
196
202
|
initialize_sqlserver_caches
|
197
203
|
use_database
|
198
|
-
unless SUPPORTED_VERSIONS.include?(database_year)
|
204
|
+
unless SUPPORTED_VERSIONS.include?(@database_year)
|
199
205
|
raise NotImplementedError, "Currently, only #{SUPPORTED_VERSIONS.to_sentence} are supported."
|
200
206
|
end
|
201
207
|
end
|
@@ -249,11 +255,11 @@ module ActiveRecord
|
|
249
255
|
end
|
250
256
|
|
251
257
|
def disconnect!
|
252
|
-
case
|
258
|
+
case @connection_options[:mode]
|
253
259
|
when :odbc
|
254
|
-
|
260
|
+
@connection.disconnect rescue nil
|
255
261
|
else :adonet
|
256
|
-
|
262
|
+
@connection.close rescue nil
|
257
263
|
end
|
258
264
|
end
|
259
265
|
|
@@ -274,24 +280,16 @@ module ActiveRecord
|
|
274
280
|
|
275
281
|
# === SQLServer Specific (DB Reflection) ======================== #
|
276
282
|
|
277
|
-
def database_version
|
278
|
-
@database_version ||= info_schema_query { select_value('SELECT @@version') }
|
279
|
-
end
|
280
|
-
|
281
|
-
def database_year
|
282
|
-
DATABASE_VERSION_REGEXP.match(database_version)[1].to_i
|
283
|
-
end
|
284
|
-
|
285
283
|
def sqlserver?
|
286
284
|
true
|
287
285
|
end
|
288
286
|
|
289
287
|
def sqlserver_2005?
|
290
|
-
database_year == 2005
|
288
|
+
@database_year == 2005
|
291
289
|
end
|
292
290
|
|
293
291
|
def sqlserver_2008?
|
294
|
-
database_year == 2008
|
292
|
+
@database_year == 2008
|
295
293
|
end
|
296
294
|
|
297
295
|
def version
|
@@ -299,7 +297,7 @@ module ActiveRecord
|
|
299
297
|
end
|
300
298
|
|
301
299
|
def inspect
|
302
|
-
"#<#{self.class} version: #{version}, year: #{database_year}, connection_options: #{@connection_options.inspect}>"
|
300
|
+
"#<#{self.class} version: #{version}, year: #{@database_year}, connection_options: #{@connection_options.inspect}>"
|
303
301
|
end
|
304
302
|
|
305
303
|
def auto_connect
|
@@ -352,10 +350,24 @@ module ActiveRecord
|
|
352
350
|
|
353
351
|
def connect
|
354
352
|
config = @connection_options
|
355
|
-
@connection = case
|
353
|
+
@connection = case @connection_options[:mode]
|
356
354
|
when :odbc
|
357
355
|
odbc = ['::ODBC','::ODBC_UTF8','::ODBC_NONE'].detect{ |odbc_ns| odbc_ns.constantize rescue nil }.constantize
|
358
|
-
|
356
|
+
if config[:dsn].include?(';')
|
357
|
+
driver = odbc::Driver.new.tap do |d|
|
358
|
+
d.name = config[:dsn_name] || 'Driver1'
|
359
|
+
driver.attrs = dsn.split(';').map{ |atr| atr.split('=') }.reject{ |kv| kv.size != 2 }.inject({}){ |h,kv| k,v = kv ; h[k] = v ; h }
|
360
|
+
end
|
361
|
+
odbc::Database.new.drvconnect(driver)
|
362
|
+
else
|
363
|
+
odbc.connect config[:dsn], config[:username], config[:password]
|
364
|
+
end.tap do |c|
|
365
|
+
if c.respond_to?(:use_time)
|
366
|
+
c.use_time = true
|
367
|
+
c.use_utc = ActiveRecord::Base.default_timezone == :utc
|
368
|
+
@connection_supports_native_types = true
|
369
|
+
end
|
370
|
+
end
|
359
371
|
when :adonet
|
360
372
|
System::Data::SqlClient::SqlConnection.new.tap do |connection|
|
361
373
|
connection.connection_string = System::Data::SqlClient::SqlConnectionStringBuilder.new.tap do |cs|
|
@@ -411,10 +423,6 @@ module ActiveRecord
|
|
411
423
|
ensure
|
412
424
|
@auto_connecting = false
|
413
425
|
end
|
414
|
-
|
415
|
-
def connection_mode
|
416
|
-
@connection_options[:mode]
|
417
|
-
end
|
418
426
|
|
419
427
|
end #class SQLServerAdapter < AbstractAdapter
|
420
428
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-sqlserver-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 3.0.
|
9
|
+
- 1
|
10
|
+
version: 3.0.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ken Collins
|
@@ -19,7 +19,7 @@ autorequire:
|
|
19
19
|
bindir: bin
|
20
20
|
cert_chain: []
|
21
21
|
|
22
|
-
date: 2010-
|
22
|
+
date: 2010-09-15 00:00:00 -04:00
|
23
23
|
default_executable:
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|