activerecord-sqlserver-adapter 2.3.20 → 2.3.21

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,9 @@
1
1
 
2
+ * 2.3.21*
3
+
4
+ * Add support/test around handling of float/real column types [Lucas Maxwell]
5
+
6
+
2
7
  * 2.3.20 *
3
8
 
4
9
  * Fixes quote column names and passes tests for ActiveRecord 2.3.14.
@@ -147,7 +147,7 @@ module ActiveRecord
147
147
  class SQLServerAdapter < AbstractAdapter
148
148
 
149
149
  ADAPTER_NAME = 'SQLServer'.freeze
150
- VERSION = '2.3.20'.freeze
150
+ VERSION = '2.3.21'.freeze
151
151
  DATABASE_VERSION_REGEXP = /Microsoft SQL Server\s+(\d{4})/
152
152
  SUPPORTED_VERSIONS = [2000,2005,2008].freeze
153
153
  LIMITABLE_TYPES = ['string','integer','float','char','nchar','varchar','nvarchar'].to_set.freeze
@@ -1332,6 +1332,8 @@ module ActiveRecord
1332
1332
  ci[:type]
1333
1333
  when /^numeric|decimal$/i
1334
1334
  "#{ci[:type]}(#{ci[:numeric_precision]},#{ci[:numeric_scale]})"
1335
+ when /^float|real$/i
1336
+ "#{ci[:type]}(#{ci[:numeric_precision]})"
1335
1337
  when /^char|nchar|varchar|nvarchar|varbinary|bigint|int|smallint$/
1336
1338
  ci[:length].to_i == -1 ? "#{ci[:type]}(max)" : "#{ci[:type]}(#{ci[:length]})"
1337
1339
  else
@@ -520,6 +520,14 @@ class AdapterTestSqlserver < ActiveRecord::TestCase
520
520
  assert_equal 'bigint', @connection.type_to_sql(:integer, 7)
521
521
  assert_equal 'bigint', @connection.type_to_sql(:integer, 8)
522
522
  end
523
+
524
+ should 'create floats when no limit supplied' do
525
+ assert_equal 'float(8)', @connection.type_to_sql(:float)
526
+ end
527
+
528
+ should 'create floats when limit is supplied' do
529
+ assert_equal 'float(27)', @connection.type_to_sql(:float, 27)
530
+ end
523
531
 
524
532
  end
525
533
 
@@ -4,23 +4,23 @@ require 'models/binary'
4
4
  class SqlServerEdgeSchema < ActiveRecord::Base; end;
5
5
 
6
6
  class ColumnTestSqlserver < ActiveRecord::TestCase
7
-
7
+
8
8
  def setup
9
9
  @connection = ActiveRecord::Base.connection
10
10
  @column_klass = ActiveRecord::ConnectionAdapters::SQLServerColumn
11
11
  end
12
-
12
+
13
13
  should 'return real_number as float' do
14
14
  assert_equal :float, TableWithRealColumn.columns_hash["real_number"].type
15
15
  end
16
-
16
+
17
17
  should 'know its #table_name and #table_klass' do
18
18
  Topic.columns.each do |column|
19
19
  assert_equal 'topics', column.table_name, "This column #{column.inspect} did not know it's #table_name"
20
20
  assert_equal Topic, column.table_klass, "This column #{column.inspect} did not know it's #table_klass"
21
21
  end
22
22
  end
23
-
23
+
24
24
  should 'return correct null, limit, and default for Topic' do
25
25
  tch = Topic.columns_hash
26
26
  assert_equal false, tch['id'].null
@@ -29,33 +29,33 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
29
29
  assert_equal true, tch['approved'].default
30
30
  assert_equal 0, tch['replies_count'].default
31
31
  end
32
-
32
+
33
33
  context 'For binary columns' do
34
34
 
35
35
  setup do
36
36
  @binary_string = "GIF89a\001\000\001\000\200\000\000\377\377\377\000\000\000!\371\004\000\000\000\000\000,\000\000\000\000\001\000\001\000\000\002\002D\001\000;"
