activerecord-sqlserver-adapter 2.3.11 → 2.3.12

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 CHANGED
@@ -1,4 +1,15 @@
1
1
 
2
+ * 2.3.12 *
3
+
4
+ * Add multiple results set support with #execute_procedure for :dblib mode. [Ken Collins]
5
+
6
+ * Allow unicode conditions strings to be quoted correctly. Like 3.0 branch. [Ken Collins]
7
+
8
+ * Simplify encoding support. [Ken Collins]
9
+
10
+ * Add binary timestamp datatype handling. [Erik Bryn]
11
+
12
+
2
13
  * 2.3.11
3
14
 
4
15
  * Add TinyTds/dblib connection mode. [Ken Collins]
data/README.rdoc CHANGED
@@ -6,6 +6,7 @@ The SQL Server adapter for rails is back for ActiveRecord 2.2 and up! We are cur
6
6
 
7
7
  == What's New
8
8
 
9
+ * New dblib connection mode using TinyTds!
9
10
  * Integration with rails :db namespaced rake tasks.
10
11
  * IronRuby support using ADONET connection mode.
11
12
  * Direct ODBC mode. No DBI anymore, means around 20% faster!
@@ -54,38 +54,16 @@ module ActiveRecord
54
54
 
55
55
  class << self
56
56
 
57
- def string_to_utf8_encoding(value)
58
- value.force_encoding('UTF-8') rescue value
59
- end
60
-
61
57
  def string_to_binary(value)
62
- value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
63
58
  "0x#{value.unpack("H*")[0]}"
64
59
  end
65
60
 
66
61
  def binary_to_string(value)
67
- value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
68
62
  value =~ /[^[:xdigit:]]/ ? value : [value].pack('H*')
69
63
  end
70
64
 
71
65
  end
72
66
 
73
- def type_cast(value)
74
- if value && type == :string && is_utf8?
75
- self.class.string_to_utf8_encoding(value)
76
- else
77
- super
78
- end
79
- end
80
-
81
- def type_cast_code(var_name)
82
- if type == :string && is_utf8?
83
- "#{self.class.name}.string_to_utf8_encoding(#{var_name})"
84
- else
85
- super
86
- end
87
- end
88
-
89
67
  def is_identity?
90
68
  @sqlserver_options[:is_identity]
91
69
  end
@@ -146,6 +124,7 @@ module ActiveRecord
146
124
  when /uniqueidentifier/i then :string
147
125
  when /datetime/i then simplified_datetime
148
126
  when /varchar\(max\)/ then :text
127
+ when /timestamp/ then :binary
149
128
  else super
150
129
  end
151
130
  end
@@ -164,19 +143,11 @@ module ActiveRecord
164
143
 
165
144
  end #SQLServerColumn
166
145
 
167
- # In ODBC mode, the adapter requires Ruby ODBC and requires that you specify
168
- # a :dsn option. Ruby ODBC is available at http://www.ch-werner.de/rubyodbc/
169
- #
170
- # Options:
171
- #
172
- # * <tt>:username</tt> -- Defaults to sa.
173
- # * <tt>:password</tt> -- Defaults to blank string.
174
- # * <tt>:dsn</tt> -- An ODBC DSN. (required)
175
- #
146
+
176
147
  class SQLServerAdapter < AbstractAdapter
177
148
 
178
149
  ADAPTER_NAME = 'SQLServer'.freeze
179
- VERSION = '2.3.11'.freeze
150
+ VERSION = '2.3.12'.freeze
180
151
  DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
181
152
  SUPPORTED_VERSIONS = [2000,2005,2008].freeze
182
153
  LIMITABLE_TYPES = ['string','integer','float','char','nchar','varchar','nvarchar'].to_set.freeze
@@ -298,8 +269,9 @@ module ActiveRecord
298
269
  when String, ActiveSupport::Multibyte::Chars
299
270
  if column && column.type == :binary
300
271
  column.class.string_to_binary(value)
