activerecord-sqlserver-adapter 4.1.8 → 4.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -0
  3. data/CHANGELOG.md +60 -0
  4. data/Gemfile +45 -0
  5. data/Guardfile +29 -0
  6. data/MIT-LICENSE +5 -5
  7. data/README.md +193 -0
  8. data/RUNNING_UNIT_TESTS.md +95 -0
  9. data/Rakefile +48 -0
  10. data/activerecord-sqlserver-adapter.gemspec +28 -0
  11. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +5 -15
  12. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
  13. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +6 -4
  14. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +9 -3
  15. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +3 -1
  16. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +130 -151
  17. data/lib/active_record/connection_adapters/sqlserver/errors.rb +0 -25
  18. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +39 -78
  19. data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +71 -47
  20. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +14 -30
  21. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +112 -108
  22. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +4 -2
  23. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +1 -1
  24. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +1 -1
  25. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +52 -7
  26. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +52 -0
  27. data/lib/active_record/connection_adapters/sqlserver/type.rb +46 -0
  28. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +15 -0
  29. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +15 -0
  30. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +13 -0
  31. data/lib/active_record/connection_adapters/sqlserver/type/castable.rb +15 -0
  32. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +15 -0
  33. data/lib/active_record/connection_adapters/sqlserver/type/core_ext/value.rb +39 -0
  34. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +14 -0
  35. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +37 -0
  36. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +13 -0
  37. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +17 -0
  38. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +13 -0
  39. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +21 -0
  40. data/lib/active_record/connection_adapters/sqlserver/type/quoter.rb +32 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +17 -0
  42. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +13 -0
  43. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +21 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +24 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +15 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +59 -0
  48. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +15 -0
  49. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +22 -0
  50. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +15 -0
  51. data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
  52. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +15 -0
  53. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +20 -0
  54. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +20 -0
  55. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +23 -0
  56. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +20 -0
  57. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +20 -0
  58. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +20 -0
  59. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +20 -0
  60. data/lib/active_record/connection_adapters/sqlserver/utils.rb +118 -12
  61. data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
  62. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +133 -198
  63. data/lib/active_record/connection_adapters/sqlserver_column.rb +15 -86
  64. data/lib/active_record/sqlserver_base.rb +2 -0
  65. data/lib/arel/visitors/sqlserver.rb +120 -393
  66. data/lib/{arel/arel_sqlserver.rb → arel_sqlserver.rb} +1 -3
  67. data/test/cases/adapter_test_sqlserver.rb +420 -0
  68. data/test/cases/coerced_tests.rb +642 -0
  69. data/test/cases/column_test_sqlserver.rb +703 -0
  70. data/test/cases/connection_test_sqlserver.rb +216 -0
  71. data/test/cases/database_statements_test_sqlserver.rb +57 -0
  72. data/test/cases/execute_procedure_test_sqlserver.rb +38 -0
  73. data/test/cases/helper_sqlserver.rb +36 -0
  74. data/test/cases/migration_test_sqlserver.rb +66 -0
  75. data/test/cases/order_test_sqlserver.rb +147 -0
  76. data/test/cases/pessimistic_locking_test_sqlserver.rb +90 -0
  77. data/test/cases/schema_dumper_test_sqlserver.rb +175 -0
  78. data/test/cases/schema_test_sqlserver.rb +54 -0
  79. data/test/cases/scratchpad_test_sqlserver.rb +9 -0
  80. data/test/cases/showplan_test_sqlserver.rb +65 -0
  81. data/test/cases/specific_schema_test_sqlserver.rb +118 -0
  82. data/test/cases/transaction_test_sqlserver.rb +61 -0
  83. data/test/cases/utils_test_sqlserver.rb +91 -0
  84. data/test/cases/uuid_test_sqlserver.rb +41 -0
  85. data/test/config.yml +35 -0
  86. data/test/fixtures/1px.gif +0 -0
  87. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
  88. data/test/models/sqlserver/customers_view.rb +3 -0
  89. data/test/models/sqlserver/datatype.rb +3 -0
  90. data/test/models/sqlserver/datatype_migration.rb +3 -0
  91. data/test/models/sqlserver/dollar_table_name.rb +3 -0
  92. data/test/models/sqlserver/edge_schema.rb +13 -0
  93. data/test/models/sqlserver/fk_has_fk.rb +3 -0
  94. data/test/models/sqlserver/fk_has_pk.rb +3 -0
  95. data/test/models/sqlserver/natural_pk_data.rb +4 -0
  96. data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
  97. data/test/models/sqlserver/no_pk_data.rb +3 -0
  98. data/test/models/sqlserver/quoted_table.rb +7 -0
  99. data/test/models/sqlserver/quoted_view_1.rb +3 -0
  100. data/test/models/sqlserver/quoted_view_2.rb +3 -0
  101. data/test/models/sqlserver/string_default.rb +3 -0
  102. data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
  103. data/test/models/sqlserver/string_defaults_view.rb +3 -0
  104. data/test/models/sqlserver/tinyint_pk.rb +3 -0
  105. data/test/models/sqlserver/upper.rb +3 -0
  106. data/test/models/sqlserver/uppered.rb +3 -0
  107. data/test/models/sqlserver/uuid.rb +3 -0
  108. data/test/schema/datatypes/2012.sql +64 -0
  109. data/test/schema/sqlserver_specific_schema.rb +181 -0
  110. data/test/support/coerceable_test_sqlserver.rb +45 -0
  111. data/test/support/load_schema_sqlserver.rb +29 -0
  112. data/test/support/minitest_sqlserver.rb +1 -0
  113. data/test/support/paths_sqlserver.rb +48 -0
  114. data/test/support/rake_helpers.rb +41 -0
  115. data/test/support/sql_counter_sqlserver.rb +32 -0
  116. metadata +271 -21
  117. data/CHANGELOG +0 -39
  118. data/VERSION +0 -1
  119. data/lib/active_record/connection_adapters/sqlserver/core_ext/relation.rb +0 -17
  120. data/lib/active_record/sqlserver_test_case.rb +0 -17
  121. data/lib/arel/nodes_sqlserver.rb +0 -14
  122. data/lib/arel/select_manager_sqlserver.rb +0 -62
