activerecord-jdbcsqlserver-adapter 50.0.0

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.
Files changed (148) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +27 -0
  4. data/CHANGELOG.md +124 -0
  5. data/CODE_OF_CONDUCT.md +31 -0
  6. data/Dockerfile +20 -0
  7. data/Gemfile +77 -0
  8. data/Guardfile +29 -0
  9. data/MIT-LICENSE +20 -0
  10. data/RAILS5-TODO.md +5 -0
  11. data/README.md +93 -0
  12. data/RUNNING_UNIT_TESTS.md +96 -0
  13. data/Rakefile +46 -0
  14. data/VERSION +1 -0
  15. data/activerecord-jdbcsqlserver-adapter.gemspec +21 -0
  16. data/appveyor.yml +39 -0
  17. data/docker-compose.ci.yml +11 -0
  18. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +27 -0
  19. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
  20. data/lib/active_record/connection_adapters/sqlserver/core_ext/date_time.rb +58 -0
  21. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +47 -0
  22. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
  23. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
  24. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +362 -0
  25. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +67 -0
  26. data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
  27. data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +192 -0
  28. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +99 -0
  29. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +34 -0
  30. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
  31. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +517 -0
  32. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +66 -0
  33. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +66 -0
  34. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +22 -0
  35. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
  36. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +112 -0
  37. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +64 -0
  38. data/lib/active_record/connection_adapters/sqlserver/type.rb +49 -0
  39. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +19 -0
  40. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +21 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +15 -0
  42. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +32 -0
  43. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +61 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +71 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +23 -0
  48. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +21 -0
  49. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +19 -0
  50. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +15 -0
  51. data/lib/active_record/connection_adapters/sqlserver/type/json.rb +11 -0
  52. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +25 -0
  53. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +19 -0
  54. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +15 -0
  55. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +25 -0
  56. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +29 -0
  57. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
  58. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +19 -0
  59. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +68 -0
  60. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +93 -0
  61. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +19 -0
  62. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +25 -0
  63. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +21 -0
  64. data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
  65. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +19 -0
  66. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +26 -0
  67. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +24 -0
  68. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +36 -0
  69. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +26 -0
  70. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +24 -0
  71. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +26 -0
  72. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +24 -0
  73. data/lib/active_record/connection_adapters/sqlserver/utils.rb +146 -0
  74. data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
  75. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +445 -0
  76. data/lib/active_record/connection_adapters/sqlserver_column.rb +28 -0
  77. data/lib/active_record/jdbc_sqlserver_connection_methods.rb +31 -0
  78. data/lib/active_record/sqlserver_base.rb +16 -0
  79. data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
  80. data/lib/activerecord-jdbcsqlserver-adapter.rb +24 -0
  81. data/lib/activerecord-sqlserver-adapter.rb +1 -0
  82. data/lib/arel/visitors/sqlserver.rb +205 -0
  83. data/lib/arel_sqlserver.rb +3 -0
  84. data/test/appveyor/dbsetup.ps1 +27 -0
  85. data/test/appveyor/dbsetup.sql +11 -0
  86. data/test/bin/wait-for.sh +79 -0
  87. data/test/cases/adapter_test_sqlserver.rb +430 -0
  88. data/test/cases/coerced_tests.rb +845 -0
  89. data/test/cases/column_test_sqlserver.rb +812 -0
  90. data/test/cases/connection_test_sqlserver.rb +71 -0
  91. data/test/cases/execute_procedure_test_sqlserver.rb +45 -0
  92. data/test/cases/fetch_test_sqlserver.rb +57 -0
  93. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +76 -0
  94. data/test/cases/helper_sqlserver.rb +44 -0
  95. data/test/cases/index_test_sqlserver.rb +47 -0
  96. data/test/cases/json_test_sqlserver.rb +32 -0
  97. data/test/cases/migration_test_sqlserver.rb +61 -0
  98. data/test/cases/order_test_sqlserver.rb +147 -0
  99. data/test/cases/pessimistic_locking_test_sqlserver.rb +94 -0
  100. data/test/cases/rake_test_sqlserver.rb +169 -0
  101. data/test/cases/schema_dumper_test_sqlserver.rb +234 -0
  102. data/test/cases/schema_test_sqlserver.rb +54 -0
  103. data/test/cases/scratchpad_test_sqlserver.rb +8 -0
  104. data/test/cases/showplan_test_sqlserver.rb +65 -0
  105. data/test/cases/specific_schema_test_sqlserver.rb +180 -0
  106. data/test/cases/transaction_test_sqlserver.rb +91 -0
  107. data/test/cases/utils_test_sqlserver.rb +129 -0
  108. data/test/cases/uuid_test_sqlserver.rb +49 -0
  109. data/test/config.yml +38 -0
  110. data/test/debug.rb +14 -0
  111. data/test/fixtures/1px.gif +0 -0
  112. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
  113. data/test/models/sqlserver/booking.rb +3 -0
  114. data/test/models/sqlserver/customers_view.rb +3 -0
  115. data/test/models/sqlserver/datatype.rb +3 -0
  116. data/test/models/sqlserver/datatype_migration.rb +8 -0
  117. data/test/models/sqlserver/dollar_table_name.rb +3 -0
  118. data/test/models/sqlserver/dot_table_name.rb +3 -0
  119. data/test/models/sqlserver/edge_schema.rb +13 -0
  120. data/test/models/sqlserver/fk_has_fk.rb +3 -0
  121. data/test/models/sqlserver/fk_has_pk.rb +3 -0
  122. data/test/models/sqlserver/natural_pk_data.rb +4 -0
  123. data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
  124. data/test/models/sqlserver/no_pk_data.rb +3 -0
  125. data/test/models/sqlserver/object_default.rb +3 -0
  126. data/test/models/sqlserver/quoted_table.rb +7 -0
  127. data/test/models/sqlserver/quoted_view_1.rb +3 -0
  128. data/test/models/sqlserver/quoted_view_2.rb +3 -0
  129. data/test/models/sqlserver/sst_memory.rb +3 -0
  130. data/test/models/sqlserver/string_default.rb +3 -0
  131. data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
  132. data/test/models/sqlserver/string_defaults_view.rb +3 -0
  133. data/test/models/sqlserver/tinyint_pk.rb +3 -0
  134. data/test/models/sqlserver/upper.rb +3 -0
  135. data/test/models/sqlserver/uppered.rb +3 -0
  136. data/test/models/sqlserver/uuid.rb +3 -0
  137. data/test/schema/datatypes/2012.sql +55 -0
  138. data/test/schema/enable-in-memory-oltp.sql +81 -0
  139. data/test/schema/sqlserver_specific_schema.rb +238 -0
  140. data/test/support/coerceable_test_sqlserver.rb +49 -0
  141. data/test/support/connection_reflection.rb +34 -0
  142. data/test/support/load_schema_sqlserver.rb +29 -0
  143. data/test/support/minitest_sqlserver.rb +1 -0
  144. data/test/support/paths_sqlserver.rb +50 -0
  145. data/test/support/rake_helpers.rb +41 -0
  146. data/test/support/sql_counter_sqlserver.rb +28 -0
  147. data/test/support/test_in_memory_oltp.rb +15 -0
  148. metadata +310 -0
