activerecord-jdbcsqlserver-adapter 50.0.0 → 52.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +4 -5
  4. data/CHANGELOG.md +22 -101
  5. data/{Dockerfile → Dockerfile.ci} +0 -0
  6. data/Gemfile +1 -3
  7. data/README.md +5 -9
  8. data/VERSION +1 -1
  9. data/activerecord-jdbcsqlserver-adapter.gemspec +2 -2
  10. data/appveyor.yml +1 -1
  11. data/docker-compose.ci.yml +7 -5
  12. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +3 -1
  13. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -1
  14. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +51 -0
  15. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +18 -20
  16. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +5 -3
  17. data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +43 -0
  18. data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +26 -0
  19. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +13 -2
  20. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +94 -28
  21. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -0
  22. data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +5 -25
  23. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +24 -1
  24. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +23 -2
  25. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +110 -74
  26. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +15 -7
  27. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +3 -4
  28. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +0 -4
  29. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +5 -0
  30. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +3 -6
  31. data/lib/active_record/connection_adapters/sqlserver/type/json.rb +1 -1
  32. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +7 -0
  33. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -0
  34. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +47 -24
  35. data/lib/active_record/tasks/sqlserver_database_tasks.rb +5 -3
  36. data/lib/activerecord-jdbcsqlserver-adapter.rb +4 -1
  37. data/lib/arel/visitors/sqlserver.rb +17 -4
  38. data/lib/arel_sqlserver.rb +0 -1
  39. data/lib/jdbc_mssql_driver_loader.rb +22 -0
  40. data/test/bin/install-freetds.sh +18 -0
  41. data/test/bin/setup.sh +19 -0
  42. data/test/cases/adapter_test_sqlserver.rb +43 -39
  43. data/test/cases/change_column_null_test_sqlserver.rb +42 -0
  44. data/test/cases/coerced_tests.rb +419 -39
  45. data/test/cases/column_test_sqlserver.rb +496 -462
  46. data/test/cases/connection_test_sqlserver.rb +2 -2
  47. data/test/cases/fetch_test_sqlserver.rb +5 -5
  48. data/test/cases/helper_sqlserver.rb +12 -1
  49. data/test/cases/json_test_sqlserver.rb +6 -6
  50. data/test/cases/migration_test_sqlserver.rb +13 -3
  51. data/test/cases/order_test_sqlserver.rb +19 -19
  52. data/test/cases/pessimistic_locking_test_sqlserver.rb +37 -20
  53. data/test/cases/rake_test_sqlserver.rb +20 -20
  54. data/test/cases/schema_dumper_test_sqlserver.rb +44 -43
  55. data/test/cases/schema_test_sqlserver.rb +2 -2
  56. data/test/cases/showplan_test_sqlserver.rb +25 -10
  57. data/test/cases/specific_schema_test_sqlserver.rb +11 -17
  58. data/test/cases/transaction_test_sqlserver.rb +9 -9
  59. data/test/cases/trigger_test_sqlserver.rb +31 -0
  60. data/test/cases/utils_test_sqlserver.rb +36 -36
  61. data/test/cases/uuid_test_sqlserver.rb +8 -8
  62. data/test/config.yml +2 -2
  63. data/test/migrations/create_clients_and_change_column_null.rb +23 -0
  64. data/test/models/sqlserver/trigger.rb +7 -0
  65. data/test/models/sqlserver/trigger_history.rb +3 -0
  66. data/test/schema/datatypes/2012.sql +1 -0
  67. data/test/schema/sqlserver_specific_schema.rb +47 -5
  68. data/test/support/core_ext/query_cache.rb +29 -0
  69. data/test/support/sql_counter_sqlserver.rb +1 -1
  70. metadata +32 -15
  71. data/RAILS5-TODO.md +0 -5
  72. data/test/models/sqlserver/dot_table_name.rb +0 -3
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -x
4
+ set -e
5
+
6
+ tag=2017-GA
7
+
8
+ docker pull metaskills/mssql-server-linux-rails:$tag
9
+
10
+ container=$(docker ps -a -q --filter ancestor=metaskills/mssql-server-linux-rails:$tag)
11
+ if [[ -z $container ]]; then
12
+ docker run -p 1433:1433 -d metaskills/mssql-server-linux-rails:$tag && sleep 10
13
+ exit
14
+ fi
15
+
16
+ container=$(docker ps -q --filter ancestor=metaskills/mssql-server-linux-rails:$tag)
17
+ if [[ -z $container ]]; then
18
+ docker start $container && sleep 10
19
+ fi
@@ -13,16 +13,17 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
13
13
  let(:basic_update_sql) { "UPDATE [customers] SET [address_street] = NULL WHERE [id] = 2" }
14
14
  let(:basic_select_sql) { "SELECT * FROM [customers] WHERE ([customers].[id] = 1)" }
15
15
 
16
- it 'has basic and non-senstive information in the adpaters inspect method' do
16
+ it 'has basic and non-sensitive information in the adapters inspect method' do
17
17
  string = connection.inspect
18
- string.must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
19
- string.must_match %r{version\: \d.\d}
20
- string.must_match %r{mode: (dblib|jdbc)}
21
- string.must_match %r{azure: (true|false)}
22
- string.wont_match %r{host}
23
- string.wont_match %r{password}
24
- string.wont_match %r{username}
25
- string.wont_match %r{port}
18
+
19
+ _(string).must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
20
+ _(string).must_match %r{version\: \d+\.\d}
21
+ _(string).must_match %r{mode: (dblib|jdbc)}
22
+ _(string).must_match %r{azure: (true|false)}
23
+ _(string).wont_match %r{host}
24
+ _(string).wont_match %r{password}
25
+ _(string).wont_match %r{username}
26
+ _(string).wont_match %r{port}
26
27
  end
