activerecord-sqlserver-adapter 6.1.3.0 → 7.0.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -69
  3. data/Gemfile +2 -4
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +7 -7
  6. data/VERSION +1 -1
  7. data/activerecord-sqlserver-adapter.gemspec +2 -2
  8. data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +7 -15
  9. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +13 -6
  10. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +2 -4
  11. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +9 -11
  12. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +15 -1
  13. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +3 -1
  14. data/lib/active_record/connection_adapters/sqlserver/type/date.rb +1 -1
  15. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +1 -1
  16. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -1
  17. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +92 -87
  18. data/lib/arel/visitors/sqlserver.rb +2 -0
  19. data/test/cases/coerced_tests.rb +287 -89
  20. data/test/cases/column_test_sqlserver.rb +58 -58
  21. data/test/cases/eager_load_too_many_ids_test_sqlserver.rb +18 -0
  22. data/test/cases/schema_dumper_test_sqlserver.rb +2 -2
  23. data/test/migrations/transaction_table/1_table_will_never_be_created.rb +1 -1
  24. data/test/support/coerceable_test_sqlserver.rb +4 -4
  25. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic.dump +0 -0
  26. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic_associations.dump +0 -0
  27. data/test/support/rake_helpers.rb +3 -1
  28. metadata +19 -19
  29. data/test/cases/active_schema_test_sqlserver.rb +0 -55
  30. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
  31. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
@@ -52,7 +52,6 @@ module ActiveRecord
52
52
  class AdapterTest < ActiveRecord::TestCase
53
53
  # Legacy binds are not supported.
54
54
  coerce_tests! :test_select_all_insert_update_delete_with_casted_binds
55
- coerce_tests! :test_select_all_insert_update_delete_with_legacy_binds
56
55
 
57
56
  # As far as I can tell, SQL Server does not support null bytes in strings.
58
57
  coerce_tests! :test_update_prepared_statement
@@ -543,29 +542,33 @@ module ActiveRecord
543
542
  assert_equal 1, four.default
544
543
  assert_equal "hello", five.default
545
544
  end
546
- end
547
- end
548
- end
549
545
 
550
- module ActiveRecord
551
- module ConnectionAdapters
552
- class QuoteARBaseTest < ActiveRecord::TestCase
553
- # Use our date format.
554
- coerce_tests! :test_quote_ar_object
555
- def test_quote_ar_object_coerced
556
- value = DatetimePrimaryKey.new(id: @time)
557
- assert_deprecated do
558
- assert_equal "'02-14-2017 12:34:56.79'", @connection.quote(value)
546
+ # Rails adds precision 6 by default, sql server uses datetime2 for datetimes with precision
547
+ coerce_tests! :test_add_column_with_postgresql_datetime_type
548
+ def test_add_column_with_postgresql_datetime_type_coerced
549
+ connection.create_table :testings do |t|
550
+ t.column :foo, :datetime
559
551
  end
552
+
553
+ column = connection.columns(:testings).find { |c| c.name == "foo" }
554
+
555
+ assert_equal :datetime, column.type
556
+ assert_equal "datetime2(6)", column.sql_type
560
557
  end
561
558
 
562
- # Use our date format.
563
- coerce_tests! :test_type_cast_ar_object
564
- def test_type_cast_ar_object_coerced
565
- value = DatetimePrimaryKey.new(id: @time)
566
- assert_deprecated do
567
- assert_equal "02-14-2017 12:34:56.79", @connection.type_cast(value)
559
+ # timestamp is datetime with default limit
560
+ coerce_tests! :test_change_column_with_timestamp_type
561
+ def test_change_column_with_timestamp_type_coerced
562
+ connection.create_table :testings do |t|
563
+ t.column :foo, :datetime, null: false
568
564
  end
565
+
566
+ connection.change_column :testings, :foo, :timestamp
567
+
568
+ column = connection.columns(:testings).find { |c| c.name == "foo" }
569
+
570
+ assert_equal :datetime, column.type
571
+ assert_equal "datetime", column.sql_type
569
572
  end
570
573
  end
571
574
  end
@@ -628,6 +631,36 @@ class MigrationTest < ActiveRecord::TestCase
628
631
  # For some reason our tests set Rails.@_env which breaks test env switching.
