activerecord-sqlserver-adapter 6.1.3.0 → 7.0.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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