activerecord-sqlserver-adapter 5.2.1 → 6.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/.editorconfig +9 -0
- data/.github/issue_template.md +23 -0
- data/.travis.yml +6 -8
- data/CHANGELOG.md +22 -32
- data/{Dockerfile → Dockerfile.ci} +1 -1
- data/Gemfile +42 -41
- data/README.md +9 -30
- data/RUNNING_UNIT_TESTS.md +3 -0
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +25 -14
- data/appveyor.yml +24 -17
- data/docker-compose.ci.yml +7 -5
- data/guides/RELEASING.md +11 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +36 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +4 -1
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +55 -14
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +38 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +16 -3
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +93 -70
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +42 -40
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +5 -2
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +5 -2
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +7 -6
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +5 -2
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +5 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +6 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +6 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +6 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/version.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +44 -10
- data/lib/active_record/connection_adapters/sqlserver_column.rb +9 -3
- data/lib/active_record/sqlserver_base.rb +8 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +2 -0
- data/lib/activerecord-sqlserver-adapter.rb +2 -0
- data/lib/arel/visitors/sqlserver.rb +40 -10
- data/lib/arel_sqlserver.rb +2 -0
- data/test/appveyor/dbsetup.ps1 +4 -4
- data/test/cases/adapter_test_sqlserver.rb +65 -1
- data/test/cases/change_column_null_test_sqlserver.rb +2 -0
- data/test/cases/coerced_tests.rb +644 -187
- data/test/cases/column_test_sqlserver.rb +2 -1
- data/test/cases/connection_test_sqlserver.rb +2 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +2 -0
- data/test/cases/fetch_test_sqlserver.rb +2 -0
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +4 -2
- data/test/cases/helper_sqlserver.rb +2 -0
- data/test/cases/in_clause_test_sqlserver.rb +36 -0
- data/test/cases/index_test_sqlserver.rb +2 -0
- data/test/cases/json_test_sqlserver.rb +2 -0
- data/test/cases/migration_test_sqlserver.rb +4 -2
- data/test/cases/order_test_sqlserver.rb +2 -0
- data/test/cases/pessimistic_locking_test_sqlserver.rb +2 -0
- data/test/cases/rake_test_sqlserver.rb +2 -0
- data/test/cases/schema_dumper_test_sqlserver.rb +3 -1
- data/test/cases/schema_test_sqlserver.rb +2 -0
- data/test/cases/scratchpad_test_sqlserver.rb +2 -0
- data/test/cases/showplan_test_sqlserver.rb +4 -2
- data/test/cases/specific_schema_test_sqlserver.rb +2 -0
- data/test/cases/transaction_test_sqlserver.rb +2 -1
- data/test/cases/trigger_test_sqlserver.rb +2 -1
- data/test/cases/utils_test_sqlserver.rb +2 -0
- data/test/cases/uuid_test_sqlserver.rb +2 -1
- data/test/debug.rb +2 -0
- data/test/migrations/create_clients_and_change_column_null.rb +2 -0
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +2 -0
- data/test/models/sqlserver/booking.rb +2 -0
- data/test/models/sqlserver/customers_view.rb +2 -0
- data/test/models/sqlserver/datatype.rb +2 -0
- data/test/models/sqlserver/datatype_migration.rb +2 -0
- data/test/models/sqlserver/dollar_table_name.rb +2 -0
- data/test/models/sqlserver/edge_schema.rb +2 -0
- data/test/models/sqlserver/fk_has_fk.rb +2 -0
- data/test/models/sqlserver/fk_has_pk.rb +2 -0
- data/test/models/sqlserver/natural_pk_data.rb +2 -0
- data/test/models/sqlserver/natural_pk_int_data.rb +2 -0
- data/test/models/sqlserver/no_pk_data.rb +2 -0
- data/test/models/sqlserver/object_default.rb +2 -0
- data/test/models/sqlserver/quoted_table.rb +2 -0
- data/test/models/sqlserver/quoted_view_1.rb +2 -0
- data/test/models/sqlserver/quoted_view_2.rb +2 -0
- data/test/models/sqlserver/sst_memory.rb +2 -0
- data/test/models/sqlserver/string_default.rb +2 -0
- data/test/models/sqlserver/string_defaults_big_view.rb +2 -0
- data/test/models/sqlserver/string_defaults_view.rb +2 -0
- data/test/models/sqlserver/tinyint_pk.rb +2 -0
- data/test/models/sqlserver/trigger.rb +2 -0
- data/test/models/sqlserver/trigger_history.rb +2 -0
- data/test/models/sqlserver/upper.rb +2 -0
- data/test/models/sqlserver/uppered.rb +2 -0
- data/test/models/sqlserver/uuid.rb +2 -0
- data/test/schema/sqlserver_specific_schema.rb +2 -0
- data/test/support/coerceable_test_sqlserver.rb +14 -5
- data/test/support/connection_reflection.rb +2 -0
- data/test/support/core_ext/query_cache.rb +3 -0
- data/test/support/load_schema_sqlserver.rb +2 -0
- data/test/support/minitest_sqlserver.rb +2 -0
- data/test/support/paths_sqlserver.rb +2 -0
- data/test/support/rake_helpers.rb +1 -0
- data/test/support/sql_counter_sqlserver.rb +3 -0
- data/test/support/test_in_memory_oltp.rb +2 -0
- metadata +18 -9
data/test/cases/coerced_tests.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'cases/helper_sqlserver'
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
require 'models/event'
|
|
6
8
|
class UniquenessValidationTest < ActiveRecord::TestCase
|
|
7
|
-
# So sp_executesql swallows this exception. Run without
|
|
9
|
+
# So sp_executesql swallows this exception. Run without prepared to see it.
|
|
8
10
|
coerce_tests! :test_validate_uniqueness_with_limit
|
|
9
11
|
def test_validate_uniqueness_with_limit_coerced
|
|
10
12
|
connection.unprepared_statement do
|
|
@@ -14,7 +16,7 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
# So sp_executesql swallows this exception. Run without
|
|
19
|
+
# So sp_executesql swallows this exception. Run without prepared to see it.
|
|
18
20
|
coerce_tests! :test_validate_uniqueness_with_limit_and_utf8
|
|
19
21
|
def test_validate_uniqueness_with_limit_and_utf8_coerced
|
|
20
22
|
connection.unprepared_statement do
|
|
@@ -23,6 +25,15 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
|
23
25
|
end
|
|
24
26
|
end
|
|
25
27
|
end
|
|
28
|
+
|
|
29
|
+
# Skip the test if database is case-insensitive.
|
|
30
|
+
coerce_tests! :test_validate_case_sensitive_uniqueness_by_default
|
|
31
|
+
def test_validate_case_sensitive_uniqueness_by_default_coerced
|
|
32
|
+
database_collation = connection.select_one("SELECT collation_name FROM sys.databases WHERE name = 'activerecord_unittest'").values.first
|
|
33
|
+
skip if database_collation.include?('_CI_')
|
|
34
|
+
|
|
35
|
+
original_test_validate_case_sensitive_uniqueness_by_default_coerced
|
|
36
|
+
end
|
|
26
37
|
end
|
|
27
38
|
|
|
28
39
|
|
|
@@ -31,14 +42,14 @@ end
|
|
|
31
42
|
require 'models/event'
|
|
32
43
|
module ActiveRecord
|
|
33
44
|
class AdapterTest < ActiveRecord::TestCase
|
|
34
|
-
# I really
|
|
45
|
+
# I really don`t think we can support legacy binds.
|
|
35
46
|
coerce_tests! :test_select_all_with_legacy_binds
|
|
36
47
|
coerce_tests! :test_insert_update_delete_with_legacy_binds
|
|
37
48
|
|
|
38
49
|
# As far as I can tell, SQL Server does not support null bytes in strings.
|
|
39
50
|
coerce_tests! :test_update_prepared_statement
|
|
40
51
|
|
|
41
|
-
# So sp_executesql swallows this exception. Run without
|
|
52
|
+
# So sp_executesql swallows this exception. Run without prepared to see it.
|
|
42
53
|
coerce_tests! :test_value_limit_violations_are_translated_to_specific_exception
|
|
43
54
|
def test_value_limit_violations_are_translated_to_specific_exception_coerced
|
|
44
55
|
connection.unprepared_statement do
|
|
@@ -48,6 +59,69 @@ module ActiveRecord
|
|
|
48
59
|
assert_not_nil error.cause
|
|
49
60
|
end
|
|
50
61
|
end
|
|
62
|
+
|
|
63
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
|
64
|
+
coerce_tests! :test_errors_when_an_insert_query_is_called_while_preventing_writes
|
|
65
|
+
def test_errors_when_an_insert_query_is_called_while_preventing_writes_coerced
|
|
66
|
+
Subscriber.send(:load_schema!)
|
|
67
|
+
original_test_errors_when_an_insert_query_is_called_while_preventing_writes
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
module ActiveRecord
|
|
76
|
+
class AdapterTestWithoutTransaction < ActiveRecord::TestCase
|
|
77
|
+
# SQL Server does not allow truncation of tables that are referenced by foreign key
|
|
78
|
+
# constraints. So manually remove/add foreign keys in test.
|
|
79
|
+
coerce_tests! :test_truncate_tables
|
|
80
|
+
def test_truncate_tables_coerced
|
|
81
|
+
# Remove foreign key constraint to allow truncation.
|
|
82
|
+
@connection.remove_foreign_key :authors, :author_addresses
|
|
83
|
+
|
|
84
|
+
assert_operator Post.count, :>, 0
|
|
85
|
+
assert_operator Author.count, :>, 0
|
|
86
|
+
assert_operator AuthorAddress.count, :>, 0
|
|
87
|
+
|
|
88
|
+
@connection.truncate_tables("author_addresses", "authors", "posts")
|
|
89
|
+
|
|
90
|
+
assert_equal 0, Post.count
|
|
91
|
+
assert_equal 0, Author.count
|
|
92
|
+
assert_equal 0, AuthorAddress.count
|
|
93
|
+
ensure
|
|
94
|
+
reset_fixtures("posts", "authors", "author_addresses")
|
|
95
|
+
|
|
96
|
+
# Restore foreign key constraint.
|
|
97
|
+
@connection.add_foreign_key :authors, :author_addresses
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# SQL Server does not allow truncation of tables that are referenced by foreign key
|
|
101
|
+
# constraints. So manually remove/add foreign keys in test.
|
|
102
|
+
coerce_tests! :test_truncate_tables_with_query_cache
|
|
103
|
+
def test_truncate_tables_with_query_cache
|
|
104
|
+
# Remove foreign key constraint to allow truncation.
|
|
105
|
+
@connection.remove_foreign_key :authors, :author_addresses
|
|
106
|
+
|
|
107
|
+
@connection.enable_query_cache!
|
|
108
|
+
|
|
109
|
+
assert_operator Post.count, :>, 0
|
|
110
|
+
assert_operator Author.count, :>, 0
|
|
111
|
+
assert_operator AuthorAddress.count, :>, 0
|
|
112
|
+
|
|
113
|
+
@connection.truncate_tables("author_addresses", "authors", "posts")
|
|
114
|
+
|
|
115
|
+
assert_equal 0, Post.count
|
|
116
|
+
assert_equal 0, Author.count
|
|
117
|
+
assert_equal 0, AuthorAddress.count
|
|
118
|
+
ensure
|
|
119
|
+
reset_fixtures("posts", "authors", "author_addresses")
|
|
120
|
+
@connection.disable_query_cache!
|
|
121
|
+
|
|
122
|
+
# Restore foreign key constraint.
|
|
123
|
+
@connection.add_foreign_key :authors, :author_addresses
|
|
124
|
+
end
|
|
51
125
|
end
|
|
52
126
|
end
|
|
53
127
|
|
|
@@ -56,29 +130,28 @@ end
|
|
|
56
130
|
|
|
57
131
|
require 'models/topic'
|
|
58
132
|
class AttributeMethodsTest < ActiveRecord::TestCase
|
|
133
|
+
# Use IFF for boolean statement in SELECT
|
|
59
134
|
coerce_tests! %r{typecast attribute from select to false}
|
|
60
135
|
def test_typecast_attribute_from_select_to_false_coerced
|
|
61
136
|
Topic.create(:title => 'Budget')
|
|
62
137
|
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
|
|
63
|
-
|
|
138
|
+
assert_not_predicate topic, :is_test?
|
|
64
139
|
end
|
|
65
140
|
|
|
141
|
+
# Use IFF for boolean statement in SELECT
|
|
66
142
|
coerce_tests! %r{typecast attribute from select to true}
|
|
67
143
|
def test_typecast_attribute_from_select_to_true_coerced
|
|
68
144
|
Topic.create(:title => 'Budget')
|
|
69
145
|
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
|
|
70
|
-
|
|
146
|
+
assert_predicate topic, :is_test?
|
|
71
147
|
end
|
|
72
148
|
end
|
|
73
149
|
|
|
74
150
|
|
|
75
|
-
|
|
76
|
-
# We do not have do the DecimalWithoutScale type.
|
|
77
|
-
coerce_tests! :test_numeric_fields
|
|
78
|
-
coerce_tests! :test_numeric_fields_with_scale
|
|
79
|
-
end
|
|
151
|
+
|
|
80
152
|
|
|
81
153
|
class BasicsTest < ActiveRecord::TestCase
|
|
154
|
+
# Use square brackets as SQL Server escaped character
|
|
82
155
|
coerce_tests! :test_column_names_are_escaped
|
|
83
156
|
def test_column_names_are_escaped_coerced
|
|
84
157
|
conn = ActiveRecord::Base.connection
|
|
@@ -96,7 +169,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
|
96
169
|
Time.use_zone("Eastern Time (US & Canada)") do
|
|
97
170
|
topic = Topic.find(1)
|
|
98
171
|
time = Time.zone.parse("2017-07-17 10:56")
|
|
99
|
-
topic.
|
|
172
|
+
topic.update!(written_on: time)
|
|
100
173
|
assert_equal(time, topic.written_on)
|
|
101
174
|
end
|
|
102
175
|
end
|
|
@@ -107,21 +180,23 @@ class BasicsTest < ActiveRecord::TestCase
|
|
|
107
180
|
Time.use_zone("Eastern Time (US & Canada)") do
|
|
108
181
|
topic = Topic.find(1)
|
|
109
182
|
time = Time.zone.parse("2017-07-17 10:56")
|
|
110
|
-
topic.
|
|
183
|
+
topic.update!(written_on: time)
|
|
111
184
|
assert_equal(time, topic.written_on)
|
|
112
185
|
end
|
|
113
186
|
end
|
|
114
187
|
end
|
|
115
188
|
end
|
|
116
189
|
|
|
117
|
-
#
|
|
118
|
-
coerce_tests! %r{
|
|
119
|
-
test "
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
190
|
+
# SQL Server does not have query for release_savepoint
|
|
191
|
+
coerce_tests! %r{an empty transaction does not raise if preventing writes}
|
|
192
|
+
test "an empty transaction does not raise if preventing writes coerced" do
|
|
193
|
+
ActiveRecord::Base.connection_handler.while_preventing_writes do
|
|
194
|
+
assert_queries(1, ignore_none: true) do
|
|
195
|
+
Bird.transaction do
|
|
196
|
+
ActiveRecord::Base.connection.materialize_transactions
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
125
200
|
end
|
|
126
201
|
end
|
|
127
202
|
|
|
@@ -132,12 +207,24 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
|
|
132
207
|
# Since @client.firm is a single first/top, and we use FETCH the order clause is used.
|
|
133
208
|
coerce_tests! :test_belongs_to_does_not_use_order_by
|
|
134
209
|
|
|
210
|
+
# Square brackets around column name
|
|
135
211
|
coerce_tests! :test_belongs_to_with_primary_key_joins_on_correct_column
|
|
136
212
|
def test_belongs_to_with_primary_key_joins_on_correct_column_coerced
|
|
137
213
|
sql = Client.joins(:firm_with_primary_key).to_sql
|
|
138
214
|
assert_no_match(/\[firm_with_primary_keys_companies\]\.\[id\]/, sql)
|
|
139
215
|
assert_match(/\[firm_with_primary_keys_companies\]\.\[name\]/, sql)
|
|
140
216
|
end
|
|
217
|
+
|
|
218
|
+
# Asserted SQL to get one row different from original test.
|
|
219
|
+
coerce_tests! :test_belongs_to
|
|
220
|
+
def test_belongs_to_coerced
|
|
221
|
+
client = Client.find(3)
|
|
222
|
+
first_firm = companies(:first_firm)
|
|
223
|
+
assert_sql(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
|
|
224
|
+
assert_equal first_firm, client.firm
|
|
225
|
+
assert_equal first_firm.name, client.firm.name
|
|
226
|
+
end
|
|
227
|
+
end
|
|
141
228
|
end
|
|
142
229
|
|
|
143
230
|
|
|
@@ -163,6 +250,7 @@ module ActiveRecord
|
|
|
163
250
|
# SQL Server adapter does not use a statement cache as query plans are already reused using `EXEC sp_executesql`.
|
|
164
251
|
coerce_tests! :test_statement_cache
|
|
165
252
|
coerce_tests! :test_statement_cache_with_query_cache
|
|
253
|
+
coerce_tests! :test_statement_cache_with_find
|
|
166
254
|
coerce_tests! :test_statement_cache_with_find_by
|
|
167
255
|
coerce_tests! :test_statement_cache_with_in_clause
|
|
168
256
|
coerce_tests! :test_statement_cache_with_sql_string_literal
|
|
@@ -170,34 +258,28 @@ module ActiveRecord
|
|
|
170
258
|
end
|
|
171
259
|
|
|
172
260
|
|
|
261
|
+
|
|
262
|
+
|
|
173
263
|
module ActiveRecord
|
|
174
264
|
class InstrumentationTest < ActiveRecord::TestCase
|
|
175
|
-
#
|
|
265
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
|
176
266
|
coerce_tests! :test_payload_name_on_load
|
|
177
267
|
def test_payload_name_on_load_coerced
|
|
178
|
-
Book.
|
|
179
|
-
|
|
180
|
-
subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
|
|
181
|
-
event = ActiveSupport::Notifications::Event.new(*args)
|
|
182
|
-
if event.payload[:sql].match "SELECT"
|
|
183
|
-
assert_equal "Book Load", event.payload[:name]
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
Book.first
|
|
187
|
-
ensure
|
|
188
|
-
ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
|
|
268
|
+
Book.send(:load_schema!)
|
|
269
|
+
original_test_payload_name_on_load
|
|
189
270
|
end
|
|
190
271
|
end
|
|
191
272
|
end
|
|
192
273
|
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
|
|
193
277
|
class CalculationsTest < ActiveRecord::TestCase
|
|
194
|
-
#
|
|
278
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
|
195
279
|
coerce_tests! :test_offset_is_kept
|
|
196
280
|
def test_offset_is_kept_coerced
|
|
197
|
-
Account.
|
|
198
|
-
|
|
199
|
-
assert_equal 1, queries.length
|
|
200
|
-
assert_match(/OFFSET/, queries.first)
|
|
281
|
+
Account.send(:load_schema!)
|
|
282
|
+
original_test_offset_is_kept
|
|
201
283
|
end
|
|
202
284
|
|
|
203
285
|
# Are decimal, not integer.
|
|
@@ -207,18 +289,20 @@ class CalculationsTest < ActiveRecord::TestCase
|
|
|
207
289
|
assert_equal BigDecimal('3.0').to_s, BigDecimal(value).to_s
|
|
208
290
|
end
|
|
209
291
|
|
|
292
|
+
# Match SQL Server limit implementation
|
|
210
293
|
coerce_tests! :test_limit_is_kept
|
|
211
294
|
def test_limit_is_kept_coerced
|
|
212
295
|
queries = capture_sql_ss { Account.limit(1).count }
|
|
213
296
|
assert_equal 1, queries.length
|
|
214
|
-
|
|
297
|
+
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/, queries.first)
|
|
215
298
|
end
|
|
216
299
|
|
|
300
|
+
# Match SQL Server limit implementation
|
|
217
301
|
coerce_tests! :test_limit_with_offset_is_kept
|
|
218
302
|
def test_limit_with_offset_is_kept_coerced
|
|
219
303
|
queries = capture_sql_ss { Account.limit(1).offset(1).count }
|
|
220
304
|
assert_equal 1, queries.length
|
|
221
|
-
|
|
305
|
+
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1/, queries.first)
|
|
222
306
|
end
|
|
223
307
|
|
|
224
308
|
# SQL Server needs an alias for the calculated column
|
|
@@ -235,27 +319,44 @@ end
|
|
|
235
319
|
|
|
236
320
|
|
|
237
321
|
|
|
322
|
+
|
|
238
323
|
module ActiveRecord
|
|
239
324
|
class Migration
|
|
240
325
|
class ChangeSchemaTest < ActiveRecord::TestCase
|
|
241
|
-
|
|
242
|
-
coerce_tests! :
|
|
243
|
-
|
|
244
|
-
|
|
326
|
+
# Integer.default is a number and not a string
|
|
327
|
+
coerce_tests! :test_create_table_with_defaults
|
|
328
|
+
def test_create_table_with_defaults_coerce
|
|
329
|
+
connection.create_table :testings do |t|
|
|
330
|
+
t.column :one, :string, default: "hello"
|
|
331
|
+
t.column :two, :boolean, default: true
|
|
332
|
+
t.column :three, :boolean, default: false
|
|
333
|
+
t.column :four, :integer, default: 1
|
|
334
|
+
t.column :five, :text, default: "hello"
|
|
335
|
+
end
|
|
245
336
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
337
|
+
columns = connection.columns(:testings)
|
|
338
|
+
one = columns.detect { |c| c.name == "one" }
|
|
339
|
+
two = columns.detect { |c| c.name == "two" }
|
|
340
|
+
three = columns.detect { |c| c.name == "three" }
|
|
341
|
+
four = columns.detect { |c| c.name == "four" }
|
|
342
|
+
five = columns.detect { |c| c.name == "five" }
|
|
343
|
+
|
|
344
|
+
assert_equal "hello", one.default
|
|
345
|
+
assert_equal true, connection.lookup_cast_type_from_column(two).deserialize(two.default)
|
|
346
|
+
assert_equal false, connection.lookup_cast_type_from_column(three).deserialize(three.default)
|
|
347
|
+
assert_equal 1, four.default
|
|
348
|
+
assert_equal "hello", five.default
|
|
349
|
+
end
|
|
249
350
|
end
|
|
250
351
|
end
|
|
251
352
|
end
|
|
252
353
|
|
|
253
354
|
|
|
254
355
|
|
|
356
|
+
|
|
255
357
|
module ActiveRecord
|
|
256
358
|
module ConnectionAdapters
|
|
257
359
|
class QuoteARBaseTest < ActiveRecord::TestCase
|
|
258
|
-
|
|
259
360
|
# Use our date format.
|
|
260
361
|
coerce_tests! :test_quote_ar_object
|
|
261
362
|
def test_quote_ar_object_coerced
|
|
@@ -269,13 +370,13 @@ module ActiveRecord
|
|
|
269
370
|
value = DatetimePrimaryKey.new(id: @time)
|
|
270
371
|
assert_equal "02-14-2017 12:34:56.79", @connection.type_cast(value)
|
|
271
372
|
end
|
|
272
|
-
|
|
273
373
|
end
|
|
274
374
|
end
|
|
275
375
|
end
|
|
276
376
|
|
|
277
377
|
|
|
278
378
|
|
|
379
|
+
|
|
279
380
|
module ActiveRecord
|
|
280
381
|
class Migration
|
|
281
382
|
class ColumnAttributesTest < ActiveRecord::TestCase
|
|
@@ -295,7 +396,7 @@ end
|
|
|
295
396
|
|
|
296
397
|
module ActiveRecord
|
|
297
398
|
class Migration
|
|
298
|
-
class ColumnsTest
|
|
399
|
+
class ColumnsTest < ActiveRecord::TestCase
|
|
299
400
|
# Our defaults are real 70000 integers vs '70000' strings.
|
|
300
401
|
coerce_tests! :test_rename_column_preserves_default_value_not_null
|
|
301
402
|
def test_rename_column_preserves_default_value_not_null_coerced
|
|
@@ -378,7 +479,7 @@ end
|
|
|
378
479
|
|
|
379
480
|
|
|
380
481
|
class CoreTest < ActiveRecord::TestCase
|
|
381
|
-
# I think fixtures are
|
|
482
|
+
# I think fixtures are using the wrong time zone and the `:first`
|
|
382
483
|
# `topics`.`bonus_time` attribute of 2005-01-30t15:28:00.00+01:00 is
|
|
383
484
|
# getting local EST time for me and set to "09:28:00.0000000".
|
|
384
485
|
coerce_tests! :test_pretty_print_persisted
|
|
@@ -404,14 +505,140 @@ end
|
|
|
404
505
|
|
|
405
506
|
|
|
406
507
|
module ActiveRecord
|
|
508
|
+
# The original module is hardcoded for PostgreSQL/SQLite/MySQL tests.
|
|
509
|
+
module DatabaseTasksSetupper
|
|
510
|
+
def setup
|
|
511
|
+
@sqlserver_tasks =
|
|
512
|
+
Class.new do
|
|
513
|
+
def create; end
|
|
514
|
+
def drop; end
|
|
515
|
+
def purge; end
|
|
516
|
+
def charset; end
|
|
517
|
+
def collation; end
|
|
518
|
+
def structure_dump(*); end
|
|
519
|
+
def structure_load(*); end
|
|
520
|
+
end.new
|
|
521
|
+
|
|
522
|
+
$stdout, @original_stdout = StringIO.new, $stdout
|
|
523
|
+
$stderr, @original_stderr = StringIO.new, $stderr
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def with_stubbed_new
|
|
527
|
+
ActiveRecord::Tasks::SQLServerDatabaseTasks.stub(:new, @sqlserver_tasks) do
|
|
528
|
+
yield
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
class DatabaseTasksCreateTest < ActiveRecord::TestCase
|
|
534
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
535
|
+
coerce_all_tests!
|
|
536
|
+
|
|
537
|
+
def test_sqlserver_create
|
|
538
|
+
with_stubbed_new do
|
|
539
|
+
assert_called(eval("@sqlserver_tasks"), :create) do
|
|
540
|
+
ActiveRecord::Tasks::DatabaseTasks.create "adapter" => :sqlserver
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
class DatabaseTasksDropTest < ActiveRecord::TestCase
|
|
547
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
548
|
+
coerce_all_tests!
|
|
549
|
+
|
|
550
|
+
def test_sqlserver_drop
|
|
551
|
+
with_stubbed_new do
|
|
552
|
+
assert_called(eval("@sqlserver_tasks"), :drop) do
|
|
553
|
+
ActiveRecord::Tasks::DatabaseTasks.drop "adapter" => :sqlserver
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
class DatabaseTasksPurgeTest < ActiveRecord::TestCase
|
|
560
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
561
|
+
coerce_all_tests!
|
|
562
|
+
|
|
563
|
+
def test_sqlserver_purge
|
|
564
|
+
with_stubbed_new do
|
|
565
|
+
assert_called(eval("@sqlserver_tasks"), :purge) do
|
|
566
|
+
ActiveRecord::Tasks::DatabaseTasks.purge "adapter" => :sqlserver
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
class DatabaseTasksCharsetTest < ActiveRecord::TestCase
|
|
573
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
574
|
+
coerce_all_tests!
|
|
575
|
+
|
|
576
|
+
def test_sqlserver_charset
|
|
577
|
+
with_stubbed_new do
|
|
578
|
+
assert_called(eval("@sqlserver_tasks"), :charset) do
|
|
579
|
+
ActiveRecord::Tasks::DatabaseTasks.charset "adapter" => :sqlserver
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
class DatabaseTasksCollationTest < ActiveRecord::TestCase
|
|
587
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
588
|
+
coerce_all_tests!
|
|
589
|
+
|
|
590
|
+
def test_sqlserver_collation
|
|
591
|
+
with_stubbed_new do
|
|
592
|
+
assert_called(eval("@sqlserver_tasks"), :collation) do
|
|
593
|
+
ActiveRecord::Tasks::DatabaseTasks.collation "adapter" => :sqlserver
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
class DatabaseTasksStructureDumpTest < ActiveRecord::TestCase
|
|
600
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
601
|
+
coerce_all_tests!
|
|
602
|
+
|
|
603
|
+
def test_sqlserver_structure_dump
|
|
604
|
+
with_stubbed_new do
|
|
605
|
+
assert_called_with(
|
|
606
|
+
eval("@sqlserver_tasks"), :structure_dump,
|
|
607
|
+
["awesome-file.sql", nil]
|
|
608
|
+
) do
|
|
609
|
+
ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => :sqlserver }, "awesome-file.sql")
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
class DatabaseTasksStructureLoadTest < ActiveRecord::TestCase
|
|
616
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
617
|
+
coerce_all_tests!
|
|
618
|
+
|
|
619
|
+
def test_sqlserver_structure_load
|
|
620
|
+
with_stubbed_new do
|
|
621
|
+
assert_called_with(
|
|
622
|
+
eval("@sqlserver_tasks"),
|
|
623
|
+
:structure_load,
|
|
624
|
+
["awesome-file.sql", nil]
|
|
625
|
+
) do
|
|
626
|
+
ActiveRecord::Tasks::DatabaseTasks.structure_load({ "adapter" => :sqlserver }, "awesome-file.sql")
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
end
|
|
631
|
+
|
|
407
632
|
class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
|
|
408
633
|
# Skip this test with /tmp/my_schema_cache.yml path on Windows.
|
|
409
634
|
coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
|
410
635
|
end
|
|
636
|
+
|
|
411
637
|
class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
|
|
412
638
|
# We extend `local_database?` so that common VM IPs can be used.
|
|
413
639
|
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
|
414
640
|
end
|
|
641
|
+
|
|
415
642
|
class DatabaseTasksDropAllTest < ActiveRecord::TestCase
|
|
416
643
|
# We extend `local_database?` so that common VM IPs can be used.
|
|
417
644
|
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
|
@@ -484,9 +711,11 @@ end
|
|
|
484
711
|
|
|
485
712
|
require 'models/topic'
|
|
486
713
|
class FinderTest < ActiveRecord::TestCase
|
|
714
|
+
# We have implicit ordering, via FETCH.
|
|
487
715
|
coerce_tests! %r{doesn't have implicit ordering},
|
|
488
|
-
:test_find_doesnt_have_implicit_ordering
|
|
716
|
+
:test_find_doesnt_have_implicit_ordering
|
|
489
717
|
|
|
718
|
+
# Square brackets around column name
|
|
490
719
|
coerce_tests! :test_exists_does_not_select_columns_without_alias
|
|
491
720
|
def test_exists_does_not_select_columns_without_alias_coerced
|
|
492
721
|
assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) do
|
|
@@ -494,6 +723,7 @@ class FinderTest < ActiveRecord::TestCase
|
|
|
494
723
|
end
|
|
495
724
|
end
|
|
496
725
|
|
|
726
|
+
# Assert SQL Server limit implementation
|
|
497
727
|
coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
|
|
498
728
|
def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
|
|
499
729
|
assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
|
|
@@ -553,13 +783,40 @@ end
|
|
|
553
783
|
class HasOneAssociationsTest < ActiveRecord::TestCase
|
|
554
784
|
# We use OFFSET/FETCH vs TOP. So we always have an order.
|
|
555
785
|
coerce_tests! :test_has_one_does_not_use_order_by
|
|
786
|
+
|
|
787
|
+
# Asserted SQL to get one row different from original test.
|
|
788
|
+
coerce_tests! :test_has_one
|
|
789
|
+
def test_has_one_coerced
|
|
790
|
+
firm = companies(:first_firm)
|
|
791
|
+
first_account = Account.find(1)
|
|
792
|
+
assert_sql(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
|
|
793
|
+
assert_equal first_account, firm.account
|
|
794
|
+
assert_equal first_account.credit_limit, firm.account.credit_limit
|
|
795
|
+
end
|
|
796
|
+
end
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
|
|
802
|
+
class HasOneThroughAssociationsTest < ActiveRecord::TestCase
|
|
803
|
+
# Asserted SQL to get one row different from original test.
|
|
804
|
+
coerce_tests! :test_has_one_through_executes_limited_query
|
|
805
|
+
def test_has_one_through_executes_limited_query_coerced
|
|
806
|
+
boring_club = clubs(:boring_club)
|
|
807
|
+
assert_sql(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
|
|
808
|
+
assert_equal boring_club, @member.general_club
|
|
809
|
+
end
|
|
810
|
+
end
|
|
556
811
|
end
|
|
557
812
|
|
|
558
813
|
|
|
559
814
|
|
|
560
815
|
|
|
816
|
+
|
|
561
817
|
require 'models/company'
|
|
562
818
|
class InheritanceTest < ActiveRecord::TestCase
|
|
819
|
+
# Rails test required inserting to a identity column.
|
|
563
820
|
coerce_tests! :test_a_bad_type_column
|
|
564
821
|
def test_a_bad_type_column_coerced
|
|
565
822
|
Company.connection.with_identity_insert_enabled('companies') do
|
|
@@ -568,6 +825,7 @@ class InheritanceTest < ActiveRecord::TestCase
|
|
|
568
825
|
assert_raise(ActiveRecord::SubclassNotFound) { Company.find(100) }
|
|
569
826
|
end
|
|
570
827
|
|
|
828
|
+
# Use Square brackets around column name
|
|
571
829
|
coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
|
|
572
830
|
def test_eager_load_belongs_to_primary_key_quoting_coerced
|
|
573
831
|
con = Account.connection
|
|
@@ -588,26 +846,10 @@ end
|
|
|
588
846
|
|
|
589
847
|
|
|
590
848
|
|
|
591
|
-
class NamedScopingTest < ActiveRecord::TestCase
|
|
592
|
-
# This works now because we add an `order(:id)` sort to break the order tie for deterministic results.
|
|
593
|
-
coerce_tests! :test_scopes_honor_current_scopes_from_when_defined
|
|
594
|
-
def test_scopes_honor_current_scopes_from_when_defined_coerced
|
|
595
|
-
assert !Post.ranked_by_comments.order(:id).limit_by(5).empty?
|
|
596
|
-
assert !authors(:david).posts.ranked_by_comments.order(:id).limit_by(5).empty?
|
|
597
|
-
assert_not_equal Post.ranked_by_comments.order(:id).limit_by(5), authors(:david).posts.ranked_by_comments.order(:id).limit_by(5)
|
|
598
|
-
assert_not_equal Post.order(:id).top(5), authors(:david).posts.order(:id).top(5)
|
|
599
|
-
# Oracle sometimes sorts differently if WHERE condition is changed
|
|
600
|
-
assert_equal authors(:david).posts.ranked_by_comments.limit_by(5).to_a.sort_by(&:id), authors(:david).posts.top(5).to_a.sort_by(&:id)
|
|
601
|
-
assert_equal Post.ranked_by_comments.limit_by(5), Post.top(5)
|
|
602
|
-
end
|
|
603
|
-
end
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
849
|
require 'models/developer'
|
|
609
850
|
require 'models/computer'
|
|
610
851
|
class NestedRelationScopingTest < ActiveRecord::TestCase
|
|
852
|
+
# Assert SQL Server limit implementation
|
|
611
853
|
coerce_tests! :test_merge_options
|
|
612
854
|
def test_merge_options_coerced
|
|
613
855
|
Developer.where('salary = 80000').scoping do
|
|
@@ -624,13 +866,36 @@ end
|
|
|
624
866
|
|
|
625
867
|
|
|
626
868
|
|
|
627
|
-
require 'models/parrot'
|
|
628
869
|
require 'models/topic'
|
|
629
870
|
class PersistenceTest < ActiveRecord::TestCase
|
|
630
|
-
#
|
|
871
|
+
# Rails test required updating a identity column.
|
|
631
872
|
coerce_tests! :test_update_columns_changing_id
|
|
632
873
|
|
|
633
|
-
#
|
|
874
|
+
# Rails test required updating a identity column.
|
|
875
|
+
coerce_tests! :test_update
|
|
876
|
+
def test_update_coerced
|
|
877
|
+
topic = Topic.find(1)
|
|
878
|
+
assert_not_predicate topic, :approved?
|
|
879
|
+
assert_equal "The First Topic", topic.title
|
|
880
|
+
|
|
881
|
+
topic.update("approved" => true, "title" => "The First Topic Updated")
|
|
882
|
+
topic.reload
|
|
883
|
+
assert_predicate topic, :approved?
|
|
884
|
+
assert_equal "The First Topic Updated", topic.title
|
|
885
|
+
|
|
886
|
+
topic.update(approved: false, title: "The First Topic")
|
|
887
|
+
topic.reload
|
|
888
|
+
assert_not_predicate topic, :approved?
|
|
889
|
+
assert_equal "The First Topic", topic.title
|
|
890
|
+
end
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
|
|
896
|
+
require 'models/author'
|
|
897
|
+
class UpdateAllTest < ActiveRecord::TestCase
|
|
898
|
+
# Rails test required updating a identity column.
|
|
634
899
|
coerce_tests! :test_update_all_doesnt_ignore_order
|
|
635
900
|
def test_update_all_doesnt_ignore_order_coerced
|
|
636
901
|
david, mary = authors(:david), authors(:mary)
|
|
@@ -643,30 +908,6 @@ class PersistenceTest < ActiveRecord::TestCase
|
|
|
643
908
|
_(david.reload.name).must_equal 'David'
|
|
644
909
|
_(mary.reload.name).must_equal 'Test'
|
|
645
910
|
end
|
|
646
|
-
|
|
647
|
-
# We can not UPDATE identity columns.
|
|
648
|
-
coerce_tests! :test_update_attributes
|
|
649
|
-
def test_update_attributes_coerced
|
|
650
|
-
topic = Topic.find(1)
|
|
651
|
-
assert !topic.approved?
|
|
652
|
-
assert_equal "The First Topic", topic.title
|
|
653
|
-
topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
|
|
654
|
-
topic.reload
|
|
655
|
-
assert topic.approved?
|
|
656
|
-
assert_equal "The First Topic Updated", topic.title
|
|
657
|
-
topic.update_attributes(approved: false, title: "The First Topic")
|
|
658
|
-
topic.reload
|
|
659
|
-
assert !topic.approved?
|
|
660
|
-
assert_equal "The First Topic", topic.title
|
|
661
|
-
# SQLServer: Here is where it breaks down. No exceptions.
|
|
662
|
-
# assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do
|
|
663
|
-
# topic.update_attributes(id: 3, title: "Hm is it possible?")
|
|
664
|
-
# end
|
|
665
|
-
# assert_not_equal "Hm is it possible?", Topic.find(3).title
|
|
666
|
-
# topic.update_attributes(id: 1234)
|
|
667
|
-
# assert_nothing_raised { topic.reload }
|
|
668
|
-
# assert_equal topic.title, Topic.find(1234).title
|
|
669
|
-
end
|
|
670
911
|
end
|
|
671
912
|
|
|
672
913
|
|
|
@@ -675,14 +916,16 @@ end
|
|
|
675
916
|
require 'models/topic'
|
|
676
917
|
module ActiveRecord
|
|
677
918
|
class PredicateBuilderTest < ActiveRecord::TestCase
|
|
919
|
+
# Same as original test except string has `N` prefix to indicate unicode string.
|
|
678
920
|
coerce_tests! :test_registering_new_handlers
|
|
679
921
|
def test_registering_new_handlers_coerced
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
922
|
+
assert_match %r{#{Regexp.escape(topic_title)} ~ N'rails'}i, Topic.where(title: /rails/).to_sql
|
|
923
|
+
end
|
|
924
|
+
|
|
925
|
+
# Same as original test except string has `N` prefix to indicate unicode string.
|
|
926
|
+
coerce_tests! :test_registering_new_handlers_for_association
|
|
927
|
+
def test_registering_new_handlers_for_association_coerced
|
|
928
|
+
assert_match %r{#{Regexp.escape(topic_title)} ~ N'rails'}i, Reply.joins(:topic).where(topics: { title: /rails/ }).to_sql
|
|
686
929
|
end
|
|
687
930
|
end
|
|
688
931
|
end
|
|
@@ -691,9 +934,15 @@ end
|
|
|
691
934
|
|
|
692
935
|
|
|
693
936
|
class PrimaryKeysTest < ActiveRecord::TestCase
|
|
694
|
-
#
|
|
695
|
-
# but as far as I can tell, this is only one for us anyway.
|
|
937
|
+
# SQL Server does not have query for release_savepoint
|
|
696
938
|
coerce_tests! :test_create_without_primary_key_no_extra_query
|
|
939
|
+
def test_create_without_primary_key_no_extra_query_coerced
|
|
940
|
+
klass = Class.new(ActiveRecord::Base) do
|
|
941
|
+
self.table_name = "dashboards"
|
|
942
|
+
end
|
|
943
|
+
klass.create! # warmup schema cache
|
|
944
|
+
assert_queries(2, ignore_none: true) { klass.create! }
|
|
945
|
+
end
|
|
697
946
|
end
|
|
698
947
|
|
|
699
948
|
|
|
@@ -701,10 +950,37 @@ end
|
|
|
701
950
|
|
|
702
951
|
require 'models/task'
|
|
703
952
|
class QueryCacheTest < ActiveRecord::TestCase
|
|
953
|
+
# SQL Server adapter not in list of supported adapters in original test.
|
|
704
954
|
coerce_tests! :test_cache_does_not_wrap_results_in_arrays
|
|
705
955
|
def test_cache_does_not_wrap_results_in_arrays_coerced
|
|
706
956
|
Task.cache do
|
|
707
|
-
|
|
957
|
+
assert_equal 2, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
|
|
958
|
+
end
|
|
959
|
+
end
|
|
960
|
+
|
|
961
|
+
# Same as original test except that we expect one query to be performed to retrieve the table's primary key.
|
|
962
|
+
# When we generate the SQL for the `find` it includes ordering on the primary key. If we reset the column
|
|
963
|
+
# information then the primary key needs to be retrieved from the database again to generate the SQL causing the
|
|
964
|
+
# original test's `assert_no_queries` assertion to fail. Assert that the query was to get the primary key.
|
|
965
|
+
coerce_tests! :test_query_cached_even_when_types_are_reset
|
|
966
|
+
def test_query_cached_even_when_types_are_reset_coerced
|
|
967
|
+
Task.cache do
|
|
968
|
+
# Warm the cache
|
|
969
|
+
Task.find(1)
|
|
970
|
+
|
|
971
|
+
# Preload the type cache again (so we don't have those queries issued during our assertions)
|
|
972
|
+
Task.connection.send(:reload_type_map)
|
|
973
|
+
|
|
974
|
+
# Clear places where type information is cached
|
|
975
|
+
Task.reset_column_information
|
|
976
|
+
Task.initialize_find_by_cache
|
|
977
|
+
Task.define_attribute_methods
|
|
978
|
+
|
|
979
|
+
assert_queries(1, ignore_none: true) do
|
|
980
|
+
Task.find(1)
|
|
981
|
+
end
|
|
982
|
+
|
|
983
|
+
assert_includes ActiveRecord::SQLCounter.log_all.first , "TC.CONSTRAINT_TYPE = N''PRIMARY KEY''"
|
|
708
984
|
end
|
|
709
985
|
end
|
|
710
986
|
end
|
|
@@ -733,6 +1009,27 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
733
1009
|
# We have implicit ordering, via FETCH.
|
|
734
1010
|
coerce_tests! %r{doesn't have implicit ordering}
|
|
735
1011
|
|
|
1012
|
+
# We have implicit ordering, via FETCH.
|
|
1013
|
+
coerce_tests! :test_reorder_with_take
|
|
1014
|
+
def test_reorder_with_take_coerced
|
|
1015
|
+
sql_log = capture_sql do
|
|
1016
|
+
assert Post.order(:title).reorder(nil).take
|
|
1017
|
+
end
|
|
1018
|
+
assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
|
|
1019
|
+
assert sql_log.all? { |sql| /order by \[posts\]\.\[id\]/i.match?(sql) }, "default ORDER BY ID was not used in the query: #{sql_log}"
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
# We have implicit ordering, via FETCH.
|
|
1023
|
+
coerce_tests! :test_reorder_with_first
|
|
1024
|
+
def test_reorder_with_first_coerced
|
|
1025
|
+
sql_log = capture_sql do
|
|
1026
|
+
assert Post.order(:title).reorder(nil).first
|
|
1027
|
+
end
|
|
1028
|
+
assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
|
|
1029
|
+
assert sql_log.all? { |sql| /order by \[posts\]\.\[id\]/i.match?(sql) }, "default ORDER BY ID was not used in the query: #{sql_log}"
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
|
|
736
1033
|
# We are not doing order duplicate removal anymore.
|
|
737
1034
|
coerce_tests! :test_order_using_scoping
|
|
738
1035
|
|
|
@@ -756,7 +1053,7 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
756
1053
|
# so we are skipping all together.
|
|
757
1054
|
coerce_tests! :test_empty_complex_chained_relations
|
|
758
1055
|
|
|
759
|
-
# Can't apply offset
|
|
1056
|
+
# Can't apply offset without ORDER
|
|
760
1057
|
coerce_tests! %r{using a custom table affects the wheres}
|
|
761
1058
|
test 'using a custom table affects the wheres coerced' do
|
|
762
1059
|
post = posts(:welcome)
|
|
@@ -764,7 +1061,7 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
764
1061
|
assert_equal post, custom_post_relation.where!(title: post.title).order(:id).take
|
|
765
1062
|
end
|
|
766
1063
|
|
|
767
|
-
# Can't apply offset
|
|
1064
|
+
# Can't apply offset without ORDER
|
|
768
1065
|
coerce_tests! %r{using a custom table with joins affects the joins}
|
|
769
1066
|
test 'using a custom table with joins affects the joins coerced' do
|
|
770
1067
|
post = posts(:welcome)
|
|
@@ -780,38 +1077,30 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
780
1077
|
end
|
|
781
1078
|
end
|
|
782
1079
|
|
|
783
|
-
class ActiveRecord::RelationTest < ActiveRecord::TestCase
|
|
784
|
-
coerce_tests! :test_relation_merging_with_merged_symbol_joins_is_aliased
|
|
785
|
-
def test_relation_merging_with_merged_symbol_joins_is_aliased__coerced
|
|
786
|
-
categorizations_with_authors = Categorization.joins(:author)
|
|
787
|
-
queries = capture_sql { Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(categorizations_with_authors).to_a }
|
|
788
|
-
|
|
789
|
-
nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
|
|
790
|
-
assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query"
|
|
791
|
-
|
|
792
|
-
# using `\W` as the column separator
|
|
793
|
-
query_matches = queries.any? do |sql|
|
|
794
|
-
%r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+\Wauthors_categorizations\W]i.match?(sql)
|
|
795
|
-
end
|
|
796
|
-
|
|
797
|
-
assert query_matches, "Should be aliasing the child INNER JOINs in query"
|
|
798
|
-
end
|
|
799
|
-
end
|
|
800
|
-
|
|
801
1080
|
|
|
802
1081
|
|
|
803
1082
|
|
|
804
1083
|
require 'models/post'
|
|
805
1084
|
class SanitizeTest < ActiveRecord::TestCase
|
|
1085
|
+
# Use nvarchar string (N'') in assert
|
|
806
1086
|
coerce_tests! :test_sanitize_sql_like_example_use_case
|
|
807
1087
|
def test_sanitize_sql_like_example_use_case_coerced
|
|
808
1088
|
searchable_post = Class.new(Post) do
|
|
809
|
-
def self.
|
|
810
|
-
where("title LIKE ?", sanitize_sql_like(term,
|
|
1089
|
+
def self.search_as_method(term)
|
|
1090
|
+
where("title LIKE ?", sanitize_sql_like(term, "!"))
|
|
811
1091
|
end
|
|
1092
|
+
|
|
1093
|
+
scope :search_as_scope, -> (term) {
|
|
1094
|
+
where("title LIKE ?", sanitize_sql_like(term, "!"))
|
|
1095
|
+
}
|
|
812
1096
|
end
|
|
813
|
-
|
|
814
|
-
|
|
1097
|
+
|
|
1098
|
+
assert_sql(/LIKE N'20!% !_reduction!_!!'/) do
|
|
1099
|
+
searchable_post.search_as_method("20% _reduction_!").to_a
|
|
1100
|
+
end
|
|
1101
|
+
|
|
1102
|
+
assert_sql(/LIKE N'20!% !_reduction!_!!'/) do
|
|
1103
|
+
searchable_post.search_as_scope("20% _reduction_!").to_a
|
|
815
1104
|
end
|
|
816
1105
|
end
|
|
817
1106
|
end
|
|
@@ -845,6 +1134,9 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
|
845
1134
|
end
|
|
846
1135
|
end
|
|
847
1136
|
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
848
1140
|
class SchemaDumperDefaultsTest < ActiveRecord::TestCase
|
|
849
1141
|
# These date formats do not match ours. We got these covered in our dumper tests.
|
|
850
1142
|
coerce_tests! :test_schema_dump_defaults_with_universally_supported_types
|
|
@@ -863,6 +1155,7 @@ end
|
|
|
863
1155
|
|
|
864
1156
|
require 'models/topic'
|
|
865
1157
|
class TransactionTest < ActiveRecord::TestCase
|
|
1158
|
+
# SQL Server does not have query for release_savepoint
|
|
866
1159
|
coerce_tests! :test_releasing_named_savepoints
|
|
867
1160
|
def test_releasing_named_savepoints_coerced
|
|
868
1161
|
Topic.transaction do
|
|
@@ -915,6 +1208,10 @@ class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
|
|
|
915
1208
|
assert_equal 'id', model.primary_key
|
|
916
1209
|
end
|
|
917
1210
|
end
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
|
|
1214
|
+
|
|
918
1215
|
class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase
|
|
919
1216
|
# We have a few view tables. use includes vs equality.
|
|
920
1217
|
coerce_tests! :test_views
|
|
@@ -974,6 +1271,7 @@ end
|
|
|
974
1271
|
|
|
975
1272
|
|
|
976
1273
|
|
|
1274
|
+
|
|
977
1275
|
class TimePrecisionTest < ActiveRecord::TestCase
|
|
978
1276
|
# datetime is rounded to increments of .000, .003, or .007 seconds
|
|
979
1277
|
coerce_tests! :test_time_precision_is_truncated_on_assignment
|
|
@@ -994,10 +1292,14 @@ class TimePrecisionTest < ActiveRecord::TestCase
|
|
|
994
1292
|
assert_equal 0, foo.start.nsec
|
|
995
1293
|
assert_equal 123457000, foo.finish.nsec
|
|
996
1294
|
end
|
|
1295
|
+
|
|
1296
|
+
# SQL Server uses default precision for time.
|
|
1297
|
+
coerce_tests! :test_no_time_precision_isnt_truncated_on_assignment
|
|
997
1298
|
end
|
|
998
1299
|
|
|
999
1300
|
|
|
1000
1301
|
|
|
1302
|
+
|
|
1001
1303
|
class DefaultNumbersTest < ActiveRecord::TestCase
|
|
1002
1304
|
# We do better with native types and do not return strings for everything.
|
|
1003
1305
|
coerce_tests! :test_default_positive_integer
|
|
@@ -1006,12 +1308,22 @@ class DefaultNumbersTest < ActiveRecord::TestCase
|
|
|
1006
1308
|
assert_equal 7, record.positive_integer
|
|
1007
1309
|
assert_equal 7, record.positive_integer_before_type_cast
|
|
1008
1310
|
end
|
|
1311
|
+
|
|
1312
|
+
# We do better with native types and do not return strings for everything.
|
|
1009
1313
|
coerce_tests! :test_default_negative_integer
|
|
1010
1314
|
def test_default_negative_integer_coerced
|
|
1011
1315
|
record = DefaultNumber.new
|
|
1012
1316
|
assert_equal -5, record.negative_integer
|
|
1013
1317
|
assert_equal -5, record.negative_integer_before_type_cast
|
|
1014
1318
|
end
|
|
1319
|
+
|
|
1320
|
+
# We do better with native types and do not return strings for everything.
|
|
1321
|
+
coerce_tests! :test_default_decimal_number
|
|
1322
|
+
def test_default_decimal_number_coerced
|
|
1323
|
+
record = DefaultNumber.new
|
|
1324
|
+
assert_equal BigDecimal("2.78"), record.decimal_number
|
|
1325
|
+
assert_equal 2.78, record.decimal_number_before_type_cast
|
|
1326
|
+
end
|
|
1015
1327
|
end
|
|
1016
1328
|
|
|
1017
1329
|
|
|
@@ -1027,10 +1339,34 @@ end
|
|
|
1027
1339
|
|
|
1028
1340
|
|
|
1029
1341
|
|
|
1342
|
+
module ActiveRecord
|
|
1343
|
+
class CacheKeyTest < ActiveRecord::TestCase
|
|
1344
|
+
# Like Mysql2 and PostgreSQL, SQL Server doesn't return a string value for updated_at. In the Rails tests
|
|
1345
|
+
# the tests are skipped if adapter is Mysql2 or PostgreSQL.
|
|
1346
|
+
coerce_tests! %r{cache_version is the same when it comes from the DB or from the user}
|
|
1347
|
+
coerce_tests! %r{cache_version does NOT call updated_at when value is from the database}
|
|
1348
|
+
coerce_tests! %r{cache_version does not truncate zeros when timestamp ends in zeros}
|
|
1349
|
+
end
|
|
1350
|
+
end
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
require "models/book"
|
|
1030
1356
|
module ActiveRecord
|
|
1031
1357
|
class StatementCacheTest < ActiveRecord::TestCase
|
|
1032
1358
|
# Getting random failures.
|
|
1033
1359
|
coerce_tests! :test_find_does_not_use_statement_cache_if_table_name_is_changed
|
|
1360
|
+
|
|
1361
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1362
|
+
coerce_tests! :test_statement_cache_values_differ
|
|
1363
|
+
def test_statement_cache_values_differ_coerced
|
|
1364
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1365
|
+
|
|
1366
|
+
original_test_statement_cache_values_differ
|
|
1367
|
+
ensure
|
|
1368
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1369
|
+
end
|
|
1034
1370
|
end
|
|
1035
1371
|
end
|
|
1036
1372
|
|
|
@@ -1049,8 +1385,12 @@ module ActiveRecord
|
|
|
1049
1385
|
end
|
|
1050
1386
|
end
|
|
1051
1387
|
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1052
1391
|
class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
1053
|
-
|
|
1392
|
+
# Use LEN() vs length() function.
|
|
1393
|
+
coerce_tests! %r{order: always allows Arel}
|
|
1054
1394
|
test 'order: always allows Arel' do
|
|
1055
1395
|
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(Arel.sql("len(title)")).pluck(:title) }
|
|
1056
1396
|
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(Arel.sql("len(title)")).pluck(:title) }
|
|
@@ -1058,6 +1398,8 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
|
1058
1398
|
assert_equal ids_depr, ids_disabled
|
|
1059
1399
|
end
|
|
1060
1400
|
|
|
1401
|
+
# Use LEN() vs length() function.
|
|
1402
|
+
coerce_tests! %r{pluck: always allows Arel}
|
|
1061
1403
|
test "pluck: always allows Arel" do
|
|
1062
1404
|
values_depr = with_unsafe_raw_sql_deprecated { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
|
|
1063
1405
|
values_disabled = with_unsafe_raw_sql_disabled { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
|
|
@@ -1065,72 +1407,20 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
|
1065
1407
|
assert_equal values_depr, values_disabled
|
|
1066
1408
|
end
|
|
1067
1409
|
|
|
1068
|
-
|
|
1069
|
-
coerce_tests! %r{order: disallows invalid Array arguments}
|
|
1070
|
-
test "order: disallows invalid Array arguments" do
|
|
1071
|
-
with_unsafe_raw_sql_disabled do
|
|
1072
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1073
|
-
Post.order(["author_id", "len(title)"]).pluck(:id)
|
|
1074
|
-
end
|
|
1075
|
-
end
|
|
1076
|
-
end
|
|
1077
|
-
|
|
1410
|
+
# Use LEN() vs length() function.
|
|
1078
1411
|
coerce_tests! %r{order: allows valid Array arguments}
|
|
1079
1412
|
test "order: allows valid Array arguments" do
|
|
1080
1413
|
ids_expected = Post.order(Arel.sql("author_id, len(title)")).pluck(:id)
|
|
1081
1414
|
|
|
1082
|
-
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id",
|
|
1083
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id",
|
|
1415
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", "len(title)"]).pluck(:id) }
|
|
1416
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", "len(title)"]).pluck(:id) }
|
|
1084
1417
|
|
|
1085
1418
|
assert_equal ids_expected, ids_depr
|
|
1086
1419
|
assert_equal ids_expected, ids_disabled
|
|
1087
1420
|
end
|
|
1421
|
+
end
|
|
1088
1422
|
|
|
1089
|
-
coerce_tests! %r{order: logs deprecation warning for unrecognized column}
|
|
1090
|
-
test "order: logs deprecation warning for unrecognized column" do
|
|
1091
|
-
with_unsafe_raw_sql_deprecated do
|
|
1092
|
-
assert_deprecated(/Dangerous query method/) do
|
|
1093
|
-
Post.order("len(title)")
|
|
1094
|
-
end
|
|
1095
|
-
end
|
|
1096
|
-
end
|
|
1097
1423
|
|
|
1098
|
-
coerce_tests! %r{pluck: disallows invalid column name}
|
|
1099
|
-
test "pluck: disallows invalid column name" do
|
|
1100
|
-
with_unsafe_raw_sql_disabled do
|
|
1101
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1102
|
-
Post.pluck("len(title)")
|
|
1103
|
-
end
|
|
1104
|
-
end
|
|
1105
|
-
end
|
|
1106
|
-
|
|
1107
|
-
coerce_tests! %r{pluck: disallows invalid column name amongst valid names}
|
|
1108
|
-
test "pluck: disallows invalid column name amongst valid names" do
|
|
1109
|
-
with_unsafe_raw_sql_disabled do
|
|
1110
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1111
|
-
Post.pluck(:title, "len(title)")
|
|
1112
|
-
end
|
|
1113
|
-
end
|
|
1114
|
-
end
|
|
1115
|
-
|
|
1116
|
-
coerce_tests! %r{pluck: disallows invalid column names with includes}
|
|
1117
|
-
test "pluck: disallows invalid column names with includes" do
|
|
1118
|
-
with_unsafe_raw_sql_disabled do
|
|
1119
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1120
|
-
Post.includes(:comments).pluck(:title, "len(title)")
|
|
1121
|
-
end
|
|
1122
|
-
end
|
|
1123
|
-
end
|
|
1124
|
-
|
|
1125
|
-
coerce_tests! %r{pluck: logs deprecation warning}
|
|
1126
|
-
test "pluck: logs deprecation warning" do
|
|
1127
|
-
with_unsafe_raw_sql_deprecated do
|
|
1128
|
-
assert_deprecated(/Dangerous query method/) do
|
|
1129
|
-
Post.includes(:comments).pluck(:title, "len(title)")
|
|
1130
|
-
end
|
|
1131
|
-
end
|
|
1132
|
-
end
|
|
1133
|
-
end
|
|
1134
1424
|
|
|
1135
1425
|
|
|
1136
1426
|
class ReservedWordTest < ActiveRecord::TestCase
|
|
@@ -1145,6 +1435,7 @@ end
|
|
|
1145
1435
|
|
|
1146
1436
|
|
|
1147
1437
|
|
|
1438
|
+
|
|
1148
1439
|
class OptimisticLockingTest < ActiveRecord::TestCase
|
|
1149
1440
|
# We do not allow updating identities, but we can test using a non-identity key
|
|
1150
1441
|
coerce_tests! :test_update_with_dirty_primary_key
|
|
@@ -1168,7 +1459,9 @@ end
|
|
|
1168
1459
|
|
|
1169
1460
|
|
|
1170
1461
|
|
|
1462
|
+
|
|
1171
1463
|
class RelationMergingTest < ActiveRecord::TestCase
|
|
1464
|
+
# Use nvarchar string (N'') in assert
|
|
1172
1465
|
coerce_tests! :test_merging_with_order_with_binds
|
|
1173
1466
|
def test_merging_with_order_with_binds_coerced
|
|
1174
1467
|
relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
|
|
@@ -1177,7 +1470,171 @@ class RelationMergingTest < ActiveRecord::TestCase
|
|
|
1177
1470
|
end
|
|
1178
1471
|
|
|
1179
1472
|
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
module ActiveRecord
|
|
1476
|
+
class DatabaseTasksTruncateAllTest < ActiveRecord::TestCase
|
|
1477
|
+
# SQL Server does not allow truncation of tables that are referenced by foreign key
|
|
1478
|
+
# constraints. As this test truncates all tables we would need to remove all foreign
|
|
1479
|
+
# key constraints and then restore them afterwards to get this test to pass.
|
|
1480
|
+
coerce_tests! :test_truncate_tables
|
|
1481
|
+
end
|
|
1482
|
+
end
|
|
1483
|
+
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
require "models/book"
|
|
1488
|
+
class EnumTest < ActiveRecord::TestCase
|
|
1489
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1490
|
+
coerce_tests! %r{enums are distinct per class}
|
|
1491
|
+
test "enums are distinct per class coerced" do
|
|
1492
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1493
|
+
|
|
1494
|
+
send(:'original_enums are distinct per class')
|
|
1495
|
+
ensure
|
|
1496
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1497
|
+
end
|
|
1498
|
+
|
|
1499
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1500
|
+
coerce_tests! %r{creating new objects with enum scopes}
|
|
1501
|
+
test "creating new objects with enum scopes coerced" do
|
|
1502
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1503
|
+
|
|
1504
|
+
send(:'original_creating new objects with enum scopes')
|
|
1505
|
+
ensure
|
|
1506
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1507
|
+
end
|
|
1508
|
+
|
|
1509
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1510
|
+
coerce_tests! %r{enums are inheritable}
|
|
1511
|
+
test "enums are inheritable coerced" do
|
|
1512
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1513
|
+
|
|
1514
|
+
send(:'original_enums are inheritable')
|
|
1515
|
+
ensure
|
|
1516
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1517
|
+
end
|
|
1518
|
+
|
|
1519
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1520
|
+
coerce_tests! %r{declare multiple enums at a time}
|
|
1521
|
+
test "declare multiple enums at a time coerced" do
|
|
1522
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1523
|
+
|
|
1524
|
+
send(:'original_declare multiple enums at a time')
|
|
1525
|
+
ensure
|
|
1526
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1527
|
+
end
|
|
1528
|
+
end
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
require 'models/task'
|
|
1535
|
+
class QueryCacheExpiryTest < ActiveRecord::TestCase
|
|
1536
|
+
|
|
1537
|
+
# SQL Server does not support skipping or upserting duplicates.
|
|
1538
|
+
coerce_tests! :test_insert_all
|
|
1539
|
+
def test_insert_all_coerced
|
|
1540
|
+
assert_raises(ArgumentError, /does not support skipping duplicates/) do
|
|
1541
|
+
Task.cache { Task.insert({ starting: Time.now }) }
|
|
1542
|
+
end
|
|
1543
|
+
|
|
1544
|
+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
|
|
1545
|
+
Task.cache { Task.insert_all!([{ starting: Time.now }]) }
|
|
1546
|
+
end
|
|
1547
|
+
|
|
1548
|
+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
|
|
1549
|
+
Task.cache { Task.insert!({ starting: Time.now }) }
|
|
1550
|
+
end
|
|
1551
|
+
|
|
1552
|
+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
|
|
1553
|
+
Task.cache { Task.insert_all!([{ starting: Time.now }]) }
|
|
1554
|
+
end
|
|
1555
|
+
|
|
1556
|
+
assert_raises(ArgumentError, /does not support upsert/) do
|
|
1557
|
+
Task.cache { Task.upsert({ starting: Time.now }) }
|
|
1558
|
+
end
|
|
1559
|
+
|
|
1560
|
+
assert_raises(ArgumentError, /does not support upsert/) do
|
|
1561
|
+
Task.cache { Task.upsert_all([{ starting: Time.now }]) }
|
|
1562
|
+
end
|
|
1563
|
+
end
|
|
1564
|
+
end
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
|
|
1568
|
+
require 'models/citation'
|
|
1180
1569
|
class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
|
|
1181
|
-
#
|
|
1570
|
+
# Original Rails test fails with SQL Server error message "The query processor ran out of internal resources and
|
|
1571
|
+
# could not produce a query plan". This error goes away if you change database compatibility level to 110 (SQL 2012)
|
|
1572
|
+
# (see https://www.mssqltips.com/sqlservertip/5279/sql-server-error-query-processor-ran-out-of-internal-resources-and-could-not-produce-a-query-plan/).
|
|
1573
|
+
# However, you cannot change the compatibility level during a test. The purpose of the test is to ensure that an
|
|
1574
|
+
# unprepared statement is used if the number of values exceeds the adapter's `bind_params_length`. The coerced test
|
|
1575
|
+
# still does this as there will be 32,768 remaining citation records in the database and the `bind_params_length` of
|
|
1576
|
+
# adapter is 2,098.
|
|
1182
1577
|
coerce_tests! :test_eager_loading_too_may_ids
|
|
1578
|
+
def test_eager_loading_too_may_ids_coerced
|
|
1579
|
+
# Remove excess records.
|
|
1580
|
+
Citation.limit(32768).order(id: :desc).delete_all
|
|
1581
|
+
|
|
1582
|
+
# Perform test
|
|
1583
|
+
citation_count = Citation.count
|
|
1584
|
+
assert_sql(/WHERE \(\[citations\]\.\[id\] IN \(0, 1/) do
|
|
1585
|
+
assert_equal citation_count, Citation.eager_load(:citations).offset(0).size
|
|
1586
|
+
end
|
|
1587
|
+
end
|
|
1588
|
+
end
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
class LogSubscriberTest < ActiveRecord::TestCase
|
|
1594
|
+
# Call original test from coerced test. Fixes issue on CI with Rails installed as a gem.
|
|
1595
|
+
coerce_tests! :test_vebose_query_logs
|
|
1596
|
+
def test_vebose_query_logs_coerced
|
|
1597
|
+
original_test_vebose_query_logs
|
|
1598
|
+
end
|
|
1599
|
+
end
|
|
1600
|
+
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
class ActiveRecordSchemaTest < ActiveRecord::TestCase
|
|
1605
|
+
# Workaround for randomly failing test.
|
|
1606
|
+
coerce_tests! :test_has_primary_key
|
|
1607
|
+
def test_has_primary_key_coerced
|
|
1608
|
+
@schema_migration.reset_column_information
|
|
1609
|
+
original_test_has_primary_key
|
|
1610
|
+
end
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
module ActiveRecord
|
|
1617
|
+
module ConnectionAdapters
|
|
1618
|
+
class ReaperTest < ActiveRecord::TestCase
|
|
1619
|
+
# Coerce can be removed if Rails version > 6.0.3
|
|
1620
|
+
coerce_tests! :test_connection_pool_starts_reaper_in_fork unless Process.respond_to?(:fork)
|
|
1621
|
+
end
|
|
1622
|
+
end
|
|
1623
|
+
end
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
class FixturesTest < ActiveRecord::TestCase
|
|
1629
|
+
# Skip test on Windows. Skip can be removed when Rails PR https://github.com/rails/rails/pull/39234 has been merged.
|
|
1630
|
+
coerce_tests! :test_binary_in_fixtures if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
|
1631
|
+
end
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
class ReloadModelsTest < ActiveRecord::TestCase
|
|
1637
|
+
# Skip test on Windows. The number of arguements passed to `IO.popen` in
|
|
1638
|
+
# `activesupport/lib/active_support/testing/isolation.rb` exceeds what Windows can handle.
|
|
1639
|
+
coerce_tests! :test_has_one_with_reload if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
|
1183
1640
|
end
|