629
632
  coerce_tests! :test_internal_metadata_stores_environment_when_other_data_exists
630
633
  coerce_tests! :test_internal_metadata_stores_environment
634
+
635
+ # Same as original but using binary type instead of blob
636
+ coerce_tests! :test_add_column_with_casted_type_if_not_exists_set_to_true
637
+ def test_add_column_with_casted_type_if_not_exists_set_to_true_coerced
638
+ migration_a = Class.new(ActiveRecord::Migration::Current) {
639
+ def version; 100 end
640
+ def migrate(x)
641
+ add_column "people", "last_name", :binary
642
+ end
643
+ }.new
644
+
645
+ migration_b = Class.new(ActiveRecord::Migration::Current) {
646
+ def version; 101 end
647
+ def migrate(x)
648
+ add_column "people", "last_name", :binary, if_not_exists: true
649
+ end
650
+ }.new
651
+
652
+ ActiveRecord::Migrator.new(:up, [migration_a], @schema_migration, 100).migrate
653
+ assert_column Person, :last_name, "migration_a should have created the last_name column on people"
654
+
655
+ assert_nothing_raised do
656
+ ActiveRecord::Migrator.new(:up, [migration_b], @schema_migration, 101).migrate
657
+ end
658
+ ensure
659
+ Person.reset_column_information
660
+ if Person.column_names.include?("last_name")
661
+ Person.connection.remove_column("people", "last_name")
662
+ end
663
+ end
631
664
  end
632
665
 
633
666
  class CoreTest < ActiveRecord::TestCase
@@ -989,6 +1022,19 @@ module ActiveRecord
989
1022
  @connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :restrict
990
1023
  end
991
1024
  end
1025
+
1026
+ # Error message depends on the database adapter.
1027
+ coerce_tests! :test_add_foreign_key_with_if_not_exists_not_set
1028
+ def test_add_foreign_key_with_if_not_exists_not_set_coerced
1029
+ @connection.add_foreign_key :astronauts, :rockets
1030
+ assert_equal 1, @connection.foreign_keys("astronauts").size
1031
+
1032
+ error = assert_raises do
1033
+ @connection.add_foreign_key :astronauts, :rockets
1034
+ end
1035
+
1036
+ assert_match(/TinyTds::Error: There is already an object named '.*' in the database/, error.message)
1037
+ end
992
1038
  end
993
1039
  end
994
1040
  end
@@ -1102,6 +1148,40 @@ class UpdateAllTest < ActiveRecord::TestCase
1102
1148
  _(david.reload.name).must_equal "David"
1103
1149
  _(mary.reload.name).must_equal "Test"
1104
1150
  end
1151
+
1152
+ # SELECT columns must be in the GROUP clause.
1153
+ coerce_tests! :test_update_all_with_group_by
1154
+ def test_update_all_with_group_by_coerced
1155
+ minimum_comments_count = 2
1156
+
1157
+ Post.most_commented(minimum_comments_count).update_all(title: "ig")
1158
+ posts = Post.select(:id, :title).group(:title).most_commented(minimum_comments_count).all.to_a
1159
+
1160
+ assert_operator posts.length, :>, 0
1161
+ assert posts.all? { |post| post.comments.length >= minimum_comments_count }
1162
+ assert posts.all? { |post| "ig" == post.title }
1163
+
1164
+ post = Post.select(:id, :title).group(:title).joins(:comments).group("posts.id").having("count(comments.id) < #{minimum_comments_count}").first
1165
+ assert_not_equal "ig", post.title
1166
+ end
1167
+ end
1168
+
1169
+ class DeleteAllTest < ActiveRecord::TestCase
1170
+ # SELECT columns must be in the GROUP clause.
1171
+ coerce_tests! :test_delete_all_with_group_by_and_having
1172
+ def test_delete_all_with_group_by_and_having_coerced
1173
+ minimum_comments_count = 2
1174
+ posts_to_be_deleted = Post.select(:id).most_commented(minimum_comments_count).all.to_a
1175
+ assert_operator posts_to_be_deleted.length, :>, 0
1176
+
1177
+ assert_difference("Post.count", -posts_to_be_deleted.length) do
1178
+ Post.most_commented(minimum_comments_count).delete_all
1179
+ end
1180
+
1181
+ posts_to_be_deleted.each do |deleted_post|
1182
+ assert_raise(ActiveRecord::RecordNotFound) { deleted_post.reload }
1183
+ end
1184
+ end
1105
1185
  end