301
- elsif column && column.respond_to?(:is_utf8?) && column.is_utf8?
302
- quoted_utf8_value(value)
272
+ # elsif column && column.type == :string
273
+ elsif value.is_utf8? || (column && column.type == :string)
274
+ "N'#{quote_string(value)}'"
303
275
  else
304
276
  super
305
277
  end
@@ -337,10 +309,6 @@ module ActiveRecord
337
309
  end
338
310
  end
339
311
 
340
- def quoted_utf8_value(value)
341
- "N'#{quote_string(value)}'"
342
- end
343
-
344
312
  # REFERENTIAL INTEGRITY ====================================#
345
313
 
346
314
  def disable_referential_integrity
@@ -441,12 +409,17 @@ module ActiveRecord
441
409
  vars = variables.map{ |v| quote(v) }.join(', ')
442
410
  sql = "EXEC #{proc_name} #{vars}".strip
443
411
  name = 'Execute Procedure'
444
- results = []
445
- case @connection_options[:mode]
446
- when :dblib
447
- results << select(sql, name).map { |r| r.with_indifferent_access }
448
- when :odbc
449
- log(sql, name) do
412
+ log(sql, name) do
413
+ case @connection_options[:mode]
414
+ when :dblib
415
+ result = @connection.execute(sql)
416
+ result.each(:as => :hash, :cache_rows => true) do |row|
417
+ r = row.with_indifferent_access
418
+ yield(r) if block_given?
419
+ end
420
+ result.each
421
+ when :odbc
422
+ results = []
450
423
  raw_connection_run(sql) do |handle|
451
424
  get_rows = lambda {
452
425
  rows = handle_to_names_and_values handle, :fetch => :all
@@ -458,11 +431,13 @@ module ActiveRecord
458
431
  get_rows.call
459
432
  end
460
433
  end
434
+ results.many? ? results : results.first
435
+ when :adonet
436
+ results = []
437
+ results << select(sql, name).map { |r| r.with_indifferent_access }
438
+ results.many? ? results : results.first
461
439
  end
462
- when :adonet
463
- results << select(sql, name).map { |r| r.with_indifferent_access }
464
440
  end
465
- results.many? ? results : results.first
466
441
  end
467
442
 
468
443
  def use_database(database=nil)
@@ -1311,7 +1286,8 @@ module ActiveRecord
1311
1286
  :nchar => { :name => "nchar" },
1312
1287
  :nvarchar => { :name => "nvarchar", :limit => 255 },
1313
1288
  :nvarchar_max => { :name => "nvarchar(max)" },
1314
- :ntext => { :name => "ntext" }
1289
+ :ntext => { :name => "ntext" },
1290
+ :ss_timestamp => { :name => 'timestamp'}
1315
1291
  })
1316
1292
  end
1317
1293
 
@@ -161,6 +161,8 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
161
161
  @time = SqlServerChronic.columns_hash['time']
162
162
  @datetime = SqlServerChronic.columns_hash['datetime']
163
163
  @smalldatetime = SqlServerChronic.columns_hash['smalldatetime']
164
+ @timestamp = SqlServerChronic.columns_hash['timestamp']
165
+ @ss_timestamp = SqlServerChronic.columns_hash['ss_timestamp']
164
166
  end
165
167
 
166
168
  should 'have correct simplified type for uncast datetime' do
@@ -184,6 +186,25 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
184
186
  assert_equal nil, @datetime.limit
185
187
  end
186
188
 
189
+ context 'with timestamps' do
190
+
191
+ should 'use datetime sql type when using :timestamp in schema statements' do
192
+ assert_equal :datetime, @timestamp.type
193
+ assert_equal 'datetime', @timestamp.sql_type
194
+ end
195
+
196
+ should 'be able to use real sql server timestamp if you really want to' do
197
+ assert_equal :binary, @ss_timestamp.type
198
+ assert_equal 'timestamp', @ss_timestamp.sql_type
199
+ end
200
+
201
+ should 'return :timestamp as a binaryish string' do
202
+ chronic = SqlServerChronic.create!.reload
203
+ assert_match %r|\000|, chronic.ss_timestamp
204
+ end
205
+
206
+ end
207
+
187
208
  context 'For smalldatetime types' do