37
37
  @saved_bdata = Binary.create!(:data => @binary_string)
38
38
  end
39
-
39
+
40
40
  should 'read and write binary data equally' do
41
41
  assert_equal @binary_string, Binary.find(@saved_bdata).data
42
42
  end
43
-
43
+
44
44
  should 'have correct attributes' do
45
45
  column = Binary.columns_hash['data']
46
46
  assert_equal :binary, column.type
47
47
  assert_equal @connection.native_binary_database_type, column.sql_type
48
48
  assert_equal nil, column.limit
49
49
  end
50
-
50
+
51
51
  should 'quote data for sqlserver with literal 0x prefix' do
52
52
  # See the output of the stored procedure: 'exec sp_datatype_info'
53
53
  sqlserver_encoded_bdata = "0x47494638396101000100800000ffffff00000021f90400000000002c00000000010001000002024401003b"
54
- assert_equal sqlserver_encoded_bdata, @column_klass.string_to_binary(@binary_string)
54
+ assert_equal sqlserver_encoded_bdata, @column_klass.string_to_binary(@binary_string)
55
55
  end
56
56
 
57
57
  end
58
-
58
+
59
59
  context 'For string columns' do
60
60
 
61
61
  setup do
@@ -73,7 +73,7 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
73
73
  assert_equal :text, @varcharmax10.type, @varcharmax10.inspect
74
74
  end
75
75
  end
76
-
76
+
77
77
  should 'have correct #sql_type per schema definition' do
78
78
  assert_equal 'char(1)', @char.sql_type, 'Specifing a char type with no limit is 1 by SQL Server standards.'
79
79
  assert_equal 'char(10)', @char10.sql_type, @char10.inspect
@@ -82,7 +82,7 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
82
82
  assert_equal 'varchar(max)', @varcharmax10.sql_type, 'A -1 limit should be converted to max (max) type.'
83
83
  end
84
84
  end
85
-
85
+
86
86
  should 'have correct #limit per schema definition' do
87
87
  assert_equal 1, @char.limit
88
88
  assert_equal 10, @char10.limit
@@ -93,10 +93,10 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
93
93
  end
94
94
 
95
95
  end
96
-
97
-
96
+
97
+
98
98
  context 'For all national/unicode columns' do
99
-
99
+
100
100
  setup do
101
101
  @nchar = SqlServerUnicode.columns_hash['nchar']
102
102
  @nvarchar = SqlServerUnicode.columns_hash['nvarchar']
@@ -107,13 +107,13 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
107
107
  @nvarcharmax = SqlServerUnicode.columns_hash['nvarchar_max']
108
108
  @nvarcharmax10 = SqlServerUnicode.columns_hash['nvarchar_max_10']
109
109
  end
110
-
110
+
111
111
  should 'all respond true to #is_utf8?' do
112
112
  SqlServerUnicode.columns_hash.except('id').values.each do |column|
113
113
  assert column.is_utf8?, "This column #{column.inspect} should have been a unicode column."
114
114
  end
115
115
  end
116
-
116
+
117
117
  should 'have correct simplified types' do
118
118
  assert_equal :string, @nchar.type
119
119
  assert_equal :string, @nvarchar.type
@@ -126,7 +126,7 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
126
126
  assert_equal :text, @nvarcharmax10.type, @nvarcharmax10.inspect
127
127
  end
128
128
  end
129
-
129
+
130
130
  should 'have correct #sql_type per schema definition' do
131
131
  assert_equal 'nchar(1)', @nchar.sql_type, 'Specifing a nchar type with no limit is 1 by SQL Server standards.'
132
132
  assert_equal 'nvarchar(255)', @nvarchar.sql_type, 'Default nvarchar limit is 255.'
@@ -139,7 +139,7 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
139
139
  assert_equal 'nvarchar(max)', @nvarcharmax10.sql_type, 'A -1 limit should be converted to max (max) type.'