1106
1186
 
1107
1187
  require "models/topic"
@@ -1143,7 +1223,8 @@ class QueryCacheTest < ActiveRecord::TestCase
1143
1223
  end
1144
1224
  end
1145
1225
 
1146
- # Same as original test except that we expect one query to be performed to retrieve the table's primary key.
1226
+ # Same as original test except that we expect one query to be performed to retrieve the table's primary key
1227
+ # and we don't call `reload_type_map` because SQL Server adapter doesn't support it.
1147
1228
  # When we generate the SQL for the `find` it includes ordering on the primary key. If we reset the column
1148
1229
  # information then the primary key needs to be retrieved from the database again to generate the SQL causing the
1149
1230
  # original test's `assert_no_queries` assertion to fail. Assert that the query was to get the primary key.
@@ -1153,9 +1234,6 @@ class QueryCacheTest < ActiveRecord::TestCase
1153
1234
  # Warm the cache
1154
1235
  Task.find(1)
1155
1236
 
1156
- # Preload the type cache again (so we don't have those queries issued during our assertions)
1157
- Task.connection.send(:reload_type_map)
1158
-
1159
1237
  # Clear places where type information is cached
1160
1238
  Task.reset_column_information
1161
1239
  Task.initialize_find_by_cache
@@ -1204,16 +1282,11 @@ class RelationTest < ActiveRecord::TestCase
1204
1282
  # We have implicit ordering, via FETCH.
1205
1283
  coerce_tests! :test_reorder_with_first
1206
1284
  def test_reorder_with_first_coerced
1285
+ post = nil
1207
1286
  sql_log = capture_sql do
1208
- message = <<~MSG.squish
1209
- `.reorder(nil)` with `.first` / `.first!` no longer
1210
- takes non-deterministic result in Rails 7.0.
1211
- To continue taking non-deterministic result, use `.take` / `.take!` instead.
1212
- MSG
1213
- assert_deprecated(message) do
1214
- assert Post.order(:title).reorder(nil).first
1215
- end
1287
+ post = Post.order(:title).reorder(nil).first
1216
1288
  end
1289
+ assert_equal posts(:welcome), post
1217
1290
  assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
1218
1291
  assert sql_log.all? { |sql| /order by \[posts\]\.\[id\]/i.match?(sql) }, "default ORDER BY ID was not used in the query: #{sql_log}"
1219
1292
  end
@@ -1278,14 +1351,13 @@ module ActiveRecord
1278
1351
  assert_equal expected, query
1279
1352
  end
1280
1353
 
1281
- # Original Rails test fails on Windows CI because the dump file was not being binary read.
1282
- coerce_tests! :test_marshal_load_legacy_relation
1283
- def test_marshal_load_legacy_relation_coerced
1284
- path = File.expand_path(
1285
- "support/marshal_compatibility_fixtures/legacy_relation.dump",
1286
- ARTest::SQLServer.root_activerecord_test
1287
- )
1288
- assert_equal 11, Marshal.load(File.binread(path)).size
1354
+ # Workaround for randomly failing test. Ordering of results not guaranteed.
1355
+ # TODO: Remove coerced test when https://github.com/rails/rails/pull/44168 merged.
1356
+ coerce_tests! :test_select_quotes_when_using_from_clause
1357
+ def test_select_quotes_when_using_from_clause_coerced
1358
+ quoted_join = ActiveRecord::Base.connection.quote_table_name("join")
1359
+ selected = Post.select(:join).from(Post.select("id as #{quoted_join}")).map(&:join)
1360
+ assert_equal Post.pluck(:id).sort, selected.sort
1289
1361
  end
1290
1362
  end
1291
1363
  end
@@ -1798,6 +1870,17 @@ class EnumTest < ActiveRecord::TestCase
1798
1870
  Book.where(author_id: nil, name: nil).delete_all
1799
1871
  Book.connection.add_index(:books, [:author_id, :name], unique: true)
1800
1872
  end