@@ -0,0 +1,812 @@
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.type.must_equal :bigint
40
+ col.null.must_equal true
41
+ col.default.must_equal 42
42
+ obj.bigint.must_equal 42
43
+ col.default_function.must_be_nil
44
+ type = connection.lookup_cast_type_from_column(col)
45
+ type.must_be_instance_of Type::BigInteger
46
+ type.limit.must_equal 8
47
+ assert_obj_set_and_save :bigint, -9_223_372_036_854_775_808
48
+ assert_obj_set_and_save :bigint, 9_223_372_036_854_775_807
49
+ end
50
+
51
+ it 'int(4)' do
52
+ col = column('int')
53
+ col.sql_type.must_equal 'int(4)'
54
+ col.type.must_equal :integer
55
+ col.null.must_equal true
56
+ col.default.must_equal 42
57
+ obj.int.must_equal 42
58
+ col.default_function.must_be_nil
59
+ type = connection.lookup_cast_type_from_column(col)
60
+ type.must_be_instance_of Type::Integer
61
+ type.limit.must_equal 4
62
+ assert_obj_set_and_save :int, -2_147_483_648
63
+ assert_obj_set_and_save :int, 2_147_483_647
64
+ end
65
+
66
+ it 'smallint(2)' do
67
+ col = column('smallint')
68
+ col.sql_type.must_equal 'smallint(2)'
69
+ col.type.must_equal :integer
70
+ col.null.must_equal true
71
+ col.default.must_equal 42
72
+ obj.smallint.must_equal 42
73
+ col.default_function.must_be_nil
74
+ type = connection.lookup_cast_type_from_column(col)
75
+ type.must_be_instance_of Type::SmallInteger
76
+ type.limit.must_equal 2
77
+ assert_obj_set_and_save :smallint, -32_768
78
+ assert_obj_set_and_save :smallint, 32_767
79
+ end
80
+
81
+ it 'tinyint(1)' do
82
+ col = column('tinyint')
83
+ col.sql_type.must_equal 'tinyint(1)'
84
+ col.type.must_equal :integer
85
+ col.null.must_equal true
86
+ col.default.must_equal 42
87
+ obj.tinyint.must_equal 42
88
+ col.default_function.must_be_nil
89
+ type = connection.lookup_cast_type_from_column(col)
90
+ type.must_be_instance_of Type::TinyInteger
91
+ type.limit.must_equal 1
92
+ assert_obj_set_and_save :tinyint, 0
93
+ assert_obj_set_and_save :tinyint, 255
94
+ end
95
+
96
+ it 'bit' do
97
+ col = column('bit')
98
+ col.sql_type.must_equal 'bit'
99
+ col.type.must_equal :boolean
100
+ col.null.must_equal true
101
+ col.default.must_equal true
102
+ obj.bit.must_equal true
103
+ col.default_function.must_be_nil
104
+ type = connection.lookup_cast_type_from_column(col)
105
+ type.must_be_instance_of Type::Boolean
106
+ type.limit.must_be_nil
107
+ obj.bit = 0
108
+ obj.bit.must_equal false
109
+ obj.save!
110
+ obj.reload.bit.must_equal false
111
+ obj.bit = '1'
112
+ obj.bit.must_equal true
113
+ obj.save!
114
+ obj.reload.bit.must_equal true
115
+ end
116
+
117
+ it 'decimal(9,2)' do
118
+ col = column('decimal_9_2')
119
+ col.sql_type.must_equal 'decimal(9,2)'
120
+ col.type.must_equal :decimal
121
+ col.null.must_equal true
122
+ col.default.must_equal BigDecimal('12345.01')
123
+ obj.decimal_9_2.must_equal BigDecimal('12345.01')
124
+ col.default_function.must_be_nil
125
+ type = connection.lookup_cast_type_from_column(col)
126
+ type.must_be_instance_of Type::Decimal
127
+ type.limit.must_be_nil
128
+ type.precision.must_equal 9
129
+ type.scale.must_equal 2
130
+ obj.decimal_9_2 = '1234567.8901'
131
+ obj.decimal_9_2.must_equal BigDecimal('1234567.89')
132
+ obj.save!
133
+ obj.reload.decimal_9_2.must_equal BigDecimal('1234567.89')
134
+ end
135
+
136
+ it 'decimal(16,4)' do
137
+ col = column('decimal_16_4')
138
+ col.sql_type.must_equal 'decimal(16,4)'
139
+ col.default.must_equal BigDecimal('1234567.89')
140
+ obj.decimal_16_4.must_equal BigDecimal('1234567.89')
141
+ col.default_function.must_be_nil
142
+ type = connection.lookup_cast_type_from_column(col)
143
+ type.precision.must_equal 16
144
+ type.scale.must_equal 4
145
+ obj.decimal_16_4 = '1234567.8901001'
146
+ obj.decimal_16_4.must_equal BigDecimal('1234567.8901')
147
+ obj.save!
148
+ obj.reload.decimal_16_4.must_equal BigDecimal('1234567.8901')
149
+ end
150
+
151
+ it 'numeric(18,0)' do
152
+ col = column('numeric_18_0')
153
+ col.sql_type.must_equal 'numeric(18,0)'
154
+ col.type.must_equal :decimal
155
+ col.null.must_equal true
156
+ col.default.must_equal BigDecimal('191')
157
+ obj.numeric_18_0.must_equal BigDecimal('191')
158
+ col.default_function.must_be_nil
159
+ type = connection.lookup_cast_type_from_column(col)
160
+ type.must_be_instance_of Type::Decimal
161
+ type.limit.must_be_nil
162
+ type.precision.must_equal 18
163
+ type.scale.must_equal 0
164
+ obj.numeric_18_0 = '192.1'
165
+ obj.numeric_18_0.must_equal BigDecimal('192')
166
+ obj.save!
167
+ obj.reload.numeric_18_0.must_equal BigDecimal('192')
168
+ end
169
+
170
+ it 'numeric(36,2)' do
171
+ col = column('numeric_36_2')
172
+ col.sql_type.must_equal 'numeric(36,2)'
173
+ col.type.must_equal :decimal
174
+ col.null.must_equal true
175
+ col.default.must_equal BigDecimal('12345678901234567890.01')
176
+ obj.numeric_36_2.must_equal BigDecimal('12345678901234567890.01')
177
+ col.default_function.must_be_nil
178
+ type = connection.lookup_cast_type_from_column(col)
179
+ type.must_be_instance_of Type::Decimal
180
+ type.limit.must_be_nil
181
+ type.precision.must_equal 36
182
+ type.scale.must_equal 2
183
+ obj.numeric_36_2 = '192.123'
184
+ obj.numeric_36_2.must_equal BigDecimal('192.12')
185
+ obj.save!
186
+ obj.reload.numeric_36_2.must_equal BigDecimal('192.12')
187
+ end
188
+
189
+ it 'money' do
190
+ col = column('money')
191
+ col.sql_type.must_equal 'money'
192
+ col.type.must_equal :money
193
+ col.null.must_equal true
194
+ col.default.must_equal BigDecimal('4.20')
195
+ obj.money.must_equal BigDecimal('4.20')
196
+ col.default_function.must_be_nil
197
+ type = connection.lookup_cast_type_from_column(col)
198
+ type.must_be_instance_of Type::Money
199
+ type.limit.must_be_nil
200
+ type.precision.must_equal 19
201
+ type.scale.must_equal 4
202
+ obj.money = '922337203685477.58061'
203
+ obj.money.must_equal BigDecimal('922337203685477.5806')
204
+ obj.save!
205
+ obj.reload.money.must_equal BigDecimal('922337203685477.5806')
206
+ end
207
+
208
+ it 'smallmoney' do
209
+ col = column('smallmoney')
210
+ col.sql_type.must_equal 'smallmoney'
211
+ col.type.must_equal :smallmoney
212
+ col.null.must_equal true
213
+ col.default.must_equal BigDecimal('4.20')
214
+ obj.smallmoney.must_equal BigDecimal('4.20')
215
+ col.default_function.must_be_nil
216
+ type = connection.lookup_cast_type_from_column(col)
217
+ type.must_be_instance_of Type::SmallMoney
218
+ type.limit.must_be_nil
219
+ type.precision.must_equal 10
220
+ type.scale.must_equal 4
221
+ obj.smallmoney = '214748.36461'
222
+ obj.smallmoney.must_equal BigDecimal('214748.3646')
223
+ obj.save!
224
+ obj.reload.smallmoney.must_equal BigDecimal('214748.3646')
225
+ end
226
+
227
+ # Approximate Numerics
228
+ # Float limits are adjusted to 24 or 53 by the database as per http://msdn.microsoft.com/en-us/library/ms173773.aspx
229
+ # Floats with a limit of <= 24 are reduced to reals by sqlserver on creation.
230
+
231
+ it 'float' do
232
+ col = column('float')
233
+ col.sql_type.must_equal 'float'
234
+ col.type.must_equal :float
235
+ col.null.must_equal true
236
+ col.default.must_equal 123.00000001
237
+ obj.float.must_equal 123.00000001
238
+ col.default_function.must_be_nil
239
+ type = connection.lookup_cast_type_from_column(col)
240
+ type.must_be_instance_of Type::Float
241
+ type.limit.must_be_nil
242
+ type.precision.must_be_nil
243
+ type.scale.must_be_nil
244
+ obj.float = '214748.36461'
245
+ obj.float.must_equal 214748.36461
246
+ obj.save!
247
+ obj.reload.float.must_equal 214748.36461
248
+ end
249
+
250
+ it 'real' do
251
+ col = column('real')
252
+ col.sql_type.must_equal 'real'
253
+ col.type.must_equal :real
254
+ col.null.must_equal true
255
+ col.default.must_be_close_to 123.45, 0.01
256
+ obj.real.must_be_close_to 123.45, 0.01
257
+ col.default_function.must_be_nil
258
+ type = connection.lookup_cast_type_from_column(col)
259
+ type.must_be_instance_of Type::Real
260
+ type.limit.must_be_nil
261
+ type.precision.must_be_nil
262
+ type.scale.must_be_nil
263
+ obj.real = '214748.36461'
264
+ obj.real.must_be_close_to 214748.36461, 0.01
265
+ obj.save!
266
+ obj.reload.real.must_be_close_to 214748.36461, 0.01
267
+ end
268
+
269
+ # Date and Time
270
+
271
+ it 'date' do
272
+ col = column('date')
273
+ col.sql_type.must_equal 'date'
274
+ col.type.must_equal :date
275
+ col.null.must_equal true
276
+ col.default.must_equal connection_dblib_73? ? Date.civil(0001, 1, 1) : '0001-01-01'
277
+ obj.date.must_equal Date.civil(0001, 1, 1)
278
+ col.default_function.must_be_nil
279
+ type = connection.lookup_cast_type_from_column(col)
280
+ type.must_be_instance_of Type::Date
281
+ type.limit.must_be_nil
282
+ type.precision.must_be_nil
283
+ type.scale.must_be_nil
284
+ # Can cast strings. SQL Server format.
285
+ obj.date = '04-01-0001'
286
+ obj.date.must_equal Date.civil(0001, 4, 1)
287
+ obj.save!
288
+ obj.date.must_equal Date.civil(0001, 4, 1)
289
+ obj.reload
290
+ obj.date.must_equal Date.civil(0001, 4, 1)
291
+ # Can cast strings. ISO format.
292
+ obj.date = '0001-04-01'
293
+ obj.date.must_equal Date.civil(0001, 4, 1)
294
+ obj.save!
295
+ obj.date.must_equal Date.civil(0001, 4, 1)
296
+ obj.reload
297
+ obj.date.must_equal Date.civil(0001, 4, 1)
298
+ # Can keep and return assigned date.
299
+ assert_obj_set_and_save :date, Date.civil(1972, 04, 14)
300
+ # Can accept and cast time objects.
301
+ obj.date = Time.utc(2010, 4, 14, 12, 34, 56, 3000)
302
+ obj.date.must_equal Date.civil(2010, 4, 14)
303
+ obj.save!
304
+ obj.reload.date.must_equal Date.civil(2010, 4, 14)
305
+ end
306
+
307
+ it 'datetime' do
308
+ col = column('datetime')
309
+ col.sql_type.must_equal 'datetime'
310
+ col.type.must_equal :datetime
311
+ col.null.must_equal true
312
+ time = Time.utc 1753, 01, 01, 00, 00, 00, 123000
313
+ col.default.must_equal time, "Microseconds were <#{col.default.usec}> vs <123000>"
314
+ obj.datetime.must_equal time, "Microseconds were <#{obj.datetime.usec}> vs <123000>"
315
+ col.default_function.must_be_nil
316
+ type = connection.lookup_cast_type_from_column(col)
317
+ type.must_be_instance_of Type::DateTime
318
+ type.limit.must_be_nil
319
+ type.precision.must_be_nil
320
+ type.scale.must_be_nil
321
+ obj.save!
322
+ #obj.must_equal obj.class.where(datetime: time).first <-------------------------------------------- All versions of this break, maybe an issue with prepared statements setting it correctly?
323
+ # Can save to proper accuracy and return again.
324
+ time = Time.utc 2010, 04, 01, 12, 34, 56, 3000
325
+ obj.datetime = time
326
+ obj.datetime.must_equal time, "Microseconds were <#{obj.datetime.usec}> vs <3000>"
327
+ obj.save!
328
+ obj.datetime.must_equal time, "Microseconds were <#{obj.datetime.usec}> vs <3000>"
329
+ obj.reload
330
+ obj.datetime.must_equal time, "Microseconds were <#{obj.datetime.usec}> vs <3000>"
331
+ #obj.must_equal obj.class.where(datetime: time).first
332
+ # Will cast to true DB value on attribute write, save and return again.
333
+ time = Time.utc 2010, 04, 01, 12, 34, 56, 234567
334
+ time2 = Time.utc 2010, 04, 01, 12, 34, 56, 233000
335
+ obj.datetime = time
336
+ obj.datetime.must_equal time2, "Microseconds were <#{obj.datetime.usec}> vs <233000>"
337
+ obj.save!
338
+ obj.datetime.must_equal time2, "Microseconds were <#{obj.datetime.usec}> vs <233000>"
339
+ obj.reload
340
+ obj.datetime.must_equal time2, "Microseconds were <#{obj.datetime.usec}> vs <233000>"
341
+ #obj.must_equal obj.class.where(datetime: time).first
342
+ #obj.must_equal obj.class.where(datetime: time2).first
343
+ # Set and find nil.
344
+ obj.datetime = nil
345
+ obj.datetime.must_be_nil
346
+ obj.save!
347
+ obj.datetime.must_be_nil
348
+ #obj.must_equal obj.class.where(datetime: nil).first
349
+ end
350
+
351
+ it 'datetime2' do
352
+ skip 'datetime2 not supported in this protocal version' unless connection_dblib_73?
353
+ col = column('datetime2_7')
354
+ col.sql_type.must_equal 'datetime2(7)'
355
+ col.type.must_equal :datetime
356
+ col.null.must_equal true
357
+ time = Time.utc 9999, 12, 31, 23, 59, 59, Rational(999999900, 1000)
358
+ col.default.must_equal time, "Nanoseconds were <#{col.default.nsec}> vs <999999900>"
359
+ obj.datetime2_7.must_equal time, "Nanoseconds were <#{obj.datetime2_7.nsec}> vs <999999900>"
360
+ col.default_function.must_be_nil
361
+ type = connection.lookup_cast_type_from_column(col)
362
+ type.must_be_instance_of Type::DateTime2
363
+ type.limit.must_be_nil
364
+ type.precision.must_equal 7
365
+ type.scale.must_be_nil
366
+ obj.save!
367
+ obj.must_equal obj.class.where(datetime2_7: time).first
368
+ # Can save 100 nanosecond precisoins and return again.
369
+ time = Time.utc 9999, 12, 31, 23, 59, 59, Rational(123456755, 1000)
370
+ time2 = Time.utc 9999, 12, 31, 23, 59, 59, Rational(123456700, 1000) # This test is actually wrong because rails specifies that it should truncate and this test tests that it rounds
371
+ obj.datetime2_7 = time
372
+ obj.datetime2_7.must_equal time2, "Nanoseconds were <#{obj.datetime2_7.nsec}> vs <123456700>"
373
+ obj.save!
374
+ obj.datetime2_7.must_equal time2, "Nanoseconds were <#{obj.datetime2_7.nsec}> vs <123456700>"
375
+ obj.reload
376
+ obj.datetime2_7.must_equal time2, "Nanoseconds were <#{obj.datetime2_7.nsec}> vs <123456700>"
377
+ obj.must_equal obj.class.where(datetime2_7: time).first
378
+ obj.must_equal obj.class.where(datetime2_7: time2).first
379
+ # Can save small fraction nanosecond precisoins and return again.
380
+ time = Time.utc 2008, 6, 21, 13, 30, 0, Rational(15020, 1000)
381
+ time2 = Time.utc 2008, 6, 21, 13, 30, 0, Rational(15000, 1000)
382
+ obj.datetime2_7 = time
383
+ obj.datetime2_7.must_equal time2, "Nanoseconds were <#{obj.datetime2_7.nsec}> vs <15000>"
384
+ obj.save!
385
+ obj.reload.datetime2_7.must_equal time2, "Nanoseconds were <#{obj.datetime2_7.nsec}> vs <15000>"
386
+ obj.must_equal obj.class.where(datetime2_7: time).first
387
+ obj.must_equal obj.class.where(datetime2_7: time2).first
388
+ # datetime2_3
389
+ time = Time.utc 9999, 12, 31, 23, 59, 59, Rational(123456789, 1000)
390
+ col = column('datetime2_3')
391
+ connection.lookup_cast_type_from_column(col).precision.must_equal 3
392
+ obj.datetime2_3 = time
393
+ obj.datetime2_3.must_equal time.change(nsec: 123000000), "Nanoseconds were <#{obj.datetime2_3.nsec}> vs <123000000>"
394
+ obj.save! ; obj.reload
395
+ obj.datetime2_3.must_equal time.change(nsec: 123000000), "Nanoseconds were <#{obj.datetime2_3.nsec}> vs <123000000>"
396
+ obj.must_equal obj.class.where(datetime2_3: time).first
397
+ # datetime2_1
398
+ col = column('datetime2_1')
399
+ connection.lookup_cast_type_from_column(col).precision.must_equal 1
400
+ obj.datetime2_1 = time
401
+ obj.datetime2_1.must_equal time.change(nsec: 100000000), "Nanoseconds were <#{obj.datetime2_1.nsec}> vs <100000000>"
402
+ obj.save! ; obj.reload
403
+ obj.datetime2_1.must_equal time.change(nsec: 100000000), "Nanoseconds were <#{obj.datetime2_1.nsec}> vs <100000000>"
404
+ obj.must_equal obj.class.where(datetime2_1: time).first
405
+ # datetime2_0
406
+ col = column('datetime2_0')
407
+ connection.lookup_cast_type_from_column(col).precision.must_equal 0
408
+ time = Time.utc 2016, 4, 19, 16, 45, 40, 771036
409
+ obj.datetime2_0 = time
410
+ obj.datetime2_0.must_equal time.change(nsec: 0), "Nanoseconds were <#{obj.datetime2_0.nsec}> vs <0>"
411
+ obj.save! ; obj.reload
412
+ obj.datetime2_0.must_equal time.change(nsec: 0), "Nanoseconds were <#{obj.datetime2_0.nsec}> vs <0>"
413
+ obj.must_equal obj.class.where(datetime2_0: time).first
414
+ end
415
+
416
+ it 'datetimeoffset' do
417
+ skip 'datetimeoffset not supported in this protocal version' unless connection_dblib_73?
418
+ col = column('datetimeoffset_7')
419
+ col.sql_type.must_equal 'datetimeoffset(7)'
420
+ col.type.must_equal :datetimeoffset
421
+ col.null.must_equal true
422
+ time = Time.new(1984, 01, 24, 04, 20, 00, -28800).change(nsec: 123456700)
423
+ col.default.must_equal time, "Nanoseconds <#{col.default.nsec}> vs <123456700>"
424
+ obj.datetimeoffset_7.must_equal time, "Nanoseconds were <#{obj.datetimeoffset_7.nsec}> vs <999999900>"
425
+ col.default_function.must_be_nil
426
+ type = connection.lookup_cast_type_from_column(col)
427
+ type.must_be_instance_of Type::DateTimeOffset
428
+ type.limit.must_be_nil
429
+ type.precision.must_equal 7
430
+ type.scale.must_be_nil
431
+ obj.save!
432
+ obj.must_equal obj.class.where(datetimeoffset_7: time).first
433
+ # Can save 100 nanosecond precisoins and return again.
434
+ time = Time.new(2010, 04, 01, 12, 34, 56, +18000).change(nsec: 123456700)
435
+ obj.datetimeoffset_7 = Time.new(2010, 04, 01, 12, 34, 56, +18000).change(nsec: 123456755)
436
+ obj.datetimeoffset_7.must_equal time, "Nanoseconds were <#{obj.datetimeoffset_7.nsec}> vs <123456700>" # Was rounding instead of truncating
437
+ obj.save!
438
+ obj.datetimeoffset_7.must_equal time, "Nanoseconds were <#{obj.datetimeoffset_7.nsec}> vs <123456700>"
439
+ obj.reload
440
+ obj.datetimeoffset_7.must_equal time, "Nanoseconds were <#{obj.datetimeoffset_7.nsec}> vs <123456700>"
441
+ obj.must_equal obj.class.where(datetimeoffset_7: time).first
442
+ # Maintains the timezone
443
+ time = ActiveSupport::TimeZone['America/Los_Angeles'].local 2010, 12, 31, 23, 59, 59, Rational(123456700, 1000)
444
+ obj.datetimeoffset_7 = time
445
+ obj.datetimeoffset_7.must_equal time
446
+ obj.save!
447
+ obj.datetimeoffset_7.must_equal time
448
+ obj.reload.datetimeoffset_7.must_equal time
449
+ obj.must_equal obj.class.where(datetimeoffset_7: time).first
450
+ # With other precisions.
451
+ time = ActiveSupport::TimeZone['America/Los_Angeles'].local 2010, 12, 31, 23, 59, 59, Rational(123456755, 1000)
452
+ col = column('datetimeoffset_3')
453
+ connection.lookup_cast_type_from_column(col).precision.must_equal 3
454
+ obj.datetimeoffset_3 = time
455
+ obj.datetimeoffset_3.must_equal time.change(nsec: 123000000), "Nanoseconds were <#{obj.datetimeoffset_3.nsec}> vs <123000000>"
456
+ obj.save!
457
+ obj.datetimeoffset_3.must_equal time.change(nsec: 123000000), "Nanoseconds were <#{obj.datetimeoffset_3.nsec}> vs <123000000>"
458
+ col = column('datetime2_1')
459
+ connection.lookup_cast_type_from_column(col).precision.must_equal 1
460
+ obj.datetime2_1 = time
461
+ obj.datetime2_1.must_equal time.change(nsec: 100000000), "Nanoseconds were <#{obj.datetime2_1.nsec}> vs <100000000>"
462
+ obj.save!
463
+ obj.datetime2_1.must_equal time.change(nsec: 100000000), "Nanoseconds were <#{obj.datetime2_1.nsec}> vs <100000000>"
464
+ end
465
+
466
+ it 'smalldatetime' do
467
+ col = column('smalldatetime')
468
+ col.sql_type.must_equal 'smalldatetime'
469
+ col.type.must_equal :smalldatetime
470
+ col.null.must_equal true
471
+ time = Time.utc(1901, 01, 01, 15, 45, 00, 000)
472
+ col.default.must_equal time
473
+ obj.smalldatetime.must_equal time
474
+ col.default_function.must_be_nil
475
+ type = connection.lookup_cast_type_from_column(col)
476
+ type.must_be_instance_of Type::SmallDateTime
477
+ type.limit.must_be_nil
478
+ type.precision.must_be_nil
479
+ type.scale.must_be_nil
480
+ obj.save!
481
+ obj.must_equal obj.class.where(smalldatetime: time).first
482
+ # Will remove fractional seconds and return again.
483
+ obj.smalldatetime = Time.utc(2078, 06, 05, 4, 20, 00, 3000)
484
+ obj.smalldatetime.must_equal Time.utc(2078, 06, 05, 4, 20, 00, 0), "Microseconds were <#{obj.smalldatetime.usec}> vs <0>"
485
+ obj.save!
486
+ obj.smalldatetime.must_equal Time.utc(2078, 06, 05, 4, 20, 00, 0), "Microseconds were <#{obj.reload.smalldatetime.usec}> vs <0>"
487
+ obj.reload
488
+ obj.smalldatetime.must_equal Time.utc(2078, 06, 05, 4, 20, 00, 0), "Microseconds were <#{obj.reload.smalldatetime.usec}> vs <0>"
489
+ end
490
+
491
+ it 'time(7)' do
492
+ skip 'time() not supported in this protocal version' unless connection_dblib_73?
493
+ col = column('time_7')
494
+ col.sql_type.must_equal 'time(7)'
495
+ col.type.must_equal :time
496
+ col.null.must_equal true
497
+ col.default.must_equal Time.utc(1900, 01, 01, 04, 20, 00, Rational(288321500, 1000)), "Nanoseconds were <#{col.default.nsec}> vs <288321500>"
498
+ col.default_function.must_be_nil
499
+ type = connection.lookup_cast_type_from_column(col)
500
+ type.must_be_instance_of Type::Time
501
+ type.limit.must_be_nil
502
+ type.precision.must_equal 7
503
+ type.scale.must_be_nil
504
+ # Time's #usec precision (low micro)
505
+ obj.time_7 = Time.utc(2000, 01, 01, 15, 45, 00, 300)
506
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 300), "Microseconds were <#{obj.time_7.usec}> vs <0>"
507
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 300), "Nanoseconds were <#{obj.time_7.nsec}> vs <300>"
508
+ obj.save! ; obj.reload
509
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 300), "Microseconds were <#{obj.time_7.usec}> vs <0>"
510
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 300), "Nanoseconds were <#{obj.time_7.nsec}> vs <300>"
511
+ # Time's #usec precision (high micro)
512
+ obj.time_7 = Time.utc(2000, 01, 01, 15, 45, 00, 234567)
513
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 234567), "Microseconds were <#{obj.time_7.usec}> vs <234567>"
514
+ obj.save! ; obj.reload
515
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 234567), "Microseconds were <#{obj.time_7.usec}> vs <234567>"
516
+ # Time's #usec precision (high nano rounded)
517
+ obj.time_7 = Time.utc(2000, 01, 01, 15, 45, 00, Rational(288321545, 1000))
518
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, Rational(288321500, 1000)), "Nanoseconds were <#{obj.time_7.nsec}> vs <288321500>"
519
+ obj.save! ; obj.reload
520
+ obj.time_7.must_equal Time.utc(2000, 01, 01, 15, 45, 00, Rational(288321500, 1000)), "Nanoseconds were <#{obj.time_7.nsec}> vs <288321500>"
521
+ end
522
+
523
+ it 'time(2)' do
524
+ skip 'time() not supported in this protocal version' unless connection_dblib_73?
525
+ col = column('time_2')
526
+ col.sql_type.must_equal 'time(2)'
527
+ col.type.must_equal :time
528
+ col.null.must_equal true
529
+ col.default.must_be_nil
530
+ col.default_function.must_be_nil
531
+ type = connection.lookup_cast_type_from_column(col)
532
+ type.must_be_instance_of Type::Time
533
+ type.limit.must_be_nil
534
+ type.precision.must_equal 2
535
+ type.scale.must_be_nil
536
+ # Always uses TinyTDS/Windows 2000-01-01 convention too.
537
+ obj.time_2 = Time.utc(2015, 01, 10, 15, 45, 00, 0)
538
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0)
539
+ obj.save! ; obj.reload
540
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0)
541
+ # Time's #usec precision (barely in 2 precision equal to 0.03 seconds)
542
+ obj.time_2 = Time.utc(2000, 01, 01, 15, 45, 00, 30000)
543
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 30000), "Microseconds were <#{obj.time_2.usec}> vs <30000>"
544
+ obj.save! ; obj.reload
545
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 30000), "Microseconds were <#{obj.time_2.usec}> vs <30000>"
546
+ # Time's #usec precision (below 2 precision)
547
+ obj.time_2 = Time.utc(2000, 01, 01, 15, 45, 00, 4000)
548
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0), "Microseconds were <#{obj.time_2.usec}> vs <0>"
549
+ obj.save! ; obj.reload
550
+ obj.time_2.must_equal Time.utc(2000, 01, 01, 15, 45, 00, 0), "Microseconds were <#{obj.time_2.usec}> vs <0>"
551
+ end
552
+
553
+ # Character Strings
554
+
555
+ it 'char(10)' do
556
+ col = column('char_10')
557
+ col.sql_type.must_equal 'char(10)'
558
+ col.type.must_equal :char
559
+ col.null.must_equal true
560
+ col.default.must_equal '1234567890'
561
+ obj.char_10.must_equal '1234567890'
562
+ col.default_function.must_be_nil
563
+ type = connection.lookup_cast_type_from_column(col)
564
+ type.must_be_instance_of Type::Char
565
+ type.limit.must_equal 10
566
+ type.precision.must_be_nil
567
+ type.scale.must_be_nil
568
+ # Basic set and save.
569
+ obj.char_10 = '012345'
570
+ obj.char_10.strip.must_equal '012345'
571
+ obj.save!
572
+ obj.reload.char_10.strip.must_equal '012345'
573
+ end
574
+
575
+ it 'varchar(50)' do
576
+ col = column('varchar_50')
577
+ col.sql_type.must_equal 'varchar(50)'
578
+ col.type.must_equal :varchar
579
+ col.null.must_equal true
580
+ col.default.must_equal 'test varchar_50'
581
+ obj.varchar_50.must_equal 'test varchar_50'
582
+ col.default_function.must_be_nil
583
+ type = connection.lookup_cast_type_from_column(col)
584
+ type.must_be_instance_of Type::Varchar
585
+ type.limit.must_equal 50
586
+ type.precision.must_be_nil
587
+ type.scale.must_be_nil
588
+ # Basic set and save.
589
+ assert_obj_set_and_save :varchar_50, 'Hello World'
590
+ end
591
+
592
+ it 'varchar(max)' do
593
+ col = column('varchar_max')
594
+ col.sql_type.must_equal 'varchar(max)'
595
+ col.type.must_equal :varchar_max
596
+ col.null.must_equal true
597
+ col.default.must_equal 'test varchar_max'
598
+ obj.varchar_max.must_equal 'test varchar_max'
599
+ col.default_function.must_be_nil
600
+ type = connection.lookup_cast_type_from_column(col)
601
+ type.must_be_instance_of Type::VarcharMax
602
+ type.limit.must_equal 2_147_483_647
603
+ type.precision.must_be_nil
604
+ type.scale.must_be_nil
605
+ # Basic set and save.
606
+ assert_obj_set_and_save :varchar_max, 'Hello World'
607
+ end
608
+
609
+ it 'text' do
610
+ col = column('text')
611
+ col.sql_type.must_equal 'text'
612
+ col.type.must_equal :text_basic
613
+ col.null.must_equal true
614
+ col.default.must_equal 'test text'
615
+ obj.text.must_equal 'test text'
616
+ col.default_function.must_be_nil
617
+ type = connection.lookup_cast_type_from_column(col)
618
+ type.must_be_instance_of Type::Text
619
+ type.limit.must_equal 2_147_483_647
620
+ type.precision.must_be_nil
621
+ type.scale.must_be_nil
622
+ # Basic set and save.
623
+ assert_obj_set_and_save :text, 'Hello World'
624
+ end
625
+
626
+ # Unicode Character Strings
627
+
628
+ it 'nchar(10)' do
629
+ col = column('nchar_10')
630
+ col.sql_type.must_equal 'nchar(10)'
631
+ col.type.must_equal :nchar
632
+ col.null.must_equal true
633
+ col.default.must_equal '12345678åå'
634
+ obj.nchar_10.must_equal '12345678åå'
635
+ col.default_function.must_be_nil
636
+ type = connection.lookup_cast_type_from_column(col)
637
+ type.must_be_instance_of Type::UnicodeChar
638
+ type.limit.must_equal 10
639
+ type.precision.must_be_nil
640
+ type.scale.must_be_nil
641
+ # Basic set and save.
642
+ obj.nchar_10 = "五六"
643
+ obj.nchar_10.strip.must_equal "五六"
644
+ obj.save!
645
+ obj.reload.nchar_10.strip.must_equal "五六"
646
+ end
647
+
648
+ it 'nvarchar(50)' do
649
+ col = column('nvarchar_50')
650
+ col.sql_type.must_equal 'nvarchar(50)'
651
+ col.type.must_equal :string
652
+ col.null.must_equal true
653
+ col.default.must_equal 'test nvarchar_50 åå'
654
+ obj.nvarchar_50.must_equal 'test nvarchar_50 åå'
655
+ col.default_function.must_be_nil
656
+ type = connection.lookup_cast_type_from_column(col)
657
+ type.must_be_instance_of Type::UnicodeVarchar
658
+ type.limit.must_equal 50
659
+ type.precision.must_be_nil
660
+ type.scale.must_be_nil
661
+ # Basic set and save.
662
+ assert_obj_set_and_save :nvarchar_50, "一二34五六"
663
+ end
664
+
665
+ it 'nvarchar(max)' do
666
+ col = column('nvarchar_max')
667
+ col.sql_type.must_equal 'nvarchar(max)'
668
+ col.type.must_equal :text
669
+ col.null.must_equal true
670
+ col.default.must_equal 'test nvarchar_max åå'
671
+ obj.nvarchar_max.must_equal 'test nvarchar_max åå'
672
+ col.default_function.must_be_nil
673
+ type = connection.lookup_cast_type_from_column(col)
674
+ type.must_be_instance_of Type::UnicodeVarcharMax
675
+ type.limit.must_equal 2_147_483_647
676
+ type.precision.must_be_nil
677
+ type.scale.must_be_nil
678
+ # Basic set and save.
679
+ assert_obj_set_and_save :nvarchar_max, "一二34五六"
680
+ end
681
+
682
+ it 'ntext' do
683
+ col = column('ntext')
684
+ col.sql_type.must_equal 'ntext'
685
+ col.type.must_equal :ntext
686
+ col.null.must_equal true
687
+ col.default.must_equal 'test ntext åå'
688
+ obj.ntext.must_equal 'test ntext åå'
689
+ col.default_function.must_be_nil
690
+ type = connection.lookup_cast_type_from_column(col)
691
+ type.must_be_instance_of Type::UnicodeText
692
+ type.limit.must_equal 2_147_483_647
693
+ type.precision.must_be_nil
694
+ type.scale.must_be_nil
695
+ # Basic set and save.
696
+ assert_obj_set_and_save :ntext, "一二34五六"
697
+ end
698
+
699
+ # Binary Strings
700
+
701
+ let(:binary_file) { File.join ARTest::SQLServer.test_root_sqlserver, 'fixtures', '1px.gif' }
702
+ let(:binary_data) { File.open(binary_file, 'rb') { |f| f.read } }
703
+
704
+ it 'binary(49)' do
705
+ col = column('binary_49')
706
+ col.sql_type.must_equal 'binary(49)'
707
+ col.type.must_equal :binary_basic
708
+ col.null.must_equal true
709
+ col.default.must_be_nil
710
+ col.default_function.must_be_nil
711
+ type = connection.lookup_cast_type_from_column(col)
712
+ type.must_be_instance_of Type::Binary
713
+ type.limit.must_equal 49
714
+ type.precision.must_be_nil
715
+ type.scale.must_be_nil
716
+ # Basic set and save.
717
+ binary_data.encoding.must_equal Encoding::BINARY
718
+ binary_data.length.must_equal 49
719
+ obj.binary_49 = binary_data
720
+ obj.binary_49.must_equal binary_data
721
+ obj.save!
722
+ obj.reload.binary_49.must_equal binary_data
723
+ end
724
+
725
+ it 'varbinary(49)' do
726
+ col = column('varbinary_49')
727
+ col.sql_type.must_equal 'varbinary(49)'
728
+ col.type.must_equal :varbinary
729
+ col.null.must_equal true
730
+ col.default.must_be_nil
731
+ col.default_function.must_be_nil
732
+ type = connection.lookup_cast_type_from_column(col)
733
+ type.must_be_instance_of Type::Varbinary
734
+ type.limit.must_equal 49
735
+ type.precision.must_be_nil
736
+ type.scale.must_be_nil
737
+ # Basic set and save.
738
+ binary_data_20 = binary_data.to(20)
739
+ binary_data_20.encoding.must_equal Encoding::BINARY
740
+ obj.varbinary_49 = binary_data_20
741
+ obj.varbinary_49.must_equal binary_data_20
742
+ obj.save!
743
+ obj.reload.varbinary_49.must_equal binary_data_20
744
+ end
745
+
746
+ it 'varbinary(max)' do
747
+ col = column('varbinary_max')
748
+ col.sql_type.must_equal 'varbinary(max)'
749
+ col.type.must_equal :binary
750
+ col.null.must_equal true
751
+ col.default.must_be_nil
752
+ col.default_function.must_be_nil
753
+ type = connection.lookup_cast_type_from_column(col)
754
+ type.must_be_instance_of Type::VarbinaryMax
755
+ type.limit.must_equal 2_147_483_647
756
+ type.precision.must_be_nil
757
+ type.scale.must_be_nil
758
+ # Basic set and save.
759
+ binary_data.encoding.must_equal Encoding::BINARY
760
+ assert_obj_set_and_save :varbinary_max, binary_data
761
+ end
762
+
763
+ # Other Data Types
764
+
765
+ it 'uniqueidentifier' do
766
+ col = column('uniqueidentifier')
767
+ col.sql_type.must_equal 'uniqueidentifier'
768
+ col.type.must_equal :uuid
769
+ col.null.must_equal true
770
+ col.default.must_be_nil
771
+ col.default_function.must_equal 'newid()'
772
+ type = connection.lookup_cast_type_from_column(col)
773
+ type.must_be_instance_of Type::Uuid
774
+ type.limit.must_be_nil
775
+ type.precision.must_be_nil
776
+ type.scale.must_be_nil
777
+ # Basic set and save.
778
+ obj.uniqueidentifier = "this will not qualify as valid"
779
+ obj.uniqueidentifier.must_be_nil
780
+ obj.save! ; obj.reload
781
+ obj.uniqueidentifier.must_match Type::Uuid::ACCEPTABLE_UUID
782
+ obj.uniqueidentifier = "6F9619FF-8B86-D011-B42D-00C04FC964FF"
783
+ obj.uniqueidentifier.must_equal "6F9619FF-8B86-D011-B42D-00C04FC964FF"
784
+ obj.save! ; obj.reload
785
+ obj.uniqueidentifier.must_equal "6F9619FF-8B86-D011-B42D-00C04FC964FF"
786
+ end
787
+
788
+ it 'timestamp' do
789
+ col = column('timestamp')
790
+ col.sql_type.must_equal 'timestamp'
791
+ col.type.must_equal :ss_timestamp
792
+ col.null.must_equal true
793
+ col.default.must_be_nil
794
+ col.default_function.must_be_nil
795
+ type = connection.lookup_cast_type_from_column(col)
796
+ type.must_be_instance_of Type::Timestamp
797
+ type.limit.must_be_nil
798
+ type.precision.must_be_nil
799
+ type.scale.must_be_nil
800
+ # Basic read.
801
+ obj.timestamp.must_be_nil
802
+ obj.save! ; obj.reload
803
+ obj.timestamp.must_match %r|\000|
804
+ obj.timestamp
805
+ # Can set another attribute
806
+ obj.uniqueidentifier = "6F9619FF-8B86-D011-B42D-00C04FC964FF"
807
+ obj.save!
808
+ end
809
+
810
+ end
811
+
812
+ end