activerecord-sqlserver-adapter_new 4.2.15

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 (132) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/CHANGELOG.md +212 -0
  4. data/CODE_OF_CONDUCT.md +31 -0
  5. data/Gemfile +61 -0
  6. data/Guardfile +29 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +201 -0
  9. data/RUNNING_UNIT_TESTS.md +121 -0
  10. data/Rakefile +48 -0
  11. data/VERSION +1 -0
  12. data/activerecord-sqlserver-adapter_new.gemspec +20 -0
  13. data/appveyor.yml +39 -0
  14. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +27 -0
  15. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +25 -0
  16. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +40 -0
  17. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +4 -0
  18. data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +34 -0
  19. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +49 -0
  20. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +386 -0
  21. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +68 -0
  22. data/lib/active_record/connection_adapters/sqlserver/errors.rb +7 -0
  23. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +69 -0
  24. data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +114 -0
  25. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +52 -0
  26. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +473 -0
  27. data/lib/active_record/connection_adapters/sqlserver/showplan.rb +66 -0
  28. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +66 -0
  29. data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +22 -0
  30. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +76 -0
  31. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +57 -0
  32. data/lib/active_record/connection_adapters/sqlserver/type.rb +46 -0
  33. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +15 -0
  34. data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +15 -0
  35. data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +12 -0
  36. data/lib/active_record/connection_adapters/sqlserver/type/char.rb +38 -0
  37. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +21 -0
  38. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +41 -0
  39. data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +17 -0
  40. data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +31 -0
  41. data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +12 -0
  42. data/lib/active_record/connection_adapters/sqlserver/type/float.rb +15 -0
  43. data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +12 -0
  44. data/lib/active_record/connection_adapters/sqlserver/type/money.rb +21 -0
  45. data/lib/active_record/connection_adapters/sqlserver/type/real.rb +15 -0
  46. data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +13 -0
  47. data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +21 -0
  48. data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +22 -0
  49. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +12 -0
  50. data/lib/active_record/connection_adapters/sqlserver/type/text.rb +15 -0
  51. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +40 -0
  52. data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +76 -0
  53. data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +15 -0
  54. data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +22 -0
  55. data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +15 -0
  56. data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +12 -0
  57. data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +15 -0
  58. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +20 -0
  59. data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +20 -0
  60. data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +23 -0
  61. data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +20 -0
  62. data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +20 -0
  63. data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +20 -0
  64. data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +20 -0
  65. data/lib/active_record/connection_adapters/sqlserver/utils.rb +136 -0
  66. data/lib/active_record/connection_adapters/sqlserver/version.rb +11 -0
  67. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +405 -0
  68. data/lib/active_record/connection_adapters/sqlserver_column.rb +53 -0
  69. data/lib/active_record/sqlserver_base.rb +20 -0
  70. data/lib/active_record/tasks/sqlserver_database_tasks.rb +131 -0
  71. data/lib/activerecord-sqlserver-adapter.rb +1 -0
  72. data/lib/arel/visitors/sqlserver.rb +214 -0
  73. data/lib/arel_sqlserver.rb +3 -0
  74. data/test/appveyor/dbsetup.ps1 +27 -0
  75. data/test/appveyor/dbsetup.sql +11 -0
  76. data/test/cases/adapter_test_sqlserver.rb +444 -0
  77. data/test/cases/coerced_tests.rb +713 -0
  78. data/test/cases/column_test_sqlserver.rb +780 -0
  79. data/test/cases/connection_test_sqlserver.rb +142 -0
  80. data/test/cases/execute_procedure_test_sqlserver.rb +44 -0
  81. data/test/cases/fetch_test_sqlserver.rb +57 -0
  82. data/test/cases/fully_qualified_identifier_test_sqlserver.rb +76 -0
  83. data/test/cases/helper_sqlserver.rb +54 -0
  84. data/test/cases/migration_test_sqlserver.rb +61 -0
  85. data/test/cases/order_test_sqlserver.rb +147 -0
  86. data/test/cases/pessimistic_locking_test_sqlserver.rb +90 -0
  87. data/test/cases/rake_test_sqlserver.rb +163 -0
  88. data/test/cases/schema_dumper_test_sqlserver.rb +198 -0
  89. data/test/cases/schema_test_sqlserver.rb +54 -0
  90. data/test/cases/scratchpad_test_sqlserver.rb +9 -0
  91. data/test/cases/showplan_test_sqlserver.rb +65 -0
  92. data/test/cases/specific_schema_test_sqlserver.rb +167 -0
  93. data/test/cases/transaction_test_sqlserver.rb +66 -0
  94. data/test/cases/utils_test_sqlserver.rb +129 -0
  95. data/test/cases/uuid_test_sqlserver.rb +48 -0
  96. data/test/config.yml +41 -0
  97. data/test/debug.rb +14 -0
  98. data/test/fixtures/1px.gif +0 -0
  99. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +11 -0
  100. data/test/models/sqlserver/booking.rb +3 -0
  101. data/test/models/sqlserver/customers_view.rb +3 -0
  102. data/test/models/sqlserver/datatype.rb +3 -0
  103. data/test/models/sqlserver/datatype_migration.rb +3 -0
  104. data/test/models/sqlserver/dollar_table_name.rb +3 -0
  105. data/test/models/sqlserver/dot_table_name.rb +3 -0
  106. data/test/models/sqlserver/edge_schema.rb +13 -0
  107. data/test/models/sqlserver/fk_has_fk.rb +3 -0
  108. data/test/models/sqlserver/fk_has_pk.rb +3 -0
  109. data/test/models/sqlserver/natural_pk_data.rb +4 -0
  110. data/test/models/sqlserver/natural_pk_int_data.rb +3 -0
  111. data/test/models/sqlserver/no_pk_data.rb +3 -0
  112. data/test/models/sqlserver/object_default.rb +3 -0
  113. data/test/models/sqlserver/quoted_table.rb +7 -0
  114. data/test/models/sqlserver/quoted_view_1.rb +3 -0
  115. data/test/models/sqlserver/quoted_view_2.rb +3 -0
  116. data/test/models/sqlserver/string_default.rb +3 -0
  117. data/test/models/sqlserver/string_defaults_big_view.rb +3 -0
  118. data/test/models/sqlserver/string_defaults_view.rb +3 -0
  119. data/test/models/sqlserver/tinyint_pk.rb +3 -0
  120. data/test/models/sqlserver/upper.rb +3 -0
  121. data/test/models/sqlserver/uppered.rb +3 -0
  122. data/test/models/sqlserver/uuid.rb +3 -0
  123. data/test/schema/datatypes/2012.sql +55 -0
  124. data/test/schema/sqlserver_specific_schema.rb +207 -0
  125. data/test/support/coerceable_test_sqlserver.rb +45 -0
  126. data/test/support/connection_reflection.rb +37 -0
  127. data/test/support/load_schema_sqlserver.rb +29 -0
  128. data/test/support/minitest_sqlserver.rb +1 -0
  129. data/test/support/paths_sqlserver.rb +50 -0
  130. data/test/support/rake_helpers.rb +41 -0
  131. data/test/support/sql_counter_sqlserver.rb +32 -0
  132. metadata +253 -0