1873
+
1874
+ # Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
1875
+ coerce_tests! %r{serializable\? with large number label}
1876
+ test "serializable? with large number label coerced" do
1877
+ Book.connection.remove_index(:books, column: [:author_id, :name])
1878
+
1879
+ send(:'original_serializable\? with large number label')
1880
+ ensure
1881
+ Book.where(author_id: nil, name: nil).delete_all
1882
+ Book.connection.add_index(:books, [:author_id, :name], unique: true)
1883
+ end
1801
1884
  end
1802
1885
 
1803
1886
  require "models/task"
@@ -1857,9 +1940,9 @@ end
1857
1940
 
1858
1941
  class LogSubscriberTest < ActiveRecord::TestCase
1859
1942
  # Call original test from coerced test. Fixes issue on CI with Rails installed as a gem.
1860
- coerce_tests! :test_vebose_query_logs
1861
- def test_vebose_query_logs_coerced
1862
- original_test_vebose_query_logs
1943
+ coerce_tests! :test_verbose_query_logs
1944
+ def test_verbose_query_logs_coerced
1945
+ original_test_verbose_query_logs
1863
1946
  end
1864
1947
 
1865
1948
  # Bindings logged slightly differently.
@@ -1886,53 +1969,6 @@ class ReloadModelsTest < ActiveRecord::TestCase
1886
1969
  coerce_tests! :test_has_one_with_reload if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
1887
1970
  end
1888
1971
 
1889
- require "models/post"
1890
- class AnnotateTest < ActiveRecord::TestCase
1891
- # Same as original coerced test except our SQL starts with `EXEC sp_executesql`.
1892
- # TODO: Remove coerce after Rails 7 (see https://github.com/rails/rails/pull/42027)
1893
- coerce_tests! :test_annotate_wraps_content_in_an_inline_comment
1894
- def test_annotate_wraps_content_in_an_inline_comment_coerced
1895
- quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
1896
-
1897
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
1898
- posts = Post.select(:id).annotate("foo")
1899
- assert posts.first
1900
- end
1901
- end
1902
-
1903
- # Same as original coerced test except our SQL starts with `EXEC sp_executesql`.
1904
- # TODO: Remove coerce after Rails 7 (see https://github.com/rails/rails/pull/42027)
1905
- coerce_tests! :test_annotate_is_sanitized
1906
- def test_annotate_is_sanitized_coerced
1907
- quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
1908
-
1909
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/}i) do
1910
- posts = Post.select(:id).annotate("*/foo/*")
1911
- assert posts.first
1912
- end
1913
-
1914
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \*\* //foo// \*\* \*/}i) do
1915
- posts = Post.select(:id).annotate("**//foo//**")
1916
- assert posts.first
1917
- end
1918
-
1919
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* \* //foo// \* \* \*/}i) do
1920
- posts = Post.select(:id).annotate("* *//foo//* *")
1921
- assert posts.first
1922
- end
1923
-
1924
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \* /foo/ \* \*/ /\* \* /bar \*/}i) do
1925
- posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
1926
- assert posts.first
1927
- end
1928
-
1929
- assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \+ MAX_EXECUTION_TIME\(1\) \*/}i) do
1930
- posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)")
1931
- assert posts.first
1932
- end
1933
- end
1934
- end
1935
-
1936
1972
  class MarshalSerializationTest < ActiveRecord::TestCase
1937
1973
  private
1938
1974
 
@@ -2007,3 +2043,165 @@ class MultiDbMigratorTest < ActiveRecord::TestCase
2007
2043
  # Test fails on Windows AppVeyor CI for unknown reason.
2008
2044
  coerce_tests! :test_migrator_db_has_no_schema_migrations_table if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
2009
2045
  end
