activerecord-sqlserver-adapter 6.1.2.0 → 7.0.0.0
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 +4 -1
- data/CHANGELOG.md +16 -41
- data/Gemfile +1 -0
- data/MIT-LICENSE +1 -1
- data/README.md +18 -9
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +2 -2
- data/appveyor.yml +4 -6
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +7 -15
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +15 -6
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +2 -4
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +11 -9
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +27 -8
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +16 -1
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +84 -74
- data/lib/arel/visitors/sqlserver.rb +2 -0
- data/test/cases/active_schema_test_sqlserver.rb +55 -0
- data/test/cases/coerced_tests.rb +301 -85
- data/test/cases/column_test_sqlserver.rb +58 -58
- data/test/cases/eager_load_too_many_ids_test_sqlserver.rb +18 -0
- data/test/cases/rake_test_sqlserver.rb +2 -1
- data/test/cases/schema_dumper_test_sqlserver.rb +1 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +1 -1
- data/test/support/coerceable_test_sqlserver.rb +4 -4
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_1_topic_associations.dump +0 -0
- data/test/support/rake_helpers.rb +3 -1
- metadata +15 -11
- 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/cases/coerced_tests.rb
CHANGED
|
@@ -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
|
|
@@ -92,6 +91,18 @@ module ActiveRecord
|
|
|
92
91
|
Subscriber.send(:load_schema!)
|
|
93
92
|
original_test_errors_when_an_insert_query_prefixed_by_a_double_dash_comment_is_called_while_preventing_writes
|
|
94
93
|
end
|
|
94
|
+
|
|
95
|
+
coerce_tests! :test_doesnt_error_when_a_select_query_has_encoding_errors
|
|
96
|
+
def test_doesnt_error_when_a_select_query_has_encoding_errors_coerced
|
|
97
|
+
ActiveRecord::Base.while_preventing_writes do
|
|
98
|
+
# TinyTDS fail on encoding errors.
|
|
99
|
+
# But at least we can assert it fails in the client and not before when trying to
|
|
100
|
+
# match the query.
|
|
101
|
+
assert_raises ActiveRecord::StatementInvalid do
|
|
102
|
+
@connection.select_all("SELECT '\xC8'")
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
95
106
|
end
|
|
96
107
|
end
|
|
97
108
|
|
|
@@ -531,29 +542,33 @@ module ActiveRecord
|
|
|
531
542
|
assert_equal 1, four.default
|
|
532
543
|
assert_equal "hello", five.default
|
|
533
544
|
end
|
|
534
|
-
end
|
|
535
|
-
end
|
|
536
|
-
end
|
|
537
545
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
def test_quote_ar_object_coerced
|
|
544
|
-
value = DatetimePrimaryKey.new(id: @time)
|
|
545
|
-
assert_deprecated do
|
|
546
|
-
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
|
|
547
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
|
|
548
557
|
end
|
|
549
558
|
|
|
550
|
-
#
|
|
551
|
-
coerce_tests! :
|
|
552
|
-
def
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
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
|
|
556
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
|
|
557
572
|
end
|
|
558
573
|
end
|
|
559
574
|
end
|
|
@@ -616,6 +631,36 @@ class MigrationTest < ActiveRecord::TestCase
|
|
|
616
631
|
# For some reason our tests set Rails.@_env which breaks test env switching.
|
|
617
632
|
coerce_tests! :test_internal_metadata_stores_environment_when_other_data_exists
|
|
618
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
|
|
619
664
|
end
|
|
620
665
|
|
|
621
666
|
class CoreTest < ActiveRecord::TestCase
|
|
@@ -977,6 +1022,19 @@ module ActiveRecord
|
|
|
977
1022
|
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :restrict
|
|
978
1023
|
end
|
|
979
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
|
|
980
1038
|
end
|
|
981
1039
|
end
|
|
982
1040
|
end
|
|
@@ -1090,6 +1148,40 @@ class UpdateAllTest < ActiveRecord::TestCase
|
|
|
1090
1148
|
_(david.reload.name).must_equal "David"
|
|
1091
1149
|
_(mary.reload.name).must_equal "Test"
|
|
1092
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
|
|
1093
1185
|
end
|
|
1094
1186
|
|
|
1095
1187
|
require "models/topic"
|
|
@@ -1131,7 +1223,8 @@ class QueryCacheTest < ActiveRecord::TestCase
|
|
|
1131
1223
|
end
|
|
1132
1224
|
end
|
|
1133
1225
|
|
|
1134
|
-
# 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.
|
|
1135
1228
|
# When we generate the SQL for the `find` it includes ordering on the primary key. If we reset the column
|
|
1136
1229
|
# information then the primary key needs to be retrieved from the database again to generate the SQL causing the
|
|
1137
1230
|
# original test's `assert_no_queries` assertion to fail. Assert that the query was to get the primary key.
|
|
@@ -1141,9 +1234,6 @@ class QueryCacheTest < ActiveRecord::TestCase
|
|
|
1141
1234
|
# Warm the cache
|
|
1142
1235
|
Task.find(1)
|
|
1143
1236
|
|
|
1144
|
-
# Preload the type cache again (so we don't have those queries issued during our assertions)
|
|
1145
|
-
Task.connection.send(:reload_type_map)
|
|
1146
|
-
|
|
1147
1237
|
# Clear places where type information is cached
|
|
1148
1238
|
Task.reset_column_information
|
|
1149
1239
|
Task.initialize_find_by_cache
|
|
@@ -1192,16 +1282,11 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
1192
1282
|
# We have implicit ordering, via FETCH.
|
|
1193
1283
|
coerce_tests! :test_reorder_with_first
|
|
1194
1284
|
def test_reorder_with_first_coerced
|
|
1285
|
+
post = nil
|
|
1195
1286
|
sql_log = capture_sql do
|
|
1196
|
-
|
|
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
|
|
1287
|
+
post = Post.order(:title).reorder(nil).first
|
|
1204
1288
|
end
|
|
1289
|
+
assert_equal posts(:welcome), post
|
|
1205
1290
|
assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
|
|
1206
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}"
|
|
1207
1292
|
end
|
|
@@ -1266,14 +1351,13 @@ module ActiveRecord
|
|
|
1266
1351
|
assert_equal expected, query
|
|
1267
1352
|
end
|
|
1268
1353
|
|
|
1269
|
-
#
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
)
|
|
1276
|
-
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
|
|
1277
1361
|
end
|
|
1278
1362
|
end
|
|
1279
1363
|
end
|
|
@@ -1402,7 +1486,8 @@ class YamlSerializationTest < ActiveRecord::TestCase
|
|
|
1402
1486
|
coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
|
|
1403
1487
|
def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
|
|
1404
1488
|
author = Author.select("authors.*, 5 as posts_count").first
|
|
1405
|
-
|
|
1489
|
+
dumped_author = YAML.dump(author)
|
|
1490
|
+
dumped = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(dumped_author) : YAML.load(dumped_author)
|
|
1406
1491
|
assert_equal 5, author.posts_count
|
|
1407
1492
|
assert_equal 5, dumped.posts_count
|
|
1408
1493
|
end
|
|
@@ -1785,6 +1870,17 @@ class EnumTest < ActiveRecord::TestCase
|
|
|
1785
1870
|
Book.where(author_id: nil, name: nil).delete_all
|
|
1786
1871
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1787
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
|
|
1788
1884
|
end
|
|
1789
1885
|
|
|
1790
1886
|
require "models/task"
|
|
@@ -1844,9 +1940,9 @@ end
|
|
|
1844
1940
|
|
|
1845
1941
|
class LogSubscriberTest < ActiveRecord::TestCase
|
|
1846
1942
|
# Call original test from coerced test. Fixes issue on CI with Rails installed as a gem.
|
|
1847
|
-
coerce_tests! :
|
|
1848
|
-
def
|
|
1849
|
-
|
|
1943
|
+
coerce_tests! :test_verbose_query_logs
|
|
1944
|
+
def test_verbose_query_logs_coerced
|
|
1945
|
+
original_test_verbose_query_logs
|
|
1850
1946
|
end
|
|
1851
1947
|
|
|
1852
1948
|
# Bindings logged slightly differently.
|
|
@@ -1873,48 +1969,6 @@ class ReloadModelsTest < ActiveRecord::TestCase
|
|
|
1873
1969
|
coerce_tests! :test_has_one_with_reload if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
|
1874
1970
|
end
|
|
1875
1971
|
|
|
1876
|
-
require "models/post"
|
|
1877
|
-
class AnnotateTest < ActiveRecord::TestCase
|
|
1878
|
-
# Same as original coerced test except our SQL starts with `EXEC sp_executesql`.
|
|
1879
|
-
# TODO: Remove coerce after Rails 7 (see https://github.com/rails/rails/pull/42027)
|
|
1880
|
-
coerce_tests! :test_annotate_wraps_content_in_an_inline_comment
|
|
1881
|
-
def test_annotate_wraps_content_in_an_inline_comment_coerced
|
|
1882
|
-
quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
|
|
1883
|
-
|
|
1884
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
|
|
1885
|
-
posts = Post.select(:id).annotate("foo")
|
|
1886
|
-
assert posts.first
|
|
1887
|
-
end
|
|
1888
|
-
end
|
|
1889
|
-
|
|
1890
|
-
# Same as original coerced test except our SQL starts with `EXEC sp_executesql`.
|
|
1891
|
-
# TODO: Remove coerce after Rails 7 (see https://github.com/rails/rails/pull/42027)
|
|
1892
|
-
coerce_tests! :test_annotate_is_sanitized
|
|
1893
|
-
def test_annotate_is_sanitized_coerced
|
|
1894
|
-
quoted_posts_id, quoted_posts = regexp_escape_table_name("posts.id"), regexp_escape_table_name("posts")
|
|
1895
|
-
|
|
1896
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
|
|
1897
|
-
posts = Post.select(:id).annotate("*/foo/*")
|
|
1898
|
-
assert posts.first
|
|
1899
|
-
end
|
|
1900
|
-
|
|
1901
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/}i) do
|
|
1902
|
-
posts = Post.select(:id).annotate("**//foo//**")
|
|
1903
|
-
assert posts.first
|
|
1904
|
-
end
|
|
1905
|
-
|
|
1906
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* foo \*/ /\* bar \*/}i) do
|
|
1907
|
-
posts = Post.select(:id).annotate("*/foo/*").annotate("*/bar")
|
|
1908
|
-
assert posts.first
|
|
1909
|
-
end
|
|
1910
|
-
|
|
1911
|
-
assert_sql(%r{SELECT #{quoted_posts_id} FROM #{quoted_posts} /\* \+ MAX_EXECUTION_TIME\(1\) \*/}i) do
|
|
1912
|
-
posts = Post.select(:id).annotate("+ MAX_EXECUTION_TIME(1)")
|
|
1913
|
-
assert posts.first
|
|
1914
|
-
end
|
|
1915
|
-
end
|
|
1916
|
-
end
|
|
1917
|
-
|
|
1918
1972
|
class MarshalSerializationTest < ActiveRecord::TestCase
|
|
1919
1973
|
private
|
|
1920
1974
|
|
|
@@ -1989,3 +2043,165 @@ class MultiDbMigratorTest < ActiveRecord::TestCase
|
|
|
1989
2043
|
# Test fails on Windows AppVeyor CI for unknown reason.
|
|
1990
2044
|
coerce_tests! :test_migrator_db_has_no_schema_migrations_table if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
|
1991
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
|