140
140
  end
141
141
  end
142
-
142
+
143
143
  should 'have correct #limit per schema definition' do
144
144
  assert_equal 1, @nchar.limit
145
145
  assert_equal 255, @nvarchar.limit
@@ -151,9 +151,9 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
151
151
  assert_equal nil, @nvarcharmax10.limit, 'Limits on max types are moot and we should let rails know that.'
152
152
  end
153
153
  end
154
-
154
+
155
155
  end
156
-
156
+
157
157
  context 'For datetime columns' do
158
158
 
159
159
  setup do
@@ -168,7 +168,7 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
168
168
  should 'have correct simplified type for uncast datetime' do
169
169
  assert_equal :datetime, @datetime.type
170
170
  end
171
-
171
+
172
172
  should 'use correct #sql_type for different sql server versions' do
173
173
  assert_equal 'datetime', @datetime.sql_type
174
174
  if sqlserver_2000? || sqlserver_2005?
@@ -179,116 +179,163 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
179
179
  assert_equal 'time', @time.sql_type
180
180
  end
181
181
  end
182
-
182
+
183
183
  should 'all be have nil #limit' do
184
184
  assert_equal nil, @date.limit
185
185
  assert_equal nil, @time.limit
186
186
  assert_equal nil, @datetime.limit
187
187
  end
188
-
188
+
189
189
  context 'with timestamps' do
190
190
 
191
191
  should 'use datetime sql type when using :timestamp in schema statements' do
192
192
  assert_equal :datetime, @timestamp.type
193
193
  assert_equal 'datetime', @timestamp.sql_type
194
194
  end
195
-
195
+
196
196
  should 'be able to use real sql server timestamp if you really want to' do
197
197
  assert_equal :binary, @ss_timestamp.type
198
198
  assert_equal 'timestamp', @ss_timestamp.sql_type
199
199
  end
200
-
200
+
201
201
  should 'return :timestamp as a binaryish string' do
202
202
  chronic = SqlServerChronic.create!.reload
203
203
  assert_match %r|\000|, chronic.ss_timestamp
204
204
  end
205
205
 
206
206
  end
207
-
207
+
208
208
  context 'For smalldatetime types' do
209
-
209
+
210
210
  should 'have created that type using rails migrations' do
211
211
  assert_equal 'smalldatetime', @smalldatetime.sql_type
212
212
  end
213
-
213
+
214
214
  should 'be able to insert column without truncation warnings or the like' do
215
215
  SqlServerChronic.create! :smalldatetime => Time.now
216
216
  end
217
-
217
+
218
218
  should 'be able to update column without truncation warnings or the like' do
219
219
  ssc = SqlServerChronic.create! :smalldatetime => 2.days.ago
220
220
  ssc.update_attributes! :smalldatetime => Time.now
221
221
  end
222
222
 
223
223
  end
224
-
224
+
225
225
  context 'which have coerced types' do
226
-
226
+
227
227
  setup do
228
228
  christmas_08 = "2008-12-25".to_time
229
229
  christmas_08_afternoon = "2008-12-25 12:00".to_time
230
230
  @chronic_date = SqlServerChronic.create!(:date => christmas_08).reload
231
231
  @chronic_time = SqlServerChronic.create!(:time => christmas_08_afternoon).reload
232
232
  end
233
-
233
+
234
234
  should 'have an inheritable attribute ' do
235
235
  assert SqlServerChronic.coerced_sqlserver_date_columns.include?('date') unless sqlserver_2008?
236
236
  end
237
-
237
+
238
238
  should 'have column and objects cast to date' do
239
239
  assert_equal :date, @date.type, "This column: \n#{@date.inspect}"
240
240
  klass = sqlserver_2008? ? Date : (connection_mode_dblib? ? Time : Date)
241
241
  assert_instance_of klass, @chronic_date.date
242
242
  end
243
-
243
+
244
244
  should 'have column objects cast to time' do