188
209
 
189
210
  should 'have created that type using rails migrations' do
@@ -9,34 +9,26 @@ class ExecuteProcedureTestSqlserver < ActiveRecord::TestCase
9
9
  should 'execute a simple procedure' do
10
10
  tables = @klass.execute_procedure :sp_tables
11
11
  assert_instance_of Array, tables
12
- assert_instance_of HashWithIndifferentAccess, tables.first
12
+ assert tables.first.respond_to?(:keys)
13
13
  end
14
14
 
15
15
  should 'take parameter arguments' do
16
16
  tables = @klass.execute_procedure :sp_tables, 'sql_server_chronics'
17
17
  table_info = tables.first
18
18
  assert_equal 1, tables.size
19
- assert_equal (ENV['ARUNIT_DB_NAME'] || 'activerecord_unittest'), table_info[:TABLE_QUALIFIER], "Table Info: #{table_info.inspect}"
20
- assert_equal 'TABLE', table_info[:TABLE_TYPE], "Table Info: #{table_info.inspect}"
19
+ assert_equal (ENV['ARUNIT_DB_NAME'] || 'activerecord_unittest'), table_info['TABLE_QUALIFIER'], "Table Info: #{table_info.inspect}"
20
+ assert_equal 'TABLE', table_info['TABLE_TYPE'], "Table Info: #{table_info.inspect}"
21
21
  end
22
22
 
23
- if connection_mode_odbc?
24
-
25
- should 'allow multiple result sets to be returned' do
26
- results1, results2 = @klass.execute_procedure('sp_helpconstraint','accounts')
27
- assert_instance_of Array, results1
28
- assert_instance_of HashWithIndifferentAccess, results1.first
29
- assert results1.first['Object Name']
30
- assert_instance_of Array, results2
31
- assert_instance_of HashWithIndifferentAccess, results2.first
32
- assert results2.first['constraint_name']
33
- assert results2.first['constraint_type']
34
- end
35
-
36
- else
37
-
38
- should 'allow multiple result sets to be returned'
39
-
23
+ should 'allow multiple result sets to be returned' do
24
+ results1, results2 = @klass.execute_procedure('sp_helpconstraint','accounts')
25
+ assert_instance_of Array, results1
26
+ assert results1.first.respond_to?(:keys)
27
+ assert results1.first['Object Name']
28
+ assert_instance_of Array, results2
29
+ assert results2.first.respond_to?(:keys)
30
+ assert results2.first['constraint_name']
31
+ assert results2.first['constraint_type']
40
32
  end
41
33
 
42
34
 
@@ -106,6 +106,7 @@ module ActiveRecord
106
106
  class << self
107
107
  def connection_mode_dblib? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :dblib ; end
108
108
  def connection_mode_odbc? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :odbc ; end
109
+ def connection_mode_adonet? ; ActiveRecord::Base.connection.instance_variable_get(:@connection_options)[:mode] == :adonet ; end
109
110
  def sqlserver_2000? ; ActiveRecord::Base.connection.sqlserver_2000? ; end
110
111
  def sqlserver_2005? ; ActiveRecord::Base.connection.sqlserver_2005? ; end
111
112
  def sqlserver_2008? ; ActiveRecord::Base.connection.sqlserver_2008? ; end
@@ -125,6 +126,7 @@ module ActiveRecord
125
126
  end
126
127
  def connection_mode_dblib? ; self.class.connection_mode_dblib? ; end
127
128
  def connection_mode_odbc? ; self.class.connection_mode_odbc? ; end
129
+ def connection_mode_adonet? ; self.class.connection_mode_adonet? ; end
128
130
  def sqlserver_2000? ; self.class.sqlserver_2000? ; end
129
131
  def sqlserver_2005? ; self.class.sqlserver_2005? ; end
130
132
  def sqlserver_2008? ; self.class.sqlserver_2008? ; end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  require 'cases/sqlserver_helper'
2
3
 
3
4
  class UnicodeTestSqlserver < ActiveRecord::TestCase