27
28
 
28
29
  it 'has a 128 max #table_alias_length' do
@@ -37,10 +38,6 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
37
38
  assert_equal 'SQLServer', connection.adapter_name
38
39
  end
39
40
 
40
- it 'supports migrations' do
41
- assert connection.supports_migrations?
42
- end
43
-
44
41
  it 'support DDL in transactions' do
45
42
  assert connection.supports_ddl_transactions?
46
43
  end
@@ -145,12 +142,12 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
145
142
  end
146
143
 
147
144
  it 'return quoted table_name to #query_requires_identity_insert? when INSERT sql contains id column' do
148
- assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql)
149
- assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted)
150
- assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered)
151
- assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_sp)
152
- assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted_sp)
153
- assert_equal '[funny_jokes]', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered_sp)
145
+ assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql)
146
+ assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted)
147
+ assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered)
148
+ assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_sp)
149
+ assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted_sp)
150
+ assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered_sp)
154
151
  end
155
152
 
156
153
  it 'return false to #query_requires_identity_insert? for normal SQL' do
@@ -166,7 +163,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
166
163
  end
167
164
 
168
165
  it 'return an empty array when calling #identity_columns for a table_name with no identity' do
169
- connection.send(:identity_columns, Subscriber.table_name).must_equal []
166
+ _(connection.send(:identity_columns, Subscriber.table_name)).must_equal []
170
167
  end
171
168
 
172
169
  end
@@ -236,6 +233,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
236
233
  end
237
234
  end
238
235
 
236
+ it 'not disable referential integrity for the same table twice' do
237
+ tables = SSTestHasPk.connection.tables_with_referential_integrity
238
+ assert_equal tables.size, tables.uniq.size
239
+ end
240
+
239
241
  end
240
242
 
241
243
  describe 'database statements' do
@@ -266,23 +268,26 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
266
268
  end
267
269
 
268
270
  it 'create integers when limit is 4' do
269
- assert_equal 'integer', connection.type_to_sql(:integer, 4)
271
+ assert_equal 'integer', connection.type_to_sql(:integer, limit: 4)
270
272
  end
271
273
 
272
274
  it 'create integers when limit is 3' do
273
- assert_equal 'integer', connection.type_to_sql(:integer, 3)
275
+ assert_equal 'integer', connection.type_to_sql(:integer, limit: 3)
276
+ end
277
+
278
+ it 'create smallints when limit is 2' do
279
+ assert_equal 'smallint', connection.type_to_sql(:integer, limit: 2)
274
280
  end
275
281
 
276
- it 'create smallints when limit is less than 3' do
277
- assert_equal 'smallint', connection.type_to_sql(:integer, 2)
278
- assert_equal 'smallint', connection.type_to_sql(:integer, 1)
282
+ it 'create tinyints when limit is 1' do
283
+ assert_equal 'tinyint', connection.type_to_sql(:integer, limit: 1)
279
284
  end
280
285
 
281
286
  it 'create bigints when limit is greateer than 4' do
282
- assert_equal 'bigint', connection.type_to_sql(:integer, 5)
283
- assert_equal 'bigint', connection.type_to_sql(:integer, 6)
284
- assert_equal 'bigint', connection.type_to_sql(:integer, 7)
285
- assert_equal 'bigint', connection.type_to_sql(:integer, 8)
287
+ assert_equal 'bigint', connection.type_to_sql(:integer, limit: 5)
288
+ assert_equal 'bigint', connection.type_to_sql(:integer, limit: 6)
289
+ assert_equal 'bigint', connection.type_to_sql(:integer, limit: 7)
290
+ assert_equal 'bigint', connection.type_to_sql(:integer, limit: 8)
286
291
  end
287
292
 
288
293
  it 'create floats when no limit supplied' do
@@ -300,7 +305,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
300
305
  end
301
306
 
302
307
  it 'find SSTestCustomersView table name' do
303
- connection.views.must_include 'sst_customers_view'
308
+ _(connection.views).must_include 'sst_customers_view'
304
309
  end
305
310
 
306
311
  it 'work with dynamic finders' do
@@ -341,9 +346,9 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
341
346
  end
342
347
 
343
348
  it 'find identity column' do
344
- SSTestCustomersView.primary_key.must_equal 'id'
345
- connection.primary_key(SSTestCustomersView.table_name).must_equal 'id'
346
- SSTestCustomersView.columns_hash['id'].must_be :is_identity?
349
+ _(SSTestCustomersView.primary_key).must_equal 'id'
350
+ _(connection.primary_key(SSTestCustomersView.table_name)).must_equal 'id'
351
+ _(SSTestCustomersView.columns_hash['id']).must_be :is_identity?
347
352
  end
348
353
 
349
354
  it 'find default values' do
@@ -368,9 +373,9 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
368
373
  end
369
374
 
370
375
  it 'find identity column' do
371
- SSTestStringDefaultsView.primary_key.must_equal 'id'
372
- connection.primary_key(SSTestStringDefaultsView.table_name).must_equal 'id'
373
- SSTestStringDefaultsView.columns_hash['id'].must_be :is_identity?
376
+ _(SSTestStringDefaultsView.primary_key).must_equal 'id'
377
+ _(connection.primary_key(SSTestStringDefaultsView.table_name)).must_equal 'id'
378
+ _(SSTestStringDefaultsView.columns_hash['id']).must_be :is_identity?
374
379
  end
