activerecord-sqlserver-adapter 6.0.3 → 6.1.0.0.rc1
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -3
- data/CHANGELOG.md +18 -77
- data/Gemfile +1 -2
- data/README.md +13 -2
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +1 -1
- data/appveyor.yml +7 -5
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +0 -13
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +7 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +0 -2
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +27 -15
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -1
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -3
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +7 -5
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +27 -7
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +0 -1
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +83 -66
- data/lib/active_record/connection_adapters/sqlserver_column.rb +17 -0
- data/lib/active_record/sqlserver_base.rb +9 -15
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +17 -14
- data/lib/arel/visitors/sqlserver.rb +60 -28
- data/test/cases/adapter_test_sqlserver.rb +17 -15
- data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
- data/test/cases/coerced_tests.rb +470 -95
- data/test/cases/disconnected_test_sqlserver.rb +39 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +9 -0
- data/test/cases/in_clause_test_sqlserver.rb +27 -0
- data/test/cases/migration_test_sqlserver.rb +7 -0
- data/test/cases/order_test_sqlserver.rb +7 -0
- data/test/cases/primary_keys_test_sqlserver.rb +103 -0
- data/test/cases/rake_test_sqlserver.rb +3 -2
- data/test/cases/schema_dumper_test_sqlserver.rb +9 -0
- data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
- data/test/models/sqlserver/sst_string_collation.rb +3 -0
- data/test/schema/sqlserver_specific_schema.rb +7 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
- data/test/support/sql_counter_sqlserver.rb +14 -12
- metadata +23 -9
data/test/cases/coerced_tests.rb
CHANGED
@@ -24,22 +24,35 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
#
|
28
|
-
coerce_tests! :
|
29
|
-
def
|
30
|
-
|
31
|
-
skip if database_collation.include?("_CI_")
|
27
|
+
# Same as original coerced test except that it handles default SQL Server case-insensitive collation.
|
28
|
+
coerce_tests! :test_validate_uniqueness_by_default_database_collation
|
29
|
+
def test_validate_uniqueness_by_default_database_collation_coerced
|
30
|
+
Topic.validates_uniqueness_of(:author_email_address)
|
32
31
|
|
33
|
-
|
32
|
+
topic1 = Topic.new(author_email_address: "david@loudthinking.com")
|
33
|
+
topic2 = Topic.new(author_email_address: "David@loudthinking.com")
|
34
|
+
|
35
|
+
assert_equal 1, Topic.where(author_email_address: "david@loudthinking.com").count
|
36
|
+
|
37
|
+
assert_not topic1.valid?
|
38
|
+
assert_not topic1.save
|
39
|
+
|
40
|
+
# Case insensitive collation (SQL_Latin1_General_CP1_CI_AS) by default.
|
41
|
+
# Should not allow "David" if "david" exists.
|
42
|
+
assert_not topic2.valid?
|
43
|
+
assert_not topic2.save
|
44
|
+
|
45
|
+
assert_equal 1, Topic.where(author_email_address: "david@loudthinking.com").count
|
46
|
+
assert_equal 1, Topic.where(author_email_address: "David@loudthinking.com").count
|
34
47
|
end
|
35
48
|
end
|
36
49
|
|
37
50
|
require "models/event"
|
38
51
|
module ActiveRecord
|
39
52
|
class AdapterTest < ActiveRecord::TestCase
|
40
|
-
#
|
41
|
-
coerce_tests! :
|
42
|
-
coerce_tests! :
|
53
|
+
# Legacy binds are not supported.
|
54
|
+
coerce_tests! :test_select_all_insert_update_delete_with_casted_binds
|
55
|
+
coerce_tests! :test_select_all_insert_update_delete_with_legacy_binds
|
43
56
|
|
44
57
|
# As far as I can tell, SQL Server does not support null bytes in strings.
|
45
58
|
coerce_tests! :test_update_prepared_statement
|
@@ -54,13 +67,63 @@ module ActiveRecord
|
|
54
67
|
assert_not_nil error.cause
|
55
68
|
end
|
56
69
|
end
|
70
|
+
end
|
71
|
+
end
|
57
72
|
|
73
|
+
module ActiveRecord
|
74
|
+
class AdapterPreventWritesTest < ActiveRecord::TestCase
|
58
75
|
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
59
76
|
coerce_tests! :test_errors_when_an_insert_query_is_called_while_preventing_writes
|
60
77
|
def test_errors_when_an_insert_query_is_called_while_preventing_writes_coerced
|
61
78
|
Subscriber.send(:load_schema!)
|
62
79
|
original_test_errors_when_an_insert_query_is_called_while_preventing_writes
|
63
80
|
end
|
81
|
+
|
82
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
83
|
+
coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
|
84
|
+
def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes_coerced
|
85
|
+
Subscriber.send(:load_schema!)
|
86
|
+
original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
|
87
|
+
end
|
88
|
+
|
89
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
90
|
+
coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
|
91
|
+
def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes_coerced
|
92
|
+
Subscriber.send(:load_schema!)
|
93
|
+
original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
module ActiveRecord
|
99
|
+
class AdapterPreventWritesLegacyTest < ActiveRecord::TestCase
|
100
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
101
|
+
coerce_tests! :test_errors_when_an_insert_query_is_called_while_preventing_writes
|
102
|
+
def test_errors_when_an_insert_query_is_called_while_preventing_writes_coerced
|
103
|
+
Subscriber.send(:load_schema!)
|
104
|
+
original_test_errors_when_an_insert_query_is_called_while_preventing_writes
|
105
|
+
end
|
106
|
+
|
107
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
108
|
+
coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_slash_star_comment_is_called_while_preventing_writes
|
109
|
+
def test_errors_when_an_insert_query_prefixed_by_a_slash_star_comment_is_called_while_preventing_writes_coerced
|
110
|
+
Subscriber.send(:load_schema!)
|
111
|
+
original_test_errors_when_an_insert_query_prefixed_by_a_slash_star_comment_is_called_while_preventing_writes
|
112
|
+
end
|
113
|
+
|
114
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
115
|
+
coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
|
116
|
+
def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes_coerced
|
117
|
+
Subscriber.send(:load_schema!)
|
118
|
+
original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
|
119
|
+
end
|
120
|
+
|
121
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
122
|
+
coerce_tests! :test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
|
123
|
+
def test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes_coerced
|
124
|
+
Subscriber.send(:load_schema!)
|
125
|
+
original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_containing_read_command_is_called_while_preventing_writes
|
126
|
+
end
|
64
127
|
end
|
65
128
|
end
|
66
129
|
|
@@ -176,7 +239,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
176
239
|
# SQL Server does not have query for release_savepoint
|
177
240
|
coerce_tests! %r{an empty transaction does not raise if preventing writes}
|
178
241
|
test "an empty transaction does not raise if preventing writes coerced" do
|
179
|
-
ActiveRecord::Base.
|
242
|
+
ActiveRecord::Base.while_preventing_writes do
|
180
243
|
assert_queries(1, ignore_none: true) do
|
181
244
|
Bird.transaction do
|
182
245
|
ActiveRecord::Base.connection.materialize_transactions
|
@@ -234,6 +297,55 @@ module ActiveRecord
|
|
234
297
|
coerce_tests! :test_statement_cache_with_find_by
|
235
298
|
coerce_tests! :test_statement_cache_with_in_clause
|
236
299
|
coerce_tests! :test_statement_cache_with_sql_string_literal
|
300
|
+
|
301
|
+
# Same as original coerced test except prepared statements include `EXEC sp_executesql` wrapper.
|
302
|
+
coerce_tests! :test_bind_params_to_sql_with_prepared_statements, :test_bind_params_to_sql_with_unprepared_statements
|
303
|
+
def test_bind_params_to_sql_with_prepared_statements_coerced
|
304
|
+
assert_bind_params_to_sql_coerced(prepared: true)
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_bind_params_to_sql_with_unprepared_statements_coerced
|
308
|
+
@connection.unprepared_statement do
|
309
|
+
assert_bind_params_to_sql_coerced(prepared: false)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
private
|
314
|
+
|
315
|
+
def assert_bind_params_to_sql_coerced(prepared:)
|
316
|
+
table = Author.quoted_table_name
|
317
|
+
pk = "#{table}.#{Author.quoted_primary_key}"
|
318
|
+
|
319
|
+
# prepared_statements: true
|
320
|
+
#
|
321
|
+
# EXEC sp_executesql N'SELECT [authors].* FROM [authors] WHERE [authors].[id] IN (@0, @1, @2) OR [authors].[id] IS NULL)', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3
|
322
|
+
#
|
323
|
+
# prepared_statements: false
|
324
|
+
#
|
325
|
+
# SELECT [authors].* FROM [authors] WHERE ([authors].[id] IN (1, 2, 3) OR [authors].[id] IS NULL)
|
326
|
+
#
|
327
|
+
sql_unprepared = "SELECT #{table}.* FROM #{table} WHERE (#{pk} IN (#{bind_params(1..3)}) OR #{pk} IS NULL)"
|
328
|
+
sql_prepared = "EXEC sp_executesql N'SELECT #{table}.* FROM #{table} WHERE (#{pk} IN (#{bind_params(1..3)}) OR #{pk} IS NULL)', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3"
|
329
|
+
|
330
|
+
authors = Author.where(id: [1, 2, 3, nil])
|
331
|
+
assert_equal sql_unprepared, @connection.to_sql(authors.arel)
|
332
|
+
assert_sql(prepared ? sql_prepared : sql_unprepared) { assert_equal 3, authors.length }
|
333
|
+
|
334
|
+
# prepared_statements: true
|
335
|
+
#
|
336
|
+
# EXEC sp_executesql N'SELECT [authors].* FROM [authors] WHERE [authors].[id] IN (@0, @1, @2)', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3
|
337
|
+
#
|
338
|
+
# prepared_statements: false
|
339
|
+
#
|
340
|
+
# SELECT [authors].* FROM [authors] WHERE [authors].[id] IN (1, 2, 3)
|
341
|
+
#
|
342
|
+
sql_unprepared = "SELECT #{table}.* FROM #{table} WHERE #{pk} IN (#{bind_params(1..3)})"
|
343
|
+
sql_prepared = "EXEC sp_executesql N'SELECT #{table}.* FROM #{table} WHERE #{pk} IN (#{bind_params(1..3)})', N'@0 bigint, @1 bigint, @2 bigint', @0 = 1, @1 = 2, @2 = 3"
|
344
|
+
|
345
|
+
authors = Author.where(id: [1, 2, 3, 9223372036854775808])
|
346
|
+
assert_equal sql_unprepared, @connection.to_sql(authors.arel)
|
347
|
+
assert_sql(prepared ? sql_prepared : sql_unprepared) { assert_equal 3, authors.length }
|
348
|
+
end
|
237
349
|
end
|
238
350
|
end
|
239
351
|
|
@@ -256,11 +368,112 @@ class CalculationsTest < ActiveRecord::TestCase
|
|
256
368
|
original_test_offset_is_kept
|
257
369
|
end
|
258
370
|
|
259
|
-
#
|
371
|
+
# The SQL Server `AVG()` function for a list of integers returns an integer (not a decimal).
|
260
372
|
coerce_tests! :test_should_return_decimal_average_of_integer_field
|
261
373
|
def test_should_return_decimal_average_of_integer_field_coerced
|
262
374
|
value = Account.average(:id)
|
263
|
-
assert_equal
|
375
|
+
assert_equal 3, value
|
376
|
+
end
|
377
|
+
|
378
|
+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
|
379
|
+
# Match SQL Server limit implementation.
|
380
|
+
coerce_tests! :test_select_avg_with_group_by_as_virtual_attribute_with_sql
|
381
|
+
def test_select_avg_with_group_by_as_virtual_attribute_with_sql_coerced
|
382
|
+
rails_core = companies(:rails_core)
|
383
|
+
|
384
|
+
sql = <<~SQL
|
385
|
+
SELECT firm_id, AVG(CAST(credit_limit AS DECIMAL)) AS avg_credit_limit
|
386
|
+
FROM accounts
|
387
|
+
WHERE firm_id = ?
|
388
|
+
GROUP BY firm_id
|
389
|
+
ORDER BY firm_id
|
390
|
+
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
|
391
|
+
SQL
|
392
|
+
|
393
|
+
account = Account.find_by_sql([sql, rails_core]).first
|
394
|
+
|
395
|
+
# id was not selected, so it should be nil
|
396
|
+
# (cannot select id because it wasn't used in the GROUP BY clause)
|
397
|
+
assert_nil account.id
|
398
|
+
|
399
|
+
# firm_id was explicitly selected, so it should be present
|
400
|
+
assert_equal(rails_core, account.firm)
|
401
|
+
|
402
|
+
# avg_credit_limit should be present as a virtual attribute
|
403
|
+
assert_equal(52.5, account.avg_credit_limit)
|
404
|
+
end
|
405
|
+
|
406
|
+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
|
407
|
+
# Order column must be in the GROUP clause.
|
408
|
+
coerce_tests! :test_select_avg_with_group_by_as_virtual_attribute_with_ar
|
409
|
+
def test_select_avg_with_group_by_as_virtual_attribute_with_ar_coerced
|
410
|
+
rails_core = companies(:rails_core)
|
411
|
+
|
412
|
+
account = Account
|
413
|
+
.select(:firm_id, "AVG(CAST(credit_limit AS DECIMAL)) AS avg_credit_limit")
|
414
|
+
.where(firm: rails_core)
|
415
|
+
.group(:firm_id)
|
416
|
+
.order(:firm_id)
|
417
|
+
.take!
|
418
|
+
|
419
|
+
# id was not selected, so it should be nil
|
420
|
+
# (cannot select id because it wasn't used in the GROUP BY clause)
|
421
|
+
assert_nil account.id
|
422
|
+
|
423
|
+
# firm_id was explicitly selected, so it should be present
|
424
|
+
assert_equal(rails_core, account.firm)
|
425
|
+
|
426
|
+
# avg_credit_limit should be present as a virtual attribute
|
427
|
+
assert_equal(52.5, account.avg_credit_limit)
|
428
|
+
end
|
429
|
+
|
430
|
+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
|
431
|
+
# SELECT columns must be in the GROUP clause.
|
432
|
+
# Match SQL Server limit implementation.
|
433
|
+
coerce_tests! :test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql
|
434
|
+
def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_sql_coerced
|
435
|
+
rails_core = companies(:rails_core)
|
436
|
+
|
437
|
+
sql = <<~SQL
|
438
|
+
SELECT companies.*, AVG(CAST(accounts.credit_limit AS DECIMAL)) AS avg_credit_limit
|
439
|
+
FROM companies
|
440
|
+
INNER JOIN accounts ON companies.id = accounts.firm_id
|
441
|
+
WHERE companies.id = ?
|
442
|
+
GROUP BY companies.id, companies.type, companies.firm_id, companies.firm_name, companies.name, companies.client_of, companies.rating, companies.account_id, companies.description
|
443
|
+
ORDER BY companies.id
|
444
|
+
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
|
445
|
+
SQL
|
446
|
+
|
447
|
+
firm = DependentFirm.find_by_sql([sql, rails_core]).first
|
448
|
+
|
449
|
+
# all the DependentFirm attributes should be present
|
450
|
+
assert_equal rails_core, firm
|
451
|
+
assert_equal rails_core.name, firm.name
|
452
|
+
|
453
|
+
# avg_credit_limit should be present as a virtual attribute
|
454
|
+
assert_equal(52.5, firm.avg_credit_limit)
|
455
|
+
end
|
456
|
+
|
457
|
+
|
458
|
+
# In SQL Server the `AVG()` function for a list of integers returns an integer so need to cast values as decimals before averaging.
|
459
|
+
# SELECT columns must be in the GROUP clause.
|
460
|
+
coerce_tests! :test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar
|
461
|
+
def test_select_avg_with_joins_and_group_by_as_virtual_attribute_with_ar_coerced
|
462
|
+
rails_core = companies(:rails_core)
|
463
|
+
|
464
|
+
firm = DependentFirm
|
465
|
+
.select("companies.*", "AVG(CAST(accounts.credit_limit AS DECIMAL)) AS avg_credit_limit")
|
466
|
+
.where(id: rails_core)
|
467
|
+
.joins(:account)
|
468
|
+
.group(:id, :type, :firm_id, :firm_name, :name, :client_of, :rating, :account_id, :description)
|
469
|
+
.take!
|
470
|
+
|
471
|
+
# all the DependentFirm attributes should be present
|
472
|
+
assert_equal rails_core, firm
|
473
|
+
assert_equal rails_core.name, firm.name
|
474
|
+
|
475
|
+
# avg_credit_limit should be present as a virtual attribute
|
476
|
+
assert_equal(52.5, firm.avg_credit_limit)
|
264
477
|
end
|
265
478
|
|
266
479
|
# Match SQL Server limit implementation
|
@@ -329,14 +542,18 @@ module ActiveRecord
|
|
329
542
|
coerce_tests! :test_quote_ar_object
|
330
543
|
def test_quote_ar_object_coerced
|
331
544
|
value = DatetimePrimaryKey.new(id: @time)
|
332
|
-
|
545
|
+
assert_deprecated do
|
546
|
+
assert_equal "'02-14-2017 12:34:56.79'", @connection.quote(value)
|
547
|
+
end
|
333
548
|
end
|
334
549
|
|
335
550
|
# Use our date format.
|
336
551
|
coerce_tests! :test_type_cast_ar_object
|
337
552
|
def test_type_cast_ar_object_coerced
|
338
553
|
value = DatetimePrimaryKey.new(id: @time)
|
339
|
-
|
554
|
+
assert_deprecated do
|
555
|
+
assert_equal "02-14-2017 12:34:56.79", @connection.type_cast(value)
|
556
|
+
end
|
340
557
|
end
|
341
558
|
end
|
342
559
|
end
|
@@ -551,11 +768,6 @@ module ActiveRecord
|
|
551
768
|
end
|
552
769
|
end
|
553
770
|
|
554
|
-
class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
|
555
|
-
# Skip this test with /tmp/my_schema_cache.yml path on Windows.
|
556
|
-
coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
557
|
-
end
|
558
|
-
|
559
771
|
class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
|
560
772
|
# We extend `local_database?` so that common VM IPs can be used.
|
561
773
|
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
@@ -620,7 +832,11 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
620
832
|
end
|
621
833
|
|
622
834
|
require "models/topic"
|
835
|
+
require "models/customer"
|
836
|
+
require "models/non_primary_key"
|
623
837
|
class FinderTest < ActiveRecord::TestCase
|
838
|
+
fixtures :customers, :topics, :authors
|
839
|
+
|
624
840
|
# We have implicit ordering, via FETCH.
|
625
841
|
coerce_tests! %r{doesn't have implicit ordering},
|
626
842
|
:test_find_doesnt_have_implicit_ordering
|
@@ -665,6 +881,87 @@ class FinderTest < ActiveRecord::TestCase
|
|
665
881
|
end
|
666
882
|
end
|
667
883
|
end
|
884
|
+
|
885
|
+
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
|
886
|
+
coerce_tests! :test_include_on_unloaded_relation_with_match
|
887
|
+
def test_include_on_unloaded_relation_with_match_coerced
|
888
|
+
assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
|
889
|
+
assert_equal true, Customer.where(name: "David").include?(customers(:david))
|
890
|
+
end
|
891
|
+
end
|
892
|
+
|
893
|
+
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
|
894
|
+
coerce_tests! :test_include_on_unloaded_relation_without_match
|
895
|
+
def test_include_on_unloaded_relation_without_match_coerced
|
896
|
+
assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
|
897
|
+
assert_equal false, Customer.where(name: "David").include?(customers(:mary))
|
898
|
+
end
|
899
|
+
end
|
900
|
+
|
901
|
+
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
|
902
|
+
coerce_tests! :test_member_on_unloaded_relation_with_match
|
903
|
+
def test_member_on_unloaded_relation_with_match_coerced
|
904
|
+
assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
|
905
|
+
assert_equal true, Customer.where(name: "David").member?(customers(:david))
|
906
|
+
end
|
907
|
+
end
|
908
|
+
|
909
|
+
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
|
910
|
+
coerce_tests! :test_member_on_unloaded_relation_without_match
|
911
|
+
def test_member_on_unloaded_relation_without_match_coerced
|
912
|
+
assert_sql(/1 AS one.*FETCH NEXT @2 ROWS ONLY.*@2 = 1/) do
|
913
|
+
assert_equal false, Customer.where(name: "David").member?(customers(:mary))
|
914
|
+
end
|
915
|
+
end
|
916
|
+
|
917
|
+
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
|
918
|
+
coerce_tests! :test_implicit_order_column_is_configurable
|
919
|
+
def test_implicit_order_column_is_configurable_coerced
|
920
|
+
old_implicit_order_column = Topic.implicit_order_column
|
921
|
+
Topic.implicit_order_column = "title"
|
922
|
+
|
923
|
+
assert_equal topics(:fifth), Topic.first
|
924
|
+
assert_equal topics(:third), Topic.last
|
925
|
+
|
926
|
+
c = Topic.connection
|
927
|
+
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.title"))} DESC, #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
|
928
|
+
Topic.last
|
929
|
+
}
|
930
|
+
ensure
|
931
|
+
Topic.implicit_order_column = old_implicit_order_column
|
932
|
+
end
|
933
|
+
|
934
|
+
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
|
935
|
+
coerce_tests! :test_implicit_order_set_to_primary_key
|
936
|
+
def test_implicit_order_set_to_primary_key_coerced
|
937
|
+
old_implicit_order_column = Topic.implicit_order_column
|
938
|
+
Topic.implicit_order_column = "id"
|
939
|
+
|
940
|
+
c = Topic.connection
|
941
|
+
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("topics.id"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
|
942
|
+
Topic.last
|
943
|
+
}
|
944
|
+
ensure
|
945
|
+
Topic.implicit_order_column = old_implicit_order_column
|
946
|
+
end
|
947
|
+
|
948
|
+
# Check for `FETCH NEXT x ROWS` rather then `LIMIT`.
|
949
|
+
coerce_tests! :test_implicit_order_for_model_without_primary_key
|
950
|
+
def test_implicit_order_for_model_without_primary_key_coerced
|
951
|
+
old_implicit_order_column = NonPrimaryKey.implicit_order_column
|
952
|
+
NonPrimaryKey.implicit_order_column = "created_at"
|
953
|
+
|
954
|
+
c = NonPrimaryKey.connection
|
955
|
+
|
956
|
+
assert_sql(/ORDER BY #{Regexp.escape(c.quote_table_name("non_primary_keys.created_at"))} DESC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) {
|
957
|
+
NonPrimaryKey.last
|
958
|
+
}
|
959
|
+
ensure
|
960
|
+
NonPrimaryKey.implicit_order_column = old_implicit_order_column
|
961
|
+
end
|
962
|
+
|
963
|
+
# SQL Server is unable to use aliased SELECT in the HAVING clause.
|
964
|
+
coerce_tests! :test_include_on_unloaded_relation_with_having_referencing_aliased_select
|
668
965
|
end
|
669
966
|
|
670
967
|
module ActiveRecord
|
@@ -896,7 +1193,14 @@ class RelationTest < ActiveRecord::TestCase
|
|
896
1193
|
coerce_tests! :test_reorder_with_first
|
897
1194
|
def test_reorder_with_first_coerced
|
898
1195
|
sql_log = capture_sql do
|
899
|
-
|
1196
|
+
message = <<~MSG.squish
|
1197
|
+
`.reorder(nil)` with `.first` / `.first!` no longer
|
1198
|
+
takes non-deterministic result in Rails 6.2.
|
1199
|
+
To continue taking non-deterministic result, use `.take` / `.take!` instead.
|
1200
|
+
MSG
|
1201
|
+
assert_deprecated(message) do
|
1202
|
+
assert Post.order(:title).reorder(nil).first
|
1203
|
+
end
|
900
1204
|
end
|
901
1205
|
assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
|
902
1206
|
assert sql_log.all? { |sql| /order by \[posts\]\.\[id\]/i.match?(sql) }, "default ORDER BY ID was not used in the query: #{sql_log}"
|
@@ -961,6 +1265,16 @@ module ActiveRecord
|
|
961
1265
|
query = Post.optimizer_hints("OMGHINT").merge(Post.optimizer_hints("OMGHINT")).to_sql
|
962
1266
|
assert_equal expected, query
|
963
1267
|
end
|
1268
|
+
|
1269
|
+
# Original Rails test fails on Windows CI because the dump file was not being binary read.
|
1270
|
+
coerce_tests! :test_marshal_load_legacy_relation
|
1271
|
+
def test_marshal_load_legacy_relation_coerced
|
1272
|
+
path = File.expand_path(
|
1273
|
+
"support/marshal_compatibility_fixtures/legacy_relation.dump",
|
1274
|
+
ARTest::SQLServer.root_activerecord_test
|
1275
|
+
)
|
1276
|
+
assert_equal 11, Marshal.load(File.binread(path)).size
|
1277
|
+
end
|
964
1278
|
end
|
965
1279
|
end
|
966
1280
|
|
@@ -1088,8 +1402,7 @@ class YamlSerializationTest < ActiveRecord::TestCase
|
|
1088
1402
|
coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
|
1089
1403
|
def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
|
1090
1404
|
author = Author.select("authors.*, 5 as posts_count").first
|
1091
|
-
|
1092
|
-
dumped = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(dumped_author) : YAML.load(dumped_author)
|
1405
|
+
dumped = YAML.load(YAML.dump(author))
|
1093
1406
|
assert_equal 5, author.posts_count
|
1094
1407
|
assert_equal 5, dumped.posts_count
|
1095
1408
|
end
|
@@ -1208,7 +1521,6 @@ module ActiveRecord
|
|
1208
1521
|
|
1209
1522
|
original_test_statement_cache_values_differ
|
1210
1523
|
ensure
|
1211
|
-
Book.where(author_id: nil, name: 'my book').delete_all
|
1212
1524
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1213
1525
|
end
|
1214
1526
|
end
|
@@ -1217,8 +1529,43 @@ end
|
|
1217
1529
|
module ActiveRecord
|
1218
1530
|
module ConnectionAdapters
|
1219
1531
|
class SchemaCacheTest < ActiveRecord::TestCase
|
1532
|
+
# Tests fail on Windows AppVeyor CI with 'Permission denied' error when renaming file during `File.atomic_write` call.
|
1533
|
+
coerce_tests! :test_yaml_dump_and_load, :test_yaml_dump_and_load_with_gzip if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
1534
|
+
|
1535
|
+
# Ruby 2.5 and 2.6 have issues to marshal Time before 1900. 2012.sql has one column with default value 1753
|
1536
|
+
coerce_tests! :test_marshal_dump_and_load_with_gzip, :test_marshal_dump_and_load_via_disk
|
1537
|
+
|
1538
|
+
# Tests fail on Windows AppVeyor CI with 'Permission denied' error when renaming file during `File.atomic_write` call.
|
1539
|
+
unless RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
1540
|
+
def test_marshal_dump_and_load_with_gzip_coerced
|
1541
|
+
with_marshable_time_defaults { original_test_marshal_dump_and_load_with_gzip }
|
1542
|
+
end
|
1543
|
+
def test_marshal_dump_and_load_via_disk_coerced
|
1544
|
+
with_marshable_time_defaults { original_test_marshal_dump_and_load_via_disk }
|
1545
|
+
end
|
1546
|
+
end
|
1547
|
+
|
1220
1548
|
private
|
1221
1549
|
|
1550
|
+
def with_marshable_time_defaults
|
1551
|
+
# Detect problems
|
1552
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7")
|
1553
|
+
column = @connection.columns(:sst_datatypes).find { |c| c.name == "datetime" }
|
1554
|
+
current_default = column.default if column.default.is_a?(Time) && column.default.year < 1900
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
# Correct problems
|
1558
|
+
if current_default.present?
|
1559
|
+
@connection.change_column_default(:sst_datatypes, :datetime, current_default.dup.change(year: 1900))
|
1560
|
+
end
|
1561
|
+
|
1562
|
+
# Run original test
|
1563
|
+
yield
|
1564
|
+
ensure
|
1565
|
+
# Revert changes
|
1566
|
+
@connection.change_column_default(:sst_datatypes, :datetime, current_default) if current_default.present?
|
1567
|
+
end
|
1568
|
+
|
1222
1569
|
# We need to give the full path for this to work.
|
1223
1570
|
def schema_dump_path
|
1224
1571
|
File.join ARTest::SQLServer.root_activerecord, "test/assets/schema_dump_5_1.yml"
|
@@ -1235,19 +1582,18 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
1235
1582
|
# Use LEN() vs length() function.
|
1236
1583
|
coerce_tests! %r{order: always allows Arel}
|
1237
1584
|
test "order: always allows Arel" do
|
1238
|
-
|
1239
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(Arel.sql("len(title)")).pluck(:title) }
|
1585
|
+
titles = Post.order(Arel.sql("len(title)")).pluck(:title)
|
1240
1586
|
|
1241
|
-
|
1587
|
+
assert_not_empty titles
|
1242
1588
|
end
|
1243
1589
|
|
1244
1590
|
# Use LEN() vs length() function.
|
1245
1591
|
coerce_tests! %r{pluck: always allows Arel}
|
1246
1592
|
test "pluck: always allows Arel" do
|
1247
|
-
|
1248
|
-
|
1593
|
+
excepted_values = Post.includes(:comments).pluck(:title).map { |title| [title, title.size] }
|
1594
|
+
values = Post.includes(:comments).pluck(:title, Arel.sql("len(title)"))
|
1249
1595
|
|
1250
|
-
assert_equal
|
1596
|
+
assert_equal excepted_values, values
|
1251
1597
|
end
|
1252
1598
|
|
1253
1599
|
# Use LEN() vs length() function.
|
@@ -1255,91 +1601,73 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
1255
1601
|
test "order: allows valid Array arguments" do
|
1256
1602
|
ids_expected = Post.order(Arel.sql("author_id, len(title)")).pluck(:id)
|
1257
1603
|
|
1258
|
-
|
1259
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", "len(title)"]).pluck(:id) }
|
1604
|
+
ids = Post.order(["author_id", "len(title)"]).pluck(:id)
|
1260
1605
|
|
1261
|
-
assert_equal ids_expected,
|
1262
|
-
assert_equal ids_expected, ids_disabled
|
1606
|
+
assert_equal ids_expected, ids
|
1263
1607
|
end
|
1264
1608
|
|
1265
1609
|
test "order: allows string column names that are quoted" do
|
1266
1610
|
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1267
1611
|
|
1268
|
-
|
1269
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[id]").pluck(:id) }
|
1612
|
+
ids = Post.order("[id]").pluck(:id)
|
1270
1613
|
|
1271
|
-
assert_equal ids_expected,
|
1272
|
-
assert_equal ids_expected, ids_disabled
|
1614
|
+
assert_equal ids_expected, ids
|
1273
1615
|
end
|
1274
1616
|
|
1275
1617
|
test "order: allows string column names that are quoted with table" do
|
1276
1618
|
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1277
1619
|
|
1278
|
-
|
1279
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[posts].[id]").pluck(:id) }
|
1620
|
+
ids = Post.order("[posts].[id]").pluck(:id)
|
1280
1621
|
|
1281
|
-
assert_equal ids_expected,
|
1282
|
-
assert_equal ids_expected, ids_disabled
|
1622
|
+
assert_equal ids_expected, ids
|
1283
1623
|
end
|
1284
1624
|
|
1285
1625
|
test "order: allows string column names that are quoted with table and user" do
|
1286
1626
|
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1287
1627
|
|
1288
|
-
|
1289
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[dbo].[posts].[id]").pluck(:id) }
|
1628
|
+
ids = Post.order("[dbo].[posts].[id]").pluck(:id)
|
1290
1629
|
|
1291
|
-
assert_equal ids_expected,
|
1292
|
-
assert_equal ids_expected, ids_disabled
|
1630
|
+
assert_equal ids_expected, ids
|
1293
1631
|
end
|
1294
1632
|
|
1295
1633
|
test "order: allows string column names that are quoted with table, user and database" do
|
1296
1634
|
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1297
1635
|
|
1298
|
-
|
1299
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[activerecord_unittest].[dbo].[posts].[id]").pluck(:id) }
|
1636
|
+
ids = Post.order("[activerecord_unittest].[dbo].[posts].[id]").pluck(:id)
|
1300
1637
|
|
1301
|
-
assert_equal ids_expected,
|
1302
|
-
assert_equal ids_expected, ids_disabled
|
1638
|
+
assert_equal ids_expected, ids
|
1303
1639
|
end
|
1304
1640
|
|
1305
1641
|
test "pluck: allows string column name that are quoted" do
|
1306
1642
|
titles_expected = Post.pluck(Arel.sql("title"))
|
1307
1643
|
|
1308
|
-
|
1309
|
-
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[title]") }
|
1644
|
+
titles = Post.pluck("[title]")
|
1310
1645
|
|
1311
|
-
assert_equal titles_expected,
|
1312
|
-
assert_equal titles_expected, titles_disabled
|
1646
|
+
assert_equal titles_expected, titles
|
1313
1647
|
end
|
1314
1648
|
|
1315
1649
|
test "pluck: allows string column name that are quoted with table" do
|
1316
1650
|
titles_expected = Post.pluck(Arel.sql("title"))
|
1317
1651
|
|
1318
|
-
|
1319
|
-
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[posts].[title]") }
|
1652
|
+
titles = Post.pluck("[posts].[title]")
|
1320
1653
|
|
1321
|
-
assert_equal titles_expected,
|
1322
|
-
assert_equal titles_expected, titles_disabled
|
1654
|
+
assert_equal titles_expected, titles
|
1323
1655
|
end
|
1324
1656
|
|
1325
1657
|
test "pluck: allows string column name that are quoted with table and user" do
|
1326
1658
|
titles_expected = Post.pluck(Arel.sql("title"))
|
1327
1659
|
|
1328
|
-
|
1329
|
-
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[dbo].[posts].[title]") }
|
1660
|
+
titles = Post.pluck("[dbo].[posts].[title]")
|
1330
1661
|
|
1331
|
-
assert_equal titles_expected,
|
1332
|
-
assert_equal titles_expected, titles_disabled
|
1662
|
+
assert_equal titles_expected, titles
|
1333
1663
|
end
|
1334
1664
|
|
1335
1665
|
test "pluck: allows string column name that are quoted with table, user and database" do
|
1336
1666
|
titles_expected = Post.pluck(Arel.sql("title"))
|
1337
1667
|
|
1338
|
-
|
1339
|
-
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[activerecord_unittest].[dbo].[posts].[title]") }
|
1668
|
+
titles = Post.pluck("[activerecord_unittest].[dbo].[posts].[title]")
|
1340
1669
|
|
1341
|
-
assert_equal titles_expected,
|
1342
|
-
assert_equal titles_expected, titles_disabled
|
1670
|
+
assert_equal titles_expected, titles
|
1343
1671
|
end
|
1344
1672
|
end
|
1345
1673
|
|
@@ -1381,6 +1709,25 @@ class RelationMergingTest < ActiveRecord::TestCase
|
|
1381
1709
|
relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
|
1382
1710
|
assert_equal ["title LIKE N'%suffix'"], relation.order_values
|
1383
1711
|
end
|
1712
|
+
|
1713
|
+
# Same as original but change first regexp to match sp_executesql binding syntax
|
1714
|
+
coerce_tests! :test_merge_doesnt_duplicate_same_clauses
|
1715
|
+
def test_merge_doesnt_duplicate_same_clauses_coerced
|
1716
|
+
david, mary, bob = authors(:david, :mary, :bob)
|
1717
|
+
|
1718
|
+
non_mary_and_bob = Author.where.not(id: [mary, bob])
|
1719
|
+
|
1720
|
+
author_id = Author.connection.quote_table_name("authors.id")
|
1721
|
+
assert_sql(/WHERE #{Regexp.escape(author_id)} NOT IN \((@\d), \g<1>\)'/) do
|
1722
|
+
assert_equal [david], non_mary_and_bob.merge(non_mary_and_bob)
|
1723
|
+
end
|
1724
|
+
|
1725
|
+
only_david = Author.where("#{author_id} IN (?)", david)
|
1726
|
+
|
1727
|
+
assert_sql(/WHERE \(#{Regexp.escape(author_id)} IN \(1\)\)\z/) do
|
1728
|
+
assert_equal [david], only_david.merge(only_david)
|
1729
|
+
end
|
1730
|
+
end
|
1384
1731
|
end
|
1385
1732
|
|
1386
1733
|
module ActiveRecord
|
@@ -1401,7 +1748,6 @@ class EnumTest < ActiveRecord::TestCase
|
|
1401
1748
|
|
1402
1749
|
send(:'original_enums are distinct per class')
|
1403
1750
|
ensure
|
1404
|
-
Book.where(author_id: nil, name: nil).delete_all
|
1405
1751
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1406
1752
|
end
|
1407
1753
|
|
@@ -1412,7 +1758,6 @@ class EnumTest < ActiveRecord::TestCase
|
|
1412
1758
|
|
1413
1759
|
send(:'original_creating new objects with enum scopes')
|
1414
1760
|
ensure
|
1415
|
-
Book.where(author_id: nil, name: nil).delete_all
|
1416
1761
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1417
1762
|
end
|
1418
1763
|
|
@@ -1423,7 +1768,6 @@ class EnumTest < ActiveRecord::TestCase
|
|
1423
1768
|
|
1424
1769
|
send(:'original_enums are inheritable')
|
1425
1770
|
ensure
|
1426
|
-
Book.where(author_id: nil, name: nil).delete_all
|
1427
1771
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1428
1772
|
end
|
1429
1773
|
|
@@ -1434,7 +1778,6 @@ class EnumTest < ActiveRecord::TestCase
|
|
1434
1778
|
|
1435
1779
|
send(:'original_declare multiple enums at a time')
|
1436
1780
|
ensure
|
1437
|
-
Book.where(author_id: nil, name: nil).delete_all
|
1438
1781
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1439
1782
|
end
|
1440
1783
|
end
|
@@ -1472,6 +1815,8 @@ end
|
|
1472
1815
|
|
1473
1816
|
require "models/citation"
|
1474
1817
|
class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
|
1818
|
+
fixtures :citations
|
1819
|
+
|
1475
1820
|
# Original Rails test fails with SQL Server error message "The query processor ran out of internal resources and
|
1476
1821
|
# could not produce a query plan". This error goes away if you change database compatibility level to 110 (SQL 2012)
|
1477
1822
|
# (see https://www.mssqltips.com/sqlservertip/5279/sql-server-error-query-processor-ran-out-of-internal-resources-and-could-not-produce-a-query-plan/).
|
@@ -1479,14 +1824,14 @@ class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
|
|
1479
1824
|
# unprepared statement is used if the number of values exceeds the adapter's `bind_params_length`. The coerced test
|
1480
1825
|
# still does this as there will be 32,768 remaining citation records in the database and the `bind_params_length` of
|
1481
1826
|
# adapter is 2,098.
|
1482
|
-
coerce_tests! :
|
1483
|
-
def
|
1827
|
+
coerce_tests! :test_eager_loading_too_many_ids
|
1828
|
+
def test_eager_loading_too_many_ids_coerced
|
1484
1829
|
# Remove excess records.
|
1485
1830
|
Citation.limit(32768).order(id: :desc).delete_all
|
1486
1831
|
|
1487
1832
|
# Perform test
|
1488
1833
|
citation_count = Citation.count
|
1489
|
-
assert_sql(/WHERE \
|
1834
|
+
assert_sql(/WHERE \[citations\]\.\[id\] IN \(0, 1/) do
|
1490
1835
|
assert_equal citation_count, Citation.eager_load(:citations).offset(0).size
|
1491
1836
|
end
|
1492
1837
|
end
|
@@ -1509,22 +1854,8 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase
|
|
1509
1854
|
end
|
1510
1855
|
end
|
1511
1856
|
|
1512
|
-
module ActiveRecord
|
1513
|
-
module ConnectionAdapters
|
1514
|
-
class ReaperTest < ActiveRecord::TestCase
|
1515
|
-
# Coerce can be removed if Rails version > 6.0.3
|
1516
|
-
coerce_tests! :test_connection_pool_starts_reaper_in_fork unless Process.respond_to?(:fork)
|
1517
|
-
end
|
1518
|
-
end
|
1519
|
-
end
|
1520
|
-
|
1521
|
-
class FixturesTest < ActiveRecord::TestCase
|
1522
|
-
# Skip test on Windows. Skip can be removed when Rails PR https://github.com/rails/rails/pull/39234 has been merged.
|
1523
|
-
coerce_tests! :test_binary_in_fixtures if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
1524
|
-
end
|
1525
|
-
|
1526
1857
|
class ReloadModelsTest < ActiveRecord::TestCase
|
1527
|
-
# Skip test on Windows. The number of
|
1858
|
+
# Skip test on Windows. The number of arguments passed to `IO.popen` in
|
1528
1859
|
# `activesupport/lib/active_support/testing/isolation.rb` exceeds what Windows can handle.
|
1529
1860
|
coerce_tests! :test_has_one_with_reload if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
1530
1861
|
end
|
@@ -1549,22 +1880,17 @@ class AnnotateTest < ActiveRecord::TestCase
|
|
1549
1880
|
def test_annotate_is_sanitized_coerced
|
1550
1881
|
quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
|
1551
1882
|
|
1552
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\*
|
1883
|
+
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
|
1553
1884
|
posts = Post.select(:id).annotate("*/foo/*")
|
1554
1885
|
assert posts.first
|
1555
1886
|
end
|
1556
1887
|
|
1557
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\*
|
1888
|
+
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
|
1558
1889
|
posts = Post.select(:id).annotate("**//foo//**")
|
1559
1890
|
assert posts.first
|
1560
1891
|
end
|
1561
1892
|
|
1562
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\*
|
1563
|
-
posts = Post.select(:id).annotate("* *//foo//* *")
|
1564
|
-
assert posts.first
|
1565
|
-
end
|
1566
|
-
|
1567
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/ /\* \* /bar \*/}i) do
|
1893
|
+
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/ /\* bar \*/}i) do
|
1568
1894
|
posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
|
1569
1895
|
assert posts.first
|
1570
1896
|
end
|
@@ -1576,6 +1902,17 @@ class AnnotateTest < ActiveRecord::TestCase
|
|
1576
1902
|
end
|
1577
1903
|
end
|
1578
1904
|
|
1905
|
+
class MarshalSerializationTest < ActiveRecord::TestCase
|
1906
|
+
private
|
1907
|
+
|
1908
|
+
def marshal_fixture_path(file_name)
|
1909
|
+
File.expand_path(
|
1910
|
+
"support/marshal_compatibility_fixtures/#{ActiveRecord::Base.connection.adapter_name}/#{file_name}.dump",
|
1911
|
+
ARTest::SQLServer.test_root_sqlserver
|
1912
|
+
)
|
1913
|
+
end
|
1914
|
+
end
|
1915
|
+
|
1579
1916
|
class NestedThroughAssociationsTest < ActiveRecord::TestCase
|
1580
1917
|
# Same as original but replace order with "order(:id)" to ensure that assert_includes_and_joins_equal doesn't raise
|
1581
1918
|
# "A column has been specified more than once in the order by list"
|
@@ -1601,3 +1938,41 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase
|
|
1601
1938
|
)
|
1602
1939
|
end
|
1603
1940
|
end
|
1941
|
+
|
1942
|
+
class BasePreventWritesTest < ActiveRecord::TestCase
|
1943
|
+
# SQL Server does not have query for release_savepoint
|
1944
|
+
coerce_tests! %r{an empty transaction does not raise if preventing writes}
|
1945
|
+
test "an empty transaction does not raise if preventing writes coerced" do
|
1946
|
+
ActiveRecord::Base.while_preventing_writes do
|
1947
|
+
assert_queries(1, ignore_none: true) do
|
1948
|
+
Bird.transaction do
|
1949
|
+
ActiveRecord::Base.connection.materialize_transactions
|
1950
|
+
end
|
1951
|
+
end
|
1952
|
+
end
|
1953
|
+
end
|
1954
|
+
|
1955
|
+
class BasePreventWritesLegacyTest < ActiveRecord::TestCase
|
1956
|
+
# SQL Server does not have query for release_savepoint
|
1957
|
+
coerce_tests! %r{an empty transaction does not raise if preventing writes}
|
1958
|
+
test "an empty transaction does not raise if preventing writes coerced" do
|
1959
|
+
ActiveRecord::Base.connection_handler.while_preventing_writes do
|
1960
|
+
assert_queries(1, ignore_none: true) do
|
1961
|
+
Bird.transaction do
|
1962
|
+
ActiveRecord::Base.connection.materialize_transactions
|
1963
|
+
end
|
1964
|
+
end
|
1965
|
+
end
|
1966
|
+
end
|
1967
|
+
end
|
1968
|
+
end
|
1969
|
+
|
1970
|
+
class MigratorTest < ActiveRecord::TestCase
|
1971
|
+
# Test fails on Windows AppVeyor CI for unknown reason.
|
1972
|
+
coerce_tests! :test_migrator_db_has_no_schema_migrations_table if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
1973
|
+
end
|
1974
|
+
|
1975
|
+
class MultiDbMigratorTest < ActiveRecord::TestCase
|
1976
|
+
# Test fails on Windows AppVeyor CI for unknown reason.
|
1977
|
+
coerce_tests! :test_migrator_db_has_no_schema_migrations_table if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
1978
|
+
end
|