activerecord-sqlserver-adapter 4.2.18 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -223
- data/Gemfile +18 -17
- data/RAILS5-TODO.md +36 -0
- data/README.md +27 -8
- data/RUNNING_UNIT_TESTS.md +0 -17
- data/Rakefile +2 -7
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +1 -1
- data/appveyor.yml +0 -2
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +15 -8
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +45 -97
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -2
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +31 -10
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +0 -18
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +101 -58
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +7 -7
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +20 -0
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +56 -32
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type.rb +34 -32
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +6 -0
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -0
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +9 -20
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +30 -0
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +28 -4
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +28 -14
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +4 -16
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +9 -0
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -0
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +5 -1
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +5 -1
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +8 -1
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +20 -8
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +25 -10
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +6 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +4 -0
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +7 -1
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +5 -1
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +15 -2
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +7 -1
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +5 -1
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +7 -1
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +5 -1
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +71 -57
- data/lib/active_record/connection_adapters/sqlserver_column.rb +5 -30
- data/lib/active_record/sqlserver_base.rb +1 -5
- data/lib/arel/visitors/sqlserver.rb +11 -20
- data/test/bin/setup.sh +4 -6
- data/test/cases/adapter_test_sqlserver.rb +11 -20
- data/test/cases/coerced_tests.rb +233 -138
- data/test/cases/column_test_sqlserver.rb +244 -227
- data/test/cases/connection_test_sqlserver.rb +5 -76
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +7 -7
- data/test/cases/helper_sqlserver.rb +4 -15
- data/test/cases/pessimistic_locking_test_sqlserver.rb +1 -1
- data/test/cases/rake_test_sqlserver.rb +20 -14
- data/test/cases/schema_dumper_test_sqlserver.rb +94 -63
- data/test/cases/schema_test_sqlserver.rb +2 -2
- data/test/cases/showplan_test_sqlserver.rb +1 -1
- data/test/cases/specific_schema_test_sqlserver.rb +7 -14
- data/test/cases/transaction_test_sqlserver.rb +1 -1
- data/test/cases/uuid_test_sqlserver.rb +0 -1
- data/test/config.yml +0 -10
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +1 -1
- data/test/schema/sqlserver_specific_schema.rb +0 -16
- data/test/support/coerceable_test_sqlserver.rb +6 -2
- data/test/support/connection_reflection.rb +0 -4
- data/test/support/sql_counter_sqlserver.rb +17 -21
- metadata +9 -7
- data/lib/active_record/connection_adapters/sqlserver/core_ext/odbc.rb +0 -34
- data/lib/active_record/connection_adapters/sqlserver/schema_cache.rb +0 -114
@@ -2,22 +2,9 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters
|
3
3
|
class SQLServerColumn < Column
|
4
4
|
|
5
|
-
def initialize(name, default,
|
6
|
-
|
7
|
-
|
8
|
-
@default_function = @sqlserver_options[:default_function]
|
9
|
-
end
|
10
|
-
|
11
|
-
def sql_type_for_statement
|
12
|
-
if is_integer? || is_real?
|
13
|
-
sql_type.sub(/\((\d+)?\)/, '')
|
14
|
-
else
|
15
|
-
sql_type
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def table_name
|
20
|
-
@sqlserver_options[:table_name]
|
5
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment = nil, sqlserver_options = {})
|
6
|
+
@sqlserver_options = sqlserver_options || {}
|
7
|
+
super(name, default, sql_type_metadata, null, table_name, default_function, collation, comment: comment)
|
21
8
|
end
|
22
9
|
|
23
10
|
def is_identity?
|
@@ -29,23 +16,11 @@ module ActiveRecord
|
|
29
16
|
end
|
30
17
|
|
31
18
|
def is_utf8?
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def is_integer?
|
36
|
-
@sql_type =~ /int/i
|
37
|
-
end
|
38
|
-
|
39
|
-
def is_real?
|
40
|
-
@sql_type =~ /real/i
|
41
|
-
end
|
42
|
-
|
43
|
-
def collation
|
44
|
-
@sqlserver_options[:collation]
|
19
|
+
sql_type =~ /nvarchar|ntext|nchar/i
|
45
20
|
end
|
46
21
|
|
47
22
|
def case_sensitive?
|
48
|
-
collation &&
|
23
|
+
collation && collation.match(/_CS/)
|
49
24
|
end
|
50
25
|
|
51
26
|
end
|
@@ -7,14 +7,10 @@ module ActiveRecord
|
|
7
7
|
case mode
|
8
8
|
when :dblib
|
9
9
|
require 'tiny_tds'
|
10
|
-
when :odbc
|
11
|
-
raise ArgumentError, 'Missing :dsn configuration.' unless config.key?(:dsn)
|
12
|
-
require 'odbc'
|
13
|
-
require 'active_record/connection_adapters/sqlserver/core_ext/odbc'
|
14
10
|
else
|
15
11
|
raise ArgumentError, "Unknown connection mode in #{config.inspect}."
|
16
12
|
end
|
17
|
-
ConnectionAdapters::SQLServerAdapter.new(nil,
|
13
|
+
ConnectionAdapters::SQLServerAdapter.new(nil, nil, config.merge(mode: mode))
|
18
14
|
end
|
19
15
|
end
|
20
16
|
end
|
@@ -19,11 +19,7 @@ module Arel
|
|
19
19
|
|
20
20
|
def visit_Arel_Nodes_Bin o, collector
|
21
21
|
visit o.expr, collector
|
22
|
-
|
23
|
-
collector
|
24
|
-
else
|
25
|
-
collector << " #{ActiveRecord::ConnectionAdapters::SQLServerAdapter.cs_equality_operator} "
|
26
|
-
end
|
22
|
+
collector << " #{ActiveRecord::ConnectionAdapters::SQLServerAdapter.cs_equality_operator} "
|
27
23
|
end
|
28
24
|
|
29
25
|
def visit_Arel_Nodes_UpdateStatement(o, a)
|
@@ -77,9 +73,13 @@ module Arel
|
|
77
73
|
# Apparently, o.engine.connection can actually be a different adapter
|
78
74
|
# than sqlserver. Can be removed if fixed in ActiveRecord. See:
|
79
75
|
# github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
|
80
|
-
table_name =
|
81
|
-
|
82
|
-
|
76
|
+
table_name = begin
|
77
|
+
if o.class.engine.connection.respond_to?(:sqlserver?) && o.class.engine.connection.database_prefix_remote_server?
|
78
|
+
remote_server_table_name(o)
|
79
|
+
else
|
80
|
+
quote_table_name(o.name)
|
81
|
+
end
|
82
|
+
rescue Exception => e
|
83
83
|
quote_table_name(o.name)
|
84
84
|
end
|
85
85
|
if o.table_alias
|
@@ -170,7 +170,7 @@ module Arel
|
|
170
170
|
core = o.cores.first
|
171
171
|
distinct = Nodes::Distinct === core.set_quantifier
|
172
172
|
oneasone = core.projections.all? { |x| x == ActiveRecord::FinderMethods::ONE_AS_ONE }
|
173
|
-
limitone = node_value(o.limit)
|
173
|
+
limitone = [nil, 0, 1].include? node_value(o.limit)
|
174
174
|
if distinct && oneasone && limitone && !o.offset
|
175
175
|
core.projections = [Arel.sql("TOP(1) 1 AS [one]")]
|
176
176
|
o.limit = nil
|
@@ -190,25 +190,16 @@ module Arel
|
|
190
190
|
|
191
191
|
def primary_Key_From_Table t
|
192
192
|
return unless t
|
193
|
-
|
194
|
-
if engine_pk = t.engine.primary_key
|
195
|
-
pk = t.engine.arel_table[engine_pk]
|
196
|
-
return pk if pk
|
197
|
-
end
|
198
|
-
pk = t.engine.connection.schema_cache.primary_keys(t.engine.table_name)
|
199
|
-
return pk if pk
|
200
|
-
column_name = t.engine.columns.first.try(:name)
|
193
|
+
column_name = schema_cache.primary_keys(t.name) || column_cache(t.name).first.try(:second).try(:name)
|
201
194
|
column_name ? t[column_name] : nil
|
202
195
|
end
|
203
196
|
|
204
197
|
def remote_server_table_name o
|
205
198
|
ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
|
206
|
-
"#{o.engine.connection.database_prefix}#{o.name}"
|
199
|
+
"#{o.class.engine.connection.database_prefix}#{o.name}"
|
207
200
|
).quoted
|
208
201
|
end
|
209
202
|
|
210
203
|
end
|
211
204
|
end
|
212
205
|
end
|
213
|
-
|
214
|
-
Arel::Visitors::VISITORS['sqlserver'] = Arel::Visitors::SQLServer
|
data/test/bin/setup.sh
CHANGED
@@ -3,17 +3,15 @@
|
|
3
3
|
set -x
|
4
4
|
set -e
|
5
5
|
|
6
|
-
|
6
|
+
docker pull metaskills/mssql-server-linux-rails
|
7
7
|
|
8
|
-
docker
|
9
|
-
|
10
|
-
container=$(docker ps -a -q --filter ancestor=metaskills/mssql-server-linux-rails:$tag)
|
8
|
+
container=$(docker ps -a -q --filter ancestor=metaskills/mssql-server-linux-rails)
|
11
9
|
if [[ -z $container ]]; then
|
12
|
-
docker run -p 1433:1433 -d metaskills/mssql-server-linux-rails
|
10
|
+
docker run -p 1433:1433 -d metaskills/mssql-server-linux-rails && sleep 10
|
13
11
|
exit
|
14
12
|
fi
|
15
13
|
|
16
|
-
container=$(docker ps -q --filter ancestor=metaskills/mssql-server-linux-rails
|
14
|
+
container=$(docker ps -q --filter ancestor=metaskills/mssql-server-linux-rails)
|
17
15
|
if [[ -z $container ]]; then
|
18
16
|
docker start $container && sleep 10
|
19
17
|
fi
|
@@ -17,7 +17,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
17
17
|
string = connection.inspect
|
18
18
|
string.must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
|
19
19
|
string.must_match %r{version\: \d.\d}
|
20
|
-
string.must_match %r{mode:
|
20
|
+
string.must_match %r{mode: dblib}
|
21
21
|
string.must_match %r{azure: (true|false)}
|
22
22
|
string.wont_match %r{host}
|
23
23
|
string.wont_match %r{password}
|
@@ -96,7 +96,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
96
96
|
connection.send :initialize_dateformatter
|
97
97
|
assert_nothing_raised do
|
98
98
|
starting = Time.utc(2000, 1, 31, 5, 42, 0)
|
99
|
-
ending =
|
99
|
+
ending = Time.new(2006, 12, 31)
|
100
100
|
Task.create! starting: starting, ending: ending
|
101
101
|
end
|
102
102
|
end
|
@@ -158,14 +158,14 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
-
it 'find identity column using #
|
161
|
+
it 'find identity column using #identity_columns' do
|
162
162
|
task_id_column = Task.columns_hash['id']
|
163
|
-
assert_equal task_id_column.name, connection.send(:
|
164
|
-
assert_equal task_id_column.sql_type, connection.send(:
|
163
|
+
assert_equal task_id_column.name, connection.send(:identity_columns, Task.table_name).first.name
|
164
|
+
assert_equal task_id_column.sql_type, connection.send(:identity_columns, Task.table_name).first.sql_type
|
165
165
|
end
|
166
166
|
|
167
|
-
it 'return
|
168
|
-
|
167
|
+
it 'return an empty array when calling #identity_columns for a table_name with no identity' do
|
168
|
+
connection.send(:identity_columns, Subscriber.table_name).must_equal []
|
169
169
|
end
|
170
170
|
|
171
171
|
end
|
@@ -364,8 +364,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
364
364
|
assert_equal 0, SSTestCustomersView.new.balance
|
365
365
|
end
|
366
366
|
|
367
|
-
it 'respond true to
|
368
|
-
assert SSTestCustomersView.
|
367
|
+
it 'respond true to data_source_exists?' do
|
368
|
+
assert SSTestCustomersView.connection.data_source_exists?(SSTestCustomersView.table_name)
|
369
369
|
end
|
370
370
|
|
371
371
|
# With aliased column names
|
@@ -392,17 +392,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
392
392
|
SSTestStringDefaultsView.columns_hash['pretend_null'].inspect
|
393
393
|
end
|
394
394
|
|
395
|
-
it 'respond true to
|
396
|
-
assert SSTestStringDefaultsView.
|
397
|
-
end
|
398
|
-
|
399
|
-
# Doing identity inserts
|
400
|
-
|
401
|
-
it 'be able to do an identity insert' do
|
402
|
-
customer = SSTestCustomersView.new
|
403
|
-
customer.id = 420
|
404
|
-
customer.save!
|
405
|
-
assert SSTestCustomersView.find(420)
|
395
|
+
it 'respond true to data_source_exists?' do
|
396
|
+
assert SSTestStringDefaultsView.connection.data_source_exists?(SSTestStringDefaultsView.table_name)
|
406
397
|
end
|
407
398
|
|
408
399
|
# That have more than 4000 chars for their defintion
|
data/test/cases/coerced_tests.rb
CHANGED
@@ -1,30 +1,49 @@
|
|
1
1
|
require 'cases/helper_sqlserver'
|
2
2
|
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
|
5
|
+
require 'models/event'
|
6
|
+
class UniquenessValidationTest < ActiveRecord::TestCase
|
7
|
+
# So sp_executesql swallows this exception. Run without prpared to see it.
|
8
|
+
coerce_tests! :test_validate_uniqueness_with_limit
|
9
|
+
def test_validate_uniqueness_with_limit_coerced
|
10
|
+
connection.unprepared_statement do
|
11
|
+
assert_raise(ActiveRecord::ValueTooLong) do
|
12
|
+
Event.create(title: "abcdefgh")
|
13
|
+
end
|
14
|
+
end
|
14
15
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
# So sp_executesql swallows this exception. Run without prpared to see it.
|
18
|
+
coerce_tests! :test_validate_uniqueness_with_limit_and_utf8
|
19
|
+
def test_validate_uniqueness_with_limit_and_utf8_coerced
|
20
|
+
connection.unprepared_statement do
|
21
|
+
assert_raise(ActiveRecord::ValueTooLong) do
|
22
|
+
Event.create(title: "一二三四五六七八")
|
23
|
+
end
|
24
|
+
end
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
21
28
|
|
29
|
+
|
30
|
+
|
31
|
+
require 'models/event'
|
22
32
|
module ActiveRecord
|
23
33
|
class AdapterTest < ActiveRecord::TestCase
|
24
|
-
|
25
34
|
# As far as I can tell, SQL Server does not support null bytes in strings.
|
26
35
|
coerce_tests! :test_update_prepared_statement
|
27
36
|
|
37
|
+
# So sp_executesql swallows this exception. Run without prpared to see it.
|
38
|
+
coerce_tests! :test_value_limit_violations_are_translated_to_specific_exception
|
39
|
+
def test_value_limit_violations_are_translated_to_specific_exception_coerced
|
40
|
+
connection.unprepared_statement do
|
41
|
+
error = assert_raises(ActiveRecord::ValueTooLong) do
|
42
|
+
Event.create(title: 'abcdefgh')
|
43
|
+
end
|
44
|
+
assert_not_nil error.cause
|
45
|
+
end
|
46
|
+
end
|
28
47
|
end
|
29
48
|
end
|
30
49
|
|
@@ -33,7 +52,6 @@ end
|
|
33
52
|
|
34
53
|
require 'models/topic'
|
35
54
|
class AttributeMethodsTest < ActiveRecord::TestCase
|
36
|
-
|
37
55
|
coerce_tests! :test_typecast_attribute_from_select_to_false
|
38
56
|
def test_typecast_attribute_from_select_to_false_coerced
|
39
57
|
Topic.create(:title => 'Budget')
|
@@ -47,26 +65,19 @@ class AttributeMethodsTest < ActiveRecord::TestCase
|
|
47
65
|
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
|
48
66
|
assert topic.is_test?
|
49
67
|
end
|
50
|
-
|
51
68
|
end
|
52
69
|
|
53
70
|
|
54
71
|
|
55
72
|
|
56
73
|
class BasicsTest < ActiveRecord::TestCase
|
57
|
-
|
58
74
|
coerce_tests! :test_column_names_are_escaped
|
59
75
|
def test_column_names_are_escaped_coerced
|
60
|
-
conn
|
61
|
-
|
62
|
-
badchar = "'"
|
63
|
-
quoted = conn.quote_column_name "foo#{badchar}bar"
|
64
|
-
assert_equal "[foo'bar]", quoted
|
76
|
+
conn = ActiveRecord::Base.connection
|
77
|
+
assert_equal '[t]]]', conn.quote_column_name('t]')
|
65
78
|
end
|
66
79
|
|
67
|
-
#
|
68
|
-
# This test has a few problems. First, it would require that we use the
|
69
|
-
# `Type::SQLServer::BigInteger.new(limit: 8)` for the `world_population` attribute.
|
80
|
+
# We do not have do the DecimalWithoutScale type.
|
70
81
|
coerce_tests! :test_numeric_fields
|
71
82
|
coerce_tests! :test_numeric_fields_with_scale
|
72
83
|
|
@@ -76,14 +87,12 @@ class BasicsTest < ActiveRecord::TestCase
|
|
76
87
|
# Caused in Rails v4.2.5 by adding `firm_id` column in this http://git.io/vBfMs
|
77
88
|
# commit. Trust Rails has this covered.
|
78
89
|
coerce_tests! :test_find_keeps_multiple_group_values
|
79
|
-
|
80
90
|
end
|
81
91
|
|
82
92
|
|
83
93
|
|
84
94
|
|
85
95
|
class BelongsToAssociationsTest < ActiveRecord::TestCase
|
86
|
-
|
87
96
|
# Since @client.firm is a single first/top, and we use FETCH the order clause is used.
|
88
97
|
coerce_tests! :test_belongs_to_does_not_use_order_by
|
89
98
|
|
@@ -93,7 +102,6 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
|
93
102
|
assert_no_match(/\[firm_with_primary_keys_companies\]\.\[id\]/, sql)
|
94
103
|
assert_match(/\[firm_with_primary_keys_companies\]\.\[name\]/, sql)
|
95
104
|
end
|
96
|
-
|
97
105
|
end
|
98
106
|
|
99
107
|
|
@@ -101,11 +109,8 @@ end
|
|
101
109
|
|
102
110
|
module ActiveRecord
|
103
111
|
class BindParameterTest < ActiveRecord::TestCase
|
104
|
-
|
105
112
|
# Never finds `sql` since we use `EXEC sp_executesql` wrappers.
|
106
|
-
coerce_tests! :test_binds_are_logged
|
107
|
-
:test_binds_are_logged_after_type_cast
|
108
|
-
|
113
|
+
coerce_tests! :test_binds_are_logged
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
@@ -113,7 +118,6 @@ end
|
|
113
118
|
|
114
119
|
|
115
120
|
class CalculationsTest < ActiveRecord::TestCase
|
116
|
-
|
117
121
|
# Are decimal, not integer.
|
118
122
|
coerce_tests! :test_should_return_decimal_average_of_integer_field
|
119
123
|
def test_should_return_decimal_average_of_integer_field_coerced
|
@@ -123,38 +127,34 @@ class CalculationsTest < ActiveRecord::TestCase
|
|
123
127
|
|
124
128
|
coerce_tests! :test_limit_is_kept
|
125
129
|
def test_limit_is_kept_coerced
|
126
|
-
queries =
|
130
|
+
queries = capture_sql_ss { Account.limit(1).count }
|
127
131
|
assert_equal 1, queries.length
|
128
|
-
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT
|
132
|
+
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1}
|
129
133
|
end
|
130
134
|
|
131
135
|
coerce_tests! :test_limit_with_offset_is_kept
|
132
136
|
def test_limit_with_offset_is_kept_coerced
|
133
|
-
queries =
|
137
|
+
queries = capture_sql_ss { Account.limit(1).offset(1).count }
|
134
138
|
assert_equal 1, queries.length
|
135
|
-
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET
|
139
|
+
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1}
|
136
140
|
end
|
137
141
|
|
142
|
+
# Leave it up to users to format selects/functions so HAVING works correctly.
|
143
|
+
coerce_tests! :test_having_with_strong_parameters
|
138
144
|
end
|
139
145
|
|
140
146
|
|
141
147
|
|
142
|
-
|
143
148
|
module ActiveRecord
|
144
149
|
class Migration
|
145
150
|
class ChangeSchemaTest < ActiveRecord::TestCase
|
146
|
-
|
147
151
|
# We test these.
|
148
152
|
coerce_tests! :test_create_table_with_bigint,
|
149
153
|
:test_create_table_with_defaults
|
150
|
-
|
151
|
-
|
152
154
|
end
|
153
155
|
class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase
|
154
|
-
|
155
156
|
# In SQL Server you have to delete the tables yourself in the right order.
|
156
157
|
coerce_tests! :test_create_table_with_force_cascade_drops_dependent_objects
|
157
|
-
|
158
158
|
end
|
159
159
|
end
|
160
160
|
end
|
@@ -165,7 +165,6 @@ end
|
|
165
165
|
module ActiveRecord
|
166
166
|
class Migration
|
167
167
|
class ColumnAttributesTest < ActiveRecord::TestCase
|
168
|
-
|
169
168
|
# We have a default 4000 varying character limit.
|
170
169
|
coerce_tests! :test_add_column_without_limit
|
171
170
|
def test_add_column_without_limit_coerced
|
@@ -173,7 +172,6 @@ module ActiveRecord
|
|
173
172
|
TestModel.reset_column_information
|
174
173
|
TestModel.columns_hash["description"].limit.must_equal 4000
|
175
174
|
end
|
176
|
-
|
177
175
|
end
|
178
176
|
end
|
179
177
|
end
|
@@ -184,14 +182,14 @@ end
|
|
184
182
|
module ActiveRecord
|
185
183
|
class Migration
|
186
184
|
class ColumnsTest
|
187
|
-
|
188
|
-
# Our defaults are reall 70000 integers vs '70000' strings.
|
185
|
+
# Our defaults are real 70000 integers vs '70000' strings.
|
189
186
|
coerce_tests! :test_rename_column_preserves_default_value_not_null
|
190
187
|
def test_rename_column_preserves_default_value_not_null_coerced
|
191
188
|
add_column 'test_models', 'salary', :integer, :default => 70000
|
192
189
|
default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
|
193
190
|
assert_equal 70000, default_before
|
194
191
|
rename_column "test_models", "salary", "annual_salary"
|
192
|
+
TestModel.reset_column_information
|
195
193
|
assert TestModel.column_names.include?("annual_salary")
|
196
194
|
default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
|
197
195
|
assert_equal 70000, default_after
|
@@ -208,6 +206,14 @@ module ActiveRecord
|
|
208
206
|
assert_equal [], connection.indexes('test_models').map(&:name)
|
209
207
|
end
|
210
208
|
|
209
|
+
# Choose `StatementInvalid` vs `ActiveRecordError`.
|
210
|
+
coerce_tests! :test_rename_nonexistent_column
|
211
|
+
def test_rename_nonexistent_column_coerced
|
212
|
+
exception = ActiveRecord::StatementInvalid
|
213
|
+
assert_raise(exception) do
|
214
|
+
rename_column "test_models", "nonexistent", "should_fail"
|
215
|
+
end
|
216
|
+
end
|
211
217
|
end
|
212
218
|
end
|
213
219
|
end
|
@@ -215,13 +221,53 @@ end
|
|
215
221
|
|
216
222
|
|
217
223
|
|
218
|
-
class
|
224
|
+
class MigrationTest < ActiveRecord::TestCase
|
225
|
+
# We do not have do the DecimalWithoutScale type.
|
226
|
+
coerce_tests! :test_add_table_with_decimals
|
227
|
+
def test_add_table_with_decimals_coerced
|
228
|
+
Person.connection.drop_table :big_numbers rescue nil
|
229
|
+
assert !BigNumber.table_exists?
|
230
|
+
GiveMeBigNumbers.up
|
231
|
+
BigNumber.reset_column_information
|
232
|
+
assert BigNumber.create(
|
233
|
+
:bank_balance => 1586.43,
|
234
|
+
:big_bank_balance => BigDecimal("1000234000567.95"),
|
235
|
+
:world_population => 6000000000,
|
236
|
+
:my_house_population => 3,
|
237
|
+
:value_of_e => BigDecimal("2.7182818284590452353602875")
|
238
|
+
)
|
239
|
+
b = BigNumber.first
|
240
|
+
assert_not_nil b
|
241
|
+
assert_not_nil b.bank_balance
|
242
|
+
assert_not_nil b.big_bank_balance
|
243
|
+
assert_not_nil b.world_population
|
244
|
+
assert_not_nil b.my_house_population
|
245
|
+
assert_not_nil b.value_of_e
|
246
|
+
assert_kind_of BigDecimal, b.world_population
|
247
|
+
assert_equal '6000000000.0', b.world_population.to_s
|
248
|
+
assert_kind_of Integer, b.my_house_population
|
249
|
+
assert_equal 3, b.my_house_population
|
250
|
+
assert_kind_of BigDecimal, b.bank_balance
|
251
|
+
assert_equal BigDecimal("1586.43"), b.bank_balance
|
252
|
+
assert_kind_of BigDecimal, b.big_bank_balance
|
253
|
+
assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
|
254
|
+
GiveMeBigNumbers.down
|
255
|
+
assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
|
256
|
+
end
|
257
|
+
|
258
|
+
# For some reason our tests set Rails.@_env which breaks test env switching.
|
259
|
+
coerce_tests! :test_migration_sets_internal_metadata_even_when_fully_migrated
|
260
|
+
coerce_tests! :test_internal_metadata_stores_environment
|
261
|
+
end
|
262
|
+
|
263
|
+
|
219
264
|
|
265
|
+
|
266
|
+
class CoreTest < ActiveRecord::TestCase
|
220
267
|
# I think fixtures are useing the wrong time zone and the `:first`
|
221
268
|
# `topics`.`bonus_time` attribute of 2005-01-30t15:28:00.00+01:00 is
|
222
269
|
# getting local EST time for me and set to "09:28:00.0000000".
|
223
270
|
coerce_tests! :test_pretty_print_persisted
|
224
|
-
|
225
271
|
end
|
226
272
|
|
227
273
|
|
@@ -229,7 +275,6 @@ end
|
|
229
275
|
|
230
276
|
module ActiveRecord
|
231
277
|
module ConnectionAdapters
|
232
|
-
|
233
278
|
# Just like PostgreSQLAdapter does.
|
234
279
|
TypeLookupTest.coerce_all_tests! if defined?(TypeLookupTest)
|
235
280
|
|
@@ -237,7 +282,6 @@ module ActiveRecord
|
|
237
282
|
# a value of 'default_env' will still show tests failing. Just ignoring all
|
238
283
|
# of them since we have no monkey in this circus.
|
239
284
|
MergeAndResolveDefaultUrlConfigTest.coerce_all_tests! if defined?(MergeAndResolveDefaultUrlConfigTest)
|
240
|
-
|
241
285
|
end
|
242
286
|
end
|
243
287
|
|
@@ -259,10 +303,16 @@ end
|
|
259
303
|
|
260
304
|
|
261
305
|
class DefaultScopingTest < ActiveRecord::TestCase
|
262
|
-
|
263
306
|
# We are not doing order duplicate removal anymore.
|
264
307
|
coerce_tests! :test_order_in_default_scope_should_not_prevail
|
265
308
|
|
309
|
+
# Use our escaped format in assertion.
|
310
|
+
coerce_tests! :test_with_abstract_class_scope_should_be_executed_in_correct_context
|
311
|
+
def test_with_abstract_class_scope_should_be_executed_in_correct_context_coerced
|
312
|
+
vegetarian_pattern, gender_pattern = [/[lions].[is_vegetarian]/, /[lions].[gender]/]
|
313
|
+
assert_match vegetarian_pattern, Lion.all.to_sql
|
314
|
+
assert_match gender_pattern, Lion.female.to_sql
|
315
|
+
end
|
266
316
|
end
|
267
317
|
|
268
318
|
|
@@ -271,7 +321,7 @@ end
|
|
271
321
|
require 'models/post'
|
272
322
|
require 'models/subscriber'
|
273
323
|
class EachTest < ActiveRecord::TestCase
|
274
|
-
|
324
|
+
# Quoting in tests does not cope with bracket quoting.
|
275
325
|
coerce_tests! :test_find_in_batches_should_quote_batch_order
|
276
326
|
def test_find_in_batches_should_quote_batch_order_coerced
|
277
327
|
c = Post.connection
|
@@ -283,20 +333,23 @@ class EachTest < ActiveRecord::TestCase
|
|
283
333
|
end
|
284
334
|
end
|
285
335
|
|
336
|
+
# Quoting in tests does not cope with bracket quoting.
|
337
|
+
coerce_tests! :test_in_batches_should_quote_batch_order
|
338
|
+
def test_in_batches_should_quote_batch_order_coerced
|
339
|
+
c = Post.connection
|
340
|
+
assert_sql(/ORDER BY \[posts\]\.\[id\]/) do
|
341
|
+
Post.in_batches(of: 1) do |relation|
|
342
|
+
assert_kind_of ActiveRecord::Relation, relation
|
343
|
+
assert_kind_of Post, relation.first
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
286
347
|
end
|
287
348
|
|
288
349
|
|
289
350
|
|
290
351
|
|
291
|
-
require 'models/owner'
|
292
|
-
class Owner < ActiveRecord::Base
|
293
|
-
scope :including_last_pet, -> {
|
294
|
-
select('owners.*, (select TOP (1) p.pet_id from pets p where p.owner_id = owners.owner_id order by p.name desc ) as last_pet_id').
|
295
|
-
includes(:last_pet)
|
296
|
-
}
|
297
|
-
end
|
298
352
|
class EagerAssociationTest < ActiveRecord::TestCase
|
299
|
-
|
300
353
|
# Use LEN() vs length() function.
|
301
354
|
coerce_tests! :test_count_with_include
|
302
355
|
def test_count_with_include_coerced
|
@@ -305,10 +358,6 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
305
358
|
|
306
359
|
# Use TOP (1) in scope vs limit 1.
|
307
360
|
coerce_tests! %r{including association based on sql condition and no database column}
|
308
|
-
it "including association based on sql condition and no database column coerced" do
|
309
|
-
assert_equal pets(:parrot), Owner.including_last_pet.first.last_pet
|
310
|
-
end
|
311
|
-
|
312
361
|
end
|
313
362
|
|
314
363
|
|
@@ -316,13 +365,12 @@ end
|
|
316
365
|
|
317
366
|
require 'models/topic'
|
318
367
|
class FinderTest < ActiveRecord::TestCase
|
319
|
-
|
320
368
|
coerce_tests! %r{doesn't have implicit ordering},
|
321
369
|
:test_find_doesnt_have_implicit_ordering # We have implicit ordering, via FETCH.
|
322
370
|
|
323
371
|
coerce_tests! :test_exists_does_not_select_columns_without_alias
|
324
372
|
def test_exists_does_not_select_columns_without_alias_coerced
|
325
|
-
assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT
|
373
|
+
assert_sql(/SELECT\s+1 AS one FROM \[topics\].*OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1/i) do
|
326
374
|
Topic.exists?
|
327
375
|
end
|
328
376
|
end
|
@@ -335,14 +383,35 @@ class FinderTest < ActiveRecord::TestCase
|
|
335
383
|
|
336
384
|
coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
|
337
385
|
def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
|
338
|
-
assert_sql(/OFFSET 0 ROWS FETCH NEXT
|
339
|
-
assert_sql(/OFFSET 0 ROWS FETCH NEXT
|
340
|
-
assert_sql(/OFFSET 0 ROWS FETCH NEXT
|
386
|
+
assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
|
387
|
+
assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 2/) { Topic.first(2).entries }
|
388
|
+
assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 5/) { Topic.last(5).entries }
|
341
389
|
end
|
342
390
|
|
343
391
|
# This fails only when run in the full test suite task. Just taking it out of the mix.
|
344
392
|
coerce_tests! :test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
|
345
393
|
|
394
|
+
# Can not use array condition due to not finding right type and hence fractional second quoting.
|
395
|
+
coerce_tests! :test_condition_utc_time_interpolation_with_default_timezone_local
|
396
|
+
def test_condition_utc_time_interpolation_with_default_timezone_local_coerced
|
397
|
+
with_env_tz 'America/New_York' do
|
398
|
+
with_timezone_config default: :local do
|
399
|
+
topic = Topic.first
|
400
|
+
assert_equal topic, Topic.where(written_on: topic.written_on.getutc).first
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
# Can not use array condition due to not finding right type and hence fractional second quoting.
|
406
|
+
coerce_tests! :test_condition_local_time_interpolation_with_default_timezone_utc
|
407
|
+
def test_condition_local_time_interpolation_with_default_timezone_utc_coerced
|
408
|
+
with_env_tz 'America/New_York' do
|
409
|
+
with_timezone_config default: :utc do
|
410
|
+
topic = Topic.first
|
411
|
+
assert_equal topic, Topic.where(written_on: topic.written_on.getlocal).first
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
346
415
|
end
|
347
416
|
|
348
417
|
|
@@ -351,7 +420,6 @@ end
|
|
351
420
|
module ActiveRecord
|
352
421
|
class Migration
|
353
422
|
class ForeignKeyTest < ActiveRecord::TestCase
|
354
|
-
|
355
423
|
# We do not support :restrict.
|
356
424
|
coerce_tests! :test_add_on_delete_restrict_foreign_key
|
357
425
|
def test_add_on_delete_restrict_foreign_key_coerced
|
@@ -362,7 +430,6 @@ module ActiveRecord
|
|
362
430
|
@connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", on_update: :restrict
|
363
431
|
end
|
364
432
|
end
|
365
|
-
|
366
433
|
end
|
367
434
|
end
|
368
435
|
end
|
@@ -371,10 +438,8 @@ end
|
|
371
438
|
|
372
439
|
|
373
440
|
class HasOneAssociationsTest < ActiveRecord::TestCase
|
374
|
-
|
375
441
|
# We use OFFSET/FETCH vs TOP. So we always have an order.
|
376
442
|
coerce_tests! :test_has_one_does_not_use_order_by
|
377
|
-
|
378
443
|
end
|
379
444
|
|
380
445
|
|
@@ -382,7 +447,6 @@ end
|
|
382
447
|
|
383
448
|
require 'models/company'
|
384
449
|
class InheritanceTest < ActiveRecord::TestCase
|
385
|
-
|
386
450
|
coerce_tests! :test_a_bad_type_column
|
387
451
|
def test_a_bad_type_column_coerced
|
388
452
|
Company.connection.with_identity_insert_enabled('companies') do
|
@@ -394,32 +458,24 @@ class InheritanceTest < ActiveRecord::TestCase
|
|
394
458
|
coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
|
395
459
|
def test_eager_load_belongs_to_primary_key_quoting_coerced
|
396
460
|
con = Account.connection
|
397
|
-
assert_sql(/\[companies\]\.\[id\]
|
461
|
+
assert_sql(/\[companies\]\.\[id\] = 1/) do
|
398
462
|
Account.all.merge!(:includes => :firm).find(1)
|
399
463
|
end
|
400
464
|
end
|
401
|
-
|
402
465
|
end
|
403
466
|
|
404
467
|
|
405
468
|
|
406
469
|
|
407
|
-
class
|
408
|
-
|
409
|
-
|
410
|
-
end
|
411
|
-
class MigrationTest < ActiveRecord::TestCase
|
412
|
-
|
413
|
-
# PENDING: [Rails5.x] Remove coerced tests and use simple symbol types.
|
414
|
-
coerce_tests! :test_add_table_with_decimals
|
415
|
-
|
470
|
+
class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
|
471
|
+
# Uses || operator in SQL. Just trust core gets value out of this test.
|
472
|
+
coerce_tests! :test_does_not_override_select
|
416
473
|
end
|
417
474
|
|
418
475
|
|
419
476
|
|
420
477
|
|
421
478
|
class NamedScopingTest < ActiveRecord::TestCase
|
422
|
-
|
423
479
|
# This works now because we add an `order(:id)` sort to break the order tie for deterministic results.
|
424
480
|
coerce_tests! :test_scopes_honor_current_scopes_from_when_defined
|
425
481
|
def test_scopes_honor_current_scopes_from_when_defined_coerced
|
@@ -431,7 +487,6 @@ class NamedScopingTest < ActiveRecord::TestCase
|
|
431
487
|
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)
|
432
488
|
assert_equal Post.ranked_by_comments.limit_by(5), Post.top(5)
|
433
489
|
end
|
434
|
-
|
435
490
|
end
|
436
491
|
|
437
492
|
|
@@ -440,7 +495,6 @@ end
|
|
440
495
|
require 'models/developer'
|
441
496
|
require 'models/computer'
|
442
497
|
class NestedRelationScopingTest < ActiveRecord::TestCase
|
443
|
-
|
444
498
|
coerce_tests! :test_merge_options
|
445
499
|
def test_merge_options_coerced
|
446
500
|
Developer.where('salary = 80000').scoping do
|
@@ -452,7 +506,6 @@ class NestedRelationScopingTest < ActiveRecord::TestCase
|
|
452
506
|
end
|
453
507
|
end
|
454
508
|
end
|
455
|
-
|
456
509
|
end
|
457
510
|
|
458
511
|
|
@@ -460,7 +513,6 @@ end
|
|
460
513
|
|
461
514
|
require 'models/topic'
|
462
515
|
class PersistenceTest < ActiveRecord::TestCase
|
463
|
-
|
464
516
|
# We can not UPDATE identity columns.
|
465
517
|
coerce_tests! :test_update_columns_changing_id
|
466
518
|
|
@@ -501,7 +553,6 @@ class PersistenceTest < ActiveRecord::TestCase
|
|
501
553
|
# assert_nothing_raised { topic.reload }
|
502
554
|
# assert_equal topic.title, Topic.find(1234).title
|
503
555
|
end
|
504
|
-
|
505
556
|
end
|
506
557
|
|
507
558
|
|
@@ -510,15 +561,15 @@ end
|
|
510
561
|
require 'models/topic'
|
511
562
|
module ActiveRecord
|
512
563
|
class PredicateBuilderTest < ActiveRecord::TestCase
|
513
|
-
|
514
564
|
coerce_tests! :test_registering_new_handlers
|
515
565
|
def test_registering_new_handlers_coerced
|
516
|
-
|
566
|
+
Topic.predicate_builder.register_handler(Regexp, proc do |column, value|
|
517
567
|
Arel::Nodes::InfixOperation.new('~', column, Arel.sql(value.source))
|
518
568
|
end)
|
519
|
-
assert_match %r{\[topics\]
|
569
|
+
assert_match %r{\[topics\].\[title\] ~ rails}i, Topic.where(title: /rails/).to_sql
|
570
|
+
ensure
|
571
|
+
Topic.reset_column_information
|
520
572
|
end
|
521
|
-
|
522
573
|
end
|
523
574
|
end
|
524
575
|
|
@@ -527,14 +578,12 @@ end
|
|
527
578
|
|
528
579
|
require 'models/task'
|
529
580
|
class QueryCacheTest < ActiveRecord::TestCase
|
530
|
-
|
531
581
|
coerce_tests! :test_cache_does_not_wrap_string_results_in_arrays
|
532
582
|
def test_cache_does_not_wrap_string_results_in_arrays_coerced
|
533
583
|
Task.cache do
|
534
584
|
assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
|
535
585
|
end
|
536
586
|
end
|
537
|
-
|
538
587
|
end
|
539
588
|
|
540
589
|
|
@@ -542,6 +591,21 @@ end
|
|
542
591
|
|
543
592
|
require 'models/post'
|
544
593
|
class RelationTest < ActiveRecord::TestCase
|
594
|
+
# Use LEN vs LENGTH function.
|
595
|
+
coerce_tests! :test_reverse_order_with_function
|
596
|
+
def test_reverse_order_with_function_coerced
|
597
|
+
topics = Topic.order("LEN(title)").reverse_order
|
598
|
+
assert_equal topics(:second).title, topics.first.title
|
599
|
+
end
|
600
|
+
|
601
|
+
# Use LEN vs LENGTH function.
|
602
|
+
coerce_tests! :test_reverse_order_with_function_other_predicates
|
603
|
+
def test_reverse_order_with_function_other_predicates_coerced
|
604
|
+
topics = Topic.order("author_name, LEN(title), id").reverse_order
|
605
|
+
assert_equal topics(:second).title, topics.first.title
|
606
|
+
topics = Topic.order("LEN(author_name), id, LEN(title)").reverse_order
|
607
|
+
assert_equal topics(:fifth).title, topics.first.title
|
608
|
+
end
|
545
609
|
|
546
610
|
# We have implicit ordering, via FETCH.
|
547
611
|
coerce_tests! %r{doesn't have implicit ordering}
|
@@ -549,18 +613,12 @@ class RelationTest < ActiveRecord::TestCase
|
|
549
613
|
# We are not doing order duplicate removal anymore.
|
550
614
|
coerce_tests! :test_order_using_scoping
|
551
615
|
|
552
|
-
# Account for our `EXEC sp_executesql...` statements.
|
553
|
-
coerce_tests! :test_to_sql_on_eager_join
|
554
|
-
def test_to_sql_on_eager_join_coerced
|
555
|
-
expected = assert_sql { Post.eager_load(:last_comment).order('comments.id DESC').to_a }.first
|
556
|
-
actual = Post.eager_load(:last_comment).order('comments.id DESC').to_sql
|
557
|
-
actual = "EXEC sp_executesql N'#{ActiveRecord::ConnectionAdapters::SQLServer::Utils.quote_string(actual)}'"
|
558
|
-
assert_equal expected, actual
|
559
|
-
end
|
560
|
-
|
561
616
|
# We are not doing order duplicate removal anymore.
|
562
617
|
coerce_tests! :test_default_scope_order_with_scope_order
|
563
618
|
|
619
|
+
# Leave it up to users to format selects/functions so HAVING works correctly.
|
620
|
+
coerce_tests! :test_multiple_where_and_having_clauses
|
621
|
+
coerce_tests! :test_having_with_binds_for_both_where_and_having
|
564
622
|
end
|
565
623
|
|
566
624
|
|
@@ -568,7 +626,6 @@ end
|
|
568
626
|
|
569
627
|
require 'models/post'
|
570
628
|
class SanitizeTest < ActiveRecord::TestCase
|
571
|
-
|
572
629
|
coerce_tests! :test_sanitize_sql_like_example_use_case
|
573
630
|
def test_sanitize_sql_like_example_use_case_coerced
|
574
631
|
searchable_post = Class.new(Post) do
|
@@ -576,18 +633,16 @@ class SanitizeTest < ActiveRecord::TestCase
|
|
576
633
|
where("title LIKE ?", sanitize_sql_like(term, '!'))
|
577
634
|
end
|
578
635
|
end
|
579
|
-
assert_sql(/\(title LIKE N'
|
636
|
+
assert_sql(/\(title LIKE N'20!% !_reduction!_!!'\)/) do
|
580
637
|
searchable_post.search("20% _reduction_!").to_a
|
581
638
|
end
|
582
639
|
end
|
583
|
-
|
584
640
|
end
|
585
641
|
|
586
642
|
|
587
643
|
|
588
644
|
|
589
645
|
class SchemaDumperTest < ActiveRecord::TestCase
|
590
|
-
|
591
646
|
# We have precision to 38.
|
592
647
|
coerce_tests! :test_schema_dump_keeps_large_precision_integer_columns_as_decimal
|
593
648
|
def test_schema_dump_keeps_large_precision_integer_columns_as_decimal_coerced
|
@@ -604,27 +659,29 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
604
659
|
# Fall through false positive with no filter.
|
605
660
|
coerce_tests! :test_schema_dumps_partial_indices
|
606
661
|
def test_schema_dumps_partial_indices_coerced
|
607
|
-
index_definition = standard_dump.split(/\n/).grep(/
|
608
|
-
assert_equal '
|
662
|
+
index_definition = standard_dump.split(/\n/).grep(/t.index.*company_partial_index/).first.strip
|
663
|
+
assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "([rating]>(10))"', index_definition
|
609
664
|
end
|
610
665
|
|
666
|
+
# We do not quote the 2.78 string default.
|
667
|
+
coerce_tests! :test_schema_dump_includes_decimal_options
|
668
|
+
def test_schema_dump_includes_decimal_options_coerced
|
669
|
+
output = dump_all_table_schema([/^[^n]/])
|
670
|
+
assert_match %r{precision: 3,[[:space:]]+scale: 2,[[:space:]]+default: 2\.78}, output
|
671
|
+
end
|
611
672
|
end
|
612
673
|
|
613
674
|
class SchemaDumperDefaultsTest < ActiveRecord::TestCase
|
614
|
-
|
615
675
|
# These date formats do not match ours. We got these covered in our dumper tests.
|
616
676
|
coerce_tests! :test_schema_dump_defaults_with_universally_supported_types
|
617
|
-
|
618
677
|
end
|
619
678
|
|
620
679
|
|
621
680
|
|
622
681
|
|
623
682
|
class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
|
624
|
-
|
625
683
|
# We trust Rails on this since we do not want to install mysql.
|
626
684
|
coerce_tests! %r{inspect on Model class does not raise}
|
627
|
-
|
628
685
|
end
|
629
686
|
|
630
687
|
|
@@ -632,7 +689,6 @@ end
|
|
632
689
|
|
633
690
|
require 'models/topic'
|
634
691
|
class TransactionTest < ActiveRecord::TestCase
|
635
|
-
|
636
692
|
coerce_tests! :test_releasing_named_savepoints
|
637
693
|
def test_releasing_named_savepoints_coerced
|
638
694
|
Topic.transaction do
|
@@ -642,7 +698,6 @@ class TransactionTest < ActiveRecord::TestCase
|
|
642
698
|
Topic.connection.release_savepoint("another")
|
643
699
|
end
|
644
700
|
end
|
645
|
-
|
646
701
|
end
|
647
702
|
|
648
703
|
|
@@ -650,7 +705,6 @@ end
|
|
650
705
|
|
651
706
|
require 'models/tag'
|
652
707
|
class TransactionIsolationTest < ActiveRecord::TestCase
|
653
|
-
|
654
708
|
# SQL Server will lock the table for counts even when both
|
655
709
|
# connections are `READ COMMITTED`. So we bypass with `READPAST`.
|
656
710
|
coerce_tests! %r{read committed}
|
@@ -667,32 +721,32 @@ class TransactionIsolationTest < ActiveRecord::TestCase
|
|
667
721
|
|
668
722
|
# I really need some help understanding this one.
|
669
723
|
coerce_tests! %r{repeatable read}
|
670
|
-
|
671
|
-
end
|
672
|
-
|
673
|
-
|
674
|
-
require 'models/post'
|
675
|
-
module ActiveRecord
|
676
|
-
class WhereChainTest < ActiveRecord::TestCase
|
677
|
-
|
678
|
-
coerce_tests! :test_not_eq_with_array_parameter
|
679
|
-
def test_not_eq_with_array_parameter_coerced
|
680
|
-
expected = Arel::Nodes::Not.new("title = N'hello'")
|
681
|
-
relation = Post.where.not(['title = ?', 'hello'])
|
682
|
-
assert_equal([expected], relation.where_values)
|
683
|
-
end
|
684
|
-
|
685
|
-
end
|
686
724
|
end
|
687
725
|
|
688
726
|
|
689
727
|
|
690
728
|
|
729
|
+
require 'models/book'
|
691
730
|
class ViewWithPrimaryKeyTest < ActiveRecord::TestCase
|
731
|
+
# We have a few view tables. use includes vs equality.
|
732
|
+
coerce_tests! :test_views
|
733
|
+
def test_views_coerced
|
734
|
+
assert_includes @connection.views, Ebook.table_name
|
735
|
+
end
|
692
736
|
|
693
737
|
# We do better than ActiveRecord and find the views PK.
|
694
738
|
coerce_tests! :test_does_not_assume_id_column_as_primary_key
|
695
|
-
|
739
|
+
def test_does_not_assume_id_column_as_primary_key_coerced
|
740
|
+
model = Class.new(ActiveRecord::Base) { self.table_name = "ebooks" }
|
741
|
+
assert_equal 'id', model.primary_key
|
742
|
+
end
|
743
|
+
end
|
744
|
+
class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase
|
745
|
+
# We have a few view tables. use includes vs equality.
|
746
|
+
coerce_tests! :test_views
|
747
|
+
def test_views_coerced
|
748
|
+
assert_includes @connection.views, Paperback.table_name
|
749
|
+
end
|
696
750
|
end
|
697
751
|
|
698
752
|
|
@@ -700,7 +754,6 @@ end
|
|
700
754
|
|
701
755
|
require 'models/author'
|
702
756
|
class YamlSerializationTest < ActiveRecord::TestCase
|
703
|
-
|
704
757
|
coerce_tests! :test_types_of_virtual_columns_are_not_changed_on_round_trip
|
705
758
|
def test_types_of_virtual_columns_are_not_changed_on_round_trip_coerced
|
706
759
|
author = Author.select('authors.*, 5 as posts_count').first
|
@@ -708,6 +761,48 @@ class YamlSerializationTest < ActiveRecord::TestCase
|
|
708
761
|
assert_equal 5, author.posts_count
|
709
762
|
assert_equal 5, dumped.posts_count
|
710
763
|
end
|
764
|
+
end
|
765
|
+
|
766
|
+
|
767
|
+
|
768
|
+
|
769
|
+
class DateTimePrecisionTest < ActiveRecord::TestCase
|
770
|
+
# Original test had `7` which we support vs `8` which we use.
|
771
|
+
coerce_tests! :test_invalid_datetime_precision_raises_error
|
772
|
+
def test_invalid_datetime_precision_raises_error_coerced
|
773
|
+
assert_raises ActiveRecord::ActiveRecordError do
|
774
|
+
@connection.create_table(:foos, force: true) do |t|
|
775
|
+
t.timestamps precision: 8
|
776
|
+
end
|
777
|
+
end
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
|
782
|
+
|
711
783
|
|
784
|
+
class DefaultNumbersTest < ActiveRecord::TestCase
|
785
|
+
# We do better with native types and do not return strings for everything.
|
786
|
+
coerce_tests! :test_default_positive_integer
|
787
|
+
def test_default_positive_integer_coerced
|
788
|
+
record = DefaultNumber.new
|
789
|
+
assert_equal 7, record.positive_integer
|
790
|
+
assert_equal 7, record.positive_integer_before_type_cast
|
791
|
+
end
|
792
|
+
coerce_tests! :test_default_negative_integer
|
793
|
+
def test_default_negative_integer_coerced
|
794
|
+
record = DefaultNumber.new
|
795
|
+
assert_equal -5, record.negative_integer
|
796
|
+
assert_equal -5, record.negative_integer_before_type_cast
|
797
|
+
end
|
712
798
|
end
|
713
799
|
|
800
|
+
|
801
|
+
|
802
|
+
|
803
|
+
module ActiveRecord
|
804
|
+
class CollectionCacheKeyTest < ActiveRecord::TestCase
|
805
|
+
# Will trust rails has this sorted since you cant offset without a limit.
|
806
|
+
coerce_tests! %r{with offset which return 0 rows}
|
807
|
+
end
|
808
|
+
end
|