@@ -29,19 +30,22 @@ class UnicodeTestSqlserver < ActiveRecord::TestCase
29
30
  context 'Testing unicode data' do
30
31
 
31
32
  setup do
32
- @unicode_data = "\344\270\200\344\272\21434\344\272\224\345\205\255"
33
- @encoded_unicode_data = "\344\270\200\344\272\21434\344\272\224\345\205\255".force_encoding('UTF-8') if ruby_19?
33
+ @unicode_data = "\344\270\200\344\272\21434\344\272\224\345\205\255" # "一二34五六"
34
34
  end
35
35
 
36
- should 'insert into nvarchar field' do
36
+ should 'insert and retrieve unicode data' do
37
37
  assert data = SqlServerUnicode.create!(:nvarchar => @unicode_data)
38
- assert_equal @unicode_data, data.reload.nvarchar
38
+ if connection_mode_dblib?
39
+ assert_equal "一二34五六", data.reload.nvarchar
40
+ elsif connection_mode_odbc?
41
+ assert_equal "一二34五六", data.reload.nvarchar, 'perhaps you are not using the utf8 odbc that does this legwork'
42
+ elsif connection_mode_adonet?
43
+ assert_equal "一二34五六", data.reload.nvarchar
44
+ else
45
+ raise 'need to add a case for this'
46
+ end
47
+ assert_equal Encoding.find('UTF-8'), data.nvarchar.encoding if ruby_19?
39
48
  end
40
-
41
- should 're-encode data on DB reads' do
42
- assert data = SqlServerUnicode.create!(:nvarchar => @unicode_data)
43
- assert_equal @encoded_unicode_data, data.reload.nvarchar
44
- end if ruby_19?
45
49
 
46
50
  end
47
51
 
@@ -9,27 +9,10 @@ class ValidationsTest < ActiveRecord::TestCase
9
9
 
10
10
  include SqlserverCoercedTest
11
11
 
12
- # This test is tricky to pass. The validation SQL would generate something like this:
13
- #
14
- # SELECT TOP 1 [events].id FROM [events] WHERE ([events].[title] COLLATE Latin1_General_CS_AS = '一二三四五')
15
- #
16
- # The problem is that we can not change the adapters quote method from this:
17
- #
18
- # elsif column && column.respond_to?(:is_utf8?) && column.is_utf8?
19
- # quoted_utf8_value(value)
20
- #
21
- # To something like this for all quoting like blind bind vars:
22
- #
23
- # elsif value.is_utf8?
24
- # quoted_utf8_value(value)
25
- #
26
- # As it would cause way more errors, sure this piggybacks on ActiveSupport's 1.8/1.9 abstract
27
- # code to infer if the passed in string is indeed a national/unicde type. Perhaps in rails 3
28
- # and using AREL this might get better, but I do not see a solution right now.
29
- #
30
12
  def test_coerced_test_validate_uniqueness_with_limit_and_utf8
31
- assert true
13
+ true
32
14
  end
33
15
 
16
+
34
17
  end
35
18
 
@@ -25,6 +25,7 @@ ActiveRecord::Schema.define do
25
25
  t.column :time, :time
26
26
  t.column :datetime, :datetime
27
27
  t.column :timestamp, :timestamp
28
+ t.column :ss_timestamp, :ss_timestamp
28
29
  t.column :smalldatetime, :smalldatetime
29
30
  end
30
31
 
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: 21
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 2
8
8
  - 3
9
- - 11
10
- version: 2.3.11
9
+ - 12
10
+ version: 2.3.12
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-10-17 00:00:00 -04:00
22
+ date: 2010-10-26 00:00:00 -04:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
@@ -30,11 +30,11 @@ dependencies:
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- hash: 5
33
+ hash: 7
34
34
  segments:
35
35
  - 2
36
- - 3
37
- version: "2.3"
36
+ - 2
37
+ version: "2.2"
38
38
  type: :runtime
39
39
  version_requirements: *id001
40
40
  description: SQL Server 2000, 2005 and 2008 Adapter For Rails.