375
380
 
376
381
  it 'find default values' do
@@ -419,12 +424,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
419
424
 
420
425
  it 'in_memory_oltp' do
421
426
  if ENV['IN_MEMORY_OLTP'] && connection.supports_in_memory_oltp?
422
- SSTMemory.primary_key.must_equal 'id'
423
- SSTMemory.columns_hash['id'].must_be :is_identity?
427
+ _(SSTMemory.primary_key).must_equal 'id'
428
+ _(SSTMemory.columns_hash['id']).must_be :is_identity?
424
429
  else
425
430
  skip 'supports_in_memory_oltp? => false'
426
431
  end
427
432
  end
428
433
 
429
434
  end
430
-
@@ -0,0 +1,42 @@
1
+ require 'cases/helper_sqlserver'
2
+ require 'migrations/create_clients_and_change_column_null'
3
+
4
+ class ChangeColumnNullTestSqlServer < ActiveRecord::TestCase
5
+ before do
6
+ @old_verbose = ActiveRecord::Migration.verbose
7
+ ActiveRecord::Migration.verbose = false
8
+ CreateClientsAndChangeColumnNull.new.up
9
+ end
10
+
11
+ after do
12
+ CreateClientsAndChangeColumnNull.new.down
13
+ ActiveRecord::Migration.verbose = @old_verbose
14
+ end
15
+
16
+ def find_column(table, name)
17
+ table.find { |column| column.name == name }
18
+ end
19
+
20
+ let(:clients_table) { connection.columns('clients') }
21
+ let(:name_column) { find_column(clients_table, 'name') }
22
+ let(:code_column) { find_column(clients_table, 'code') }
23
+ let(:value_column) { find_column(clients_table, 'value') }
24
+
25
+ describe '#change_column_null' do
26
+ it 'does not change the column limit' do
27
+ _(name_column.limit).must_equal 15
28
+ end
29
+
30
+ it 'does not change the column default' do
31
+ _(code_column.default).must_equal 'n/a'
32
+ end
33
+
34
+ it 'does not change the column precision' do
35
+ _(value_column.precision).must_equal 32
36
+ end
37
+
38
+ it 'does not change the column scale' do
39
+ _(value_column.scale).must_equal 8
40
+ end
41
+ end
42
+ end
@@ -31,6 +31,10 @@ end
31
31
  require 'models/event'
32
32
  module ActiveRecord
33
33
  class AdapterTest < ActiveRecord::TestCase
34
+ # I really dont think we can support legacy binds.
35
+ coerce_tests! :test_select_all_with_legacy_binds
36
+ coerce_tests! :test_insert_update_delete_with_legacy_binds
37
+
34
38
  # As far as I can tell, SQL Server does not support null bytes in strings.
35
39
  coerce_tests! :test_update_prepared_statement
36
40
  coerce_tests! :test_log_invalid_encoding if defined? JRUBY_VERSION # JRuby just happily converts the encoding
@@ -53,14 +57,14 @@ end
53
57
 
54
58
  require 'models/topic'
55
59
  class AttributeMethodsTest < ActiveRecord::TestCase
56
- coerce_tests! :test_typecast_attribute_from_select_to_false
60
+ coerce_tests! %r{typecast attribute from select to false}
57
61
  def test_typecast_attribute_from_select_to_false_coerced
58
62
  Topic.create(:title => 'Budget')
59
63
  topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
60
64
  assert !topic.is_test?
61
65
  end
62
66
 
63
- coerce_tests! :test_typecast_attribute_from_select_to_true
67
+ coerce_tests! %r{typecast attribute from select to true}
64
68
  def test_typecast_attribute_from_select_to_true_coerced
65
69
  Topic.create(:title => 'Budget')
66
70
  topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
@@ -69,7 +73,11 @@ class AttributeMethodsTest < ActiveRecord::TestCase
69
73
  end
70
74
 
71
75
 
72
-
76
+ class NumericDataTest < ActiveRecord::TestCase
77
+ # We do not have do the DecimalWithoutScale type.
78
+ coerce_tests! :test_numeric_fields
79
+ coerce_tests! :test_numeric_fields_with_scale
80
+ end
73
81
 
74
82
  class BasicsTest < ActiveRecord::TestCase
75
83
  coerce_tests! :test_column_names_are_escaped
@@ -78,16 +86,44 @@ class BasicsTest < ActiveRecord::TestCase
78
86
  assert_equal '[t]]]', conn.quote_column_name('t]')
79
87
  end
80
88
 
81
- # We do not have do the DecimalWithoutScale type.
82
- coerce_tests! :test_numeric_fields
83
- coerce_tests! :test_numeric_fields_with_scale
84
-
85
89
  # Just like PostgreSQLAdapter does.
86
90
  coerce_tests! :test_respect_internal_encoding
87
91
 
88
92
  # Caused in Rails v4.2.5 by adding `firm_id` column in this http://git.io/vBfMs
89
93
  # commit. Trust Rails has this covered.
90
94
  coerce_tests! :test_find_keeps_multiple_group_values