245
245
  assert_equal :time, @time.type, "This column: \n#{@time.inspect}"
246
246
  assert_instance_of Time, @chronic_time.time
247
247
  end
248
-
248
+
249
249
  end
250
250
 
251
251
  end
252
-
252
+
253
253
  context 'For decimal and numeric columns' do
254
-
254
+
255
255
  setup do
256
256
  @bank_balance = NumericData.columns_hash['bank_balance']
257
257
  @big_bank_balance = NumericData.columns_hash['big_bank_balance']
258
258
  @world_population = NumericData.columns_hash['world_population']
259
259
  @my_house_population = NumericData.columns_hash['my_house_population']
260
260
  end
261
-
261
+
262
262
  should 'have correct simplified types' do
263
263
  assert_equal :decimal, @bank_balance.type
264
264
  assert_equal :decimal, @big_bank_balance.type
265
265
  assert_equal :integer, @world_population.type, 'Since #extract_scale == 0'
266
266
  assert_equal :integer, @my_house_population.type, 'Since #extract_scale == 0'
267
267
  end
268
-
268
+
269
269
  should 'have correct #sql_type' do
270
270
  assert_equal 'decimal(10,2)', @bank_balance.sql_type
271
271
  assert_equal 'decimal(15,2)', @big_bank_balance.sql_type
272
272
  assert_equal 'decimal(10,0)', @world_population.sql_type
273
273
  assert_equal 'decimal(2,0)', @my_house_population.sql_type
274
274
  end
275
-
275
+
276
276
  should 'have correct #limit' do
277
277
  assert_equal nil, @bank_balance.limit
278
278
  assert_equal nil, @big_bank_balance.limit
279
279
  assert_equal nil, @world_population.limit
280
280
  assert_equal nil, @my_house_population.limit
281
281
  end
282
-
282
+
283
283
  should 'return correct precisions and scales' do
284
284
  assert_equal [10,2], [@bank_balance.precision, @bank_balance.scale]
285
285
  assert_equal [15,2], [@big_bank_balance.precision, @big_bank_balance.scale]
286
286
  assert_equal [10,0], [@world_population.precision, @world_population.scale]
287
287
  assert_equal [2,0], [@my_house_population.precision, @my_house_population.scale]
288
288
  end
289
-
289
+
290
290
  end
291
-
291
+
292
+ context 'For float columns' do
293
+ # NOTE: float limits are adjusted to 24 or 53 by the database as per
294
+ # http://msdn.microsoft.com/en-us/library/ms173773.aspx
295
+ # NOTE: floats with a limit of <= 24 are reduced to reals by sqlserver on creation
296
+
297
+ setup do
298
+ @temperature = FloatData.columns_hash['temperature']
299
+ @freezing = FloatData.columns_hash['temperature_8']
300
+ @mild = FloatData.columns_hash['temperature_24']
301
+ @beach = FloatData.columns_hash['temperature_32']
302
+ @desert = FloatData.columns_hash['temperature_53']
303
+ end
304
+
305
+ should 'have correct simplified types' do
306
+ assert_equal :float, @temperature.type
307
+ assert_equal :float, @freezing.type
308
+ assert_equal :float, @mild.type
309
+ assert_equal :float, @beach.type
310
+ assert_equal :float, @desert.type
311
+ end
312
+
313
+ should 'have correct #sql_type' do
314
+ assert_equal 'real(24)', @temperature.sql_type
315
+ assert_equal 'real(24)', @freezing.sql_type
316
+ assert_equal 'real(24)', @mild.sql_type
317
+ assert_equal 'float(53)', @beach.sql_type
318
+ assert_equal 'float(53)', @desert.sql_type
319
+ end
320
+
321
+ should 'have correct #limit' do
322
+ assert_equal 24, @temperature.limit
323
+ assert_equal 24, @freezing.limit
324
+ assert_equal 24, @mild.limit
325
+ assert_equal 53, @beach.limit
326
+ assert_equal 53, @desert.limit
327
+ end
328
+
329
+ should 'return nil precisions and scales' do
330
+ assert_equal [nil,nil], [@temperature.precision, @temperature.scale]
331
+ assert_equal [nil,nil], [@freezing.precision, @freezing.scale]
332
+ assert_equal [nil,nil], [@mild.precision, @mild.scale]
333
+ assert_equal [nil,nil], [@beach.precision, @beach.scale]
334
+ assert_equal [nil,nil], [@desert.precision, @desert.scale]
335
+ end
336
+
337
+ end
338
+
292
339
  context 'For tinyint columns' do
