activerecord-sqlserver-adapter 3.0.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|