95
+
96
+ def test_update_date_time_attributes
97
+ Time.use_zone("Eastern Time (US & Canada)") do
98
+ topic = Topic.find(1)
99
+ time = Time.zone.parse("2017-07-17 10:56")
100
+ topic.update_attributes!(written_on: time)
101
+ assert_equal(time, topic.written_on)
102
+ end
103
+ end
104
+
105
+ def test_update_date_time_attributes_with_default_timezone_local
106
+ with_env_tz 'America/New_York' do
107
+ with_timezone_config default: :local do
108
+ Time.use_zone("Eastern Time (US & Canada)") do
109
+ topic = Topic.find(1)
110
+ time = Time.zone.parse("2017-07-17 10:56")
111
+ topic.update_attributes!(written_on: time)
112
+ assert_equal(time, topic.written_on)
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ # Need to escape `quoted_id` once it contains brackets
119
+ coerce_tests! %r{column names are quoted when using #from clause and model has ignored columns}
120
+ test "column names are quoted when using #from clause and model has ignored columns coerced" do
121
+ refute_empty Developer.ignored_columns
122
+ query = Developer.from("developers").to_sql
123
+ quoted_id = "#{Developer.quoted_table_name}.#{Developer.quoted_primary_key}"
124
+
125
+ assert_match(/SELECT #{Regexp.escape(quoted_id)}.* FROM developers/, query)
126
+ end
91
127
  end
92
128
 
93
129
 
@@ -108,17 +144,63 @@ end
108
144
 
109
145
 
110
146
 
147
+ # module ActiveRecord
148
+ # class BindParameterTest < ActiveRecord::TestCase
149
+ # # Same as original coerced test except log is found using `EXEC sp_executesql` wrapper.
150
+ # # coerce_tests! :test_binds_are_logged
151
+ # # def test_binds_are_logged_coerced
152
+ # # sub = Arel::Nodes::BindParam.new(1)
153
+ # # binds = [Relation::QueryAttribute.new("id", 1, Type::Value.new)]
154
+ # # sql = "select * from topics where id = #{sub.to_sql}"
155
+ # #
156
+ # # @connection.exec_query(sql, "SQL", binds)
157
+ # #
158
+ # # logged_sql = "EXEC sp_executesql N'#{sql}', N'#{sub.to_sql} int', #{sub.to_sql} = 1"
159
+ # # message = @subscriber.calls.find { |args| args[4][:sql] == logged_sql }
160
+ # #
161
+ # # assert_equal binds, message[4][:binds]
162
+ # # end
163
+ # #
164
+ # # # SQL Server adapter does not use a statement cache as query plans are already reused using `EXEC sp_executesql`.
165
+ # # coerce_tests! :test_statement_cache
166
+ # # coerce_tests! :test_statement_cache_with_query_cache
167
+ # # coerce_tests! :test_statement_cache_with_find_by
168
+ # # coerce_tests! :test_statement_cache_with_in_clause
169
+ # # coerce_tests! :test_statement_cache_with_sql_string_literal
170
+ # end
171
+ # end
172
+
173
+
111
174
  module ActiveRecord
112
- class BindParameterTest < ActiveRecord::TestCase
113
- # Never finds `sql` since we use `EXEC sp_executesql` wrappers.
114
- coerce_tests! :test_binds_are_logged
175
+ class InstrumentationTest < ActiveRecord::TestCase
176
+ # This fails randomly due to schema cache being lost?
177
+ coerce_tests! :test_payload_name_on_load
178
+ def test_payload_name_on_load_coerced
179
+ Book.create(name: "test book")
180
+ Book.first
181
+ subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
182
+ event = ActiveSupport::Notifications::Event.new(*args)
183
+ if event.payload[:sql].match "SELECT"
184
+ assert_equal "Book Load", event.payload[:name]
185
+ end
186
+ end
187
+ Book.first
188
+ ensure
189
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
190
+ end
115
191
  end
116
192
  end
117
193
 
118
-
119
-
120
-
121
194
  class CalculationsTest < ActiveRecord::TestCase
195
+ # This fails randomly due to schema cache being lost?
196
+ coerce_tests! :test_offset_is_kept
197
+ def test_offset_is_kept_coerced
198
+ Account.first
199
+ queries = assert_sql { Account.offset(1).count }
200
+ assert_equal 1, queries.length
201
+ assert_match(/OFFSET/, queries.first)
202
+ end
203
+
122
204
  # Are decimal, not integer.
123
205
  coerce_tests! :test_should_return_decimal_average_of_integer_field
124
206
  def test_should_return_decimal_average_of_integer_field_coerced
@@ -130,28 +212,36 @@ class CalculationsTest < ActiveRecord::TestCase
130
212
  def test_limit_is_kept_coerced
131
213
  queries = capture_sql_ss { Account.limit(1).count }
132
214
  assert_equal 1, queries.length
133
- queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1}
215
+ _(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1}
134
216
  end unless defined? JRUBY_VERSION
135
217
 
136
218
  def test_limit_is_kept_coerced
137
219
  queries = capture_sql_ss { Account.limit(1).count }
138
220
  assert_equal 1, queries.length
139
- queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY}
221
+ _(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY}
140
222
  end if defined? JRUBY_VERSION
141
223
 
142
224
  coerce_tests! :test_limit_with_offset_is_kept
143
225
  def test_limit_with_offset_is_kept_coerced
144
226
  queries = capture_sql_ss { Account.limit(1).offset(1).count }
145
227
  assert_equal 1, queries.length
146
- queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1}
228
+ _(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1}
147
229
  end unless defined? JRUBY_VERSION
148
230
 
149
231
  def test_limit_with_offset_is_kept_coerced