2046
+
2047
+ require "models/book"
2048
+ class FieldOrderedValuesTest < ActiveRecord::TestCase
2049
+ # Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
2050
+ coerce_tests! :test_in_order_of_with_enums_values
2051
+ def test_in_order_of_with_enums_values_coerced
2052
+ Book.connection.remove_index(:books, column: [:author_id, :name])
2053
+
2054
+ original_test_in_order_of_with_enums_values
2055
+ ensure
2056
+ Book.where(author_id: nil, name: nil).delete_all
2057
+ Book.connection.add_index(:books, [:author_id, :name], unique: true)
2058
+ end
2059
+
2060
+ # Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
2061
+ coerce_tests! :test_in_order_of_with_enums_keys
2062
+ def test_in_order_of_with_enums_keys_coerced
2063
+ Book.connection.remove_index(:books, column: [:author_id, :name])
2064
+
2065
+ original_test_in_order_of_with_enums_keys
2066
+ ensure
2067
+ Book.where(author_id: nil, name: nil).delete_all
2068
+ Book.connection.add_index(:books, [:author_id, :name], unique: true)
2069
+ end
2070
+ end
2071
+
2072
+ require "models/dashboard"
2073
+ class QueryLogsTest < ActiveRecord::TestCase
2074
+ # Same as original coerced test except our SQL ends with binding.
2075
+ # TODO: Remove coerce after Rails 7.1.0 (see https://github.com/rails/rails/pull/44053)
2076
+ coerce_tests! :test_custom_basic_tags, :test_custom_proc_tags, :test_multiple_custom_tags, :test_custom_proc_context_tags
2077
+ def test_custom_basic_tags_coerced
2078
+ ActiveRecord::QueryLogs.tags = [ :application, { custom_string: "test content" } ]
2079
+
2080
+ assert_sql(%r{/\*application:active_record,custom_string:test content\*/}) do
2081
+ Dashboard.first
2082
+ end
2083
+ end
2084
+
2085
+ def test_custom_proc_tags_coerced
2086
+ ActiveRecord::QueryLogs.tags = [ :application, { custom_proc: -> { "test content" } } ]
2087
+
2088
+ assert_sql(%r{/\*application:active_record,custom_proc:test content\*/}) do
2089
+ Dashboard.first
2090
+ end
2091
+ end
2092
+
2093
+ def test_multiple_custom_tags_coerced
2094
+ ActiveRecord::QueryLogs.tags = [
2095
+ :application,
2096
+ { custom_proc: -> { "test content" }, another_proc: -> { "more test content" } },
2097
+ ]
2098
+
2099
+ assert_sql(%r{/\*application:active_record,custom_proc:test content,another_proc:more test content\*/}) do
2100
+ Dashboard.first
2101
+ end
2102
+ end
2103
+
2104
+ def test_custom_proc_context_tags_coerced
2105
+ ActiveSupport::ExecutionContext[:foo] = "bar"
2106
+ ActiveRecord::QueryLogs.tags = [ :application, { custom_context_proc: ->(context) { context[:foo] } } ]
2107
+
2108
+ assert_sql(%r{/\*application:active_record,custom_context_proc:bar\*/}) do
2109
+ Dashboard.first
2110
+ end
2111
+ end
2112
+ end
2113
+
2114
+ # SQL Server does not support upsert yet
2115
+ # TODO: Remove coerce after Rails 7.1.0 (see https://github.com/rails/rails/pull/44050)
2116
+ class InsertAllTest < ActiveRecord::TestCase
2117
+ coerce_tests! :test_upsert_all_only_updates_the_column_provided_via_update_only
2118
+ def test_upsert_all_only_updates_the_column_provided_via_update_only_coerced
2119
+ assert_raises(ArgumentError, /does not support upsert/) do
2120
+ original_test_upsert_all_only_updates_the_column_provided_via_update_only
2121
+ end
2122
+ end
2123
+
2124
+ coerce_tests! :test_upsert_all_only_updates_the_list_of_columns_provided_via_update_only
2125
+ def test_upsert_all_only_updates_the_list_of_columns_provided_via_update_only_coerced
2126
+ assert_raises(ArgumentError, /does not support upsert/) do
2127
+ original_test_upsert_all_only_updates_the_list_of_columns_provided_via_update_only
2128
+ end
2129
+ end
2130
+
2131
+ coerce_tests! :test_upsert_all_implicitly_sets_timestamps_on_create_when_model_record_timestamps_is_true
2132
+ def test_upsert_all_implicitly_sets_timestamps_on_create_when_model_record_timestamps_is_true_coerced
2133
+ assert_raises(ArgumentError, /does not support upsert/) do
2134
+ original_test_upsert_all_implicitly_sets_timestamps_on_create_when_model_record_timestamps_is_true
2135
+ end
2136
+ end
2137
+
2138
+ coerce_tests! :test_upsert_all_respects_created_at_precision_when_touched_implicitly
2139
+ def test_upsert_all_respects_created_at_precision_when_touched_implicitly_coerced
2140
+ assert_raises(ArgumentError, /does not support upsert/) do
2141
+ original_test_upsert_all_respects_created_at_precision_when_touched_implicitly
2142
+ end
2143
+ end
2144
+
2145
+ coerce_tests! :test_upsert_all_does_not_implicitly_set_timestamps_on_create_when_model_record_timestamps_is_true_but_overridden
2146
+ def test_upsert_all_does_not_implicitly_set_timestamps_on_create_when_model_record_timestamps_is_true_but_overridden_coerced
2147
+ assert_raises(ArgumentError, /does not support upsert/) do
2148
+ original_test_upsert_all_does_not_implicitly_set_timestamps_on_create_when_model_record_timestamps_is_true_but_overridden
2149
+ end
2150
+ end
2151
+
2152
+ coerce_tests! :test_upsert_all_does_not_implicitly_set_timestamps_on_create_when_model_record_timestamps_is_false
2153
+ def test_upsert_all_does_not_implicitly_set_timestamps_on_create_when_model_record_timestamps_is_false_coerced
2154
+ assert_raises(ArgumentError, /does not support upsert/) do
2155
+ original_test_upsert_all_does_not_implicitly_set_timestamps_on_create_when_model_record_timestamps_is_false
2156
+ end
2157
+ end
2158
+
2159
+ coerce_tests! :test_upsert_all_implicitly_sets_timestamps_on_create_when_model_record_timestamps_is_false_but_overridden
2160
+ def test_upsert_all_implicitly_sets_timestamps_on_create_when_model_record_timestamps_is_false_but_overridden_coerced
2161
+ assert_raises(ArgumentError, /does not support upsert/) do
2162
+ original_test_upsert_all_implicitly_sets_timestamps_on_create_when_model_record_timestamps_is_false_but_overridden
2163
+ end
2164
+ end
2165
+ end
2166
+
2167
+ class HasOneThroughDisableJoinsAssociationsTest < ActiveRecord::TestCase
2168
+ # TODO: Remove coerce after Rails 7.1.0 (see https://github.com/rails/rails/pull/44051)
2169
+ coerce_tests! :test_disable_joins_through_with_enum_type
2170
+ def test_disable_joins_through_with_enum_type_coerced
2171
+ joins = capture_sql { @member.club }
2172
+ no_joins = capture_sql { @member.club_without_joins }
2173
+
2174
+ assert_equal 1, joins.size
2175
+ assert_equal 2, no_joins.size
2176
+
2177
+ assert_match(/INNER JOIN/, joins.first)
2178
+ no_joins.each do |nj|
2179
+ assert_no_match(/INNER JOIN/, nj)
2180
+ end
2181
+
2182
+ assert_match(/\[memberships\]\.\[type\]/, no_joins.first)
2183
+ end
2184
+ end
2185
+
2186
+ class InsertAllTest < ActiveRecord::TestCase
2187
+ coerce_tests! :test_insert_all_returns_requested_sql_fields
2188
+ # Same as original but using INSERTED.name as UPPER argument
2189
+ def test_insert_all_returns_requested_sql_fields_coerced
2190
+ skip unless supports_insert_returning?
2191
+
2192
+ result = Book.insert_all! [{ name: "Rework", author_id: 1 }], returning: Arel.sql("UPPER(INSERTED.name) as name")
2193
+ assert_equal %w[ REWORK ], result.pluck("name")
2194
+ end
2195
+ end
2196
+
2197
+ class ActiveRecord::Encryption::EncryptableRecordTest < ActiveRecord::EncryptionTestCase
2198
+ # TODO: Remove coerce after Rails 7.1.0 (see https://github.com/rails/rails/pull/44052)
2199
+ # Same as original but SQL Server string is varchar(4000), not varchar(255) as other adapters. Produce invalid strings with 4001 characters
2200
+ coerce_tests! %r{validate column sizes}
2201
+ test "validate column sizes coerced" do
2202
+ assert EncryptedAuthor.new(name: "jorge").valid?
2203
+ assert_not EncryptedAuthor.new(name: "a" * 4001).valid?
2204
+ author = EncryptedAuthor.create(name: "a" * 4001)
2205
+ assert_not author.valid?
2206
+ end
2207
+ end