@@ -0,0 +1,713 @@
1
+ require 'cases/helper_sqlserver'
2
+
3
+
4
+ # Windows/Appveyor
5
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
6
+ # All of these are due to Time.local(2000).zone. See http://git.io/v3t0o
7
+ class BelongsToAssociationsTest < ActiveRecord::TestCase
8
+ coerce_tests! :test_belongs_to_with_touch_option_on_touch_without_updated_at_attributes
9
+ end
10
+ class BasicsTest < ActiveRecord::TestCase
11
+ coerce_tests! :test_preserving_time_objects_with_local_time_conversion_to_default_timezone_utc
12
+ coerce_tests! :test_preserving_time_objects_with_time_with_zone_conversion_to_default_timezone_local
13
+ coerce_tests! :test_preserving_time_objects_with_utc_time_conversion_to_default_timezone_local
14
+ end
15
+ class DirtyTest < ActiveRecord::TestCase
16
+ coerce_tests! :test_save_always_should_update_timestamps_when_serialized_attributes_are_present
17
+ coerce_tests! :test_previous_changes # Coupled to above test.
18
+ end
19
+ end
20
+
21
+
22
+ module ActiveRecord
23
+ class AdapterTest < ActiveRecord::TestCase
24
+
25
+ # As far as I can tell, SQL Server does not support null bytes in strings.
26
+ coerce_tests! :test_update_prepared_statement
27
+
28
+ end
29
+ end
30
+
31
+
32
+
33
+
34
+ require 'models/topic'
35
+ class AttributeMethodsTest < ActiveRecord::TestCase
36
+
37
+ coerce_tests! :test_typecast_attribute_from_select_to_false
38
+ def test_typecast_attribute_from_select_to_false_coerced
39
+ Topic.create(:title => 'Budget')
40
+ topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
41
+ assert !topic.is_test?
42
+ end
43
+
44
+ coerce_tests! :test_typecast_attribute_from_select_to_true
45
+ def test_typecast_attribute_from_select_to_true_coerced
46
+ Topic.create(:title => 'Budget')
47
+ topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
48
+ assert topic.is_test?
49
+ end
50
+
51
+ end
52
+
53
+
54
+
55
+
56
+ class BasicsTest < ActiveRecord::TestCase
57
+
58
+ coerce_tests! :test_column_names_are_escaped
59
+ def test_column_names_are_escaped_coerced
60
+ conn = ActiveRecord::Base.connection
61
+ classname = conn.class.name[/[^:]*$/]
62
+ badchar = "'"
63
+ quoted = conn.quote_column_name "foo#{badchar}bar"
64
+ assert_equal "[foo'bar]", quoted
65
+ end
66
+
67
+ # PENDING: [Rails5.x] Remove coerced tests and use simple symbol types..
68
+ # This test has a few problems. First, it would require that we use the
69
+ # `Type::SQLServer::BigInteger.new(limit: 8)` for the `world_population` attribute.
70
+ coerce_tests! :test_numeric_fields
71
+ coerce_tests! :test_numeric_fields_with_scale
72
+
73
+ # Just like PostgreSQLAdapter does.
74
+ coerce_tests! :test_respect_internal_encoding
75
+
76
+ # Caused in Rails v4.2.5 by adding `firm_id` column in this http://git.io/vBfMs
77
+ # commit. Trust Rails has this covered.
78
+ coerce_tests! :test_find_keeps_multiple_group_values
79
+
80
+ end
81
+
82
+
83
+
84
+
85
+ class BelongsToAssociationsTest < ActiveRecord::TestCase
86
+
87
+ # Since @client.firm is a single first/top, and we use FETCH the order clause is used.
88
+ coerce_tests! :test_belongs_to_does_not_use_order_by
89
+
90
+ coerce_tests! :test_belongs_to_with_primary_key_joins_on_correct_column
91
+ def test_belongs_to_with_primary_key_joins_on_correct_column_coerced
92
+ sql = Client.joins(:firm_with_primary_key).to_sql
93
+ assert_no_match(/\[firm_with_primary_keys_companies\]\.\[id\]/, sql)
94
+ assert_match(/\[firm_with_primary_keys_companies\]\.\[name\]/, sql)
95
+ end
96
+
97
+ end
98
+
99
+
100
+
101
+
102
+ module ActiveRecord
103
+ class BindParameterTest < ActiveRecord::TestCase
104
+
105
+ # Never finds `sql` since we use `EXEC sp_executesql` wrappers.
106
+ coerce_tests! :test_binds_are_logged,
107
+ :test_binds_are_logged_after_type_cast
108
+
109
+ end
110
+ end
111
+
112
+
113
+
114
+
115
+ class CalculationsTest < ActiveRecord::TestCase
116
+
117
+ # Are decimal, not integer.
118
+ coerce_tests! :test_should_return_decimal_average_of_integer_field
119
+ def test_should_return_decimal_average_of_integer_field_coerced
120
+ value = Account.average(:id)
121
+ assert_equal BigDecimal('3.0').to_s, BigDecimal(value).to_s
122
+ end
123
+
124
+ coerce_tests! :test_limit_is_kept
125
+ def test_limit_is_kept_coerced
126
+ queries = assert_sql { Account.limit(1).count }
127
+ assert_equal 1, queries.length
128
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY}
129
+ end
130
+
131
+ coerce_tests! :test_limit_with_offset_is_kept
132
+ def test_limit_with_offset_is_kept_coerced
133
+ queries = assert_sql { Account.limit(1).offset(1).count }
134
+ assert_equal 1, queries.length
135
+ queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY}
136
+ end
137
+
138
+ end
139
+
140
+
141
+
142
+
143
+ module ActiveRecord
144
+ class Migration
145
+ class ChangeSchemaTest < ActiveRecord::TestCase
146
+
147
+ # We test these.
148
+ coerce_tests! :test_create_table_with_bigint,
149
+ :test_create_table_with_defaults
150
+
151
+
152
+ end
153
+ class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase
154
+
155
+ # In SQL Server you have to delete the tables yourself in the right order.
156
+ coerce_tests! :test_create_table_with_force_cascade_drops_dependent_objects
157
+
158
+ end
159
+ end
160
+ end
161
+
162
+
163
+
164
+
165
+ module ActiveRecord
166
+ class Migration
167
+ class ColumnAttributesTest < ActiveRecord::TestCase
168
+
169
+ # We have a default 4000 varying character limit.
170
+ coerce_tests! :test_add_column_without_limit
171
+ def test_add_column_without_limit_coerced
172
+ add_column :test_models, :description, :string, limit: nil
173
+ TestModel.reset_column_information
174
+ TestModel.columns_hash["description"].limit.must_equal 4000
175
+ end
176
+
177
+ end
178
+ end
179
+ end
180
+
181
+
182
+
183
+
184
+ module ActiveRecord
185
+ class Migration
186
+ class ColumnsTest
187
+
188
+ # Our defaults are reall 70000 integers vs '70000' strings.
189
+ coerce_tests! :test_rename_column_preserves_default_value_not_null
190
+ def test_rename_column_preserves_default_value_not_null_coerced
191
+ add_column 'test_models', 'salary', :integer, :default => 70000
192
+ default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
193
+ assert_equal 70000, default_before
194
+ rename_column "test_models", "salary", "annual_salary"
195
+ assert TestModel.column_names.include?("annual_salary")
196
+ default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
197
+ assert_equal 70000, default_after
198
+ end
199
+
200
+ # Dropping the column removes the single index.
201
+ coerce_tests! :test_remove_column_with_multi_column_index
202
+ def test_remove_column_with_multi_column_index_coerced
203
+ add_column "test_models", :hat_size, :integer
204
+ add_column "test_models", :hat_style, :string, :limit => 100
205
+ add_index "test_models", ["hat_style", "hat_size"], :unique => true
206
+ assert_equal 1, connection.indexes('test_models').size
207
+ remove_column("test_models", "hat_size")
208
+ assert_equal [], connection.indexes('test_models').map(&:name)
209
+ end
210
+
211
+ end
212
+ end
213
+ end
214
+
215
+
216
+
217
+
218
+ class CoreTest < ActiveRecord::TestCase
219
+
220
+ # I think fixtures are useing the wrong time zone and the `:first`
221
+ # `topics`.`bonus_time` attribute of 2005-01-30t15:28:00.00+01:00 is
222
+ # getting local EST time for me and set to "09:28:00.0000000".
223
+ coerce_tests! :test_pretty_print_persisted
224
+
225
+ end
226
+
227
+
228
+
229
+
230
+ module ActiveRecord
231
+ module ConnectionAdapters
232
+
233
+ # Just like PostgreSQLAdapter does.
234
+ TypeLookupTest.coerce_all_tests! if defined?(TypeLookupTest)
235
+
236
+ # All sorts of errors due to how we test. Even setting ENV['RAILS_ENV'] to
237
+ # a value of 'default_env' will still show tests failing. Just ignoring all
238
+ # of them since we have no monkey in this circus.
239
+ MergeAndResolveDefaultUrlConfigTest.coerce_all_tests! if defined?(MergeAndResolveDefaultUrlConfigTest)
240
+
241
+ end
242
+ end
243
+
244
+
245
+
246
+
247
+ module ActiveRecord
248
+ class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
249
+ # We extend `local_database?` so that common VM IPs can be used.
250
+ coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
251
+ end
252
+ class DatabaseTasksDropAllTest < ActiveRecord::TestCase
253
+ # We extend `local_database?` so that common VM IPs can be used.
254
+ coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
255
+ end
256
+ end
257
+
258
+
259
+
260
+
261
+ class DefaultScopingTest < ActiveRecord::TestCase
262
+
263
+ # We are not doing order duplicate removal anymore.
264
+ coerce_tests! :test_order_in_default_scope_should_not_prevail
265
+
266
+ end
267
+
268
+
269
+
270
+
271
+ require 'models/post'
272
+ require 'models/subscriber'
273
+ class EachTest < ActiveRecord::TestCase
274
+
275
+ coerce_tests! :test_find_in_batches_should_quote_batch_order
276
+ def test_find_in_batches_should_quote_batch_order_coerced
277
+ c = Post.connection
278
+ assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
279
+ Post.find_in_batches(:batch_size => 1) do |batch|
280
+ assert_kind_of Array, batch
281
+ assert_kind_of Post, batch.first
282
+ end
283
+ end
284
+ end
285
+
286
+ end
287
+
288
+
289
+
290
+
291
+ require 'models/owner'
292
+ class Owner < ActiveRecord::Base
293
+ scope :including_last_pet, -> {
294
+ select('owners.*, (select TOP (1) p.pet_id from pets p where p.owner_id = owners.owner_id order by p.name desc ) as last_pet_id').
295
+ includes(:last_pet)
296
+ }
297
+ end
298
+ class EagerAssociationTest < ActiveRecord::TestCase
299
+
300
+ # Use LEN() vs length() function.
301
+ coerce_tests! :test_count_with_include
302
+ def test_count_with_include_coerced
303
+ assert_equal 3, authors(:david).posts_with_comments.where("LEN(comments.body) > 15").references(:comments).count
304
+ end
305
+
306
+ # Use TOP (1) in scope vs limit 1.
307
+ coerce_tests! %r{including association based on sql condition and no database column}
308
+ it "including association based on sql condition and no database column coerced" do
309
+ assert_equal pets(:parrot), Owner.including_last_pet.first.last_pet
310
+ end
311
+
312
+ end
313
+
314
+
315
+
316
+
317
+ require 'models/topic'
318
+ class FinderTest < ActiveRecord::TestCase
319
+
320
+ coerce_tests! %r{doesn't have implicit ordering},
321
+ :test_find_doesnt_have_implicit_ordering # We have implicit ordering, via FETCH.
322
+
323
+ coerce_tests! :test_exists_does_not_select_columns_without_alias
324
+ def test_exists_does_not_select_columns_without_alias_coerced
325
+ assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY/i) do
326
+ Topic.exists?
327
+ end
328
+ end
329
+
330
+ coerce_tests! :test_string_sanitation
331
+ def test_string_sanitation_coerced
332
+ assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
333
+ assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
334
+ end
335
+
336
+ coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
337
+ def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
338
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY/) { Topic.take(3).entries }
339
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY/) { Topic.first(2).entries }
340
+ assert_sql(/OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY/) { Topic.last(5).entries }
341
+ end
342
+
343
+ # This fails only when run in the full test suite task. Just taking it out of the mix.
344
+ coerce_tests! :test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
345
+
346
+ end
347
+
348
+
349
+
350
+
351
+ module ActiveRecord
352
+ class Migration
353
+ class ForeignKeyTest < ActiveRecord::TestCase
354
+
355
+ # We do not support :restrict.
356
+ coerce_tests! :test_add_on_delete_restrict_foreign_key
357
+ def test_add_on_delete_restrict_foreign_key_coerced
358
+ assert_raises ArgumentError do
359
+ @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_delete: :restrict
360
+ end
361
+ assert_raises ArgumentError do
362
+ @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :restrict
363
+ end
364
+ end
365
+
366
+ end
367
+ end
368
+ end
369
+
370
+
371
+
372
+
373
+ class HasOneAssociationsTest < ActiveRecord::TestCase
374
+
375
+ # We use OFFSET/FETCH vs TOP. So we always have an order.
376
+ coerce_tests! :test_has_one_does_not_use_order_by
377
+
378
+ end
379
+
380
+
381
+
382
+
383
+ require 'models/company'
384
+ class InheritanceTest < ActiveRecord::TestCase
385
+
386
+ coerce_tests! :test_a_bad_type_column
387
+ def test_a_bad_type_column_coerced
388
+ Company.connection.with_identity_insert_enabled('companies') do
389
+ Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
390
+ end
391
+ assert_raise(ActiveRecord::SubclassNotFound) { Company.find(100) }
392
+ end
393
+
394
+ coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
395
+ def test_eager_load_belongs_to_primary_key_quoting_coerced
396
+ con = Account.connection
397
+ assert_sql(/\[companies\]\.\[id\] IN \(1\)/) do
398
+ Account.all.merge!(:includes => :firm).find(1)
399
+ end
400
+ end
401
+
402
+ end
403
+
404
+
405
+
406
+
407
+ class BigNumber < ActiveRecord::Base
408
+ attribute :value_of_e, Type::SQLServer::Integer.new
409
+ attribute :my_house_population, Type::SQLServer::Integer.new
410
+ end
411
+ class MigrationTest < ActiveRecord::TestCase
412
+
413
+ # PENDING: [Rails5.x] Remove coerced tests and use simple symbol types.
414
+ coerce_tests! :test_add_table_with_decimals
415
+
416
+ end
417
+
418
+
419
+
420
+
421
+ class NamedScopingTest < ActiveRecord::TestCase
422
+
423
+ # This works now because we add an `order(:id)` sort to break the order tie for deterministic results.
424
+ coerce_tests! :test_scopes_honor_current_scopes_from_when_defined
425
+ def test_scopes_honor_current_scopes_from_when_defined_coerced
426
+ assert !Post.ranked_by_comments.order(:id).limit_by(5).empty?
427
+ assert !authors(:david).posts.ranked_by_comments.order(:id).limit_by(5).empty?
428
+ assert_not_equal Post.ranked_by_comments.order(:id).limit_by(5), authors(:david).posts.ranked_by_comments.order(:id).limit_by(5)
429
+ assert_not_equal Post.order(:id).top(5), authors(:david).posts.order(:id).top(5)
430
+ # Oracle sometimes sorts differently if WHERE condition is changed
431
+ assert_equal authors(:david).posts.ranked_by_comments.limit_by(5).to_a.sort_by(&:id), authors(:david).posts.top(5).to_a.sort_by(&:id)
432
+ assert_equal Post.ranked_by_comments.limit_by(5), Post.top(5)
433
+ end
434
+
435
+ end
436
+
437
+
438
+
439
+
440
+ require 'models/developer'
441
+ require 'models/computer'
442
+ class NestedRelationScopingTest < ActiveRecord::TestCase
443
+
444
+ coerce_tests! :test_merge_options
445
+ def test_merge_options_coerced
446
+ Developer.where('salary = 80000').scoping do
447
+ Developer.limit(10).scoping do
448
+ devs = Developer.all
449
+ sql = devs.to_sql
450
+ assert_match '(salary = 80000)', sql
451
+ assert_match 'FETCH NEXT 10 ROWS ONLY', sql
452
+ end
453
+ end
454
+ end
455
+
456
+ end
457
+
458
+
459
+
460
+
461
+ require 'models/topic'
462
+ class PersistenceTest < ActiveRecord::TestCase
463
+
464
+ # We can not UPDATE identity columns.
465
+ coerce_tests! :test_update_columns_changing_id
466
+
467
+ # Previous test required updating a identity column.
468
+ coerce_tests! :test_update_all_doesnt_ignore_order
469
+ def test_update_all_doesnt_ignore_order_coerced
470
+ david, mary = authors(:david), authors(:mary)
471
+ david.id.must_equal 1
472
+ mary.id.must_equal 2
473
+ david.name.wont_equal mary.name
474
+ assert_sql(/UPDATE.*\(SELECT \[authors\].\[id\] FROM \[authors\].*ORDER BY \[authors\].\[id\]/i) do
475
+ Author.where('[id] > 1').order(:id).update_all(name: 'Test')
476
+ end
477
+ david.reload.name.must_equal 'David'
478
+ mary.reload.name.must_equal 'Test'
479
+ end
480
+
481
+ # We can not UPDATE identity columns.
482
+ coerce_tests! :test_update_attributes
483
+ def test_update_attributes_coerced
484
+ topic = Topic.find(1)
485
+ assert !topic.approved?
486
+ assert_equal "The First Topic", topic.title
487
+ topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
488
+ topic.reload
489
+ assert topic.approved?
490
+ assert_equal "The First Topic Updated", topic.title
491
+ topic.update_attributes(approved: false, title: "The First Topic")
492
+ topic.reload
493
+ assert !topic.approved?
494
+ assert_equal "The First Topic", topic.title
495
+ # SQLServer: Here is where it breaks down. No exceptions.
496
+ # assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do
497
+ # topic.update_attributes(id: 3, title: "Hm is it possible?")
498
+ # end
499
+ # assert_not_equal "Hm is it possible?", Topic.find(3).title
500
+ # topic.update_attributes(id: 1234)
501
+ # assert_nothing_raised { topic.reload }
502
+ # assert_equal topic.title, Topic.find(1234).title
503
+ end
504
+
505
+ end
506
+
507
+
508
+
509
+
510
+ require 'models/topic'
511
+ module ActiveRecord
512
+ class PredicateBuilderTest < ActiveRecord::TestCase
513
+
514
+ coerce_tests! :test_registering_new_handlers
515
+ def test_registering_new_handlers_coerced
516
+ PredicateBuilder.register_handler(Regexp, proc do |column, value|
517
+ Arel::Nodes::InfixOperation.new('~', column, Arel.sql(value.source))
518
+ end)
519
+ assert_match %r{\[topics\]\.\[title\] ~ rails}i, Topic.where(title: /rails/).to_sql
520
+ end
521
+
522
+ end
523
+ end
524
+
525
+
526
+
527
+
528
+ require 'models/task'
529
+ class QueryCacheTest < ActiveRecord::TestCase
530
+
531
+ coerce_tests! :test_cache_does_not_wrap_string_results_in_arrays
532
+ def test_cache_does_not_wrap_string_results_in_arrays_coerced
533
+ Task.cache do
534
+ assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
535
+ end
536
+ end
537
+
538
+ end
539
+
540
+
541
+
542
+
543
+ require 'models/post'
544
+ class RelationTest < ActiveRecord::TestCase
545
+
546
+ # We have implicit ordering, via FETCH.
547
+ coerce_tests! %r{doesn't have implicit ordering}
548
+
549
+ # We are not doing order duplicate removal anymore.
550
+ coerce_tests! :test_order_using_scoping
551
+
552
+ # Account for our `EXEC sp_executesql...` statements.
553
+ coerce_tests! :test_to_sql_on_eager_join
554
+ def test_to_sql_on_eager_join_coerced
555
+ expected = assert_sql { Post.eager_load(:last_comment).order('comments.id DESC').to_a }.first
556
+ actual = Post.eager_load(:last_comment).order('comments.id DESC').to_sql
557
+ actual = "EXEC sp_executesql N'#{ActiveRecord::ConnectionAdapters::SQLServer::Utils.quote_string(actual)}'"
558
+ assert_equal expected, actual
559
+ end
560
+
561
+ # We are not doing order duplicate removal anymore.
562
+ coerce_tests! :test_default_scope_order_with_scope_order
563
+
564
+ end
565
+
566
+
567
+
568
+
569
+ require 'models/post'
570
+ class SanitizeTest < ActiveRecord::TestCase
571
+
572
+ coerce_tests! :test_sanitize_sql_like_example_use_case
573
+ def test_sanitize_sql_like_example_use_case_coerced
574
+ searchable_post = Class.new(Post) do
575
+ def self.search(term)
576
+ where("title LIKE ?", sanitize_sql_like(term, '!'))
577
+ end
578
+ end
579
+ assert_sql(/\(title LIKE N''20!% !_reduction!_!!''\)/) do
580
+ searchable_post.search("20% _reduction_!").to_a
581
+ end
582
+ end
583
+
584
+ end
585
+
586
+
587
+
588
+
589
+ class SchemaDumperTest < ActiveRecord::TestCase
590
+
591
+ # We have precision to 38.
592
+ coerce_tests! :test_schema_dump_keeps_large_precision_integer_columns_as_decimal
593
+ def test_schema_dump_keeps_large_precision_integer_columns_as_decimal_coerced
594
+ output = standard_dump
595
+ assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 38}, output
596
+ end
597
+
598
+ # This accidently returns the wrong number because of our tables too.
599
+ coerce_tests! :test_types_line_up
600
+
601
+ # This is a poorly written test and really does not catch the bottom'ness it is meant too. Ours throw it off.
602
+ coerce_tests! :test_foreign_keys_are_dumped_at_the_bottom_to_circumvent_dependency_issues
603
+
604
+ # Fall through false positive with no filter.
605
+ coerce_tests! :test_schema_dumps_partial_indices
606
+ def test_schema_dumps_partial_indices_coerced
607
+ index_definition = standard_dump.split(/\n/).grep(/add_index.*company_partial_index/).first.strip
608
+ assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "([rating]>(10))"', index_definition
609
+ end
610
+
611
+ end
612
+
613
+ class SchemaDumperDefaultsTest < ActiveRecord::TestCase
614
+
615
+ # These date formats do not match ours. We got these covered in our dumper tests.
616
+ coerce_tests! :test_schema_dump_defaults_with_universally_supported_types
617
+
618
+ end
619
+
620
+
621
+
622
+
623
+ class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
624
+
625
+ # We trust Rails on this since we do not want to install mysql.
626
+ coerce_tests! %r{inspect on Model class does not raise}
627
+
628
+ end
629
+
630
+
631
+
632
+
633
+ require 'models/topic'
634
+ class TransactionTest < ActiveRecord::TestCase
635
+
636
+ coerce_tests! :test_releasing_named_savepoints
637
+ def test_releasing_named_savepoints_coerced
638
+ Topic.transaction do
639
+ Topic.connection.create_savepoint("another")
640
+ Topic.connection.release_savepoint("another")
641
+ # We do not have a notion of releasing, so this does nothing vs raise an error.
642
+ Topic.connection.release_savepoint("another")
643
+ end
644
+ end
645
+
646
+ end
647
+
648
+
649
+
650
+
651
+ require 'models/tag'
652
+ class TransactionIsolationTest < ActiveRecord::TestCase
653
+
654
+ # SQL Server will lock the table for counts even when both
655
+ # connections are `READ COMMITTED`. So we bypass with `READPAST`.
656
+ coerce_tests! %r{read committed}
657
+ test "read committed coerced" do
658
+ Tag.transaction(isolation: :read_committed) do
659
+ assert_equal 0, Tag.count
660
+ Tag2.transaction do
661
+ Tag2.create
662
+ assert_equal 0, Tag.lock('WITH(READPAST)').count
663
+ end
664
+ end
665
+ assert_equal 1, Tag.count
666
+ end
667
+
668
+ # I really need some help understanding this one.
669
+ coerce_tests! %r{repeatable read}
670
+
671
+ end
672
+
673
+
674
+ require 'models/post'
675
+ module ActiveRecord
676
+ class WhereChainTest < ActiveRecord::TestCase
677
+
678
+ coerce_tests! :test_not_eq_with_array_parameter
679
+ def test_not_eq_with_array_parameter_coerced
680
+ expected = Arel::Nodes::Not.new("title = N'hello'")
681
+ relation = Post.where.not(['title = ?', 'hello'])
682
+ assert_equal([expected], relation.where_values)
683
+ end
684
+
685
+ end
686
+ end
687
+
688
+
689
+
690
+
691
+ class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
692
+
693
+ # We do better than ActiveRecord and find the views PK.
694
+ coerce_tests! :test_does_not_assume_id_column_as_primary_key
695
+
696
+ end
697
+
698
+
699
+
700
+
701
+ require 'models/author'
702
+ class YamlSerializationTest < ActiveRecord::TestCase
703
+
704
+ coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
705
+ def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
706
+ author = Author.select('authors.*, 5 as posts_count').first
707
+ dumped = YAML.load(YAML.dump(author))
708
+ assert_equal 5, author.posts_count
709
+ assert_equal 5, dumped.posts_count
710
+ end
711
+
712
+ end
713
+