150
232
  queries = capture_sql_ss { Account.limit(1).offset(1).count }
151
233
  assert_equal 1, queries.length
152
- queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET \? ROWS FETCH NEXT \? ROWS ONLY}
234
+ _(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET \? ROWS FETCH NEXT \? ROWS ONLY}
153
235
  end if defined? JRUBY_VERSION
154
236
 
237
+ # SQL Server needs an alias for the calculated column
238
+ coerce_tests! :test_distinct_count_all_with_custom_select_and_order
239
+ def test_distinct_count_all_with_custom_select_and_order_coerced
240
+ accounts = Account.distinct.select("credit_limit % 10 AS the_limit").order(Arel.sql("credit_limit % 10"))
241
+ assert_queries(1) { assert_equal 3, accounts.count(:all) }
242
+ assert_queries(1) { assert_equal 3, accounts.load.size }
243
+ end
244
+
155
245
  # Leave it up to users to format selects/functions so HAVING works correctly.
156
246
  coerce_tests! :test_having_with_strong_parameters
157
247
  end
@@ -165,6 +255,7 @@ module ActiveRecord
165
255
  coerce_tests! :test_create_table_with_bigint,
166
256
  :test_create_table_with_defaults
167
257
  end
258
+
168
259
  class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase
169
260
  # In SQL Server you have to delete the tables yourself in the right order.
170
261
  coerce_tests! :test_create_table_with_force_cascade_drops_dependent_objects
@@ -174,6 +265,29 @@ end
174
265
 
175
266
 
176
267
 
268
+ module ActiveRecord
269
+ module ConnectionAdapters
270
+ class QuoteARBaseTest < ActiveRecord::TestCase
271
+
272
+ # Use our date format.
273
+ coerce_tests! :test_quote_ar_object
274
+ def test_quote_ar_object_coerced
275
+ value = DatetimePrimaryKey.new(id: @time)
276
+ assert_equal "'02-14-2017 12:34:56.789'", @connection.quote(value)
277
+ end
278
+
279
+ # Use our date format.
280
+ coerce_tests! :test_type_cast_ar_object
281
+ def test_type_cast_ar_object_coerced
282
+ value = DatetimePrimaryKey.new(id: @time)
283
+ assert_equal "02-14-2017 12:34:56.789", @connection.type_cast(value)
284
+ end
285
+
286
+ end
287
+ end
288
+ end
289
+
290
+
177
291
 
178
292
  module ActiveRecord
179
293
  class Migration
@@ -183,7 +297,7 @@ module ActiveRecord
183
297
  def test_add_column_without_limit_coerced
184
298
  add_column :test_models, :description, :string, limit: nil
185
299
  TestModel.reset_column_information
186
- TestModel.columns_hash["description"].limit.must_equal 4000
300
+ _(TestModel.columns_hash["description"].limit).must_equal 4000
187
301
  end
188
302
  end
189
303
  end
@@ -269,7 +383,7 @@ class MigrationTest < ActiveRecord::TestCase
269
383
  end
270
384
 
271
385
  # For some reason our tests set Rails.@_env which breaks test env switching.
272
- coerce_tests! :test_migration_sets_internal_metadata_even_when_fully_migrated
386
+ coerce_tests! :test_internal_metadata_stores_environment_when_other_data_exists
273
387
  coerce_tests! :test_internal_metadata_stores_environment
274
388
  end
275
389
 
@@ -295,6 +409,7 @@ module ActiveRecord
295
409
  # a value of 'default_env' will still show tests failing. Just ignoring all
296
410
  # of them since we have no monkey in this circus.
297
411
  MergeAndResolveDefaultUrlConfigTest.coerce_all_tests! if defined?(MergeAndResolveDefaultUrlConfigTest)
412
+ ConnectionHandlerTest.coerce_all_tests! if defined?(ConnectionHandlerTest)
298
413
  end
299
414
  end
300
415
 
@@ -302,6 +417,10 @@ end
302
417
 
303
418
 
304
419
  module ActiveRecord
420
+ class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
421
+ # Skip this test with /tmp/my_schema_cache.yml path on Windows.
422
+ coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
423
+ end
305
424
  class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
306
425
  # We extend `local_database?` so that common VM IPs can be used.
307
426
  coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
@@ -395,12 +514,6 @@ class FinderTest < ActiveRecord::TestCase
395
514
  end
396
515
  end if defined? JRUBY_VERSION
397
516
 
398
- coerce_tests! :test_string_sanitation
399
- def test_string_sanitation_coerced
400
- assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
401
- assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
402
- end
403
-
404
517
  coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
405
518
  def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
406
519
  assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
@@ -485,7 +598,7 @@ class InheritanceTest < ActiveRecord::TestCase
485
598
  coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
486
599
  def test_eager_load_belongs_to_primary_key_quoting_coerced
487
600
  con = Account.connection
488
- assert_sql(/\[companies\]\.\[id\] = 1/) do
601
+ assert_sql(/\[companies\]\.\[id\] = \?/) do
489
602
  Account.all.merge!(:includes => :firm).find(1)
490
603
  end
491
604
  end
@@ -538,6 +651,7 @@ end
538
651
 
539
652
 
540
653
 
654
+ require 'models/parrot'
541
655
  require 'models/topic'
542
656
  class PersistenceTest < ActiveRecord::TestCase
543
657
  # We can not UPDATE identity columns.
@@ -547,14 +661,14 @@ class PersistenceTest < ActiveRecord::TestCase
547
661
  coerce_tests! :test_update_all_doesnt_ignore_order