293
340
 
294
341
  setup do
@@ -302,6 +349,6 @@ class ColumnTestSqlserver < ActiveRecord::TestCase
302
349
  end
303
350
 
304
351
  end
305
-
306
-
352
+
353
+
307
354
  end
@@ -30,6 +30,7 @@ class TableWithRealColumn < ActiveRecord::Base; end
30
30
  class FkTestHasFk < ActiveRecord::Base ; end
31
31
  class FkTestHasPk < ActiveRecord::Base ; end
32
32
  class NumericData < ActiveRecord::Base ; self.table_name = 'numeric_data' ; end
33
+ class FloatData < ActiveRecord::Base ; self.table_name = 'float_data' ; end
33
34
  class CustomersView < ActiveRecord::Base ; self.table_name = 'customers_view' ; end
34
35
  class StringDefaultsView < ActiveRecord::Base ; self.table_name = 'string_defaults_view' ; end
35
36
  class StringDefaultsBigView < ActiveRecord::Base ; self.table_name = 'string_defaults_big_view' ; end
@@ -1,15 +1,23 @@
1
1
  ActiveRecord::Schema.define do
2
-
2
+
3
+ create_table :float_data, :force => true do |t|
4
+ t.float :temperature
5
+ t.float :temperature_8, :limit => 8
6
+ t.float :temperature_24, :limit => 24
7
+ t.float :temperature_32, :limit => 32
8
+ t.float :temperature_53, :limit => 53
9
+ end
10
+
3
11
  create_table :table_with_real_columns, :force => true do |t|
4
12
  t.column :real_number, :real
5
13
  end
6
-
14
+
7
15
  create_table :defaults, :force => true do |t|
8
16
  t.column :positive_integer, :integer, :default => 1
9
17
  t.column :negative_integer, :integer, :default => -1
10
18
  t.column :decimal_number, :decimal, :precision => 3, :scale => 2, :default => 2.78
11
19
  end
12
-
20
+
13
21
  create_table :string_defaults, :force => true do |t|
14
22
  t.column :string_with_null_default, :string, :default => nil
15
23
  t.column :string_with_pretend_null_one, :string, :default => 'null'
@@ -19,7 +27,7 @@ ActiveRecord::Schema.define do
19
27
  t.column :string_with_pretend_paren_three, :string, :default => '(3)'
20
28
  t.column :string_with_multiline_default, :string, :default => "Some long default with a\nnew line."
21
29
  end
22
-
30
+
23
31
  create_table :sql_server_chronics, :force => true do |t|
24
32
  t.column :date, :date
25
33
  t.column :time, :time
@@ -28,7 +36,7 @@ ActiveRecord::Schema.define do
28
36
  t.column :ss_timestamp, :ss_timestamp
29
37
  t.column :smalldatetime, :smalldatetime
30
38
  end
31
-
39
+
32
40
  create_table(:fk_test_has_fks, :force => true) { |t| t.column(:fk_id, :integer, :null => false) }
33
41
  create_table(:fk_test_has_pks, :force => true) { }
34
42
  execute <<-ADDFKSQL