@@ -0,0 +1,703 @@
1
+ # encoding: UTF-8
2
+ require 'cases/helper_sqlserver'
3
+
4
+ class ColumnTestSQLServer < ActiveRecord::TestCase
5
+
6
+ it '#table_name' do
7
+ assert SSTestDatatype.columns.all? { |c| c.table_name == 'sst_datatypes' }
8
+ assert SSTestCustomersView.columns.all? { |c| c.table_name == 'customers' }
9
+ end
10
+
11
+ describe 'ActiveRecord::ConnectionAdapters::SQLServer::Type' do
12
+
13
+ let(:obj) { SSTestDatatype.new }
14
+
15
+ Type = ActiveRecord::ConnectionAdapters::SQLServer::Type
16
+
17
+ def new_obj ; SSTestDatatype.new ; end
18
+ def column(name) ; SSTestDatatype.columns_hash[name] ; end
19
+ def assert_obj_set_and_save(attribute, value)
20
+ obj.send :"#{attribute}=", value
21
+ obj.send(attribute).must_equal value
22
+ obj.save!
23
+ obj.reload.send(attribute).must_equal value
24
+ end
25
+
26
+ # http://msdn.microsoft.com/en-us/library/ms187752.aspx
27
+
28
+ # Exact Numerics
29
+
30
+ it 'int(4) PRIMARY KEY' do
31
+ col = column('id')
32
+ col.sql_type.must_equal 'int(4)'
33
+ col.null.must_equal false
34
+ end
35
+
36
+ it 'bigint(8)' do
37
+ col = column('bigint')
38
+ col.sql_type.must_equal 'bigint(8)'
39
+ col.null.must_equal true
40
+ col.default.must_equal 42
41
+ obj.bigint.must_equal 42
42
+ col.default_function.must_equal nil
43
+ type = col.cast_type
44
+ type.must_be_instance_of Type::BigInteger
45
+ type.type.must_equal :bigint
46
+ type.must_be :number?
47
+ type.limit.must_equal 8
48
+ assert_obj_set_and_save :bigint, -9_223_372_036_854_775_808
49
+ assert_raises(RangeError) { new_obj.bigint = -9_223_372_036_854_775_809 }
50
+ assert_obj_set_and_save :bigint, 9_223_372_036_854_775_807
51
+ assert_raises(RangeError) { new_obj.bigint = 9_223_372_036_854_775_808 }
52
+ end
53
+
54
+ it 'int(4)' do
55
+ col = column('int')
56
+ col.sql_type.must_equal 'int(4)'
57
+ col.null.must_equal true
58
+ col.default.must_equal 42
59
+ obj.int.must_equal 42
60
+ col.default_function.must_equal nil
61
+ type = col.cast_type
62
+ type.must_be_instance_of Type::Integer
63
+ type.type.must_equal :integer
64
+ type.must_be :number?
65
+ type.limit.must_equal 4
66
+ assert_obj_set_and_save :int, -2_147_483_648
67
+ assert_raises(RangeError) { new_obj.int = -2_147_483_649 }
68
+ assert_obj_set_and_save :int, 2_147_483_647
69
+ assert_raises(RangeError) { new_obj.int = 2_147_483_648 }
70
+ end
71
+
72
+ it 'smallint(2)' do
73
+ col = column('smallint')
74
+ col.sql_type.must_equal 'smallint(2)'
75
+ col.null.must_equal true
76
+ col.default.must_equal 42
77
+ obj.smallint.must_equal 42
78
+ col.default_function.must_equal nil
79
+ type = col.cast_type
80
+ type.must_be_instance_of Type::SmallInteger
81
+ type.type.must_equal :integer
82
+ type.must_be :number?
83
+ type.limit.must_equal 2
84
+ assert_obj_set_and_save :smallint, -32_768
85
+ assert_raises(RangeError) { new_obj.smallint = -32_769 }
86
+ assert_obj_set_and_save :smallint, 32_767
87
+ assert_raises(RangeError) { new_obj.smallint = 32_768 }
88
+ end
89
+
90
+ it 'tinyint(1)' do
91
+ col = column('tinyint')
92
+ col.sql_type.must_equal 'tinyint(1)'
93
+ col.null.must_equal true
94
+ col.default.must_equal 42
95
+ obj.tinyint.must_equal 42
96
+ col.default_function.must_equal nil
97
+ type = col.cast_type
98
+ type.must_be_instance_of Type::TinyInteger
99
+ type.type.must_equal :integer
100
+ type.must_be :number?
101
+ type.limit.must_equal 1
102
+ assert_obj_set_and_save :tinyint, 0
103
+ assert_raises(RangeError) { new_obj.tinyint = -1 }
104
+ assert_obj_set_and_save :tinyint, 255
105
+ assert_raises(RangeError) { new_obj.tinyint = 256 }
106
+ end
107
+
108
+ it 'bit' do
109
+ col = column('bit')
110
+ col.sql_type.must_equal 'bit'
111
+ col.null.must_equal true
112
+ col.default.must_equal true
113
+ obj.bit.must_equal true
114
+ col.default_function.must_equal nil
115
+ type = col.cast_type
116
+ type.must_be_instance_of Type::Boolean
117
+ type.type.must_equal :boolean
118
+ type.wont_be :number?
119
+ type.limit.must_equal nil
120
+ obj.bit = 0
121
+ obj.bit.must_equal false
122
+ obj.save!
123
+ obj.reload.bit.must_equal false
124
+ obj.bit = '1'
125
+ obj.bit.must_equal true
126
+ obj.save!
127
+ obj.reload.bit.must_equal true
128
+ end
129
+
130
+ it 'decimal(9,2)' do
131
+ col = column('decimal_9_2')
132
+ col.sql_type.must_equal 'decimal(9,2)'
133
+ col.null.must_equal true
134
+ col.default.must_equal BigDecimal('12345.01')
135
+ obj.decimal_9_2.must_equal BigDecimal('12345.01')
136
+ col.default_function.must_equal nil
137
+ type = col.cast_type
138
+ type.must_be_instance_of Type::Decimal
139
+ type.type.must_equal :decimal
140
+ type.must_be :number?
141
+ type.limit.must_equal nil
142
+ type.precision.must_equal 9
143
+ type.scale.must_equal 2
144
+ obj.decimal_9_2 = '1234567.8901'
145
+ obj.decimal_9_2.must_equal BigDecimal('1234567.8901') # Cast from user one day.
146
+ obj.save!
147
+ obj.reload.decimal_9_2.must_equal BigDecimal('1234567.89')
148
+ end
149
+
150
+ it 'decimal(16,4)' do
151
+ col = column('decimal_16_4')
152
+ col.sql_type.must_equal 'decimal(16,4)'
153
+ col.default.must_equal BigDecimal('1234567.89')
154
+ obj.decimal_16_4.must_equal BigDecimal('1234567.89')
155
+ col.default_function.must_equal nil
156
+ type = col.cast_type
157
+ type.precision.must_equal 16
158
+ type.scale.must_equal 4
159
+ obj.decimal_16_4 = '1234567.8901001'
160
+ obj.decimal_16_4.must_equal BigDecimal('1234567.8901001') # Cast from user one day.
161
+ obj.save!
162
+ obj.reload.decimal_16_4.must_equal BigDecimal('1234567.8901')
163
+ end
164
+
165
+ it 'numeric(18,0)' do
166
+ col = column('numeric_18_0')
167
+ col.sql_type.must_equal 'numeric(18,0)'
168
+ col.null.must_equal true
169
+ col.default.must_equal BigDecimal('191')
170
+ obj.numeric_18_0.must_equal BigDecimal('191')
171
+ col.default_function.must_equal nil
172
+ type = col.cast_type
173
+ type.must_be_instance_of Type::Decimal
174
+ type.type.must_equal :decimal
175
+ type.must_be :number?
176
+ type.limit.must_equal nil
177
+ type.precision.must_equal 18
178
+ type.scale.must_equal 0
179
+ obj.numeric_18_0 = '192.1'
180
+ obj.numeric_18_0.must_equal BigDecimal('192.1') # Cast from user one day.
181
+ obj.save!
182
+ obj.reload.numeric_18_0.must_equal BigDecimal('192')
183
+ end
184
+
185
+ it 'numeric(36,2)' do
186
+ col = column('numeric_36_2')
187
+ col.sql_type.must_equal 'numeric(36,2)'
188
+ col.null.must_equal true
189
+ col.default.must_equal BigDecimal('12345678901234567890.01')
190
+ obj.numeric_36_2.must_equal BigDecimal('12345678901234567890.01')
191
+ col.default_function.must_equal nil
192
+ type = col.cast_type
193
+ type.must_be_instance_of Type::Decimal
194
+ type.type.must_equal :decimal
195
+ type.must_be :number?
196
+ type.limit.must_equal nil
197
+ type.precision.must_equal 36
198
+ type.scale.must_equal 2
199
+ obj.numeric_36_2 = '192.123'
200
+ obj.numeric_36_2.must_equal BigDecimal('192.123') # Cast from user one day.
201
+ obj.save!
202
+ obj.reload.numeric_36_2.must_equal BigDecimal('192.12')
203
+ end
204
+
205
+ it 'money' do
206
+ col = column('money')
207
+ col.sql_type.must_equal 'money'
208
+ col.null.must_equal true
209
+ col.default.must_equal BigDecimal('4.20')
210
+ obj.money.must_equal BigDecimal('4.20')
211
+ col.default_function.must_equal nil
212
+ type = col.cast_type
213
+ type.must_be_instance_of Type::Money
214
+ type.type.must_equal :money
215
+ type.must_be :number?
216
+ type.limit.must_equal nil
217
+ type.precision.must_equal 19
218
+ type.scale.must_equal 4
219
+ obj.money = '922337203685477.58061'
220
+ obj.money.must_equal BigDecimal('922337203685477.58061')
221
+ obj.save!
222
+ obj.reload.money.must_equal BigDecimal('922337203685477.5806')
223
+ end
224
+
225
+ it 'smallmoney' do
226
+ col = column('smallmoney')
227
+ col.sql_type.must_equal 'smallmoney'
228
+ col.null.must_equal true
229
+ col.default.must_equal BigDecimal('4.20')
230
+ obj.smallmoney.must_equal BigDecimal('4.20')
231
+ col.default_function.must_equal nil
232
+ type = col.cast_type
233
+ type.must_be_instance_of Type::SmallMoney
234
+ type.type.must_equal :smallmoney
235
+ type.must_be :number?
236
+ type.limit.must_equal nil
237
+ type.precision.must_equal 10
238
+ type.scale.must_equal 4
239
+ obj.smallmoney = '214748.36461'
240
+ obj.smallmoney.must_equal BigDecimal('214748.36461')
241
+ obj.save!
242
+ obj.reload.smallmoney.must_equal BigDecimal('214748.3646')
243
+ end
244
+
245
+ # Approximate Numerics
246
+ # Float limits are adjusted to 24 or 53 by the database as per http://msdn.microsoft.com/en-us/library/ms173773.aspx
247
+ # Floats with a limit of <= 24 are reduced to reals by sqlserver on creation.
248
+
249
+ it 'float' do
250
+ col = column('float')
251
+ col.sql_type.must_equal 'float'
252
+ col.null.must_equal true
253
+ col.default.must_equal 123.00000001
254
+ obj.float.must_equal 123.00000001
255
+ col.default_function.must_equal nil
256
+ type = col.cast_type
257
+ type.must_be_instance_of Type::Float
258
+ type.type.must_equal :float
259
+ type.must_be :number?
260
+ type.limit.must_equal nil
261
+ type.precision.must_equal nil
262
+ type.scale.must_equal nil
263
+ obj.float = '214748.36461'
264
+ obj.float.must_equal 214748.36461
265
+ obj.save!
266
+ obj.reload.float.must_equal 214748.36461
267
+ end
268
+
269
+ it 'real' do
270
+ col = column('real')
271
+ col.sql_type.must_equal 'real'
272
+ col.null.must_equal true
273
+ col.default.must_be_close_to 123.45, 0.01
274
+ obj.real.must_be_close_to 123.45, 0.01
275
+ col.default_function.must_equal nil
276
+ type = col.cast_type
277
+ type.must_be_instance_of Type::Real
278
+ type.type.must_equal :real
279
+ type.must_be :number?
280
+ type.limit.must_equal nil
281
+ type.precision.must_equal nil
282
+ type.scale.must_equal nil
283
+ obj.real = '214748.36461'
284
+ obj.real.must_be_close_to 214748.36461, 0.01
285
+ obj.save!
286
+ obj.reload.real.must_be_close_to 214748.36461, 0.01
287
+ end
288
+
289
+ # Date and Time
290
+
291
+ it 'date' do
292
+ col = column('date')
293
+ col.sql_type.must_equal 'date'
294
+ col.null.must_equal true
295
+ col.default.must_equal '0001-01-01' # TODO: None type casted default. Really want Date.civil(0001, 1, 1).
296
+ obj.date.must_equal Date.civil(0001, 1, 1)
297
+ col.default_function.must_equal nil
298
+ type = col.cast_type
299
+ type.must_be_instance_of Type::Date
300
+ type.type.must_equal :date
301
+ type.wont_be :number?
302
+ type.limit.must_equal nil
303
+ type.precision.must_equal nil
304
+ type.scale.must_equal nil
305
+ # Can cast strings.
306
+ obj.date = '0001-01-01'
307
+ obj.date.must_equal Date.civil(0001, 1, 1)
308
+ obj.save!
309
+ obj.reload.date.must_equal Date.civil(0001, 1, 1)
310
+ # Can keep and return assigned date.
311
+ assert_obj_set_and_save :date, Date.civil(1972, 04, 14)
312
+ # Can accept and cast time objects.
313
+ obj.date = Time.utc(2010, 4, 14, 12, 34, 56, 3000)
314
+ obj.date.must_equal Date.civil(2010, 4, 14)
315
+ obj.save!
316
+ obj.reload.date.must_equal Date.civil(2010, 4, 14)
317
+ end
318
+
319
+ it 'datetime' do
320
+ col = column('datetime')
321
+ col.sql_type.must_equal 'datetime'
322
+ col.null.must_equal true
323
+ col.default.must_equal Time.utc(1753, 01, 01, 00, 00, 00, 000)
324
+ obj.datetime.must_equal Time.utc(1753, 01, 01, 00, 00, 00, 000)
325
+ col.default_function.must_equal nil
326
+ type = col.cast_type
327
+ type.must_be_instance_of Type::DateTime
328
+ type.type.must_equal :datetime
329
+ type.wont_be :number?
330
+ type.limit.must_equal nil
331
+ type.precision.must_equal nil
332
+ type.scale.must_equal nil
333
+ # Can save .003 seconds and return again.
334
+ obj.datetime = Time.utc(2010, 01, 01, 12, 34, 56, 3000)
335
+ obj.datetime.must_equal Time.utc(2010, 01, 01, 12, 34, 56, 3000), "Microseconds were <#{obj.datetime.usec}> vs <3000>"
336
+ obj.save!
337
+ obj.reload.datetime.must_equal Time.utc(2010, 01, 01, 12, 34, 56, 3000), "Microseconds were <#{obj.reload.datetime.usec}> vs <3000>"
338
+ # Will cast to true DB value on attribute write, save and return again.
339
+ obj.datetime = Time.utc(2010, 01, 01, 12, 34, 56, 234567)
340
+ obj.datetime.must_equal Time.utc(2010, 01, 01, 12, 34, 56, 233000), "Microseconds were <#{obj.datetime.usec}> vs <233000>"
341
+ obj.save!
342
+ obj.reload.datetime.must_equal Time.utc(2010, 01, 01, 12, 34, 56, 233000), "Microseconds were <#{obj.reload.datetime.usec}> vs <233000>"
343
+ end
344
+
345
+ it 'smalldatetime' do
346
+ col = column('smalldatetime')
347
+ col.sql_type.must_equal 'smalldatetime'
348
+ col.null.must_equal true
349
+ col.default.must_equal Time.utc(1901, 01, 01, 15, 45, 00, 000)
350
+ obj.smalldatetime.must_equal Time.utc(1901, 01, 01, 15, 45, 00, 000)
351
+ col.default_function.must_equal nil
352
+ type = col.cast_type
353
+ type.must_be_instance_of Type::SmallDateTime
354
+ type.type.must_equal :datetime
355
+ type.wont_be :number?
356
+ type.limit.must_equal nil
357
+ type.precision.must_equal nil
358
+ type.scale.must_equal nil
359
+ # Will remove fractional seconds and return again.
360
+ obj.smalldatetime = Time.utc(2078, 06, 05, 4, 20, 00, 3000)
361
+ obj.smalldatetime.must_equal Time.utc(2078, 06, 05, 4, 20, 00, 0), "Microseconds were <#{obj.smalldatetime.usec}> vs <0>"
362
+ obj.save!
363
+ obj.reload.smalldatetime.must_equal Time.utc(2078, 06, 05, 4, 20, 00, 0), "Microseconds were <#{obj.reload.smalldatetime.usec}> vs <0>"
364
+ end
365
+
366
+ it 'time(2)' do
367
+ col = column('time_2')
368
+ col.sql_type.must_equal 'time(2)'
369
+ col.null.must_equal true
370
+ col.default.must_equal nil
371
+ col.default_function.must_equal nil
372
+ type = col.cast_type
373
+ type.must_be_instance_of Type::Time
374
+ type.type.must_equal :time
375
+ type.wont_be :number?
376
+ type.limit.must_equal nil
377
+ type.precision.must_equal 2
378
+ type.scale.must_equal nil
379
+ # Always uses ActiveRecord's 2000-01-01 convention too.
380
+ obj.time_2 = Time.utc(2015, 01, 10, 15, 45, 00, 0)
381
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0)
382
+ obj.save!
383
+ obj.reload.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0)
384
+ # Midnight the beggining of the day.
385
+ obj.time_2 = Time.utc(2000, 01, 01).midnight.change(usec: 0)
386
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 00, 00, 00, 0)
387
+ obj.save!
388
+ obj.reload.time_2.must_equal Time.utc(2000, 01, 01, 00, 00, 00, 0)
389
+ # The end of day.
390
+ obj.time_2 = Time.utc(2000, 01, 01).end_of_day.change(usec: 0)
391
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 23, 59, 59, 0)
392
+ obj.save!
393
+ obj.reload.time_2.must_equal Time.utc(2000, 01, 01, 23, 59, 59, 0)
394
+ # Time's #usec precision (barely in 2 precision equal to 0.03 seconds)
395
+ obj.time_2 = Time.utc(2000, 01, 01, 15, 45, 00, 30000)
396
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 30000), "Microseconds were <#{obj.time_2.usec}> vs <30000>"
397
+ obj.save!
398
+ obj.reload.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 30000), "Microseconds were <#{obj.reload.time_2.usec}> vs <30000>"
399
+ # Time's #usec precision (below 2 precision)
400
+ obj.time_2 = Time.utc(2000, 01, 01, 15, 45, 00, 4000)
401
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0), "Microseconds were <#{obj.time_2.usec}> vs <0>"
402
+ obj.save!
403
+ obj.reload.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0), "Microseconds were <#{obj.reload.time_2.usec}> vs <0>"
404
+ end
405
+
406
+ it 'time(7)' do
407
+ col = column('time_7')
408
+ col.sql_type.must_equal 'time(7)'
409
+ col.null.must_equal true
410
+ col.default.must_equal nil
411
+ col.default_function.must_equal nil
412
+ type = col.cast_type
413
+ type.must_be_instance_of Type::Time
414
+ type.type.must_equal :time
415
+ type.wont_be :number?
416
+ type.limit.must_equal nil
417
+ type.precision.must_equal nil, 'so it is clean in schema dumper'
418
+ type.scale.must_equal nil
419
+ # Time's #usec precision (low)
420
+ obj.time_7 = Time.utc(2000, 01, 01, 15, 45, 00, 300)
421
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 300), "Microseconds were <#{obj.time_7.usec}> vs <300>"
422
+ obj.save!
423
+ obj.reload.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 300), "Microseconds were <#{obj.reload.time_7.usec}> vs <300>"
424
+ # Time's #usec precision (high)
425
+ obj.time_7 = Time.utc(2000, 01, 01, 15, 45, 00, 234567)
426
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 234567), "Microseconds were <#{obj.time_7.usec}> vs <234567>"
427
+ obj.save!
428
+ obj.reload.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 234567), "Microseconds were <#{obj.reload.time_7.usec}> vs <234567>"
429
+ end
430
+
431
+ # Character Strings
432
+
433
+ it 'char(10)' do
434
+ col = column('char_10')
435
+ col.sql_type.must_equal 'char(10)'
436
+ col.null.must_equal true
437
+ col.default.must_equal '1234567890'
438
+ obj.char_10.must_equal '1234567890'
439
+ col.default_function.must_equal nil
440
+ type = col.cast_type
441
+ type.must_be_instance_of Type::Char
442
+ type.type.must_equal :char
443
+ type.wont_be :number?
444
+ type.limit.must_equal 10
445
+ type.precision.must_equal nil
446
+ type.scale.must_equal nil
447
+ # Basic set and save.
448
+ obj.char_10 = '012345'
449
+ obj.char_10.strip.must_equal '012345'
450
+ obj.save!
451
+ obj.reload.char_10.strip.must_equal '012345'
452
+ end
453
+
454
+ it 'varchar(50)' do
455
+ col = column('varchar_50')
456
+ col.sql_type.must_equal 'varchar(50)'
457
+ col.null.must_equal true
458
+ col.default.must_equal 'test varchar_50'
459
+ obj.varchar_50.must_equal 'test varchar_50'
460
+ col.default_function.must_equal nil
461
+ type = col.cast_type
462
+ type.must_be_instance_of Type::Varchar
463
+ type.type.must_equal :varchar
464
+ type.wont_be :number?
465
+ type.limit.must_equal 50
466
+ type.precision.must_equal nil
467
+ type.scale.must_equal nil
468
+ # Basic set and save.
469
+ assert_obj_set_and_save :varchar_50, 'Hello World'
470
+ end
471
+
472
+ it 'varchar(max)' do
473
+ col = column('varchar_max')
474
+ col.sql_type.must_equal 'varchar(max)'
475
+ col.null.must_equal true
476
+ col.default.must_equal 'test varchar_max'
477
+ obj.varchar_max.must_equal 'test varchar_max'
478
+ col.default_function.must_equal nil
479
+ type = col.cast_type
480
+ type.must_be_instance_of Type::VarcharMax
481
+ type.type.must_equal :varchar_max
482
+ type.wont_be :number?
483
+ type.limit.must_equal 2_147_483_647
484
+ type.precision.must_equal nil
485
+ type.scale.must_equal nil
486
+ # Basic set and save.
487
+ assert_obj_set_and_save :varchar_max, 'Hello World'
488
+ end
489
+
490
+ it 'text' do
491
+ col = column('text')
492
+ col.sql_type.must_equal 'text'
493
+ col.null.must_equal true
494
+ col.default.must_equal 'test text'
495
+ obj.text.must_equal 'test text'
496
+ col.default_function.must_equal nil
497
+ type = col.cast_type
498
+ type.must_be_instance_of Type::Text
499
+ type.type.must_equal :text_basic
500
+ type.wont_be :number?
501
+ type.limit.must_equal 2_147_483_647
502
+ type.precision.must_equal nil
503
+ type.scale.must_equal nil
504
+ # Basic set and save.
505
+ assert_obj_set_and_save :text, 'Hello World'
506
+ end
507
+
508
+ # Unicode Character Strings
509
+
510
+ it 'nchar(10)' do
511
+ col = column('nchar_10')
512
+ col.sql_type.must_equal 'nchar(10)'
513
+ col.null.must_equal true
514
+ col.default.must_equal '12345678åå'
515
+ obj.nchar_10.must_equal '12345678åå'
516
+ col.default_function.must_equal nil
517
+ type = col.cast_type
518
+ type.must_be_instance_of Type::UnicodeChar
519
+ type.type.must_equal :nchar
520
+ type.wont_be :number?
521
+ type.limit.must_equal 10
522
+ type.precision.must_equal nil
523
+ type.scale.must_equal nil
524
+ # Basic set and save.
525
+ obj.nchar_10 = "五六"
526
+ obj.nchar_10.strip.must_equal "五六"
527
+ obj.save!
528
+ obj.reload.nchar_10.strip.must_equal "五六"
529
+ end
530
+
531
+ it 'nvarchar(50)' do
532
+ col = column('nvarchar_50')
533
+ col.sql_type.must_equal 'nvarchar(50)'
534
+ col.null.must_equal true
535
+ col.default.must_equal 'test nvarchar_50 åå'
536
+ obj.nvarchar_50.must_equal 'test nvarchar_50 åå'
537
+ col.default_function.must_equal nil
538
+ type = col.cast_type
539
+ type.must_be_instance_of Type::UnicodeVarchar
540
+ type.type.must_equal :string
541
+ type.wont_be :number?
542
+ type.limit.must_equal 50
543
+ type.precision.must_equal nil
544
+ type.scale.must_equal nil
545
+ # Basic set and save.
546
+ assert_obj_set_and_save :nvarchar_50, "一二34五六"
547
+ end
548
+
549
+ it 'nvarchar(max)' do
550
+ col = column('nvarchar_max')
551
+ col.sql_type.must_equal 'nvarchar(max)'
552
+ col.null.must_equal true
553
+ col.default.must_equal 'test nvarchar_max åå'
554
+ obj.nvarchar_max.must_equal 'test nvarchar_max åå'
555
+ col.default_function.must_equal nil
556
+ type = col.cast_type
557
+ type.must_be_instance_of Type::UnicodeVarcharMax
558
+ type.type.must_equal :text
559
+ type.wont_be :number?
560
+ type.limit.must_equal 2_147_483_647
561
+ type.precision.must_equal nil
562
+ type.scale.must_equal nil
563
+ # Basic set and save.
564
+ assert_obj_set_and_save :nvarchar_max, "一二34五六"
565
+ end
566
+
567
+ it 'ntext' do
568
+ col = column('ntext')
569
+ col.sql_type.must_equal 'ntext'
570
+ col.null.must_equal true
571
+ col.default.must_equal 'test ntext åå'
572
+ obj.ntext.must_equal 'test ntext åå'
573
+ col.default_function.must_equal nil
574
+ type = col.cast_type
575
+ type.must_be_instance_of Type::UnicodeText
576
+ type.type.must_equal :ntext
577
+ type.wont_be :number?
578
+ type.limit.must_equal 2_147_483_647
579
+ type.precision.must_equal nil
580
+ type.scale.must_equal nil
581
+ # Basic set and save.
582
+ assert_obj_set_and_save :ntext, "一二34五六"
583
+ end
584
+
585
+ # Binary Strings
586
+
587
+ let(:binary_file) { File.join ARTest::SQLServer.test_root_sqlserver, 'fixtures', '1px.gif' }
588
+ let(:binary_data) { File.open(binary_file, 'rb') { |f| f.read } }
589
+
590
+ it 'binary(49)' do
591
+ col = column('binary_49')
592
+ col.sql_type.must_equal 'binary(49)'
593
+ col.null.must_equal true
594
+ col.default.must_equal nil
595
+ col.default_function.must_equal nil
596
+ type = col.cast_type
597
+ type.must_be_instance_of Type::Binary
598
+ type.type.must_equal :binary_basic
599
+ type.wont_be :number?
600
+ type.limit.must_equal 49
601
+ type.precision.must_equal nil
602
+ type.scale.must_equal nil
603
+ # Basic set and save.
604
+ binary_data.encoding.must_equal Encoding::BINARY
605
+ binary_data.length.must_equal 49
606
+ obj.binary_49 = binary_data
607
+ obj.binary_49.must_equal binary_data
608
+ obj.save!
609
+ obj.reload.binary_49.must_equal binary_data
610
+ end
611
+
612
+ it 'varbinary(49)' do
613
+ col = column('varbinary_49')
614
+ col.sql_type.must_equal 'varbinary(49)'
615
+ col.null.must_equal true
616
+ col.default.must_equal nil
617
+ col.default_function.must_equal nil
618
+ type = col.cast_type
619
+ type.must_be_instance_of Type::Varbinary
620
+ type.type.must_equal :varbinary
621
+ type.wont_be :number?
622
+ type.limit.must_equal 49
623
+ type.precision.must_equal nil
624
+ type.scale.must_equal nil
625
+ # Basic set and save.
626
+ binary_data_20 = binary_data.to(20)
627
+ binary_data_20.encoding.must_equal Encoding::BINARY
628
+ obj.varbinary_49 = binary_data_20
629
+ obj.varbinary_49.must_equal binary_data_20
630
+ obj.save!
631
+ obj.reload.varbinary_49.must_equal binary_data_20
632
+ end
633
+
634
+ it 'varbinary(max)' do
635
+ col = column('varbinary_max')
636
+ col.sql_type.must_equal 'varbinary(max)'
637
+ col.null.must_equal true
638
+ col.default.must_equal nil
639
+ col.default_function.must_equal nil
640
+ type = col.cast_type
641
+ type.must_be_instance_of Type::VarbinaryMax
642
+ type.type.must_equal :binary
643
+ type.wont_be :number?
644
+ type.limit.must_equal 2_147_483_647
645
+ type.precision.must_equal nil
646
+ type.scale.must_equal nil
647
+ # Basic set and save.
648
+ binary_data.encoding.must_equal Encoding::BINARY
649
+ assert_obj_set_and_save :varbinary_max, binary_data
650
+ end
651
+
652
+ # Other Data Types
653
+
654
+ it 'uniqueidentifier' do
655
+ col = column('uniqueidentifier')
656
+ col.sql_type.must_equal 'uniqueidentifier'
657
+ col.null.must_equal true
658
+ col.default.must_equal nil
659
+ col.default_function.must_equal 'newid()'
660
+ type = col.cast_type
661
+ type.must_be_instance_of Type::Uuid
662
+ type.type.must_equal :uuid
663
+ type.wont_be :number?
664
+ type.limit.must_equal nil
665
+ type.precision.must_equal nil
666
+ type.scale.must_equal nil
667
+ # Basic set and save.
668
+ obj.uniqueidentifier = "this will not qualify as valid"
669
+ obj.uniqueidentifier.must_equal nil
670
+ obj.save! ; obj.reload
671
+ obj.uniqueidentifier.must_match Type::Uuid::ACCEPTABLE_UUID
672
+ obj.uniqueidentifier = "6F9619FF-8B86-D011-B42D-00C04FC964FF"
673
+ obj.uniqueidentifier.must_equal "6F9619FF-8B86-D011-B42D-00C04FC964FF"
674
+ obj.save! ; obj.reload
675
+ obj.uniqueidentifier.must_equal "6F9619FF-8B86-D011-B42D-00C04FC964FF"
676
+ end
677
+
678
+ it 'timestamp' do
679
+ col = column('timestamp')
680
+ col.sql_type.must_equal 'timestamp'
681
+ col.null.must_equal true
682
+ col.default.must_equal nil
683
+ col.default_function.must_equal nil
684
+ type = col.cast_type
685
+ type.must_be_instance_of Type::Timestamp
686
+ type.type.must_equal :ss_timestamp
687
+ type.wont_be :number?
688
+ type.limit.must_equal nil
689
+ type.precision.must_equal nil
690
+ type.scale.must_equal nil
691
+ # Basic read.
692
+ obj.timestamp.must_equal nil
693
+ obj.save! ; obj.reload
694
+ obj.timestamp.must_match %r|\000|
695
+ obj.timestamp
696
+ # Can set another attribute
697
+ obj.uniqueidentifier = "6F9619FF-8B86-D011-B42D-00C04FC964FF"
698
+ obj.save!
699
+ end
700
+
701
+ end
702
+
703
+ end