548
662
  def test_update_all_doesnt_ignore_order_coerced
549
663
  david, mary = authors(:david), authors(:mary)
550
- david.id.must_equal 1
551
- mary.id.must_equal 2
552
- david.name.wont_equal mary.name
664
+ _(david.id).must_equal 1
665
+ _(mary.id).must_equal 2
666
+ _(david.name).wont_equal mary.name
553
667
  assert_sql(/UPDATE.*\(SELECT \[authors\].\[id\] FROM \[authors\].*ORDER BY \[authors\].\[id\]/i) do
554
668
  Author.where('[id] > 1').order(:id).update_all(name: 'Test')
555
669
  end
556
- david.reload.name.must_equal 'David'
557
- mary.reload.name.must_equal 'Test'
670
+ _(david.reload.name).must_equal 'David'
671
+ _(mary.reload.name).must_equal 'Test'
558
672
  end
559
673
 
560
674
  # We can not UPDATE identity columns.
@@ -580,6 +694,19 @@ class PersistenceTest < ActiveRecord::TestCase
580
694
  # assert_nothing_raised { topic.reload }
581
695
  # assert_equal topic.title, Topic.find(1234).title
582
696
  end
697
+
698
+ coerce_tests! :test_delete_new_record
699
+ def test_delete_new_record_coerced
700
+ client = Client.new(name: "37signals")
701
+ client.delete
702
+ assert_predicate client, :frozen?
703
+
704
+ assert_not client.save
705
+ assert_raise(ActiveRecord::RecordNotSaved) { client.save! }
706
+
707
+ assert_predicate client, :frozen?
708
+ assert_raise(FrozenError) { client.name = "something else" } # For some reason we get a FrozenError instead of a RuntimeError here
709
+ end
583
710
  end
584
711
 
585
712
 
@@ -603,10 +730,19 @@ end
603
730
 
604
731
 
605
732
 
733
+ class PrimaryKeysTest < ActiveRecord::TestCase
734
+ # Gonna trust Rails core for this. We end up with 2 querys vs 3 asserted
735
+ # but as far as I can tell, this is only one for us anyway.
736
+ coerce_tests! :test_create_without_primary_key_no_extra_query
737
+ end
738
+
739
+
740
+
741
+
606
742
  require 'models/task'
607
743
  class QueryCacheTest < ActiveRecord::TestCase
608
- coerce_tests! :test_cache_does_not_wrap_string_results_in_arrays
609
- def test_cache_does_not_wrap_string_results_in_arrays_coerced
744
+ coerce_tests! :test_cache_does_not_wrap_results_in_arrays
745
+ def test_cache_does_not_wrap_results_in_arrays_coerced
610
746
  Task.cache do
611
747
  assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
612
748
  end
@@ -621,16 +757,16 @@ class RelationTest < ActiveRecord::TestCase
621
757
  # Use LEN vs LENGTH function.
622
758
  coerce_tests! :test_reverse_order_with_function
623
759
  def test_reverse_order_with_function_coerced
624
- topics = Topic.order("LEN(title)").reverse_order
760
+ topics = Topic.order(Arel.sql("LEN(title)")).reverse_order
625
761
  assert_equal topics(:second).title, topics.first.title
626
762
  end
627
763
 
628
764
  # Use LEN vs LENGTH function.
629
765
  coerce_tests! :test_reverse_order_with_function_other_predicates
630
766
  def test_reverse_order_with_function_other_predicates_coerced
631
- topics = Topic.order("author_name, LEN(title), id").reverse_order
767
+ topics = Topic.order(Arel.sql("author_name, LEN(title), id")).reverse_order
632
768
  assert_equal topics(:second).title, topics.first.title
633
- topics = Topic.order("LEN(author_name), id, LEN(title)").reverse_order
769
+ topics = Topic.order(Arel.sql("LEN(author_name), id, LEN(title)")).reverse_order
634
770
  assert_equal topics(:fifth).title, topics.first.title
635
771
  end
636
772
 
@@ -646,6 +782,60 @@ class RelationTest < ActiveRecord::TestCase
646
782
  # Leave it up to users to format selects/functions so HAVING works correctly.
647
783
  coerce_tests! :test_multiple_where_and_having_clauses
648
784
  coerce_tests! :test_having_with_binds_for_both_where_and_having
785
+
786
+ # Find any limit via our expression.
787
+ coerce_tests! %r{relations don't load all records in #inspect}
788
+ def test_relations_dont_load_all_records_in_inspect_coerced
789
+ assert_sql(/NEXT \? ROWS ONLY/) do
790
+ Post.all.inspect
791
+ end
792
+ end
793
+
794
+ # I wanted to add `.order("author_id")` scope to avoid error: Column "posts.id" is invalid in the ORDER BY
795
+ # However, this pull request on Rails core drops order on exists relation. https://github.com/rails/rails/pull/28699
796
+ # so we are skipping all together.
797
+ coerce_tests! :test_empty_complex_chained_relations
798
+
799
+ # Can't apply offset withour ORDER
800
+ coerce_tests! %r{using a custom table affects the wheres}
801
+ test 'using a custom table affects the wheres coerced' do
802
+ post = posts(:welcome)
803
+
804
+ assert_equal post, custom_post_relation.where!(title: post.title).order(:id).take
805
+ end
806
+
807
+ # Can't apply offset withour ORDER
808
+ coerce_tests! %r{using a custom table with joins affects the joins}
809
+ test 'using a custom table with joins affects the joins coerced' do
810
+ post = posts(:welcome)
811
+
812
+ assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).order(:id).take
813
+ end
814
+
815
+ # Use LEN() vs length() function.
816
+ coerce_tests! :test_reverse_arel_assoc_order_with_function
817
+ def test_reverse_arel_assoc_order_with_function_coerced
818
+ topics = Topic.order(Arel.sql("LEN(title)") => :asc).reverse_order
819
+ assert_equal topics(:second).title, topics.first.title
820
+ end
821
+ end
822
+
823
+ class ActiveRecord::RelationTest < ActiveRecord::TestCase
824
+ coerce_tests! :test_relation_merging_with_merged_symbol_joins_is_aliased
825
+ def test_relation_merging_with_merged_symbol_joins_is_aliased__coerced
826
+ categorizations_with_authors = Categorization.joins(:author)
827
+ queries = capture_sql { Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(categorizations_with_authors).to_a }
828
+
829
+ nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
830
+ assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query"
831
+
832
+ # using `\W` as the column separator
833
+ query_matches = queries.any? do |sql|
834
+ %r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+\Wauthors_categorizations\W]i.match?(sql)
835
+ end
836
+
837
+ assert query_matches, "Should be aliasing the child INNER JOINs in query"
838
+ end
649
839
  end
650
840
 
651
841
 
@@ -677,9 +867,6 @@ class SchemaDumperTest < ActiveRecord::TestCase
677
867
  assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 38}, output
678
868
  end
679
869
 
680
- # This accidently returns the wrong number because of our tables too.
681
- coerce_tests! :test_types_line_up
682
-
683
870
  # This is a poorly written test and really does not catch the bottom'ness it is meant too. Ours throw it off.
684
871
  coerce_tests! :test_foreign_keys_are_dumped_at_the_bottom_to_circumvent_dependency_issues
685
872
 
@@ -803,10 +990,55 @@ class DateTimePrecisionTest < ActiveRecord::TestCase
803
990
  end
804
991
  end
805
992
  end
993
+
994
+ unless defined? JRUBY_VERSION
995
+ # datetime is rounded to increments of .000, .003, or .007 seconds
996
+ coerce_tests! :test_datetime_precision_is_truncated_on_assignment
997
+ def test_datetime_precision_is_truncated_on_assignment_coerced
998
+ @connection.create_table(:foos, force: true)
999
+ @connection.add_column :foos, :created_at, :datetime, precision: 0
1000
+ @connection.add_column :foos, :updated_at, :datetime, precision: 6
1001
+
1002
+ time = ::Time.now.change(nsec: 123456789)
1003
+ foo = Foo.new(created_at: time, updated_at: time)
1004
+
1005
+ assert_equal 0, foo.created_at.nsec
1006
+ assert_equal 123457000, foo.updated_at.nsec
1007
+
1008
+ foo.save!
1009
+ foo.reload
1010
+
1011
+ assert_equal 0, foo.created_at.nsec
1012
+ assert_equal 123457000, foo.updated_at.nsec
1013
+ end
1014
+ end
806
1015
  end
807
1016
 
808
1017
 
809
1018
 
1019
+ class TimePrecisionTest < ActiveRecord::TestCase
1020
+ # datetime is rounded to increments of .000, .003, or .007 seconds
1021
+ coerce_tests! :test_time_precision_is_truncated_on_assignment
1022
+ def test_time_precision_is_truncated_on_assignment_coerced
1023
+ @connection.create_table(:foos, force: true)
1024
+ @connection.add_column :foos, :start, :time, precision: 0
1025
+ @connection.add_column :foos, :finish, :time, precision: 6
1026
+
1027
+ time = ::Time.now.change(nsec: 123456789)
1028
+ foo = Foo.new(start: time, finish: time)
1029
+
1030
+ assert_equal 0, foo.start.nsec
1031
+ assert_equal 123457000, foo.finish.nsec
1032
+
1033
+ foo.save!
1034
+ foo.reload
1035
+
1036
+ assert_equal 0, foo.start.nsec
1037
+ assert_equal 123457000, foo.finish.nsec
1038
+ end
1039
+ end unless defined? JRUBY_VERSION
1040
+
1041
+
810
1042
 
811
1043
  class DefaultNumbersTest < ActiveRecord::TestCase
812
1044
  # We do better with native types and do not return strings for everything.
@@ -843,3 +1075,151 @@ module ActiveRecord
843
1075
  #coerce_tests! :test_find_does_not_use_statement_cache_if_table_name_is_changed
844
1076
  end
845
1077
  end