@@ -37,7 +45,7 @@ ActiveRecord::Schema.define do
37
45
  FOREIGN KEY (#{quote_column_name('fk_id')})
38
46
  REFERENCES #{quote_table_name('fk_test_has_pks')} (#{quote_column_name('id')})
39
47
  ADDFKSQL
40
-
48
+
41
49
  create_table :sql_server_unicodes, :force => true do |t|
42
50
  t.column :nchar, :nchar
43
51
  t.column :nvarchar, :nvarchar
@@ -46,24 +54,24 @@ ActiveRecord::Schema.define do
46
54
  t.column :nchar_10, :nchar, :limit => 10
47
55
  t.column :nvarchar_100, :nvarchar, :limit => 100
48
56
  if ActiveRecord::Base.connection.sqlserver_2005? || ActiveRecord::Base.connection.sqlserver_2008?
49
- t.column :nvarchar_max, :nvarchar_max
57
+ t.column :nvarchar_max, :nvarchar_max
50
58
  t.column :nvarchar_max_10, :nvarchar_max, :limit => 10
51
59
  end
52
60
  end
53
-
61
+
54
62
  create_table :sql_server_strings, :force => true do |t|
55
63
  t.column :char, :char
56
64
  t.column :char_10, :char, :limit => 10
57
65
  if ActiveRecord::Base.connection.sqlserver_2005? || ActiveRecord::Base.connection.sqlserver_2008?
58
- t.column :varchar_max, :varchar_max
66
+ t.column :varchar_max, :varchar_max
59
67
  t.column :varchar_max_10, :varchar_max, :limit => 10
60
68
  end
61
69
  end
62
-
70
+
63
71
  create_table :sql_server_binary_types, :force => true do |t|
64
72
  # TODO: Add some different native binary types and test.
65
73
  end
66
-
74
+
67
75
  create_table :sql_server_edge_schemas, :force => true do |t|
68
76
  t.string :description
69
77
  t.column :bigint, :bigint
@@ -72,14 +80,14 @@ ActiveRecord::Schema.define do
72
80
  end
73
81
  execute %|ALTER TABLE [sql_server_edge_schemas] ADD [guid_newid] uniqueidentifier DEFAULT NEWID();|
74
82
  execute %|ALTER TABLE [sql_server_edge_schemas] ADD [guid_newseqid] uniqueidentifier DEFAULT NEWSEQUENTIALID();| unless ActiveRecord::Base.connection.sqlserver_2000?
75
-
83
+
76
84
  create_table 'quoted-table', :force => true do |t|
77
85
  end
78
86
  execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'quoted-view1') DROP VIEW [quoted-view1]"
79
87
  execute "CREATE VIEW [quoted-view1] AS SELECT * FROM [quoted-table]"
80
88
  execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'quoted-view2') DROP VIEW [quoted-view2]"
81
89
  execute "CREATE VIEW [quoted-view2] AS \n /*#{'x'*4000}}*/ \n SELECT * FROM [quoted-table]"
82
-
90
+
83
91
  execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'customers_view') DROP VIEW customers_view"
84
92
  execute <<-CUSTOMERSVIEW
85
93
  CREATE VIEW customers_view AS
@@ -93,7 +101,7 @@ ActiveRecord::Schema.define do
93
101
  SELECT id, string_with_pretend_null_one as pretend_null
94
102
  FROM string_defaults
95
103
  STRINGDEFAULTSVIEW
96
-
104
+
97
105
  execute "IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'string_defaults_big_view') DROP VIEW string_defaults_big_view"
98
106
  execute <<-STRINGDEFAULTSBIGVIEW
99
107
  CREATE VIEW string_defaults_big_view AS
@@ -101,5 +109,5 @@ ActiveRecord::Schema.define do
101
109
  /*#{'x'*4000}}*/
102
110
  FROM string_defaults
103
111
  STRINGDEFAULTSBIGVIEW
104
-
112
+
105
113
  end
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: 43
4
+ hash: 41
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
8
  - 3
9
- - 20
10
- version: 2.3.20
9
+ - 21
10
+ version: 2.3.21
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: 2011-08-17 00:00:00 -04:00
22
+ date: 2011-08-25 00:00:00 -04:00
23
23
  default_executable:
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency