activerecord-sqlserver-adapter 2.3.24 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/CHANGELOG +5 -108
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +33 -61
  4. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +57 -0
  5. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +57 -0
  6. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
  7. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +336 -0
  8. data/lib/active_record/connection_adapters/sqlserver/errors.rb +33 -0
  9. data/lib/active_record/connection_adapters/sqlserver/query_cache.rb +17 -0
  10. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +61 -0
  11. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +373 -0
  12. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +131 -1121
  13. data/lib/arel/engines/sql/compilers/sqlserver_compiler.rb +267 -0
  14. metadata +26 -76
  15. data/RUNNING_UNIT_TESTS +0 -31
  16. data/Rakefile +0 -60
  17. data/lib/active_record/connection_adapters/sqlserver_adapter/core_ext/active_record.rb +0 -151
  18. data/lib/active_record/connection_adapters/sqlserver_adapter/core_ext/odbc.rb +0 -40
  19. data/test/cases/aaaa_create_tables_test_sqlserver.rb +0 -19
  20. data/test/cases/adapter_test_sqlserver.rb +0 -755
  21. data/test/cases/attribute_methods_test_sqlserver.rb +0 -33
  22. data/test/cases/basics_test_sqlserver.rb +0 -86
  23. data/test/cases/calculations_test_sqlserver.rb +0 -20
  24. data/test/cases/column_test_sqlserver.rb +0 -354
  25. data/test/cases/connection_test_sqlserver.rb +0 -148
  26. data/test/cases/eager_association_test_sqlserver.rb +0 -42
  27. data/test/cases/execute_procedure_test_sqlserver.rb +0 -35
  28. data/test/cases/inheritance_test_sqlserver.rb +0 -28
  29. data/test/cases/method_scoping_test_sqlserver.rb +0 -28
  30. data/test/cases/migration_test_sqlserver.rb +0 -108
  31. data/test/cases/named_scope_test_sqlserver.rb +0 -21
  32. data/test/cases/offset_and_limit_test_sqlserver.rb +0 -108
  33. data/test/cases/pessimistic_locking_test_sqlserver.rb +0 -125
  34. data/test/cases/query_cache_test_sqlserver.rb +0 -24
  35. data/test/cases/schema_dumper_test_sqlserver.rb +0 -72
  36. data/test/cases/specific_schema_test_sqlserver.rb +0 -154
  37. data/test/cases/sqlserver_helper.rb +0 -140
  38. data/test/cases/table_name_test_sqlserver.rb +0 -38
  39. data/test/cases/transaction_test_sqlserver.rb +0 -93
  40. data/test/cases/unicode_test_sqlserver.rb +0 -54
  41. data/test/cases/validations_test_sqlserver.rb +0 -18
  42. data/test/connections/native_sqlserver/connection.rb +0 -26
  43. data/test/connections/native_sqlserver_odbc/connection.rb +0 -28
  44. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +0 -11
  45. data/test/schema/sqlserver_specific_schema.rb +0 -113
@@ -1,33 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
- require 'models/topic'
3
-
4
- class AttributeMethodsTestSqlserver < ActiveRecord::TestCase
5
- end
6
-
7
- class AttributeMethodsTest < ActiveRecord::TestCase
8
-
9
- COERCED_TESTS = [
10
- :test_typecast_attribute_from_select_to_false,
11
- :test_typecast_attribute_from_select_to_true
12
- ]
13
-
14
- include SqlserverCoercedTest
15
-
16
- fixtures :topics
17
-
18
-
19
- def test_coerced_typecast_attribute_from_select_to_false
20
- topic = Topic.create(:title => 'Budget')
21
- topic = Topic.find(:first, :select => "topics.*, CASE WHEN 1=2 THEN 1 ELSE 0 END as is_test")
22
- assert !topic.is_test?
23
- end
24
-
25
- def test_coerced_typecast_attribute_from_select_to_true
26
- topic = Topic.create(:title => 'Budget')
27
- topic = Topic.find(:first, :select => "topics.*, CASE WHEN 2=2 THEN 1 ELSE 0 END as is_test")
28
- assert topic.is_test?
29
- end
30
-
31
-
32
- end
33
-
@@ -1,86 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
- require 'models/developer'
3
- require 'models/topic'
4
-
5
- class BasicsTestSqlserver < ActiveRecord::TestCase
6
- end
7
-
8
- class BasicsTest < ActiveRecord::TestCase
9
-
10
- COERCED_TESTS = [
11
- :test_column_names_are_escaped,
12
- :test_read_attributes_before_type_cast_on_datetime,
13
- :test_preserving_date_objects,
14
- :test_to_xml ]
15
-
16
- include SqlserverCoercedTest
17
-
18
- fixtures :developers
19
-
20
- def test_coerced_column_names_are_escaped
21
- assert_equal "[foo]]bar]", ActiveRecord::Base.connection.quote_column_name("foo]bar")
22
- end
23
-
24
- def test_coerced_test_read_attributes_before_type_cast_on_datetime
25
- developer = Developer.find(:first)
26
- if developer.created_at_before_type_cast.is_a?(String)
27
- assert_equal developer.created_at.to_s(:db)+'.000' , developer.attributes_before_type_cast["created_at"]
28
- end
29
- end
30
-
31
- def test_coerced_test_preserving_date_objects
32
- klass = sqlserver_2008? ? Date : (connection_mode_dblib? ? Time : Date)
33
- assert_kind_of klass, Topic.find(1).last_read, "The last_read attribute should be of the #{klass.name} class"
34
- end
35
-
36
- def test_coerced_test_to_xml
37
- xml = REXML::Document.new(topics(:first).to_xml(:indent => 0))
38
- bonus_time_in_current_timezone = topics(:first).bonus_time.xmlschema
39
- written_on_in_current_timezone = topics(:first).written_on.xmlschema
40
-
41
- assert_equal "topic", xml.root.name
42
- assert_equal "The First Topic" , xml.elements["//title"].text
43
- assert_equal "David" , xml.elements["//author-name"].text
44
-
45
- assert_equal "1", xml.elements["//id"].text
46
- assert_equal "integer" , xml.elements["//id"].attributes['type']
47
-
48
- assert_equal "1", xml.elements["//replies-count"].text
49
- assert_equal "integer" , xml.elements["//replies-count"].attributes['type']
50
-
51
- assert_equal written_on_in_current_timezone, xml.elements["//written-on"].text
52
- assert_equal "datetime" , xml.elements["//written-on"].attributes['type']
53
-
54
- assert_equal "--- Have a nice day\n" , xml.elements["//content"].text
55
- assert_equal "yaml" , xml.elements["//content"].attributes['type']
56
-
57
- assert_equal "david@loudthinking.com", xml.elements["//author-email-address"].text
58
-
59
- assert_equal nil, xml.elements["//parent-id"].text
60
- assert_equal "integer", xml.elements["//parent-id"].attributes['type']
61
- assert_equal "true", xml.elements["//parent-id"].attributes['nil']
62
-
63
- if sqlserver_2000? || sqlserver_2005?
64
- last_read_in_current_timezone, last_read_type = if connection_mode_odbc?
65
- ["2004-04-15", "date"]
66
- elsif connection_mode_dblib?
67
- ["2004-04-15 00:00:00", "date"]
68
- else
69
- [topics(:first).last_read.xmlschema, "datetime"]
70
- end
71
- assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
72
- assert_equal last_read_type , xml.elements["//last-read"].attributes['type']
73
- else
74
- assert_equal "2004-04-15", xml.elements["//last-read"].text
75
- assert_equal "date" , xml.elements["//last-read"].attributes['type']
76
- end
77
-
78
- assert_equal "false", xml.elements["//approved"].text
79
- assert_equal "boolean" , xml.elements["//approved"].attributes['type']
80
-
81
- assert_equal bonus_time_in_current_timezone, xml.elements["//bonus-time"].text
82
- assert_equal "datetime" , xml.elements["//bonus-time"].attributes['type']
83
- end
84
-
85
-
86
- end
@@ -1,20 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
- require 'models/company'
3
-
4
- class CalculationsTestSqlserver < ActiveRecord::TestCase
5
- end
6
-
7
- class CalculationsTest < ActiveRecord::TestCase
8
-
9
- COERCED_TESTS = [:test_should_sum_expression]
10
-
11
- include SqlserverCoercedTest
12
-
13
- fixtures :accounts
14
-
15
- def test_coerced_test_should_sum_expression
16
- assert_equal 636, Account.sum("2 * credit_limit")
17
- end
18
-
19
-
20
- end
@@ -1,354 +0,0 @@
1
- require 'cases/sqlserver_helper'
2
- require 'models/binary'
3
-
4
- class SqlServerEdgeSchema < ActiveRecord::Base; end;
5
-
6
- class ColumnTestSqlserver < ActiveRecord::TestCase
7
-
8
- def setup
9
- @connection = ActiveRecord::Base.connection
10
- @column_klass = ActiveRecord::ConnectionAdapters::SQLServerColumn
11
- end
12
-
13
- should 'return real_number as float' do
14
- assert_equal :float, TableWithRealColumn.columns_hash["real_number"].type
15
- end
16
-
17
- should 'know its #table_name and #table_klass' do
18
- Topic.columns.each do |column|
19
- assert_equal 'topics', column.table_name, "This column #{column.inspect} did not know it's #table_name"
20
- assert_equal Topic, column.table_klass, "This column #{column.inspect} did not know it's #table_klass"
21
- end
22
- end
23
-
24
- should 'return correct null, limit, and default for Topic' do
25
- tch = Topic.columns_hash
26
- assert_equal false, tch['id'].null
27
- assert_equal true, tch['title'].null
28
- assert_equal 255, tch['author_name'].limit
29
- assert_equal true, tch['approved'].default
30
- assert_equal 0, tch['replies_count'].default
31
- end
32
-
33
- context 'For binary columns' do
34
-
35
- setup do
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
- @saved_bdata = Binary.create!(:data => @binary_string)
38
- end
39
-
40
- should 'read and write binary data equally' do
41
- assert_equal @binary_string, Binary.find(@saved_bdata).data
42
- end
43
-
44
- should 'have correct attributes' do
45
- column = Binary.columns_hash['data']
46
- assert_equal :binary, column.type
47
- assert_equal @connection.native_binary_database_type, column.sql_type
48
- assert_equal nil, column.limit
49
- end
50
-
51
- should 'quote data for sqlserver with literal 0x prefix' do
52
- # See the output of the stored procedure: 'exec sp_datatype_info'
53
- sqlserver_encoded_bdata = "0x47494638396101000100800000ffffff00000021f90400000000002c00000000010001000002024401003b"
54
- assert_equal sqlserver_encoded_bdata, @column_klass.string_to_binary(@binary_string)
55
- end
56
-
57
- end
58
-
59
- context 'For string columns' do
60
-
61
- setup do
62
- @char = SqlServerString.columns_hash['char']
63
- @char10 = SqlServerString.columns_hash['char_10']
64
- @varcharmax = SqlServerString.columns_hash['varchar_max']
65
- @varcharmax10 = SqlServerString.columns_hash['varchar_max_10']
66
- end
67
-
68
- should 'have correct simplified types' do
69
- assert_equal :string, @char.type
70
- assert_equal :string, @char10.type
71
- if sqlserver_2005? || sqlserver_2008?
72
- assert_equal :text, @varcharmax.type, @varcharmax.inspect
73
- assert_equal :text, @varcharmax10.type, @varcharmax10.inspect
74
- end
75
- end
76
-
77
- should 'have correct #sql_type per schema definition' do
78
- assert_equal 'char(1)', @char.sql_type, 'Specifing a char type with no limit is 1 by SQL Server standards.'
79
- assert_equal 'char(10)', @char10.sql_type, @char10.inspect
80
- if sqlserver_2005? || sqlserver_2008?
81
- assert_equal 'varchar(max)', @varcharmax.sql_type, 'A -1 limit should be converted to max (max) type.'
82
- assert_equal 'varchar(max)', @varcharmax10.sql_type, 'A -1 limit should be converted to max (max) type.'
83
- end
84
- end
85
-
86
- should 'have correct #limit per schema definition' do
87
- assert_equal 1, @char.limit
88
- assert_equal 10, @char10.limit
89
- if sqlserver_2005? || sqlserver_2008?
90
- assert_equal nil, @varcharmax.limit, 'Limits on max types are moot and we should let rails know that.'
91
- assert_equal nil, @varcharmax10.limit, 'Limits on max types are moot and we should let rails know that.'
92
- end
93
- end
94
-
95
- end
96
-
97
-
98
- context 'For all national/unicode columns' do
99
-
100
- setup do
101
- @nchar = SqlServerUnicode.columns_hash['nchar']
102
- @nvarchar = SqlServerUnicode.columns_hash['nvarchar']
103
- @ntext = SqlServerUnicode.columns_hash['ntext']
104
- @ntext10 = SqlServerUnicode.columns_hash['ntext_10']
105
- @nchar10 = SqlServerUnicode.columns_hash['nchar_10']
106
- @nvarchar100 = SqlServerUnicode.columns_hash['nvarchar_100']
107
- @nvarcharmax = SqlServerUnicode.columns_hash['nvarchar_max']
108
- @nvarcharmax10 = SqlServerUnicode.columns_hash['nvarchar_max_10']
109
- end
110
-
111
- should 'all respond true to #is_utf8?' do
112
- SqlServerUnicode.columns_hash.except('id').values.each do |column|
113
- assert column.is_utf8?, "This column #{column.inspect} should have been a unicode column."
114
- end
115
- end
116
-
117
- should 'have correct simplified types' do
118
- assert_equal :string, @nchar.type
119
- assert_equal :string, @nvarchar.type
120
- assert_equal :text, @ntext.type
121
- assert_equal :text, @ntext10.type
122
- assert_equal :string, @nchar10.type
123
- assert_equal :string, @nvarchar100.type
124
- if sqlserver_2005? || sqlserver_2008?
125
- assert_equal :text, @nvarcharmax.type, @nvarcharmax.inspect
126
- assert_equal :text, @nvarcharmax10.type, @nvarcharmax10.inspect
127
- end
128
- end
129
-
130
- should 'have correct #sql_type per schema definition' do
131
- assert_equal 'nchar(1)', @nchar.sql_type, 'Specifing a nchar type with no limit is 1 by SQL Server standards.'
132
- assert_equal 'nvarchar(255)', @nvarchar.sql_type, 'Default nvarchar limit is 255.'
133
- assert_equal 'ntext', @ntext.sql_type, 'Nice and clean ntext, limit means nothing here.'
134
- assert_equal 'ntext', @ntext10.sql_type, 'Even a next with a limit of 10 specified will mean nothing.'
135
- assert_equal 'nchar(10)', @nchar10.sql_type, 'An nchar with a limit of 10 needs to have it show up here.'
136
- assert_equal 'nvarchar(100)', @nvarchar100.sql_type, 'An nvarchar with a specified limit of 100 needs to show it.'
137
- if sqlserver_2005? || sqlserver_2008?
138
- assert_equal 'nvarchar(max)', @nvarcharmax.sql_type, 'A -1 limit should be converted to max (max) type.'
139
- assert_equal 'nvarchar(max)', @nvarcharmax10.sql_type, 'A -1 limit should be converted to max (max) type.'
140
- end
141
- end
142
-
143
- should 'have correct #limit per schema definition' do
144
- assert_equal 1, @nchar.limit
145
- assert_equal 255, @nvarchar.limit
146
- assert_equal nil, @ntext.limit, 'An ntext column limit is moot, it is a fixed variable length'
147
- assert_equal 10, @nchar10.limit
148
- assert_equal 100, @nvarchar100.limit
149
- if sqlserver_2005? || sqlserver_2008?
150
- assert_equal nil, @nvarcharmax.limit, 'Limits on max types are moot and we should let rails know that.'
151
- assert_equal nil, @nvarcharmax10.limit, 'Limits on max types are moot and we should let rails know that.'
152
- end
153
- end
154
-
155
- end
156
-
157
- context 'For datetime columns' do
158
-
159
- setup do
160
- @date = SqlServerChronic.columns_hash['date']
161
- @time = SqlServerChronic.columns_hash['time']
162
- @datetime = SqlServerChronic.columns_hash['datetime']
163
- @smalldatetime = SqlServerChronic.columns_hash['smalldatetime']
164
- @timestamp = SqlServerChronic.columns_hash['timestamp']
165
- @ss_timestamp = SqlServerChronic.columns_hash['ss_timestamp']
166
- end
167
-
168
- should 'have correct simplified type for uncast datetime' do
169
- assert_equal :datetime, @datetime.type
170
- end
171
-
172
- should 'use correct #sql_type for different sql server versions' do
173
- assert_equal 'datetime', @datetime.sql_type
174
- if sqlserver_2000? || sqlserver_2005?
175
- assert_equal 'datetime', @date.sql_type
176
- assert_equal 'datetime', @time.sql_type
177
- else
178
- assert_equal 'date', @date.sql_type
179
- assert_equal 'time', @time.sql_type
180
- end
181
- end
182
-
183
- should 'all be have nil #limit' do
184
- assert_equal nil, @date.limit
185
- assert_equal nil, @time.limit
186
- assert_equal nil, @datetime.limit
187
- end
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
-
208
- context 'For smalldatetime types' do
209
-
210
- should 'have created that type using rails migrations' do
211
- assert_equal 'smalldatetime', @smalldatetime.sql_type
212
- end
213
-
214
- should 'be able to insert column without truncation warnings or the like' do
215
- SqlServerChronic.create! :smalldatetime => Time.now
216
- end
217
-
218
- should 'be able to update column without truncation warnings or the like' do
219
- ssc = SqlServerChronic.create! :smalldatetime => 2.days.ago
220
- ssc.update_attributes! :smalldatetime => Time.now
221
- end
222
-
223
- end
224
-
225
- context 'which have coerced types' do
226
-
227
- setup do
228
- christmas_08 = "2008-12-25".to_time
229
- christmas_08_afternoon = "2008-12-25 12:00".to_time
230
- @chronic_date = SqlServerChronic.create!(:date => christmas_08).reload
231
- @chronic_time = SqlServerChronic.create!(:time => christmas_08_afternoon).reload
232
- end
233
-
234
- should 'have an inheritable attribute ' do
235
- assert SqlServerChronic.coerced_sqlserver_date_columns.include?('date') unless sqlserver_2008?
236
- end
237
-
238
- should 'have column and objects cast to date' do
239
- assert_equal :date, @date.type, "This column: \n#{@date.inspect}"
240
- klass = sqlserver_2008? ? Date : (connection_mode_dblib? ? Time : Date)
241
- assert_instance_of klass, @chronic_date.date
242
- end
243
-
244
- should 'have column objects cast to time' do
245
- assert_equal :time, @time.type, "This column: \n#{@time.inspect}"
246
- assert_instance_of Time, @chronic_time.time
247
- end
248
-
249
- end
250
-
251
- end
252
-
253
- context 'For decimal and numeric columns' do
254
-
255
- setup do
256
- @bank_balance = NumericData.columns_hash['bank_balance']
257
- @big_bank_balance = NumericData.columns_hash['big_bank_balance']
258
- @world_population = NumericData.columns_hash['world_population']
259
- @my_house_population = NumericData.columns_hash['my_house_population']
260
- end
261
-
262
- should 'have correct simplified types' do
263
- assert_equal :decimal, @bank_balance.type
264
- assert_equal :decimal, @big_bank_balance.type
265
- assert_equal :integer, @world_population.type, 'Since #extract_scale == 0'
266
- assert_equal :integer, @my_house_population.type, 'Since #extract_scale == 0'
267
- end
268
-
269
- should 'have correct #sql_type' do
270
- assert_equal 'decimal(10,2)', @bank_balance.sql_type
271
- assert_equal 'decimal(15,2)', @big_bank_balance.sql_type
272
- assert_equal 'decimal(10,0)', @world_population.sql_type
273
- assert_equal 'decimal(2,0)', @my_house_population.sql_type
274
- end
275
-
276
- should 'have correct #limit' do
277
- assert_equal nil, @bank_balance.limit
278
- assert_equal nil, @big_bank_balance.limit
279
- assert_equal nil, @world_population.limit
280
- assert_equal nil, @my_house_population.limit
281
- end
282
-
283
- should 'return correct precisions and scales' do
284
- assert_equal [10,2], [@bank_balance.precision, @bank_balance.scale]
285
- assert_equal [15,2], [@big_bank_balance.precision, @big_bank_balance.scale]
286
- assert_equal [10,0], [@world_population.precision, @world_population.scale]
287
- assert_equal [2,0], [@my_house_population.precision, @my_house_population.scale]
288
- end
289
-
290
- end
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
-
339
- context 'For tinyint columns' do
340
-
341
- setup do
342
- @tinyint = SqlServerEdgeSchema.columns_hash['tinyint']
343
- end
344
-
345
- should 'be all it should be' do
346
- assert_equal :integer, @tinyint.type
347
- assert_nil @tinyint.scale
348
- assert_equal 'tinyint(1)', @tinyint.sql_type
349
- end
350
-
351
- end
352
-
353
-
354
- end