activerecord-sqlserver-adapter 5.2.0 → 6.0.1
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/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +6 -8
- data/CHANGELOG.md +46 -11
- data/{Dockerfile → Dockerfile.ci} +2 -2
- data/Gemfile +48 -41
- data/Guardfile +9 -8
- data/README.md +9 -37
- data/RUNNING_UNIT_TESTS.md +3 -0
- data/Rakefile +14 -16
- 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 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +22 -2
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +3 -3
- 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 +44 -0
- 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 +28 -0
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +88 -44
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +10 -12
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +46 -8
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +16 -5
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -7
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +197 -165
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +43 -44
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +7 -9
- data/lib/active_record/connection_adapters/sqlserver/type.rb +37 -35
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +7 -4
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +6 -6
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +8 -9
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -11
- data/lib/active_record/connection_adapters/sqlserver/version.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +132 -92
- data/lib/active_record/connection_adapters/sqlserver_column.rb +9 -5
- data/lib/active_record/sqlserver_base.rb +9 -1
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +28 -32
- data/lib/activerecord-sqlserver-adapter.rb +3 -1
- data/lib/arel/visitors/sqlserver.rb +58 -24
- data/lib/arel_sqlserver.rb +4 -2
- data/test/appveyor/dbsetup.ps1 +4 -4
- data/test/cases/adapter_test_sqlserver.rb +223 -180
- data/test/cases/change_column_null_test_sqlserver.rb +17 -15
- data/test/cases/coerced_tests.rb +654 -360
- data/test/cases/column_test_sqlserver.rb +635 -604
- data/test/cases/connection_test_sqlserver.rb +18 -21
- data/test/cases/execute_procedure_test_sqlserver.rb +20 -20
- data/test/cases/fetch_test_sqlserver.rb +17 -23
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +15 -19
- data/test/cases/helper_sqlserver.rb +20 -15
- data/test/cases/in_clause_test_sqlserver.rb +36 -0
- data/test/cases/index_test_sqlserver.rb +15 -15
- data/test/cases/json_test_sqlserver.rb +25 -25
- data/test/cases/migration_test_sqlserver.rb +30 -26
- data/test/cases/order_test_sqlserver.rb +53 -54
- data/test/cases/pessimistic_locking_test_sqlserver.rb +31 -37
- data/test/cases/rake_test_sqlserver.rb +44 -56
- data/test/cases/schema_dumper_test_sqlserver.rb +117 -112
- data/test/cases/schema_test_sqlserver.rb +20 -26
- data/test/cases/scratchpad_test_sqlserver.rb +4 -4
- data/test/cases/showplan_test_sqlserver.rb +32 -39
- data/test/cases/specific_schema_test_sqlserver.rb +75 -72
- data/test/cases/transaction_test_sqlserver.rb +27 -29
- data/test/cases/trigger_test_sqlserver.rb +18 -17
- data/test/cases/utils_test_sqlserver.rb +78 -78
- data/test/cases/uuid_test_sqlserver.rb +19 -20
- data/test/debug.rb +8 -6
- data/test/migrations/create_clients_and_change_column_null.rb +3 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +4 -4
- data/test/models/sqlserver/booking.rb +3 -1
- data/test/models/sqlserver/customers_view.rb +3 -1
- 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 +3 -1
- data/test/models/sqlserver/edge_schema.rb +3 -3
- data/test/models/sqlserver/fk_has_fk.rb +3 -1
- data/test/models/sqlserver/fk_has_pk.rb +3 -1
- data/test/models/sqlserver/natural_pk_data.rb +4 -2
- data/test/models/sqlserver/natural_pk_int_data.rb +3 -1
- data/test/models/sqlserver/no_pk_data.rb +3 -1
- data/test/models/sqlserver/object_default.rb +3 -1
- data/test/models/sqlserver/quoted_table.rb +4 -2
- data/test/models/sqlserver/quoted_view_1.rb +3 -1
- data/test/models/sqlserver/quoted_view_2.rb +3 -1
- data/test/models/sqlserver/sst_memory.rb +3 -1
- data/test/models/sqlserver/string_default.rb +3 -1
- data/test/models/sqlserver/string_defaults_big_view.rb +3 -1
- data/test/models/sqlserver/string_defaults_view.rb +3 -1
- data/test/models/sqlserver/tinyint_pk.rb +3 -1
- data/test/models/sqlserver/trigger.rb +4 -2
- data/test/models/sqlserver/trigger_history.rb +3 -1
- data/test/models/sqlserver/upper.rb +3 -1
- data/test/models/sqlserver/uppered.rb +3 -1
- data/test/models/sqlserver/uuid.rb +3 -1
- data/test/schema/datatypes/2012.sql +1 -0
- data/test/schema/sqlserver_specific_schema.rb +31 -21
- data/test/support/coerceable_test_sqlserver.rb +15 -9
- data/test/support/connection_reflection.rb +3 -2
- data/test/support/core_ext/query_cache.rb +4 -1
- data/test/support/load_schema_sqlserver.rb +5 -5
- data/test/support/minitest_sqlserver.rb +3 -1
- data/test/support/paths_sqlserver.rb +11 -11
- data/test/support/rake_helpers.rb +13 -10
- data/test/support/sql_counter_sqlserver.rb +3 -4
- data/test/support/test_in_memory_oltp.rb +9 -7
- metadata +23 -13
- data/BACKERS.md +0 -32
- data/circle.yml +0 -38
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cases/helper_sqlserver"
|
|
4
|
+
require "migrations/create_clients_and_change_column_null"
|
|
3
5
|
|
|
4
6
|
class ChangeColumnNullTestSqlServer < ActiveRecord::TestCase
|
|
5
7
|
before do
|
|
@@ -17,26 +19,26 @@ class ChangeColumnNullTestSqlServer < ActiveRecord::TestCase
|
|
|
17
19
|
table.find { |column| column.name == name }
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
let(:clients_table) { connection.columns(
|
|
21
|
-
let(:name_column) { find_column(clients_table,
|
|
22
|
-
let(:code_column) { find_column(clients_table,
|
|
23
|
-
let(:value_column) { find_column(clients_table,
|
|
22
|
+
let(:clients_table) { connection.columns("clients") }
|
|
23
|
+
let(:name_column) { find_column(clients_table, "name") }
|
|
24
|
+
let(:code_column) { find_column(clients_table, "code") }
|
|
25
|
+
let(:value_column) { find_column(clients_table, "value") }
|
|
24
26
|
|
|
25
|
-
describe
|
|
26
|
-
it
|
|
27
|
-
name_column.limit.must_equal 15
|
|
27
|
+
describe "#change_column_null" do
|
|
28
|
+
it "does not change the column limit" do
|
|
29
|
+
_(name_column.limit).must_equal 15
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
it
|
|
31
|
-
code_column.default.must_equal
|
|
32
|
+
it "does not change the column default" do
|
|
33
|
+
_(code_column.default).must_equal "n/a"
|
|
32
34
|
end
|
|
33
35
|
|
|
34
|
-
it
|
|
35
|
-
value_column.precision.must_equal 32
|
|
36
|
+
it "does not change the column precision" do
|
|
37
|
+
_(value_column.precision).must_equal 32
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
it
|
|
39
|
-
value_column.scale.must_equal 8
|
|
40
|
+
it "does not change the column scale" do
|
|
41
|
+
_(value_column.scale).must_equal 8
|
|
40
42
|
end
|
|
41
43
|
end
|
|
42
44
|
end
|
data/test/cases/coerced_tests.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "cases/helper_sqlserver"
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
require 'models/event'
|
|
5
|
+
require "models/event"
|
|
6
6
|
class UniquenessValidationTest < ActiveRecord::TestCase
|
|
7
|
-
# So sp_executesql swallows this exception. Run without
|
|
7
|
+
# So sp_executesql swallows this exception. Run without prepared to see it.
|
|
8
8
|
coerce_tests! :test_validate_uniqueness_with_limit
|
|
9
9
|
def test_validate_uniqueness_with_limit_coerced
|
|
10
10
|
connection.unprepared_statement do
|
|
@@ -14,7 +14,7 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
# So sp_executesql swallows this exception. Run without
|
|
17
|
+
# So sp_executesql swallows this exception. Run without prepared to see it.
|
|
18
18
|
coerce_tests! :test_validate_uniqueness_with_limit_and_utf8
|
|
19
19
|
def test_validate_uniqueness_with_limit_and_utf8_coerced
|
|
20
20
|
connection.unprepared_statement do
|
|
@@ -23,66 +23,125 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
26
|
|
|
27
|
+
# Skip the test if database is case-insensitive.
|
|
28
|
+
coerce_tests! :test_validate_case_sensitive_uniqueness_by_default
|
|
29
|
+
def test_validate_case_sensitive_uniqueness_by_default_coerced
|
|
30
|
+
database_collation = connection.select_one("SELECT collation_name FROM sys.databases WHERE name = 'activerecord_unittest'").values.first
|
|
31
|
+
skip if database_collation.include?("_CI_")
|
|
29
32
|
|
|
33
|
+
original_test_validate_case_sensitive_uniqueness_by_default_coerced
|
|
34
|
+
end
|
|
35
|
+
end
|
|
30
36
|
|
|
31
|
-
require
|
|
37
|
+
require "models/event"
|
|
32
38
|
module ActiveRecord
|
|
33
39
|
class AdapterTest < ActiveRecord::TestCase
|
|
34
|
-
# I really
|
|
40
|
+
# I really don`t think we can support legacy binds.
|
|
35
41
|
coerce_tests! :test_select_all_with_legacy_binds
|
|
36
42
|
coerce_tests! :test_insert_update_delete_with_legacy_binds
|
|
37
43
|
|
|
38
44
|
# As far as I can tell, SQL Server does not support null bytes in strings.
|
|
39
45
|
coerce_tests! :test_update_prepared_statement
|
|
40
46
|
|
|
41
|
-
# So sp_executesql swallows this exception. Run without
|
|
47
|
+
# So sp_executesql swallows this exception. Run without prepared to see it.
|
|
42
48
|
coerce_tests! :test_value_limit_violations_are_translated_to_specific_exception
|
|
43
49
|
def test_value_limit_violations_are_translated_to_specific_exception_coerced
|
|
44
50
|
connection.unprepared_statement do
|
|
45
51
|
error = assert_raises(ActiveRecord::ValueTooLong) do
|
|
46
|
-
Event.create(title:
|
|
52
|
+
Event.create(title: "abcdefgh")
|
|
47
53
|
end
|
|
48
54
|
assert_not_nil error.cause
|
|
49
55
|
end
|
|
50
56
|
end
|
|
57
|
+
|
|
58
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
|
59
|
+
coerce_tests! :test_errors_when_an_insert_query_is_called_while_preventing_writes
|
|
60
|
+
def test_errors_when_an_insert_query_is_called_while_preventing_writes_coerced
|
|
61
|
+
Subscriber.send(:load_schema!)
|
|
62
|
+
original_test_errors_when_an_insert_query_is_called_while_preventing_writes
|
|
63
|
+
end
|
|
51
64
|
end
|
|
52
65
|
end
|
|
53
66
|
|
|
67
|
+
module ActiveRecord
|
|
68
|
+
class AdapterTestWithoutTransaction < ActiveRecord::TestCase
|
|
69
|
+
# SQL Server does not allow truncation of tables that are referenced by foreign key
|
|
70
|
+
# constraints. So manually remove/add foreign keys in test.
|
|
71
|
+
coerce_tests! :test_truncate_tables
|
|
72
|
+
def test_truncate_tables_coerced
|
|
73
|
+
# Remove foreign key constraint to allow truncation.
|
|
74
|
+
@connection.remove_foreign_key :authors, :author_addresses
|
|
75
|
+
|
|
76
|
+
assert_operator Post.count, :>, 0
|
|
77
|
+
assert_operator Author.count, :>, 0
|
|
78
|
+
assert_operator AuthorAddress.count, :>, 0
|
|
79
|
+
|
|
80
|
+
@connection.truncate_tables("author_addresses", "authors", "posts")
|
|
81
|
+
|
|
82
|
+
assert_equal 0, Post.count
|
|
83
|
+
assert_equal 0, Author.count
|
|
84
|
+
assert_equal 0, AuthorAddress.count
|
|
85
|
+
ensure
|
|
86
|
+
reset_fixtures("posts", "authors", "author_addresses")
|
|
87
|
+
|
|
88
|
+
# Restore foreign key constraint.
|
|
89
|
+
@connection.add_foreign_key :authors, :author_addresses
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# SQL Server does not allow truncation of tables that are referenced by foreign key
|
|
93
|
+
# constraints. So manually remove/add foreign keys in test.
|
|
94
|
+
coerce_tests! :test_truncate_tables_with_query_cache
|
|
95
|
+
def test_truncate_tables_with_query_cache
|
|
96
|
+
# Remove foreign key constraint to allow truncation.
|
|
97
|
+
@connection.remove_foreign_key :authors, :author_addresses
|
|
98
|
+
|
|
99
|
+
@connection.enable_query_cache!
|
|
100
|
+
|
|
101
|
+
assert_operator Post.count, :>, 0
|
|
102
|
+
assert_operator Author.count, :>, 0
|
|
103
|
+
assert_operator AuthorAddress.count, :>, 0
|
|
54
104
|
|
|
105
|
+
@connection.truncate_tables("author_addresses", "authors", "posts")
|
|
55
106
|
|
|
107
|
+
assert_equal 0, Post.count
|
|
108
|
+
assert_equal 0, Author.count
|
|
109
|
+
assert_equal 0, AuthorAddress.count
|
|
110
|
+
ensure
|
|
111
|
+
reset_fixtures("posts", "authors", "author_addresses")
|
|
112
|
+
@connection.disable_query_cache!
|
|
56
113
|
|
|
57
|
-
|
|
114
|
+
# Restore foreign key constraint.
|
|
115
|
+
@connection.add_foreign_key :authors, :author_addresses
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
require "models/topic"
|
|
58
121
|
class AttributeMethodsTest < ActiveRecord::TestCase
|
|
122
|
+
# Use IFF for boolean statement in SELECT
|
|
59
123
|
coerce_tests! %r{typecast attribute from select to false}
|
|
60
124
|
def test_typecast_attribute_from_select_to_false_coerced
|
|
61
|
-
Topic.create(:title =>
|
|
125
|
+
Topic.create(:title => "Budget")
|
|
62
126
|
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
|
|
63
|
-
|
|
127
|
+
assert_not_predicate topic, :is_test?
|
|
64
128
|
end
|
|
65
129
|
|
|
130
|
+
# Use IFF for boolean statement in SELECT
|
|
66
131
|
coerce_tests! %r{typecast attribute from select to true}
|
|
67
132
|
def test_typecast_attribute_from_select_to_true_coerced
|
|
68
|
-
Topic.create(:title =>
|
|
133
|
+
Topic.create(:title => "Budget")
|
|
69
134
|
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
|
|
70
|
-
|
|
135
|
+
assert_predicate topic, :is_test?
|
|
71
136
|
end
|
|
72
137
|
end
|
|
73
138
|
|
|
74
|
-
|
|
75
|
-
class NumericDataTest < ActiveRecord::TestCase
|
|
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
|
|
80
|
-
|
|
81
139
|
class BasicsTest < ActiveRecord::TestCase
|
|
140
|
+
# Use square brackets as SQL Server escaped character
|
|
82
141
|
coerce_tests! :test_column_names_are_escaped
|
|
83
142
|
def test_column_names_are_escaped_coerced
|
|
84
143
|
conn = ActiveRecord::Base.connection
|
|
85
|
-
assert_equal
|
|
144
|
+
assert_equal "[t]]]", conn.quote_column_name("t]")
|
|
86
145
|
end
|
|
87
146
|
|
|
88
147
|
# Just like PostgreSQLAdapter does.
|
|
@@ -96,110 +155,128 @@ class BasicsTest < ActiveRecord::TestCase
|
|
|
96
155
|
Time.use_zone("Eastern Time (US & Canada)") do
|
|
97
156
|
topic = Topic.find(1)
|
|
98
157
|
time = Time.zone.parse("2017-07-17 10:56")
|
|
99
|
-
topic.
|
|
158
|
+
topic.update!(written_on: time)
|
|
100
159
|
assert_equal(time, topic.written_on)
|
|
101
160
|
end
|
|
102
161
|
end
|
|
103
162
|
|
|
104
163
|
def test_update_date_time_attributes_with_default_timezone_local
|
|
105
|
-
with_env_tz
|
|
164
|
+
with_env_tz "America/New_York" do
|
|
106
165
|
with_timezone_config default: :local do
|
|
107
166
|
Time.use_zone("Eastern Time (US & Canada)") do
|
|
108
167
|
topic = Topic.find(1)
|
|
109
168
|
time = Time.zone.parse("2017-07-17 10:56")
|
|
110
|
-
topic.
|
|
169
|
+
topic.update!(written_on: time)
|
|
111
170
|
assert_equal(time, topic.written_on)
|
|
112
171
|
end
|
|
113
172
|
end
|
|
114
173
|
end
|
|
115
174
|
end
|
|
116
175
|
|
|
117
|
-
#
|
|
118
|
-
coerce_tests! %r{
|
|
119
|
-
test "
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
176
|
+
# SQL Server does not have query for release_savepoint
|
|
177
|
+
coerce_tests! %r{an empty transaction does not raise if preventing writes}
|
|
178
|
+
test "an empty transaction does not raise if preventing writes coerced" do
|
|
179
|
+
ActiveRecord::Base.connection_handler.while_preventing_writes do
|
|
180
|
+
assert_queries(1, ignore_none: true) do
|
|
181
|
+
Bird.transaction do
|
|
182
|
+
ActiveRecord::Base.connection.materialize_transactions
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
125
186
|
end
|
|
126
187
|
end
|
|
127
188
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
189
|
class BelongsToAssociationsTest < ActiveRecord::TestCase
|
|
132
190
|
# Since @client.firm is a single first/top, and we use FETCH the order clause is used.
|
|
133
191
|
coerce_tests! :test_belongs_to_does_not_use_order_by
|
|
134
192
|
|
|
193
|
+
# Square brackets around column name
|
|
135
194
|
coerce_tests! :test_belongs_to_with_primary_key_joins_on_correct_column
|
|
136
195
|
def test_belongs_to_with_primary_key_joins_on_correct_column_coerced
|
|
137
196
|
sql = Client.joins(:firm_with_primary_key).to_sql
|
|
138
197
|
assert_no_match(/\[firm_with_primary_keys_companies\]\.\[id\]/, sql)
|
|
139
198
|
assert_match(/\[firm_with_primary_keys_companies\]\.\[name\]/, sql)
|
|
140
199
|
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
|
|
144
200
|
|
|
201
|
+
# Asserted SQL to get one row different from original test.
|
|
202
|
+
coerce_tests! :test_belongs_to
|
|
203
|
+
def test_belongs_to_coerced
|
|
204
|
+
client = Client.find(3)
|
|
205
|
+
first_firm = companies(:first_firm)
|
|
206
|
+
assert_sql(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
|
|
207
|
+
assert_equal first_firm, client.firm
|
|
208
|
+
assert_equal first_firm.name, client.firm.name
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
145
212
|
|
|
146
213
|
module ActiveRecord
|
|
147
214
|
class BindParameterTest < ActiveRecord::TestCase
|
|
148
|
-
#
|
|
215
|
+
# Same as original coerced test except log is found using `EXEC sp_executesql` wrapper.
|
|
149
216
|
coerce_tests! :test_binds_are_logged
|
|
217
|
+
def test_binds_are_logged_coerced
|
|
218
|
+
sub = Arel::Nodes::BindParam.new(1)
|
|
219
|
+
binds = [Relation::QueryAttribute.new("id", 1, Type::Value.new)]
|
|
220
|
+
sql = "select * from topics where id = #{sub.to_sql}"
|
|
221
|
+
|
|
222
|
+
@connection.exec_query(sql, "SQL", binds)
|
|
223
|
+
|
|
224
|
+
logged_sql = "EXEC sp_executesql N'#{sql}', N'#{sub.to_sql} int', #{sub.to_sql} = 1"
|
|
225
|
+
message = @subscriber.calls.find { |args| args[4][:sql] == logged_sql }
|
|
226
|
+
|
|
227
|
+
assert_equal binds, message[4][:binds]
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# SQL Server adapter does not use a statement cache as query plans are already reused using `EXEC sp_executesql`.
|
|
231
|
+
coerce_tests! :test_statement_cache
|
|
232
|
+
coerce_tests! :test_statement_cache_with_query_cache
|
|
233
|
+
coerce_tests! :test_statement_cache_with_find
|
|
234
|
+
coerce_tests! :test_statement_cache_with_find_by
|
|
235
|
+
coerce_tests! :test_statement_cache_with_in_clause
|
|
236
|
+
coerce_tests! :test_statement_cache_with_sql_string_literal
|
|
150
237
|
end
|
|
151
238
|
end
|
|
152
239
|
|
|
153
|
-
|
|
154
240
|
module ActiveRecord
|
|
155
241
|
class InstrumentationTest < ActiveRecord::TestCase
|
|
156
|
-
#
|
|
242
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
|
157
243
|
coerce_tests! :test_payload_name_on_load
|
|
158
244
|
def test_payload_name_on_load_coerced
|
|
159
|
-
Book.
|
|
160
|
-
|
|
161
|
-
subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
|
|
162
|
-
event = ActiveSupport::Notifications::Event.new(*args)
|
|
163
|
-
if event.payload[:sql].match "SELECT"
|
|
164
|
-
assert_equal "Book Load", event.payload[:name]
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
Book.first
|
|
168
|
-
ensure
|
|
169
|
-
ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
|
|
245
|
+
Book.send(:load_schema!)
|
|
246
|
+
original_test_payload_name_on_load
|
|
170
247
|
end
|
|
171
248
|
end
|
|
172
249
|
end
|
|
173
250
|
|
|
174
251
|
class CalculationsTest < ActiveRecord::TestCase
|
|
175
|
-
#
|
|
252
|
+
# Fix randomly failing test. The loading of the model's schema was affecting the test.
|
|
176
253
|
coerce_tests! :test_offset_is_kept
|
|
177
254
|
def test_offset_is_kept_coerced
|
|
178
|
-
Account.
|
|
179
|
-
|
|
180
|
-
assert_equal 1, queries.length
|
|
181
|
-
assert_match(/OFFSET/, queries.first)
|
|
255
|
+
Account.send(:load_schema!)
|
|
256
|
+
original_test_offset_is_kept
|
|
182
257
|
end
|
|
183
258
|
|
|
184
259
|
# Are decimal, not integer.
|
|
185
260
|
coerce_tests! :test_should_return_decimal_average_of_integer_field
|
|
186
261
|
def test_should_return_decimal_average_of_integer_field_coerced
|
|
187
262
|
value = Account.average(:id)
|
|
188
|
-
assert_equal BigDecimal(
|
|
263
|
+
assert_equal BigDecimal("3.0").to_s, BigDecimal(value).to_s
|
|
189
264
|
end
|
|
190
265
|
|
|
266
|
+
# Match SQL Server limit implementation
|
|
191
267
|
coerce_tests! :test_limit_is_kept
|
|
192
268
|
def test_limit_is_kept_coerced
|
|
193
269
|
queries = capture_sql_ss { Account.limit(1).count }
|
|
194
270
|
assert_equal 1, queries.length
|
|
195
|
-
|
|
271
|
+
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/, queries.first)
|
|
196
272
|
end
|
|
197
273
|
|
|
274
|
+
# Match SQL Server limit implementation
|
|
198
275
|
coerce_tests! :test_limit_with_offset_is_kept
|
|
199
276
|
def test_limit_with_offset_is_kept_coerced
|
|
200
277
|
queries = capture_sql_ss { Account.limit(1).offset(1).count }
|
|
201
278
|
assert_equal 1, queries.length
|
|
202
|
-
|
|
279
|
+
assert_match(/ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1/, queries.first)
|
|
203
280
|
end
|
|
204
281
|
|
|
205
282
|
# SQL Server needs an alias for the calculated column
|
|
@@ -214,49 +291,57 @@ class CalculationsTest < ActiveRecord::TestCase
|
|
|
214
291
|
coerce_tests! :test_having_with_strong_parameters
|
|
215
292
|
end
|
|
216
293
|
|
|
217
|
-
|
|
218
|
-
|
|
219
294
|
module ActiveRecord
|
|
220
295
|
class Migration
|
|
221
296
|
class ChangeSchemaTest < ActiveRecord::TestCase
|
|
222
|
-
|
|
223
|
-
coerce_tests! :
|
|
224
|
-
|
|
225
|
-
|
|
297
|
+
# Integer.default is a number and not a string
|
|
298
|
+
coerce_tests! :test_create_table_with_defaults
|
|
299
|
+
def test_create_table_with_defaults_coerce
|
|
300
|
+
connection.create_table :testings do |t|
|
|
301
|
+
t.column :one, :string, default: "hello"
|
|
302
|
+
t.column :two, :boolean, default: true
|
|
303
|
+
t.column :three, :boolean, default: false
|
|
304
|
+
t.column :four, :integer, default: 1
|
|
305
|
+
t.column :five, :text, default: "hello"
|
|
306
|
+
end
|
|
226
307
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
308
|
+
columns = connection.columns(:testings)
|
|
309
|
+
one = columns.detect { |c| c.name == "one" }
|
|
310
|
+
two = columns.detect { |c| c.name == "two" }
|
|
311
|
+
three = columns.detect { |c| c.name == "three" }
|
|
312
|
+
four = columns.detect { |c| c.name == "four" }
|
|
313
|
+
five = columns.detect { |c| c.name == "five" }
|
|
314
|
+
|
|
315
|
+
assert_equal "hello", one.default
|
|
316
|
+
assert_equal true, connection.lookup_cast_type_from_column(two).deserialize(two.default)
|
|
317
|
+
assert_equal false, connection.lookup_cast_type_from_column(three).deserialize(three.default)
|
|
318
|
+
assert_equal 1, four.default
|
|
319
|
+
assert_equal "hello", five.default
|
|
320
|
+
end
|
|
230
321
|
end
|
|
231
322
|
end
|
|
232
323
|
end
|
|
233
324
|
|
|
234
|
-
|
|
235
|
-
|
|
236
325
|
module ActiveRecord
|
|
237
326
|
module ConnectionAdapters
|
|
238
327
|
class QuoteARBaseTest < ActiveRecord::TestCase
|
|
239
|
-
|
|
240
328
|
# Use our date format.
|
|
241
329
|
coerce_tests! :test_quote_ar_object
|
|
242
330
|
def test_quote_ar_object_coerced
|
|
243
331
|
value = DatetimePrimaryKey.new(id: @time)
|
|
244
|
-
assert_equal "'02-14-2017 12:34:56.79'",
|
|
332
|
+
assert_equal "'02-14-2017 12:34:56.79'", @connection.quote(value)
|
|
245
333
|
end
|
|
246
334
|
|
|
247
335
|
# Use our date format.
|
|
248
336
|
coerce_tests! :test_type_cast_ar_object
|
|
249
337
|
def test_type_cast_ar_object_coerced
|
|
250
338
|
value = DatetimePrimaryKey.new(id: @time)
|
|
251
|
-
assert_equal "02-14-2017 12:34:56.79",
|
|
339
|
+
assert_equal "02-14-2017 12:34:56.79", @connection.type_cast(value)
|
|
252
340
|
end
|
|
253
|
-
|
|
254
341
|
end
|
|
255
342
|
end
|
|
256
343
|
end
|
|
257
344
|
|
|
258
|
-
|
|
259
|
-
|
|
260
345
|
module ActiveRecord
|
|
261
346
|
class Migration
|
|
262
347
|
class ColumnAttributesTest < ActiveRecord::TestCase
|
|
@@ -265,22 +350,19 @@ module ActiveRecord
|
|
|
265
350
|
def test_add_column_without_limit_coerced
|
|
266
351
|
add_column :test_models, :description, :string, limit: nil
|
|
267
352
|
TestModel.reset_column_information
|
|
268
|
-
TestModel.columns_hash["description"].limit.must_equal 4000
|
|
353
|
+
_(TestModel.columns_hash["description"].limit).must_equal 4000
|
|
269
354
|
end
|
|
270
355
|
end
|
|
271
356
|
end
|
|
272
357
|
end
|
|
273
358
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
359
|
module ActiveRecord
|
|
278
360
|
class Migration
|
|
279
|
-
class ColumnsTest
|
|
361
|
+
class ColumnsTest < ActiveRecord::TestCase
|
|
280
362
|
# Our defaults are real 70000 integers vs '70000' strings.
|
|
281
363
|
coerce_tests! :test_rename_column_preserves_default_value_not_null
|
|
282
364
|
def test_rename_column_preserves_default_value_not_null_coerced
|
|
283
|
-
add_column
|
|
365
|
+
add_column "test_models", "salary", :integer, :default => 70000
|
|
284
366
|
default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
|
|
285
367
|
assert_equal 70000, default_before
|
|
286
368
|
rename_column "test_models", "salary", "annual_salary"
|
|
@@ -296,9 +378,9 @@ module ActiveRecord
|
|
|
296
378
|
add_column "test_models", :hat_size, :integer
|
|
297
379
|
add_column "test_models", :hat_style, :string, :limit => 100
|
|
298
380
|
add_index "test_models", ["hat_style", "hat_size"], :unique => true
|
|
299
|
-
assert_equal 1, connection.indexes(
|
|
381
|
+
assert_equal 1, connection.indexes("test_models").size
|
|
300
382
|
remove_column("test_models", "hat_size")
|
|
301
|
-
assert_equal [], connection.indexes(
|
|
383
|
+
assert_equal [], connection.indexes("test_models").map(&:name)
|
|
302
384
|
end
|
|
303
385
|
|
|
304
386
|
# Choose `StatementInvalid` vs `ActiveRecordError`.
|
|
@@ -313,9 +395,6 @@ module ActiveRecord
|
|
|
313
395
|
end
|
|
314
396
|
end
|
|
315
397
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
398
|
class MigrationTest < ActiveRecord::TestCase
|
|
320
399
|
# We do not have do the DecimalWithoutScale type.
|
|
321
400
|
coerce_tests! :test_add_table_with_decimals
|
|
@@ -339,7 +418,7 @@ class MigrationTest < ActiveRecord::TestCase
|
|
|
339
418
|
assert_not_nil b.my_house_population
|
|
340
419
|
assert_not_nil b.value_of_e
|
|
341
420
|
assert_kind_of BigDecimal, b.world_population
|
|
342
|
-
assert_equal
|
|
421
|
+
assert_equal "6000000000.0", b.world_population.to_s
|
|
343
422
|
assert_kind_of Integer, b.my_house_population
|
|
344
423
|
assert_equal 3, b.my_house_population
|
|
345
424
|
assert_kind_of BigDecimal, b.bank_balance
|
|
@@ -355,19 +434,13 @@ class MigrationTest < ActiveRecord::TestCase
|
|
|
355
434
|
coerce_tests! :test_internal_metadata_stores_environment
|
|
356
435
|
end
|
|
357
436
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
437
|
class CoreTest < ActiveRecord::TestCase
|
|
362
|
-
# I think fixtures are
|
|
438
|
+
# I think fixtures are using the wrong time zone and the `:first`
|
|
363
439
|
# `topics`.`bonus_time` attribute of 2005-01-30t15:28:00.00+01:00 is
|
|
364
440
|
# getting local EST time for me and set to "09:28:00.0000000".
|
|
365
441
|
coerce_tests! :test_pretty_print_persisted
|
|
366
442
|
end
|
|
367
443
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
444
|
module ActiveRecord
|
|
372
445
|
module ConnectionAdapters
|
|
373
446
|
# Just like PostgreSQLAdapter does.
|
|
@@ -381,27 +454,152 @@ module ActiveRecord
|
|
|
381
454
|
end
|
|
382
455
|
end
|
|
383
456
|
|
|
457
|
+
module ActiveRecord
|
|
458
|
+
# The original module is hardcoded for PostgreSQL/SQLite/MySQL tests.
|
|
459
|
+
module DatabaseTasksSetupper
|
|
460
|
+
def setup
|
|
461
|
+
@sqlserver_tasks =
|
|
462
|
+
Class.new do
|
|
463
|
+
def create; end
|
|
384
464
|
|
|
465
|
+
def drop; end
|
|
385
466
|
|
|
467
|
+
def purge; end
|
|
468
|
+
|
|
469
|
+
def charset; end
|
|
470
|
+
|
|
471
|
+
def collation; end
|
|
472
|
+
|
|
473
|
+
def structure_dump(*); end
|
|
474
|
+
|
|
475
|
+
def structure_load(*); end
|
|
476
|
+
end.new
|
|
477
|
+
|
|
478
|
+
$stdout, @original_stdout = StringIO.new, $stdout
|
|
479
|
+
$stderr, @original_stderr = StringIO.new, $stderr
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def with_stubbed_new
|
|
483
|
+
ActiveRecord::Tasks::SQLServerDatabaseTasks.stub(:new, @sqlserver_tasks) do
|
|
484
|
+
yield
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
class DatabaseTasksCreateTest < ActiveRecord::TestCase
|
|
490
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
491
|
+
coerce_all_tests!
|
|
492
|
+
|
|
493
|
+
def test_sqlserver_create
|
|
494
|
+
with_stubbed_new do
|
|
495
|
+
assert_called(eval("@sqlserver_tasks"), :create) do
|
|
496
|
+
ActiveRecord::Tasks::DatabaseTasks.create "adapter" => :sqlserver
|
|
497
|
+
end
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
class DatabaseTasksDropTest < ActiveRecord::TestCase
|
|
503
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
504
|
+
coerce_all_tests!
|
|
505
|
+
|
|
506
|
+
def test_sqlserver_drop
|
|
507
|
+
with_stubbed_new do
|
|
508
|
+
assert_called(eval("@sqlserver_tasks"), :drop) do
|
|
509
|
+
ActiveRecord::Tasks::DatabaseTasks.drop "adapter" => :sqlserver
|
|
510
|
+
end
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
class DatabaseTasksPurgeTest < ActiveRecord::TestCase
|
|
516
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
517
|
+
coerce_all_tests!
|
|
518
|
+
|
|
519
|
+
def test_sqlserver_purge
|
|
520
|
+
with_stubbed_new do
|
|
521
|
+
assert_called(eval("@sqlserver_tasks"), :purge) do
|
|
522
|
+
ActiveRecord::Tasks::DatabaseTasks.purge "adapter" => :sqlserver
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
class DatabaseTasksCharsetTest < ActiveRecord::TestCase
|
|
529
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
530
|
+
coerce_all_tests!
|
|
531
|
+
|
|
532
|
+
def test_sqlserver_charset
|
|
533
|
+
with_stubbed_new do
|
|
534
|
+
assert_called(eval("@sqlserver_tasks"), :charset) do
|
|
535
|
+
ActiveRecord::Tasks::DatabaseTasks.charset "adapter" => :sqlserver
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
class DatabaseTasksCollationTest < ActiveRecord::TestCase
|
|
542
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
543
|
+
coerce_all_tests!
|
|
544
|
+
|
|
545
|
+
def test_sqlserver_collation
|
|
546
|
+
with_stubbed_new do
|
|
547
|
+
assert_called(eval("@sqlserver_tasks"), :collation) do
|
|
548
|
+
ActiveRecord::Tasks::DatabaseTasks.collation "adapter" => :sqlserver
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
class DatabaseTasksStructureDumpTest < ActiveRecord::TestCase
|
|
555
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
556
|
+
coerce_all_tests!
|
|
557
|
+
|
|
558
|
+
def test_sqlserver_structure_dump
|
|
559
|
+
with_stubbed_new do
|
|
560
|
+
assert_called_with(
|
|
561
|
+
eval("@sqlserver_tasks"), :structure_dump,
|
|
562
|
+
["awesome-file.sql", nil]
|
|
563
|
+
) do
|
|
564
|
+
ActiveRecord::Tasks::DatabaseTasks.structure_dump({ "adapter" => :sqlserver }, "awesome-file.sql")
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
class DatabaseTasksStructureLoadTest < ActiveRecord::TestCase
|
|
571
|
+
# Coerce PostgreSQL/SQLite/MySQL tests.
|
|
572
|
+
coerce_all_tests!
|
|
573
|
+
|
|
574
|
+
def test_sqlserver_structure_load
|
|
575
|
+
with_stubbed_new do
|
|
576
|
+
assert_called_with(
|
|
577
|
+
eval("@sqlserver_tasks"),
|
|
578
|
+
:structure_load,
|
|
579
|
+
["awesome-file.sql", nil]
|
|
580
|
+
) do
|
|
581
|
+
ActiveRecord::Tasks::DatabaseTasks.structure_load({ "adapter" => :sqlserver }, "awesome-file.sql")
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
end
|
|
585
|
+
end
|
|
386
586
|
|
|
387
|
-
module ActiveRecord
|
|
388
587
|
class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
|
|
389
588
|
# Skip this test with /tmp/my_schema_cache.yml path on Windows.
|
|
390
|
-
coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG[
|
|
589
|
+
coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
|
391
590
|
end
|
|
591
|
+
|
|
392
592
|
class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
|
|
393
593
|
# We extend `local_database?` so that common VM IPs can be used.
|
|
394
594
|
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
|
395
595
|
end
|
|
596
|
+
|
|
396
597
|
class DatabaseTasksDropAllTest < ActiveRecord::TestCase
|
|
397
598
|
# We extend `local_database?` so that common VM IPs can be used.
|
|
398
599
|
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
|
399
600
|
end
|
|
400
601
|
end
|
|
401
602
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
603
|
class DefaultScopingTest < ActiveRecord::TestCase
|
|
406
604
|
# We are not doing order duplicate removal anymore.
|
|
407
605
|
coerce_tests! :test_order_in_default_scope_should_not_prevail
|
|
@@ -415,16 +613,13 @@ class DefaultScopingTest < ActiveRecord::TestCase
|
|
|
415
613
|
end
|
|
416
614
|
end
|
|
417
615
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
require 'models/post'
|
|
422
|
-
require 'models/subscriber'
|
|
616
|
+
require "models/post"
|
|
617
|
+
require "models/subscriber"
|
|
423
618
|
class EachTest < ActiveRecord::TestCase
|
|
424
619
|
# Quoting in tests does not cope with bracket quoting.
|
|
425
620
|
coerce_tests! :test_find_in_batches_should_quote_batch_order
|
|
426
621
|
def test_find_in_batches_should_quote_batch_order_coerced
|
|
427
|
-
|
|
622
|
+
Post.connection
|
|
428
623
|
assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
|
|
429
624
|
Post.find_in_batches(:batch_size => 1) do |batch|
|
|
430
625
|
assert_kind_of Array, batch
|
|
@@ -436,7 +631,7 @@ class EachTest < ActiveRecord::TestCase
|
|
|
436
631
|
# Quoting in tests does not cope with bracket quoting.
|
|
437
632
|
coerce_tests! :test_in_batches_should_quote_batch_order
|
|
438
633
|
def test_in_batches_should_quote_batch_order_coerced
|
|
439
|
-
|
|
634
|
+
Post.connection
|
|
440
635
|
assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
|
|
441
636
|
Post.in_batches(of: 1) do |relation|
|
|
442
637
|
assert_kind_of ActiveRecord::Relation, relation
|
|
@@ -446,9 +641,6 @@ class EachTest < ActiveRecord::TestCase
|
|
|
446
641
|
end
|
|
447
642
|
end
|
|
448
643
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
644
|
class EagerAssociationTest < ActiveRecord::TestCase
|
|
453
645
|
# Use LEN() vs length() function.
|
|
454
646
|
coerce_tests! :test_count_with_include
|
|
@@ -460,14 +652,13 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
|
460
652
|
coerce_tests! %r{including association based on sql condition and no database column}
|
|
461
653
|
end
|
|
462
654
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
require 'models/topic'
|
|
655
|
+
require "models/topic"
|
|
467
656
|
class FinderTest < ActiveRecord::TestCase
|
|
657
|
+
# We have implicit ordering, via FETCH.
|
|
468
658
|
coerce_tests! %r{doesn't have implicit ordering},
|
|
469
|
-
:test_find_doesnt_have_implicit_ordering
|
|
659
|
+
:test_find_doesnt_have_implicit_ordering
|
|
470
660
|
|
|
661
|
+
# Square brackets around column name
|
|
471
662
|
coerce_tests! :test_exists_does_not_select_columns_without_alias
|
|
472
663
|
def test_exists_does_not_select_columns_without_alias_coerced
|
|
473
664
|
assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) do
|
|
@@ -475,6 +666,7 @@ class FinderTest < ActiveRecord::TestCase
|
|
|
475
666
|
end
|
|
476
667
|
end
|
|
477
668
|
|
|
669
|
+
# Assert SQL Server limit implementation
|
|
478
670
|
coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
|
|
479
671
|
def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
|
|
480
672
|
assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
|
|
@@ -488,7 +680,7 @@ class FinderTest < ActiveRecord::TestCase
|
|
|
488
680
|
# Can not use array condition due to not finding right type and hence fractional second quoting.
|
|
489
681
|
coerce_tests! :test_condition_utc_time_interpolation_with_default_timezone_local
|
|
490
682
|
def test_condition_utc_time_interpolation_with_default_timezone_local_coerced
|
|
491
|
-
with_env_tz
|
|
683
|
+
with_env_tz "America/New_York" do
|
|
492
684
|
with_timezone_config default: :local do
|
|
493
685
|
topic = Topic.first
|
|
494
686
|
assert_equal topic, Topic.where(written_on: topic.written_on.getutc).first
|
|
@@ -499,7 +691,7 @@ class FinderTest < ActiveRecord::TestCase
|
|
|
499
691
|
# Can not use array condition due to not finding right type and hence fractional second quoting.
|
|
500
692
|
coerce_tests! :test_condition_local_time_interpolation_with_default_timezone_utc
|
|
501
693
|
def test_condition_local_time_interpolation_with_default_timezone_utc_coerced
|
|
502
|
-
with_env_tz
|
|
694
|
+
with_env_tz "America/New_York" do
|
|
503
695
|
with_timezone_config default: :utc do
|
|
504
696
|
topic = Topic.first
|
|
505
697
|
assert_equal topic, Topic.where(written_on: topic.written_on.getlocal).first
|
|
@@ -508,9 +700,6 @@ class FinderTest < ActiveRecord::TestCase
|
|
|
508
700
|
end
|
|
509
701
|
end
|
|
510
702
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
703
|
module ActiveRecord
|
|
515
704
|
class Migration
|
|
516
705
|
class ForeignKeyTest < ActiveRecord::TestCase
|
|
@@ -528,172 +717,184 @@ module ActiveRecord
|
|
|
528
717
|
end
|
|
529
718
|
end
|
|
530
719
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
720
|
class HasOneAssociationsTest < ActiveRecord::TestCase
|
|
535
721
|
# We use OFFSET/FETCH vs TOP. So we always have an order.
|
|
536
722
|
coerce_tests! :test_has_one_does_not_use_order_by
|
|
537
|
-
end
|
|
538
|
-
|
|
539
723
|
|
|
724
|
+
# Asserted SQL to get one row different from original test.
|
|
725
|
+
coerce_tests! :test_has_one
|
|
726
|
+
def test_has_one_coerced
|
|
727
|
+
firm = companies(:first_firm)
|
|
728
|
+
first_account = Account.find(1)
|
|
729
|
+
assert_sql(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
|
|
730
|
+
assert_equal first_account, firm.account
|
|
731
|
+
assert_equal first_account.credit_limit, firm.account.credit_limit
|
|
732
|
+
end
|
|
733
|
+
end
|
|
734
|
+
end
|
|
540
735
|
|
|
736
|
+
class HasOneThroughAssociationsTest < ActiveRecord::TestCase
|
|
737
|
+
# Asserted SQL to get one row different from original test.
|
|
738
|
+
coerce_tests! :test_has_one_through_executes_limited_query
|
|
739
|
+
def test_has_one_through_executes_limited_query_coerced
|
|
740
|
+
boring_club = clubs(:boring_club)
|
|
741
|
+
assert_sql(/FETCH NEXT @(\d) ROWS ONLY(.)*@\1 = 1/) do
|
|
742
|
+
assert_equal boring_club, @member.general_club
|
|
743
|
+
end
|
|
744
|
+
end
|
|
745
|
+
end
|
|
541
746
|
|
|
542
|
-
require
|
|
747
|
+
require "models/company"
|
|
543
748
|
class InheritanceTest < ActiveRecord::TestCase
|
|
749
|
+
# Rails test required inserting to a identity column.
|
|
544
750
|
coerce_tests! :test_a_bad_type_column
|
|
545
751
|
def test_a_bad_type_column_coerced
|
|
546
|
-
Company.connection.with_identity_insert_enabled(
|
|
752
|
+
Company.connection.with_identity_insert_enabled("companies") do
|
|
547
753
|
Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
|
|
548
754
|
end
|
|
549
755
|
assert_raise(ActiveRecord::SubclassNotFound) { Company.find(100) }
|
|
550
756
|
end
|
|
551
757
|
|
|
758
|
+
# Use Square brackets around column name
|
|
552
759
|
coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
|
|
553
760
|
def test_eager_load_belongs_to_primary_key_quoting_coerced
|
|
554
|
-
|
|
761
|
+
Account.connection
|
|
555
762
|
assert_sql(/\[companies\]\.\[id\] = @0.* @0 = 1/) do
|
|
556
763
|
Account.all.merge!(:includes => :firm).find(1)
|
|
557
764
|
end
|
|
558
765
|
end
|
|
559
766
|
end
|
|
560
767
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
768
|
class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
|
|
565
769
|
# Uses || operator in SQL. Just trust core gets value out of this test.
|
|
566
770
|
coerce_tests! :test_does_not_override_select
|
|
567
771
|
end
|
|
568
772
|
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
class NamedScopingTest < ActiveRecord::TestCase
|
|
573
|
-
# This works now because we add an `order(:id)` sort to break the order tie for deterministic results.
|
|
574
|
-
coerce_tests! :test_scopes_honor_current_scopes_from_when_defined
|
|
575
|
-
def test_scopes_honor_current_scopes_from_when_defined_coerced
|
|
576
|
-
assert !Post.ranked_by_comments.order(:id).limit_by(5).empty?
|
|
577
|
-
assert !authors(:david).posts.ranked_by_comments.order(:id).limit_by(5).empty?
|
|
578
|
-
assert_not_equal Post.ranked_by_comments.order(:id).limit_by(5), authors(:david).posts.ranked_by_comments.order(:id).limit_by(5)
|
|
579
|
-
assert_not_equal Post.order(:id).top(5), authors(:david).posts.order(:id).top(5)
|
|
580
|
-
# Oracle sometimes sorts differently if WHERE condition is changed
|
|
581
|
-
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)
|
|
582
|
-
assert_equal Post.ranked_by_comments.limit_by(5), Post.top(5)
|
|
583
|
-
end
|
|
584
|
-
end
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
require 'models/developer'
|
|
590
|
-
require 'models/computer'
|
|
773
|
+
require "models/developer"
|
|
774
|
+
require "models/computer"
|
|
591
775
|
class NestedRelationScopingTest < ActiveRecord::TestCase
|
|
776
|
+
# Assert SQL Server limit implementation
|
|
592
777
|
coerce_tests! :test_merge_options
|
|
593
778
|
def test_merge_options_coerced
|
|
594
|
-
Developer.where(
|
|
779
|
+
Developer.where("salary = 80000").scoping do
|
|
595
780
|
Developer.limit(10).scoping do
|
|
596
781
|
devs = Developer.all
|
|
597
782
|
sql = devs.to_sql
|
|
598
|
-
assert_match
|
|
599
|
-
assert_match
|
|
783
|
+
assert_match "(salary = 80000)", sql
|
|
784
|
+
assert_match "FETCH NEXT 10 ROWS ONLY", sql
|
|
600
785
|
end
|
|
601
786
|
end
|
|
602
787
|
end
|
|
603
788
|
end
|
|
604
789
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
require 'models/parrot'
|
|
609
|
-
require 'models/topic'
|
|
790
|
+
require "models/topic"
|
|
610
791
|
class PersistenceTest < ActiveRecord::TestCase
|
|
611
|
-
#
|
|
792
|
+
# Rails test required updating a identity column.
|
|
612
793
|
coerce_tests! :test_update_columns_changing_id
|
|
613
794
|
|
|
614
|
-
#
|
|
615
|
-
coerce_tests! :
|
|
616
|
-
def
|
|
617
|
-
david, mary = authors(:david), authors(:mary)
|
|
618
|
-
david.id.must_equal 1
|
|
619
|
-
mary.id.must_equal 2
|
|
620
|
-
david.name.wont_equal mary.name
|
|
621
|
-
assert_sql(/UPDATE.*\(SELECT \[authors\].\[id\] FROM \[authors\].*ORDER BY \[authors\].\[id\]/i) do
|
|
622
|
-
Author.where('[id] > 1').order(:id).update_all(name: 'Test')
|
|
623
|
-
end
|
|
624
|
-
david.reload.name.must_equal 'David'
|
|
625
|
-
mary.reload.name.must_equal 'Test'
|
|
626
|
-
end
|
|
627
|
-
|
|
628
|
-
# We can not UPDATE identity columns.
|
|
629
|
-
coerce_tests! :test_update_attributes
|
|
630
|
-
def test_update_attributes_coerced
|
|
795
|
+
# Rails test required updating a identity column.
|
|
796
|
+
coerce_tests! :test_update
|
|
797
|
+
def test_update_coerced
|
|
631
798
|
topic = Topic.find(1)
|
|
632
|
-
|
|
799
|
+
assert_not_predicate topic, :approved?
|
|
633
800
|
assert_equal "The First Topic", topic.title
|
|
634
|
-
|
|
801
|
+
|
|
802
|
+
topic.update("approved" => true, "title" => "The First Topic Updated")
|
|
635
803
|
topic.reload
|
|
636
|
-
|
|
804
|
+
assert_predicate topic, :approved?
|
|
637
805
|
assert_equal "The First Topic Updated", topic.title
|
|
638
|
-
|
|
806
|
+
|
|
807
|
+
topic.update(approved: false, title: "The First Topic")
|
|
639
808
|
topic.reload
|
|
640
|
-
|
|
809
|
+
assert_not_predicate topic, :approved?
|
|
641
810
|
assert_equal "The First Topic", topic.title
|
|
642
|
-
# SQLServer: Here is where it breaks down. No exceptions.
|
|
643
|
-
# assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do
|
|
644
|
-
# topic.update_attributes(id: 3, title: "Hm is it possible?")
|
|
645
|
-
# end
|
|
646
|
-
# assert_not_equal "Hm is it possible?", Topic.find(3).title
|
|
647
|
-
# topic.update_attributes(id: 1234)
|
|
648
|
-
# assert_nothing_raised { topic.reload }
|
|
649
|
-
# assert_equal topic.title, Topic.find(1234).title
|
|
650
811
|
end
|
|
651
812
|
end
|
|
652
813
|
|
|
814
|
+
require "models/author"
|
|
815
|
+
class UpdateAllTest < ActiveRecord::TestCase
|
|
816
|
+
# Rails test required updating a identity column.
|
|
817
|
+
coerce_tests! :test_update_all_doesnt_ignore_order
|
|
818
|
+
def test_update_all_doesnt_ignore_order_coerced
|
|
819
|
+
david, mary = authors(:david), authors(:mary)
|
|
820
|
+
_(david.id).must_equal 1
|
|
821
|
+
_(mary.id).must_equal 2
|
|
822
|
+
_(david.name).wont_equal mary.name
|
|
823
|
+
assert_sql(/UPDATE.*\(SELECT \[authors\].\[id\] FROM \[authors\].*ORDER BY \[authors\].\[id\]/i) do
|
|
824
|
+
Author.where("[id] > 1").order(:id).update_all(name: "Test")
|
|
825
|
+
end
|
|
826
|
+
_(david.reload.name).must_equal "David"
|
|
827
|
+
_(mary.reload.name).must_equal "Test"
|
|
828
|
+
end
|
|
829
|
+
end
|
|
653
830
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
require 'models/topic'
|
|
831
|
+
require "models/topic"
|
|
657
832
|
module ActiveRecord
|
|
658
833
|
class PredicateBuilderTest < ActiveRecord::TestCase
|
|
834
|
+
# Same as original test except string has `N` prefix to indicate unicode string.
|
|
659
835
|
coerce_tests! :test_registering_new_handlers
|
|
660
836
|
def test_registering_new_handlers_coerced
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
837
|
+
assert_match %r{#{Regexp.escape(topic_title)} ~ N'rails'}i, Topic.where(title: /rails/).to_sql
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
# Same as original test except string has `N` prefix to indicate unicode string.
|
|
841
|
+
coerce_tests! :test_registering_new_handlers_for_association
|
|
842
|
+
def test_registering_new_handlers_for_association_coerced
|
|
843
|
+
assert_match %r{#{Regexp.escape(topic_title)} ~ N'rails'}i, Reply.joins(:topic).where(topics: { title: /rails/ }).to_sql
|
|
667
844
|
end
|
|
668
845
|
end
|
|
669
846
|
end
|
|
670
847
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
848
|
class PrimaryKeysTest < ActiveRecord::TestCase
|
|
675
|
-
#
|
|
676
|
-
# but as far as I can tell, this is only one for us anyway.
|
|
849
|
+
# SQL Server does not have query for release_savepoint
|
|
677
850
|
coerce_tests! :test_create_without_primary_key_no_extra_query
|
|
851
|
+
def test_create_without_primary_key_no_extra_query_coerced
|
|
852
|
+
klass = Class.new(ActiveRecord::Base) do
|
|
853
|
+
self.table_name = "dashboards"
|
|
854
|
+
end
|
|
855
|
+
klass.create! # warmup schema cache
|
|
856
|
+
assert_queries(2, ignore_none: true) { klass.create! }
|
|
857
|
+
end
|
|
678
858
|
end
|
|
679
859
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
require 'models/task'
|
|
860
|
+
require "models/task"
|
|
684
861
|
class QueryCacheTest < ActiveRecord::TestCase
|
|
862
|
+
# SQL Server adapter not in list of supported adapters in original test.
|
|
685
863
|
coerce_tests! :test_cache_does_not_wrap_results_in_arrays
|
|
686
864
|
def test_cache_does_not_wrap_results_in_arrays_coerced
|
|
687
865
|
Task.cache do
|
|
688
|
-
|
|
866
|
+
assert_equal 2, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
|
|
689
867
|
end
|
|
690
868
|
end
|
|
691
|
-
end
|
|
692
869
|
|
|
870
|
+
# Same as original test except that we expect one query to be performed to retrieve the table's primary key.
|
|
871
|
+
# When we generate the SQL for the `find` it includes ordering on the primary key. If we reset the column
|
|
872
|
+
# information then the primary key needs to be retrieved from the database again to generate the SQL causing the
|
|
873
|
+
# original test's `assert_no_queries` assertion to fail. Assert that the query was to get the primary key.
|
|
874
|
+
coerce_tests! :test_query_cached_even_when_types_are_reset
|
|
875
|
+
def test_query_cached_even_when_types_are_reset_coerced
|
|
876
|
+
Task.cache do
|
|
877
|
+
# Warm the cache
|
|
878
|
+
Task.find(1)
|
|
879
|
+
|
|
880
|
+
# Preload the type cache again (so we don't have those queries issued during our assertions)
|
|
881
|
+
Task.connection.send(:reload_type_map)
|
|
693
882
|
|
|
883
|
+
# Clear places where type information is cached
|
|
884
|
+
Task.reset_column_information
|
|
885
|
+
Task.initialize_find_by_cache
|
|
886
|
+
Task.define_attribute_methods
|
|
694
887
|
|
|
888
|
+
assert_queries(1, ignore_none: true) do
|
|
889
|
+
Task.find(1)
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
assert_includes ActiveRecord::SQLCounter.log_all.first, "TC.CONSTRAINT_TYPE = N''PRIMARY KEY''"
|
|
893
|
+
end
|
|
894
|
+
end
|
|
895
|
+
end
|
|
695
896
|
|
|
696
|
-
require
|
|
897
|
+
require "models/post"
|
|
697
898
|
class RelationTest < ActiveRecord::TestCase
|
|
698
899
|
# Use LEN vs LENGTH function.
|
|
699
900
|
coerce_tests! :test_reverse_order_with_function
|
|
@@ -714,6 +915,26 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
714
915
|
# We have implicit ordering, via FETCH.
|
|
715
916
|
coerce_tests! %r{doesn't have implicit ordering}
|
|
716
917
|
|
|
918
|
+
# We have implicit ordering, via FETCH.
|
|
919
|
+
coerce_tests! :test_reorder_with_take
|
|
920
|
+
def test_reorder_with_take_coerced
|
|
921
|
+
sql_log = capture_sql do
|
|
922
|
+
assert Post.order(:title).reorder(nil).take
|
|
923
|
+
end
|
|
924
|
+
assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
|
|
925
|
+
assert sql_log.all? { |sql| /order by \[posts\]\.\[id\]/i.match?(sql) }, "default ORDER BY ID was not used in the query: #{sql_log}"
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
# We have implicit ordering, via FETCH.
|
|
929
|
+
coerce_tests! :test_reorder_with_first
|
|
930
|
+
def test_reorder_with_first_coerced
|
|
931
|
+
sql_log = capture_sql do
|
|
932
|
+
assert Post.order(:title).reorder(nil).first
|
|
933
|
+
end
|
|
934
|
+
assert sql_log.none? { |sql| /order by [posts].[title]/i.match?(sql) }, "ORDER BY title was used in the query: #{sql_log}"
|
|
935
|
+
assert sql_log.all? { |sql| /order by \[posts\]\.\[id\]/i.match?(sql) }, "default ORDER BY ID was not used in the query: #{sql_log}"
|
|
936
|
+
end
|
|
937
|
+
|
|
717
938
|
# We are not doing order duplicate removal anymore.
|
|
718
939
|
coerce_tests! :test_order_using_scoping
|
|
719
940
|
|
|
@@ -737,17 +958,17 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
737
958
|
# so we are skipping all together.
|
|
738
959
|
coerce_tests! :test_empty_complex_chained_relations
|
|
739
960
|
|
|
740
|
-
# Can't apply offset
|
|
961
|
+
# Can't apply offset without ORDER
|
|
741
962
|
coerce_tests! %r{using a custom table affects the wheres}
|
|
742
|
-
test
|
|
963
|
+
test "using a custom table affects the wheres coerced" do
|
|
743
964
|
post = posts(:welcome)
|
|
744
965
|
|
|
745
966
|
assert_equal post, custom_post_relation.where!(title: post.title).order(:id).take
|
|
746
967
|
end
|
|
747
968
|
|
|
748
|
-
# Can't apply offset
|
|
969
|
+
# Can't apply offset without ORDER
|
|
749
970
|
coerce_tests! %r{using a custom table with joins affects the joins}
|
|
750
|
-
test
|
|
971
|
+
test "using a custom table with joins affects the joins coerced" do
|
|
751
972
|
post = posts(:welcome)
|
|
752
973
|
|
|
753
974
|
assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).order(:id).take
|
|
@@ -761,45 +982,31 @@ class RelationTest < ActiveRecord::TestCase
|
|
|
761
982
|
end
|
|
762
983
|
end
|
|
763
984
|
|
|
764
|
-
|
|
765
|
-
coerce_tests! :test_relation_merging_with_merged_symbol_joins_is_aliased
|
|
766
|
-
def test_relation_merging_with_merged_symbol_joins_is_aliased__coerced
|
|
767
|
-
categorizations_with_authors = Categorization.joins(:author)
|
|
768
|
-
queries = capture_sql { Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(categorizations_with_authors).to_a }
|
|
769
|
-
|
|
770
|
-
nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
|
|
771
|
-
assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query"
|
|
772
|
-
|
|
773
|
-
# using `\W` as the column separator
|
|
774
|
-
query_matches = queries.any? do |sql|
|
|
775
|
-
%r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+\Wauthors_categorizations\W]i.match?(sql)
|
|
776
|
-
end
|
|
777
|
-
|
|
778
|
-
assert query_matches, "Should be aliasing the child INNER JOINs in query"
|
|
779
|
-
end
|
|
780
|
-
end
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
require 'models/post'
|
|
985
|
+
require "models/post"
|
|
786
986
|
class SanitizeTest < ActiveRecord::TestCase
|
|
987
|
+
# Use nvarchar string (N'') in assert
|
|
787
988
|
coerce_tests! :test_sanitize_sql_like_example_use_case
|
|
788
989
|
def test_sanitize_sql_like_example_use_case_coerced
|
|
789
990
|
searchable_post = Class.new(Post) do
|
|
790
|
-
def self.
|
|
791
|
-
where("title LIKE ?", sanitize_sql_like(term,
|
|
991
|
+
def self.search_as_method(term)
|
|
992
|
+
where("title LIKE ?", sanitize_sql_like(term, "!"))
|
|
792
993
|
end
|
|
994
|
+
|
|
995
|
+
scope :search_as_scope, ->(term) {
|
|
996
|
+
where("title LIKE ?", sanitize_sql_like(term, "!"))
|
|
997
|
+
}
|
|
793
998
|
end
|
|
794
|
-
|
|
795
|
-
|
|
999
|
+
|
|
1000
|
+
assert_sql(/LIKE N'20!% !_reduction!_!!'/) do
|
|
1001
|
+
searchable_post.search_as_method("20% _reduction_!").to_a
|
|
1002
|
+
end
|
|
1003
|
+
|
|
1004
|
+
assert_sql(/LIKE N'20!% !_reduction!_!!'/) do
|
|
1005
|
+
searchable_post.search_as_scope("20% _reduction_!").to_a
|
|
796
1006
|
end
|
|
797
1007
|
end
|
|
798
1008
|
end
|
|
799
1009
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
1010
|
class SchemaDumperTest < ActiveRecord::TestCase
|
|
804
1011
|
# We have precision to 38.
|
|
805
1012
|
coerce_tests! :test_schema_dump_keeps_large_precision_integer_columns_as_decimal
|
|
@@ -831,19 +1038,14 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase
|
|
|
831
1038
|
coerce_tests! :test_schema_dump_defaults_with_universally_supported_types
|
|
832
1039
|
end
|
|
833
1040
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
1041
|
class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
|
|
838
1042
|
# We trust Rails on this since we do not want to install mysql.
|
|
839
1043
|
coerce_tests! %r{inspect on Model class does not raise}
|
|
840
1044
|
end
|
|
841
1045
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
require 'models/topic'
|
|
1046
|
+
require "models/topic"
|
|
846
1047
|
class TransactionTest < ActiveRecord::TestCase
|
|
1048
|
+
# SQL Server does not have query for release_savepoint
|
|
847
1049
|
coerce_tests! :test_releasing_named_savepoints
|
|
848
1050
|
def test_releasing_named_savepoints_coerced
|
|
849
1051
|
Topic.transaction do
|
|
@@ -855,10 +1057,7 @@ class TransactionTest < ActiveRecord::TestCase
|
|
|
855
1057
|
end
|
|
856
1058
|
end
|
|
857
1059
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
require 'models/tag'
|
|
1060
|
+
require "models/tag"
|
|
862
1061
|
class TransactionIsolationTest < ActiveRecord::TestCase
|
|
863
1062
|
# SQL Server will lock the table for counts even when both
|
|
864
1063
|
# connections are `READ COMMITTED`. So we bypass with `READPAST`.
|
|
@@ -868,7 +1067,7 @@ class TransactionIsolationTest < ActiveRecord::TestCase
|
|
|
868
1067
|
assert_equal 0, Tag.count
|
|
869
1068
|
Tag2.transaction do
|
|
870
1069
|
Tag2.create
|
|
871
|
-
assert_equal 0, Tag.lock(
|
|
1070
|
+
assert_equal 0, Tag.lock("WITH(READPAST)").count
|
|
872
1071
|
end
|
|
873
1072
|
end
|
|
874
1073
|
assert_equal 1, Tag.count
|
|
@@ -878,10 +1077,7 @@ class TransactionIsolationTest < ActiveRecord::TestCase
|
|
|
878
1077
|
coerce_tests! %r{repeatable read}
|
|
879
1078
|
end
|
|
880
1079
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
require 'models/book'
|
|
1080
|
+
require "models/book"
|
|
885
1081
|
class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
|
|
886
1082
|
# We have a few view tables. use includes vs equality.
|
|
887
1083
|
coerce_tests! :test_views
|
|
@@ -893,9 +1089,10 @@ class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
|
|
|
893
1089
|
coerce_tests! :test_does_not_assume_id_column_as_primary_key
|
|
894
1090
|
def test_does_not_assume_id_column_as_primary_key_coerced
|
|
895
1091
|
model = Class.new(ActiveRecord::Base) { self.table_name = "ebooks" }
|
|
896
|
-
assert_equal
|
|
1092
|
+
assert_equal "id", model.primary_key
|
|
897
1093
|
end
|
|
898
1094
|
end
|
|
1095
|
+
|
|
899
1096
|
class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase
|
|
900
1097
|
# We have a few view tables. use includes vs equality.
|
|
901
1098
|
coerce_tests! :test_views
|
|
@@ -904,23 +1101,17 @@ class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase
|
|
|
904
1101
|
end
|
|
905
1102
|
end
|
|
906
1103
|
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
require 'models/author'
|
|
1104
|
+
require "models/author"
|
|
911
1105
|
class YamlSerializationTest < ActiveRecord::TestCase
|
|
912
1106
|
coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
|
|
913
1107
|
def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
|
|
914
|
-
author = Author.select(
|
|
1108
|
+
author = Author.select("authors.*, 5 as posts_count").first
|
|
915
1109
|
dumped = YAML.load(YAML.dump(author))
|
|
916
1110
|
assert_equal 5, author.posts_count
|
|
917
1111
|
assert_equal 5, dumped.posts_count
|
|
918
1112
|
end
|
|
919
1113
|
end
|
|
920
1114
|
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
1115
|
class DateTimePrecisionTest < ActiveRecord::TestCase
|
|
925
1116
|
# Original test had `7` which we support vs `8` which we use.
|
|
926
1117
|
coerce_tests! :test_invalid_datetime_precision_raises_error
|
|
@@ -936,7 +1127,7 @@ class DateTimePrecisionTest < ActiveRecord::TestCase
|
|
|
936
1127
|
coerce_tests! :test_datetime_precision_is_truncated_on_assignment
|
|
937
1128
|
def test_datetime_precision_is_truncated_on_assignment_coerced
|
|
938
1129
|
@connection.create_table(:foos, force: true)
|
|
939
|
-
@connection.add_column :foos, :created_at,
|
|
1130
|
+
@connection.add_column :foos, :created_at, :datetime, precision: 0
|
|
940
1131
|
@connection.add_column :foos, :updated_at, :datetime, precision: 6
|
|
941
1132
|
|
|
942
1133
|
time = ::Time.now.change(nsec: 123456789)
|
|
@@ -953,8 +1144,6 @@ class DateTimePrecisionTest < ActiveRecord::TestCase
|
|
|
953
1144
|
end
|
|
954
1145
|
end
|
|
955
1146
|
|
|
956
|
-
|
|
957
|
-
|
|
958
1147
|
class TimePrecisionTest < ActiveRecord::TestCase
|
|
959
1148
|
# datetime is rounded to increments of .000, .003, or .007 seconds
|
|
960
1149
|
coerce_tests! :test_time_precision_is_truncated_on_assignment
|
|
@@ -975,9 +1164,10 @@ class TimePrecisionTest < ActiveRecord::TestCase
|
|
|
975
1164
|
assert_equal 0, foo.start.nsec
|
|
976
1165
|
assert_equal 123457000, foo.finish.nsec
|
|
977
1166
|
end
|
|
978
|
-
end
|
|
979
|
-
|
|
980
1167
|
|
|
1168
|
+
# SQL Server uses default precision for time.
|
|
1169
|
+
coerce_tests! :test_no_time_precision_isnt_truncated_on_assignment
|
|
1170
|
+
end
|
|
981
1171
|
|
|
982
1172
|
class DefaultNumbersTest < ActiveRecord::TestCase
|
|
983
1173
|
# We do better with native types and do not return strings for everything.
|
|
@@ -987,16 +1177,23 @@ class DefaultNumbersTest < ActiveRecord::TestCase
|
|
|
987
1177
|
assert_equal 7, record.positive_integer
|
|
988
1178
|
assert_equal 7, record.positive_integer_before_type_cast
|
|
989
1179
|
end
|
|
1180
|
+
|
|
1181
|
+
# We do better with native types and do not return strings for everything.
|
|
990
1182
|
coerce_tests! :test_default_negative_integer
|
|
991
1183
|
def test_default_negative_integer_coerced
|
|
992
1184
|
record = DefaultNumber.new
|
|
993
1185
|
assert_equal -5, record.negative_integer
|
|
994
1186
|
assert_equal -5, record.negative_integer_before_type_cast
|
|
995
1187
|
end
|
|
996
|
-
end
|
|
997
|
-
|
|
998
|
-
|
|
999
1188
|
|
|
1189
|
+
# We do better with native types and do not return strings for everything.
|
|
1190
|
+
coerce_tests! :test_default_decimal_number
|
|
1191
|
+
def test_default_decimal_number_coerced
|
|
1192
|
+
record = DefaultNumber.new
|
|
1193
|
+
assert_equal BigDecimal("2.78"), record.decimal_number
|
|
1194
|
+
assert_equal 2.78, record.decimal_number_before_type_cast
|
|
1195
|
+
end
|
|
1196
|
+
end
|
|
1000
1197
|
|
|
1001
1198
|
module ActiveRecord
|
|
1002
1199
|
class CollectionCacheKeyTest < ActiveRecord::TestCase
|
|
@@ -1005,40 +1202,59 @@ module ActiveRecord
|
|
|
1005
1202
|
end
|
|
1006
1203
|
end
|
|
1007
1204
|
|
|
1205
|
+
module ActiveRecord
|
|
1206
|
+
class CacheKeyTest < ActiveRecord::TestCase
|
|
1207
|
+
# Like Mysql2 and PostgreSQL, SQL Server doesn't return a string value for updated_at. In the Rails tests
|
|
1208
|
+
# the tests are skipped if adapter is Mysql2 or PostgreSQL.
|
|
1209
|
+
coerce_tests! %r{cache_version is the same when it comes from the DB or from the user}
|
|
1210
|
+
coerce_tests! %r{cache_version does NOT call updated_at when value is from the database}
|
|
1211
|
+
coerce_tests! %r{cache_version does not truncate zeros when timestamp ends in zeros}
|
|
1212
|
+
end
|
|
1213
|
+
end
|
|
1008
1214
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1215
|
+
require "models/book"
|
|
1011
1216
|
module ActiveRecord
|
|
1012
1217
|
class StatementCacheTest < ActiveRecord::TestCase
|
|
1013
1218
|
# Getting random failures.
|
|
1014
1219
|
coerce_tests! :test_find_does_not_use_statement_cache_if_table_name_is_changed
|
|
1015
|
-
end
|
|
1016
|
-
end
|
|
1017
|
-
|
|
1018
1220
|
|
|
1221
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1222
|
+
coerce_tests! :test_statement_cache_values_differ
|
|
1223
|
+
def test_statement_cache_values_differ_coerced
|
|
1224
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1019
1225
|
|
|
1226
|
+
original_test_statement_cache_values_differ
|
|
1227
|
+
ensure
|
|
1228
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1229
|
+
end
|
|
1230
|
+
end
|
|
1231
|
+
end
|
|
1020
1232
|
|
|
1021
1233
|
module ActiveRecord
|
|
1022
1234
|
module ConnectionAdapters
|
|
1023
1235
|
class SchemaCacheTest < ActiveRecord::TestCase
|
|
1024
1236
|
private
|
|
1237
|
+
|
|
1025
1238
|
# We need to give the full path for this to work.
|
|
1026
1239
|
def schema_dump_path
|
|
1027
|
-
File.join ARTest::SQLServer.root_activerecord,
|
|
1240
|
+
File.join ARTest::SQLServer.root_activerecord, "test/assets/schema_dump_5_1.yml"
|
|
1028
1241
|
end
|
|
1029
1242
|
end
|
|
1030
1243
|
end
|
|
1031
1244
|
end
|
|
1032
1245
|
|
|
1033
1246
|
class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
1034
|
-
|
|
1035
|
-
|
|
1247
|
+
# Use LEN() vs length() function.
|
|
1248
|
+
coerce_tests! %r{order: always allows Arel}
|
|
1249
|
+
test "order: always allows Arel" do
|
|
1036
1250
|
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(Arel.sql("len(title)")).pluck(:title) }
|
|
1037
1251
|
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(Arel.sql("len(title)")).pluck(:title) }
|
|
1038
1252
|
|
|
1039
1253
|
assert_equal ids_depr, ids_disabled
|
|
1040
1254
|
end
|
|
1041
1255
|
|
|
1256
|
+
# Use LEN() vs length() function.
|
|
1257
|
+
coerce_tests! %r{pluck: always allows Arel}
|
|
1042
1258
|
test "pluck: always allows Arel" do
|
|
1043
1259
|
values_depr = with_unsafe_raw_sql_deprecated { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
|
|
1044
1260
|
values_disabled = with_unsafe_raw_sql_disabled { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
|
|
@@ -1046,74 +1262,19 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
|
1046
1262
|
assert_equal values_depr, values_disabled
|
|
1047
1263
|
end
|
|
1048
1264
|
|
|
1049
|
-
|
|
1050
|
-
coerce_tests! %r{order: disallows invalid Array arguments}
|
|
1051
|
-
test "order: disallows invalid Array arguments" do
|
|
1052
|
-
with_unsafe_raw_sql_disabled do
|
|
1053
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1054
|
-
Post.order(["author_id", "len(title)"]).pluck(:id)
|
|
1055
|
-
end
|
|
1056
|
-
end
|
|
1057
|
-
end
|
|
1058
|
-
|
|
1265
|
+
# Use LEN() vs length() function.
|
|
1059
1266
|
coerce_tests! %r{order: allows valid Array arguments}
|
|
1060
1267
|
test "order: allows valid Array arguments" do
|
|
1061
1268
|
ids_expected = Post.order(Arel.sql("author_id, len(title)")).pluck(:id)
|
|
1062
1269
|
|
|
1063
|
-
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id",
|
|
1064
|
-
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id",
|
|
1270
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", "len(title)"]).pluck(:id) }
|
|
1271
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", "len(title)"]).pluck(:id) }
|
|
1065
1272
|
|
|
1066
1273
|
assert_equal ids_expected, ids_depr
|
|
1067
1274
|
assert_equal ids_expected, ids_disabled
|
|
1068
1275
|
end
|
|
1069
|
-
|
|
1070
|
-
coerce_tests! %r{order: logs deprecation warning for unrecognized column}
|
|
1071
|
-
test "order: logs deprecation warning for unrecognized column" do
|
|
1072
|
-
with_unsafe_raw_sql_deprecated do
|
|
1073
|
-
assert_deprecated(/Dangerous query method/) do
|
|
1074
|
-
Post.order("len(title)")
|
|
1075
|
-
end
|
|
1076
|
-
end
|
|
1077
|
-
end
|
|
1078
|
-
|
|
1079
|
-
coerce_tests! %r{pluck: disallows invalid column name}
|
|
1080
|
-
test "pluck: disallows invalid column name" do
|
|
1081
|
-
with_unsafe_raw_sql_disabled do
|
|
1082
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1083
|
-
Post.pluck("len(title)")
|
|
1084
|
-
end
|
|
1085
|
-
end
|
|
1086
|
-
end
|
|
1087
|
-
|
|
1088
|
-
coerce_tests! %r{pluck: disallows invalid column name amongst valid names}
|
|
1089
|
-
test "pluck: disallows invalid column name amongst valid names" do
|
|
1090
|
-
with_unsafe_raw_sql_disabled do
|
|
1091
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1092
|
-
Post.pluck(:title, "len(title)")
|
|
1093
|
-
end
|
|
1094
|
-
end
|
|
1095
|
-
end
|
|
1096
|
-
|
|
1097
|
-
coerce_tests! %r{pluck: disallows invalid column names with includes}
|
|
1098
|
-
test "pluck: disallows invalid column names with includes" do
|
|
1099
|
-
with_unsafe_raw_sql_disabled do
|
|
1100
|
-
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
|
1101
|
-
Post.includes(:comments).pluck(:title, "len(title)")
|
|
1102
|
-
end
|
|
1103
|
-
end
|
|
1104
|
-
end
|
|
1105
|
-
|
|
1106
|
-
coerce_tests! %r{pluck: logs deprecation warning}
|
|
1107
|
-
test "pluck: logs deprecation warning" do
|
|
1108
|
-
with_unsafe_raw_sql_deprecated do
|
|
1109
|
-
assert_deprecated(/Dangerous query method/) do
|
|
1110
|
-
Post.includes(:comments).pluck(:title, "len(title)")
|
|
1111
|
-
end
|
|
1112
|
-
end
|
|
1113
|
-
end
|
|
1114
1276
|
end
|
|
1115
1277
|
|
|
1116
|
-
|
|
1117
1278
|
class ReservedWordTest < ActiveRecord::TestCase
|
|
1118
1279
|
coerce_tests! :test_change_columns
|
|
1119
1280
|
def test_change_columns_coerced
|
|
@@ -1124,32 +1285,29 @@ class ReservedWordTest < ActiveRecord::TestCase
|
|
|
1124
1285
|
end
|
|
1125
1286
|
end
|
|
1126
1287
|
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
1288
|
class OptimisticLockingTest < ActiveRecord::TestCase
|
|
1130
1289
|
# We do not allow updating identities, but we can test using a non-identity key
|
|
1131
1290
|
coerce_tests! :test_update_with_dirty_primary_key
|
|
1132
1291
|
def test_update_with_dirty_primary_key_coerced
|
|
1133
1292
|
assert_raises(ActiveRecord::RecordNotUnique) do
|
|
1134
|
-
record = StringKeyObject.find(
|
|
1135
|
-
record.id =
|
|
1293
|
+
record = StringKeyObject.find("record1")
|
|
1294
|
+
record.id = "record2"
|
|
1136
1295
|
record.save!
|
|
1137
1296
|
end
|
|
1138
1297
|
|
|
1139
|
-
record = StringKeyObject.find(
|
|
1140
|
-
record.id =
|
|
1298
|
+
record = StringKeyObject.find("record1")
|
|
1299
|
+
record.id = "record42"
|
|
1141
1300
|
record.save!
|
|
1142
1301
|
|
|
1143
|
-
assert StringKeyObject.find(
|
|
1302
|
+
assert StringKeyObject.find("record42")
|
|
1144
1303
|
assert_raises(ActiveRecord::RecordNotFound) do
|
|
1145
|
-
StringKeyObject.find(
|
|
1304
|
+
StringKeyObject.find("record1")
|
|
1146
1305
|
end
|
|
1147
1306
|
end
|
|
1148
1307
|
end
|
|
1149
1308
|
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
1309
|
class RelationMergingTest < ActiveRecord::TestCase
|
|
1310
|
+
# Use nvarchar string (N'') in assert
|
|
1153
1311
|
coerce_tests! :test_merging_with_order_with_binds
|
|
1154
1312
|
def test_merging_with_order_with_binds_coerced
|
|
1155
1313
|
relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
|
|
@@ -1157,8 +1315,144 @@ class RelationMergingTest < ActiveRecord::TestCase
|
|
|
1157
1315
|
end
|
|
1158
1316
|
end
|
|
1159
1317
|
|
|
1318
|
+
module ActiveRecord
|
|
1319
|
+
class DatabaseTasksTruncateAllTest < ActiveRecord::TestCase
|
|
1320
|
+
# SQL Server does not allow truncation of tables that are referenced by foreign key
|
|
1321
|
+
# constraints. As this test truncates all tables we would need to remove all foreign
|
|
1322
|
+
# key constraints and then restore them afterwards to get this test to pass.
|
|
1323
|
+
coerce_tests! :test_truncate_tables
|
|
1324
|
+
end
|
|
1325
|
+
end
|
|
1326
|
+
|
|
1327
|
+
require "models/book"
|
|
1328
|
+
class EnumTest < ActiveRecord::TestCase
|
|
1329
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1330
|
+
coerce_tests! %r{enums are distinct per class}
|
|
1331
|
+
test "enums are distinct per class coerced" do
|
|
1332
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1333
|
+
|
|
1334
|
+
send(:'original_enums are distinct per class')
|
|
1335
|
+
ensure
|
|
1336
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1337
|
+
end
|
|
1160
1338
|
|
|
1339
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1340
|
+
coerce_tests! %r{creating new objects with enum scopes}
|
|
1341
|
+
test "creating new objects with enum scopes coerced" do
|
|
1342
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1343
|
+
|
|
1344
|
+
send(:'original_creating new objects with enum scopes')
|
|
1345
|
+
ensure
|
|
1346
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1347
|
+
end
|
|
1348
|
+
|
|
1349
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1350
|
+
coerce_tests! %r{enums are inheritable}
|
|
1351
|
+
test "enums are inheritable coerced" do
|
|
1352
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1353
|
+
|
|
1354
|
+
send(:'original_enums are inheritable')
|
|
1355
|
+
ensure
|
|
1356
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1357
|
+
end
|
|
1358
|
+
|
|
1359
|
+
# Need to remove index as SQL Server considers NULLs on a unique-index to be equal unlike PostgreSQL/MySQL/SQLite.
|
|
1360
|
+
coerce_tests! %r{declare multiple enums at a time}
|
|
1361
|
+
test "declare multiple enums at a time coerced" do
|
|
1362
|
+
Book.connection.remove_index(:books, column: [:author_id, :name])
|
|
1363
|
+
|
|
1364
|
+
send(:'original_declare multiple enums at a time')
|
|
1365
|
+
ensure
|
|
1366
|
+
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
|
1367
|
+
end
|
|
1368
|
+
end
|
|
1369
|
+
|
|
1370
|
+
require "models/task"
|
|
1371
|
+
class QueryCacheExpiryTest < ActiveRecord::TestCase
|
|
1372
|
+
# SQL Server does not support skipping or upserting duplicates.
|
|
1373
|
+
coerce_tests! :test_insert_all
|
|
1374
|
+
def test_insert_all_coerced
|
|
1375
|
+
assert_raises(ArgumentError, /does not support skipping duplicates/) do
|
|
1376
|
+
Task.cache { Task.insert({ starting: Time.now }) }
|
|
1377
|
+
end
|
|
1378
|
+
|
|
1379
|
+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
|
|
1380
|
+
Task.cache { Task.insert_all!([{ starting: Time.now }]) }
|
|
1381
|
+
end
|
|
1382
|
+
|
|
1383
|
+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
|
|
1384
|
+
Task.cache { Task.insert!({ starting: Time.now }) }
|
|
1385
|
+
end
|
|
1386
|
+
|
|
1387
|
+
assert_called(ActiveRecord::Base.connection, :clear_query_cache, times: 2) do
|
|
1388
|
+
Task.cache { Task.insert_all!([{ starting: Time.now }]) }
|
|
1389
|
+
end
|
|
1390
|
+
|
|
1391
|
+
assert_raises(ArgumentError, /does not support upsert/) do
|
|
1392
|
+
Task.cache { Task.upsert({ starting: Time.now }) }
|
|
1393
|
+
end
|
|
1394
|
+
|
|
1395
|
+
assert_raises(ArgumentError, /does not support upsert/) do
|
|
1396
|
+
Task.cache { Task.upsert_all([{ starting: Time.now }]) }
|
|
1397
|
+
end
|
|
1398
|
+
end
|
|
1399
|
+
end
|
|
1400
|
+
|
|
1401
|
+
require "models/citation"
|
|
1161
1402
|
class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
|
|
1162
|
-
#
|
|
1403
|
+
# Original Rails test fails with SQL Server error message "The query processor ran out of internal resources and
|
|
1404
|
+
# could not produce a query plan". This error goes away if you change database compatibility level to 110 (SQL 2012)
|
|
1405
|
+
# (see https://www.mssqltips.com/sqlservertip/5279/sql-server-error-query-processor-ran-out-of-internal-resources-and-could-not-produce-a-query-plan/).
|
|
1406
|
+
# However, you cannot change the compatibility level during a test. The purpose of the test is to ensure that an
|
|
1407
|
+
# unprepared statement is used if the number of values exceeds the adapter's `bind_params_length`. The coerced test
|
|
1408
|
+
# still does this as there will be 32,768 remaining citation records in the database and the `bind_params_length` of
|
|
1409
|
+
# adapter is 2,098.
|
|
1163
1410
|
coerce_tests! :test_eager_loading_too_may_ids
|
|
1411
|
+
def test_eager_loading_too_may_ids_coerced
|
|
1412
|
+
# Remove excess records.
|
|
1413
|
+
Citation.limit(32768).order(id: :desc).delete_all
|
|
1414
|
+
|
|
1415
|
+
# Perform test
|
|
1416
|
+
citation_count = Citation.count
|
|
1417
|
+
assert_sql(/WHERE \(\[citations\]\.\[id\] IN \(0, 1/) do
|
|
1418
|
+
assert_equal citation_count, Citation.eager_load(:citations).offset(0).size
|
|
1419
|
+
end
|
|
1420
|
+
end
|
|
1421
|
+
end
|
|
1422
|
+
|
|
1423
|
+
class LogSubscriberTest < ActiveRecord::TestCase
|
|
1424
|
+
# Call original test from coerced test. Fixes issue on CI with Rails installed as a gem.
|
|
1425
|
+
coerce_tests! :test_vebose_query_logs
|
|
1426
|
+
def test_vebose_query_logs_coerced
|
|
1427
|
+
original_test_vebose_query_logs
|
|
1428
|
+
end
|
|
1429
|
+
end
|
|
1430
|
+
|
|
1431
|
+
class ActiveRecordSchemaTest < ActiveRecord::TestCase
|
|
1432
|
+
# Workaround for randomly failing test.
|
|
1433
|
+
coerce_tests! :test_has_primary_key
|
|
1434
|
+
def test_has_primary_key_coerced
|
|
1435
|
+
@schema_migration.reset_column_information
|
|
1436
|
+
original_test_has_primary_key
|
|
1437
|
+
end
|
|
1438
|
+
end
|
|
1439
|
+
|
|
1440
|
+
module ActiveRecord
|
|
1441
|
+
module ConnectionAdapters
|
|
1442
|
+
class ReaperTest < ActiveRecord::TestCase
|
|
1443
|
+
# Coerce can be removed if Rails version > 6.0.3
|
|
1444
|
+
coerce_tests! :test_connection_pool_starts_reaper_in_fork unless Process.respond_to?(:fork)
|
|
1445
|
+
end
|
|
1446
|
+
end
|
|
1447
|
+
end
|
|
1448
|
+
|
|
1449
|
+
class FixturesTest < ActiveRecord::TestCase
|
|
1450
|
+
# Skip test on Windows. Skip can be removed when Rails PR https://github.com/rails/rails/pull/39234 has been merged.
|
|
1451
|
+
coerce_tests! :test_binary_in_fixtures if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
|
1452
|
+
end
|
|
1453
|
+
|
|
1454
|
+
class ReloadModelsTest < ActiveRecord::TestCase
|
|
1455
|
+
# Skip test on Windows. The number of arguements passed to `IO.popen` in
|
|
1456
|
+
# `activesupport/lib/active_support/testing/isolation.rb` exceeds what Windows can handle.
|
|
1457
|
+
coerce_tests! :test_has_one_with_reload if RbConfig::CONFIG["host_os"] =~ /mswin|mingw/
|
|
1164
1458
|
end
|