1078
+
1079
+
1080
+
1081
+
1082
+ module ActiveRecord
1083
+ module ConnectionAdapters
1084
+ class SchemaCacheTest < ActiveRecord::TestCase
1085
+ private
1086
+ # We need to give the full path for this to work.
1087
+ def schema_dump_path
1088
+ File.join ARTest::SQLServer.root_activerecord, 'test/assets/schema_dump_5_1.yml'
1089
+ end
1090
+ end
1091
+ end
1092
+ end
1093
+
1094
+ class UnsafeRawSqlTest < ActiveRecord::TestCase
1095
+ coerce_tests! %r{always allows Arel}
1096
+ test 'order: always allows Arel' do
1097
+ ids_depr = with_unsafe_raw_sql_deprecated { Post.order(Arel.sql("len(title)")).pluck(:title) }
1098
+ ids_disabled = with_unsafe_raw_sql_disabled { Post.order(Arel.sql("len(title)")).pluck(:title) }
1099
+
1100
+ assert_equal ids_depr, ids_disabled
1101
+ end
1102
+
1103
+ test "pluck: always allows Arel" do
1104
+ values_depr = with_unsafe_raw_sql_deprecated { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
1105
+ values_disabled = with_unsafe_raw_sql_disabled { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
1106
+
1107
+ assert_equal values_depr, values_disabled
1108
+ end
1109
+
1110
+
1111
+ coerce_tests! %r{order: disallows invalid Array arguments}
1112
+ test "order: disallows invalid Array arguments" do
1113
+ with_unsafe_raw_sql_disabled do
1114
+ assert_raises(ActiveRecord::UnknownAttributeReference) do
1115
+ Post.order(["author_id", "len(title)"]).pluck(:id)
1116
+ end
1117
+ end
1118
+ end
1119
+
1120
+ coerce_tests! %r{order: allows valid Array arguments}
1121
+ test "order: allows valid Array arguments" do
1122
+ ids_expected = Post.order(Arel.sql("author_id, len(title)")).pluck(:id)
1123
+
1124
+ ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", Arel.sql("len(title)")]).pluck(:id) }
1125
+ ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", Arel.sql("len(title)")]).pluck(:id) }
1126
+
1127
+ assert_equal ids_expected, ids_depr
1128
+ assert_equal ids_expected, ids_disabled
1129
+ end
1130
+
1131
+ coerce_tests! %r{order: logs deprecation warning for unrecognized column}
1132
+ test "order: logs deprecation warning for unrecognized column" do
1133
+ with_unsafe_raw_sql_deprecated do
1134
+ assert_deprecated(/Dangerous query method/) do
1135
+ Post.order("len(title)")
1136
+ end
1137
+ end
1138
+ end
1139
+
1140
+ coerce_tests! %r{pluck: disallows invalid column name}
1141
+ test "pluck: disallows invalid column name" do
1142
+ with_unsafe_raw_sql_disabled do
1143
+ assert_raises(ActiveRecord::UnknownAttributeReference) do
1144
+ Post.pluck("len(title)")
1145
+ end
1146
+ end
1147
+ end
1148
+
1149
+ coerce_tests! %r{pluck: disallows invalid column name amongst valid names}
1150
+ test "pluck: disallows invalid column name amongst valid names" do
1151
+ with_unsafe_raw_sql_disabled do
1152
+ assert_raises(ActiveRecord::UnknownAttributeReference) do
1153
+ Post.pluck(:title, "len(title)")
1154
+ end
1155
+ end
1156
+ end
1157
+
1158
+ coerce_tests! %r{pluck: disallows invalid column names with includes}
1159
+ test "pluck: disallows invalid column names with includes" do
1160
+ with_unsafe_raw_sql_disabled do
1161
+ assert_raises(ActiveRecord::UnknownAttributeReference) do
1162
+ Post.includes(:comments).pluck(:title, "len(title)")
1163
+ end
1164
+ end
1165
+ end
1166
+
1167
+ coerce_tests! %r{pluck: logs deprecation warning}
1168
+ test "pluck: logs deprecation warning" do
1169
+ with_unsafe_raw_sql_deprecated do
1170
+ assert_deprecated(/Dangerous query method/) do
1171
+ Post.includes(:comments).pluck(:title, "len(title)")
1172
+ end
1173
+ end
1174
+ end
1175
+ end
1176
+
1177
+
1178
+ class ReservedWordTest < ActiveRecord::TestCase
1179
+ coerce_tests! :test_change_columns
1180
+ def test_change_columns_coerced
1181
+ assert_nothing_raised { @connection.change_column_default(:group, :order, "whatever") }
1182
+ assert_nothing_raised { @connection.change_column("group", "order", :text) }
1183
+ assert_nothing_raised { @connection.change_column_null("group", "order", true) }
1184
+ assert_nothing_raised { @connection.rename_column(:group, :order, :values) }
1185
+ end
1186
+ end
1187
+
1188
+
1189
+
1190
+ class OptimisticLockingTest < ActiveRecord::TestCase
1191
+ # We do not allow updating identities, but we can test using a non-identity key
1192
+ coerce_tests! :test_update_with_dirty_primary_key
1193
+ def test_update_with_dirty_primary_key_coerced
1194
+ assert_raises(ActiveRecord::RecordNotUnique) do
1195
+ record = StringKeyObject.find('record1')
1196
+ record.id = 'record2'
1197
+ record.save!
1198
+ end
1199
+
1200
+ record = StringKeyObject.find('record1')
1201
+ record.id = 'record42'
1202
+ record.save!
1203
+
1204
+ assert StringKeyObject.find('record42')
1205
+ assert_raises(ActiveRecord::RecordNotFound) do
1206
+ StringKeyObject.find('record1')
1207
+ end
1208
+ end
1209
+ end
1210
+
1211
+
1212
+
1213
+ class RelationMergingTest < ActiveRecord::TestCase
1214
+ coerce_tests! :test_merging_with_order_with_binds
1215
+ def test_merging_with_order_with_binds_coerced
1216
+ relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
1217
+ assert_equal ["title LIKE N'%suffix'"], relation.order_values
1218
+ end
1219
+ end
1220
+
1221
+
1222
+ class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
1223
+ # Temporarily coerce this test due to https://github.com/rails/rails/issues/34945
1224
+ coerce_tests! :test_eager_loading_too_may_ids
1225
+ end