activerecord-jdbcsqlserver-adapter 50.0.0 → 52.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.travis.yml +4 -5
- data/CHANGELOG.md +22 -101
- data/{Dockerfile → Dockerfile.ci} +0 -0
- data/Gemfile +1 -3
- data/README.md +5 -9
- data/VERSION +1 -1
- data/activerecord-jdbcsqlserver-adapter.gemspec +2 -2
- data/appveyor.yml +1 -1
- data/docker-compose.ci.yml +7 -5
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +51 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +18 -20
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +5 -3
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +43 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +26 -0
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +13 -2
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +94 -28
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +5 -25
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +24 -1
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +23 -2
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +110 -74
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +15 -7
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +5 -0
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +3 -6
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +7 -0
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +47 -24
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +5 -3
- data/lib/activerecord-jdbcsqlserver-adapter.rb +4 -1
- data/lib/arel/visitors/sqlserver.rb +17 -4
- data/lib/arel_sqlserver.rb +0 -1
- data/lib/jdbc_mssql_driver_loader.rb +22 -0
- data/test/bin/install-freetds.sh +18 -0
- data/test/bin/setup.sh +19 -0
- data/test/cases/adapter_test_sqlserver.rb +43 -39
- data/test/cases/change_column_null_test_sqlserver.rb +42 -0
- data/test/cases/coerced_tests.rb +419 -39
- data/test/cases/column_test_sqlserver.rb +496 -462
- data/test/cases/connection_test_sqlserver.rb +2 -2
- data/test/cases/fetch_test_sqlserver.rb +5 -5
- data/test/cases/helper_sqlserver.rb +12 -1
- data/test/cases/json_test_sqlserver.rb +6 -6
- data/test/cases/migration_test_sqlserver.rb +13 -3
- data/test/cases/order_test_sqlserver.rb +19 -19
- data/test/cases/pessimistic_locking_test_sqlserver.rb +37 -20
- data/test/cases/rake_test_sqlserver.rb +20 -20
- data/test/cases/schema_dumper_test_sqlserver.rb +44 -43
- data/test/cases/schema_test_sqlserver.rb +2 -2
- data/test/cases/showplan_test_sqlserver.rb +25 -10
- data/test/cases/specific_schema_test_sqlserver.rb +11 -17
- data/test/cases/transaction_test_sqlserver.rb +9 -9
- data/test/cases/trigger_test_sqlserver.rb +31 -0
- data/test/cases/utils_test_sqlserver.rb +36 -36
- data/test/cases/uuid_test_sqlserver.rb +8 -8
- data/test/config.yml +2 -2
- data/test/migrations/create_clients_and_change_column_null.rb +23 -0
- data/test/models/sqlserver/trigger.rb +7 -0
- data/test/models/sqlserver/trigger_history.rb +3 -0
- data/test/schema/datatypes/2012.sql +1 -0
- data/test/schema/sqlserver_specific_schema.rb +47 -5
- data/test/support/core_ext/query_cache.rb +29 -0
- data/test/support/sql_counter_sqlserver.rb +1 -1
- metadata +32 -15
- data/RAILS5-TODO.md +0 -5
- data/test/models/sqlserver/dot_table_name.rb +0 -3
data/test/bin/setup.sh
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -x
|
4
|
+
set -e
|
5
|
+
|
6
|
+
tag=2017-GA
|
7
|
+
|
8
|
+
docker pull metaskills/mssql-server-linux-rails:$tag
|
9
|
+
|
10
|
+
container=$(docker ps -a -q --filter ancestor=metaskills/mssql-server-linux-rails:$tag)
|
11
|
+
if [[ -z $container ]]; then
|
12
|
+
docker run -p 1433:1433 -d metaskills/mssql-server-linux-rails:$tag && sleep 10
|
13
|
+
exit
|
14
|
+
fi
|
15
|
+
|
16
|
+
container=$(docker ps -q --filter ancestor=metaskills/mssql-server-linux-rails:$tag)
|
17
|
+
if [[ -z $container ]]; then
|
18
|
+
docker start $container && sleep 10
|
19
|
+
fi
|
@@ -13,16 +13,17 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
13
13
|
let(:basic_update_sql) { "UPDATE [customers] SET [address_street] = NULL WHERE [id] = 2" }
|
14
14
|
let(:basic_select_sql) { "SELECT * FROM [customers] WHERE ([customers].[id] = 1)" }
|
15
15
|
|
16
|
-
it 'has basic and non-
|
16
|
+
it 'has basic and non-sensitive information in the adapters inspect method' do
|
17
17
|
string = connection.inspect
|
18
|
-
|
19
|
-
string.must_match %r{
|
20
|
-
string.must_match %r{
|
21
|
-
string.must_match %r{
|
22
|
-
string.
|
23
|
-
string.wont_match %r{
|
24
|
-
string.wont_match %r{
|
25
|
-
string.wont_match %r{
|
18
|
+
|
19
|
+
_(string).must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
|
20
|
+
_(string).must_match %r{version\: \d+\.\d}
|
21
|
+
_(string).must_match %r{mode: (dblib|jdbc)}
|
22
|
+
_(string).must_match %r{azure: (true|false)}
|
23
|
+
_(string).wont_match %r{host}
|
24
|
+
_(string).wont_match %r{password}
|
25
|
+
_(string).wont_match %r{username}
|
26
|
+
_(string).wont_match %r{port}
|
26
27
|
end
|
27
28
|
|
28
29
|
it 'has a 128 max #table_alias_length' do
|
@@ -37,10 +38,6 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
37
38
|
assert_equal 'SQLServer', connection.adapter_name
|
38
39
|
end
|
39
40
|
|
40
|
-
it 'supports migrations' do
|
41
|
-
assert connection.supports_migrations?
|
42
|
-
end
|
43
|
-
|
44
41
|
it 'support DDL in transactions' do
|
45
42
|
assert connection.supports_ddl_transactions?
|
46
43
|
end
|
@@ -145,12 +142,12 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
145
142
|
end
|
146
143
|
|
147
144
|
it 'return quoted table_name to #query_requires_identity_insert? when INSERT sql contains id column' do
|
148
|
-
assert_equal '
|
149
|
-
assert_equal '
|
150
|
-
assert_equal '
|
151
|
-
assert_equal '
|
152
|
-
assert_equal '
|
153
|
-
assert_equal '
|
145
|
+
assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql)
|
146
|
+
assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted)
|
147
|
+
assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered)
|
148
|
+
assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_sp)
|
149
|
+
assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unquoted_sp)
|
150
|
+
assert_equal 'funny_jokes', connection.send(:query_requires_identity_insert?,@identity_insert_sql_unordered_sp)
|
154
151
|
end
|
155
152
|
|
156
153
|
it 'return false to #query_requires_identity_insert? for normal SQL' do
|
@@ -166,7 +163,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
166
163
|
end
|
167
164
|
|
168
165
|
it 'return an empty array when calling #identity_columns for a table_name with no identity' do
|
169
|
-
connection.send(:identity_columns, Subscriber.table_name).must_equal []
|
166
|
+
_(connection.send(:identity_columns, Subscriber.table_name)).must_equal []
|
170
167
|
end
|
171
168
|
|
172
169
|
end
|
@@ -236,6 +233,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
236
233
|
end
|
237
234
|
end
|
238
235
|
|
236
|
+
it 'not disable referential integrity for the same table twice' do
|
237
|
+
tables = SSTestHasPk.connection.tables_with_referential_integrity
|
238
|
+
assert_equal tables.size, tables.uniq.size
|
239
|
+
end
|
240
|
+
|
239
241
|
end
|
240
242
|
|
241
243
|
describe 'database statements' do
|
@@ -266,23 +268,26 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
266
268
|
end
|
267
269
|
|
268
270
|
it 'create integers when limit is 4' do
|
269
|
-
assert_equal 'integer', connection.type_to_sql(:integer, 4)
|
271
|
+
assert_equal 'integer', connection.type_to_sql(:integer, limit: 4)
|
270
272
|
end
|
271
273
|
|
272
274
|
it 'create integers when limit is 3' do
|
273
|
-
assert_equal 'integer', connection.type_to_sql(:integer, 3)
|
275
|
+
assert_equal 'integer', connection.type_to_sql(:integer, limit: 3)
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'create smallints when limit is 2' do
|
279
|
+
assert_equal 'smallint', connection.type_to_sql(:integer, limit: 2)
|
274
280
|
end
|
275
281
|
|
276
|
-
it 'create
|
277
|
-
assert_equal '
|
278
|
-
assert_equal 'smallint', connection.type_to_sql(:integer, 1)
|
282
|
+
it 'create tinyints when limit is 1' do
|
283
|
+
assert_equal 'tinyint', connection.type_to_sql(:integer, limit: 1)
|
279
284
|
end
|
280
285
|
|
281
286
|
it 'create bigints when limit is greateer than 4' do
|
282
|
-
assert_equal 'bigint', connection.type_to_sql(:integer, 5)
|
283
|
-
assert_equal 'bigint', connection.type_to_sql(:integer, 6)
|
284
|
-
assert_equal 'bigint', connection.type_to_sql(:integer, 7)
|
285
|
-
assert_equal 'bigint', connection.type_to_sql(:integer, 8)
|
287
|
+
assert_equal 'bigint', connection.type_to_sql(:integer, limit: 5)
|
288
|
+
assert_equal 'bigint', connection.type_to_sql(:integer, limit: 6)
|
289
|
+
assert_equal 'bigint', connection.type_to_sql(:integer, limit: 7)
|
290
|
+
assert_equal 'bigint', connection.type_to_sql(:integer, limit: 8)
|
286
291
|
end
|
287
292
|
|
288
293
|
it 'create floats when no limit supplied' do
|
@@ -300,7 +305,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
300
305
|
end
|
301
306
|
|
302
307
|
it 'find SSTestCustomersView table name' do
|
303
|
-
connection.views.must_include 'sst_customers_view'
|
308
|
+
_(connection.views).must_include 'sst_customers_view'
|
304
309
|
end
|
305
310
|
|
306
311
|
it 'work with dynamic finders' do
|
@@ -341,9 +346,9 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
341
346
|
end
|
342
347
|
|
343
348
|
it 'find identity column' do
|
344
|
-
SSTestCustomersView.primary_key.must_equal 'id'
|
345
|
-
connection.primary_key(SSTestCustomersView.table_name).must_equal 'id'
|
346
|
-
SSTestCustomersView.columns_hash['id'].must_be :is_identity?
|
349
|
+
_(SSTestCustomersView.primary_key).must_equal 'id'
|
350
|
+
_(connection.primary_key(SSTestCustomersView.table_name)).must_equal 'id'
|
351
|
+
_(SSTestCustomersView.columns_hash['id']).must_be :is_identity?
|
347
352
|
end
|
348
353
|
|
349
354
|
it 'find default values' do
|
@@ -368,9 +373,9 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
368
373
|
end
|
369
374
|
|
370
375
|
it 'find identity column' do
|
371
|
-
SSTestStringDefaultsView.primary_key.must_equal 'id'
|
372
|
-
connection.primary_key(SSTestStringDefaultsView.table_name).must_equal 'id'
|
373
|
-
SSTestStringDefaultsView.columns_hash['id'].must_be :is_identity?
|
376
|
+
_(SSTestStringDefaultsView.primary_key).must_equal 'id'
|
377
|
+
_(connection.primary_key(SSTestStringDefaultsView.table_name)).must_equal 'id'
|
378
|
+
_(SSTestStringDefaultsView.columns_hash['id']).must_be :is_identity?
|
374
379
|
end
|
375
380
|
|
376
381
|
it 'find default values' do
|
@@ -419,12 +424,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
419
424
|
|
420
425
|
it 'in_memory_oltp' do
|
421
426
|
if ENV['IN_MEMORY_OLTP'] && connection.supports_in_memory_oltp?
|
422
|
-
SSTMemory.primary_key.must_equal 'id'
|
423
|
-
SSTMemory.columns_hash['id'].must_be :is_identity?
|
427
|
+
_(SSTMemory.primary_key).must_equal 'id'
|
428
|
+
_(SSTMemory.columns_hash['id']).must_be :is_identity?
|
424
429
|
else
|
425
430
|
skip 'supports_in_memory_oltp? => false'
|
426
431
|
end
|
427
432
|
end
|
428
433
|
|
429
434
|
end
|
430
|
-
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'cases/helper_sqlserver'
|
2
|
+
require 'migrations/create_clients_and_change_column_null'
|
3
|
+
|
4
|
+
class ChangeColumnNullTestSqlServer < ActiveRecord::TestCase
|
5
|
+
before do
|
6
|
+
@old_verbose = ActiveRecord::Migration.verbose
|
7
|
+
ActiveRecord::Migration.verbose = false
|
8
|
+
CreateClientsAndChangeColumnNull.new.up
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
CreateClientsAndChangeColumnNull.new.down
|
13
|
+
ActiveRecord::Migration.verbose = @old_verbose
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_column(table, name)
|
17
|
+
table.find { |column| column.name == name }
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:clients_table) { connection.columns('clients') }
|
21
|
+
let(:name_column) { find_column(clients_table, 'name') }
|
22
|
+
let(:code_column) { find_column(clients_table, 'code') }
|
23
|
+
let(:value_column) { find_column(clients_table, 'value') }
|
24
|
+
|
25
|
+
describe '#change_column_null' do
|
26
|
+
it 'does not change the column limit' do
|
27
|
+
_(name_column.limit).must_equal 15
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'does not change the column default' do
|
31
|
+
_(code_column.default).must_equal 'n/a'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'does not change the column precision' do
|
35
|
+
_(value_column.precision).must_equal 32
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'does not change the column scale' do
|
39
|
+
_(value_column.scale).must_equal 8
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/test/cases/coerced_tests.rb
CHANGED
@@ -31,6 +31,10 @@ end
|
|
31
31
|
require 'models/event'
|
32
32
|
module ActiveRecord
|
33
33
|
class AdapterTest < ActiveRecord::TestCase
|
34
|
+
# I really dont think we can support legacy binds.
|
35
|
+
coerce_tests! :test_select_all_with_legacy_binds
|
36
|
+
coerce_tests! :test_insert_update_delete_with_legacy_binds
|
37
|
+
|
34
38
|
# As far as I can tell, SQL Server does not support null bytes in strings.
|
35
39
|
coerce_tests! :test_update_prepared_statement
|
36
40
|
coerce_tests! :test_log_invalid_encoding if defined? JRUBY_VERSION # JRuby just happily converts the encoding
|
@@ -53,14 +57,14 @@ end
|
|
53
57
|
|
54
58
|
require 'models/topic'
|
55
59
|
class AttributeMethodsTest < ActiveRecord::TestCase
|
56
|
-
coerce_tests!
|
60
|
+
coerce_tests! %r{typecast attribute from select to false}
|
57
61
|
def test_typecast_attribute_from_select_to_false_coerced
|
58
62
|
Topic.create(:title => 'Budget')
|
59
63
|
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 2, 1, 0) as is_test").first
|
60
64
|
assert !topic.is_test?
|
61
65
|
end
|
62
66
|
|
63
|
-
coerce_tests!
|
67
|
+
coerce_tests! %r{typecast attribute from select to true}
|
64
68
|
def test_typecast_attribute_from_select_to_true_coerced
|
65
69
|
Topic.create(:title => 'Budget')
|
66
70
|
topic = Topic.all.merge!(:select => "topics.*, IIF (1 = 1, 1, 0) as is_test").first
|
@@ -69,7 +73,11 @@ class AttributeMethodsTest < ActiveRecord::TestCase
|
|
69
73
|
end
|
70
74
|
|
71
75
|
|
72
|
-
|
76
|
+
class NumericDataTest < ActiveRecord::TestCase
|
77
|
+
# We do not have do the DecimalWithoutScale type.
|
78
|
+
coerce_tests! :test_numeric_fields
|
79
|
+
coerce_tests! :test_numeric_fields_with_scale
|
80
|
+
end
|
73
81
|
|
74
82
|
class BasicsTest < ActiveRecord::TestCase
|
75
83
|
coerce_tests! :test_column_names_are_escaped
|
@@ -78,16 +86,44 @@ class BasicsTest < ActiveRecord::TestCase
|
|
78
86
|
assert_equal '[t]]]', conn.quote_column_name('t]')
|
79
87
|
end
|
80
88
|
|
81
|
-
# We do not have do the DecimalWithoutScale type.
|
82
|
-
coerce_tests! :test_numeric_fields
|
83
|
-
coerce_tests! :test_numeric_fields_with_scale
|
84
|
-
|
85
89
|
# Just like PostgreSQLAdapter does.
|
86
90
|
coerce_tests! :test_respect_internal_encoding
|
87
91
|
|
88
92
|
# Caused in Rails v4.2.5 by adding `firm_id` column in this http://git.io/vBfMs
|
89
93
|
# commit. Trust Rails has this covered.
|
90
94
|
coerce_tests! :test_find_keeps_multiple_group_values
|
95
|
+
|
96
|
+
def test_update_date_time_attributes
|
97
|
+
Time.use_zone("Eastern Time (US & Canada)") do
|
98
|
+
topic = Topic.find(1)
|
99
|
+
time = Time.zone.parse("2017-07-17 10:56")
|
100
|
+
topic.update_attributes!(written_on: time)
|
101
|
+
assert_equal(time, topic.written_on)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_update_date_time_attributes_with_default_timezone_local
|
106
|
+
with_env_tz 'America/New_York' do
|
107
|
+
with_timezone_config default: :local do
|
108
|
+
Time.use_zone("Eastern Time (US & Canada)") do
|
109
|
+
topic = Topic.find(1)
|
110
|
+
time = Time.zone.parse("2017-07-17 10:56")
|
111
|
+
topic.update_attributes!(written_on: time)
|
112
|
+
assert_equal(time, topic.written_on)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Need to escape `quoted_id` once it contains brackets
|
119
|
+
coerce_tests! %r{column names are quoted when using #from clause and model has ignored columns}
|
120
|
+
test "column names are quoted when using #from clause and model has ignored columns coerced" do
|
121
|
+
refute_empty Developer.ignored_columns
|
122
|
+
query = Developer.from("developers").to_sql
|
123
|
+
quoted_id = "#{Developer.quoted_table_name}.#{Developer.quoted_primary_key}"
|
124
|
+
|
125
|
+
assert_match(/SELECT #{Regexp.escape(quoted_id)}.* FROM developers/, query)
|
126
|
+
end
|
91
127
|
end
|
92
128
|
|
93
129
|
|
@@ -108,17 +144,63 @@ end
|
|
108
144
|
|
109
145
|
|
110
146
|
|
147
|
+
# module ActiveRecord
|
148
|
+
# class BindParameterTest < ActiveRecord::TestCase
|
149
|
+
# # Same as original coerced test except log is found using `EXEC sp_executesql` wrapper.
|
150
|
+
# # coerce_tests! :test_binds_are_logged
|
151
|
+
# # def test_binds_are_logged_coerced
|
152
|
+
# # sub = Arel::Nodes::BindParam.new(1)
|
153
|
+
# # binds = [Relation::QueryAttribute.new("id", 1, Type::Value.new)]
|
154
|
+
# # sql = "select * from topics where id = #{sub.to_sql}"
|
155
|
+
# #
|
156
|
+
# # @connection.exec_query(sql, "SQL", binds)
|
157
|
+
# #
|
158
|
+
# # logged_sql = "EXEC sp_executesql N'#{sql}', N'#{sub.to_sql} int', #{sub.to_sql} = 1"
|
159
|
+
# # message = @subscriber.calls.find { |args| args[4][:sql] == logged_sql }
|
160
|
+
# #
|
161
|
+
# # assert_equal binds, message[4][:binds]
|
162
|
+
# # end
|
163
|
+
# #
|
164
|
+
# # # SQL Server adapter does not use a statement cache as query plans are already reused using `EXEC sp_executesql`.
|
165
|
+
# # coerce_tests! :test_statement_cache
|
166
|
+
# # coerce_tests! :test_statement_cache_with_query_cache
|
167
|
+
# # coerce_tests! :test_statement_cache_with_find_by
|
168
|
+
# # coerce_tests! :test_statement_cache_with_in_clause
|
169
|
+
# # coerce_tests! :test_statement_cache_with_sql_string_literal
|
170
|
+
# end
|
171
|
+
# end
|
172
|
+
|
173
|
+
|
111
174
|
module ActiveRecord
|
112
|
-
class
|
113
|
-
#
|
114
|
-
coerce_tests! :
|
175
|
+
class InstrumentationTest < ActiveRecord::TestCase
|
176
|
+
# This fails randomly due to schema cache being lost?
|
177
|
+
coerce_tests! :test_payload_name_on_load
|
178
|
+
def test_payload_name_on_load_coerced
|
179
|
+
Book.create(name: "test book")
|
180
|
+
Book.first
|
181
|
+
subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |*args|
|
182
|
+
event = ActiveSupport::Notifications::Event.new(*args)
|
183
|
+
if event.payload[:sql].match "SELECT"
|
184
|
+
assert_equal "Book Load", event.payload[:name]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
Book.first
|
188
|
+
ensure
|
189
|
+
ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
|
190
|
+
end
|
115
191
|
end
|
116
192
|
end
|
117
193
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
194
|
class CalculationsTest < ActiveRecord::TestCase
|
195
|
+
# This fails randomly due to schema cache being lost?
|
196
|
+
coerce_tests! :test_offset_is_kept
|
197
|
+
def test_offset_is_kept_coerced
|
198
|
+
Account.first
|
199
|
+
queries = assert_sql { Account.offset(1).count }
|
200
|
+
assert_equal 1, queries.length
|
201
|
+
assert_match(/OFFSET/, queries.first)
|
202
|
+
end
|
203
|
+
|
122
204
|
# Are decimal, not integer.
|
123
205
|
coerce_tests! :test_should_return_decimal_average_of_integer_field
|
124
206
|
def test_should_return_decimal_average_of_integer_field_coerced
|
@@ -130,28 +212,36 @@ class CalculationsTest < ActiveRecord::TestCase
|
|
130
212
|
def test_limit_is_kept_coerced
|
131
213
|
queries = capture_sql_ss { Account.limit(1).count }
|
132
214
|
assert_equal 1, queries.length
|
133
|
-
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1}
|
215
|
+
_(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.*@0 = 1}
|
134
216
|
end unless defined? JRUBY_VERSION
|
135
217
|
|
136
218
|
def test_limit_is_kept_coerced
|
137
219
|
queries = capture_sql_ss { Account.limit(1).count }
|
138
220
|
assert_equal 1, queries.length
|
139
|
-
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY}
|
221
|
+
_(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET 0 ROWS FETCH NEXT \? ROWS ONLY}
|
140
222
|
end if defined? JRUBY_VERSION
|
141
223
|
|
142
224
|
coerce_tests! :test_limit_with_offset_is_kept
|
143
225
|
def test_limit_with_offset_is_kept_coerced
|
144
226
|
queries = capture_sql_ss { Account.limit(1).offset(1).count }
|
145
227
|
assert_equal 1, queries.length
|
146
|
-
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1}
|
228
|
+
_(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY.*@0 = 1, @1 = 1}
|
147
229
|
end unless defined? JRUBY_VERSION
|
148
230
|
|
149
231
|
def test_limit_with_offset_is_kept_coerced
|
150
232
|
queries = capture_sql_ss { Account.limit(1).offset(1).count }
|
151
233
|
assert_equal 1, queries.length
|
152
|
-
queries.first.must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET \? ROWS FETCH NEXT \? ROWS ONLY}
|
234
|
+
_(queries.first).must_match %r{ORDER BY \[accounts\]\.\[id\] ASC OFFSET \? ROWS FETCH NEXT \? ROWS ONLY}
|
153
235
|
end if defined? JRUBY_VERSION
|
154
236
|
|
237
|
+
# SQL Server needs an alias for the calculated column
|
238
|
+
coerce_tests! :test_distinct_count_all_with_custom_select_and_order
|
239
|
+
def test_distinct_count_all_with_custom_select_and_order_coerced
|
240
|
+
accounts = Account.distinct.select("credit_limit % 10 AS the_limit").order(Arel.sql("credit_limit % 10"))
|
241
|
+
assert_queries(1) { assert_equal 3, accounts.count(:all) }
|
242
|
+
assert_queries(1) { assert_equal 3, accounts.load.size }
|
243
|
+
end
|
244
|
+
|
155
245
|
# Leave it up to users to format selects/functions so HAVING works correctly.
|
156
246
|
coerce_tests! :test_having_with_strong_parameters
|
157
247
|
end
|
@@ -165,6 +255,7 @@ module ActiveRecord
|
|
165
255
|
coerce_tests! :test_create_table_with_bigint,
|
166
256
|
:test_create_table_with_defaults
|
167
257
|
end
|
258
|
+
|
168
259
|
class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase
|
169
260
|
# In SQL Server you have to delete the tables yourself in the right order.
|
170
261
|
coerce_tests! :test_create_table_with_force_cascade_drops_dependent_objects
|
@@ -174,6 +265,29 @@ end
|
|
174
265
|
|
175
266
|
|
176
267
|
|
268
|
+
module ActiveRecord
|
269
|
+
module ConnectionAdapters
|
270
|
+
class QuoteARBaseTest < ActiveRecord::TestCase
|
271
|
+
|
272
|
+
# Use our date format.
|
273
|
+
coerce_tests! :test_quote_ar_object
|
274
|
+
def test_quote_ar_object_coerced
|
275
|
+
value = DatetimePrimaryKey.new(id: @time)
|
276
|
+
assert_equal "'02-14-2017 12:34:56.789'", @connection.quote(value)
|
277
|
+
end
|
278
|
+
|
279
|
+
# Use our date format.
|
280
|
+
coerce_tests! :test_type_cast_ar_object
|
281
|
+
def test_type_cast_ar_object_coerced
|
282
|
+
value = DatetimePrimaryKey.new(id: @time)
|
283
|
+
assert_equal "02-14-2017 12:34:56.789", @connection.type_cast(value)
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
|
177
291
|
|
178
292
|
module ActiveRecord
|
179
293
|
class Migration
|
@@ -183,7 +297,7 @@ module ActiveRecord
|
|
183
297
|
def test_add_column_without_limit_coerced
|
184
298
|
add_column :test_models, :description, :string, limit: nil
|
185
299
|
TestModel.reset_column_information
|
186
|
-
TestModel.columns_hash["description"].limit.must_equal 4000
|
300
|
+
_(TestModel.columns_hash["description"].limit).must_equal 4000
|
187
301
|
end
|
188
302
|
end
|
189
303
|
end
|
@@ -269,7 +383,7 @@ class MigrationTest < ActiveRecord::TestCase
|
|
269
383
|
end
|
270
384
|
|
271
385
|
# For some reason our tests set Rails.@_env which breaks test env switching.
|
272
|
-
coerce_tests! :
|
386
|
+
coerce_tests! :test_internal_metadata_stores_environment_when_other_data_exists
|
273
387
|
coerce_tests! :test_internal_metadata_stores_environment
|
274
388
|
end
|
275
389
|
|
@@ -295,6 +409,7 @@ module ActiveRecord
|
|
295
409
|
# a value of 'default_env' will still show tests failing. Just ignoring all
|
296
410
|
# of them since we have no monkey in this circus.
|
297
411
|
MergeAndResolveDefaultUrlConfigTest.coerce_all_tests! if defined?(MergeAndResolveDefaultUrlConfigTest)
|
412
|
+
ConnectionHandlerTest.coerce_all_tests! if defined?(ConnectionHandlerTest)
|
298
413
|
end
|
299
414
|
end
|
300
415
|
|
@@ -302,6 +417,10 @@ end
|
|
302
417
|
|
303
418
|
|
304
419
|
module ActiveRecord
|
420
|
+
class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
|
421
|
+
# Skip this test with /tmp/my_schema_cache.yml path on Windows.
|
422
|
+
coerce_tests! :test_dump_schema_cache if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
423
|
+
end
|
305
424
|
class DatabaseTasksCreateAllTest < ActiveRecord::TestCase
|
306
425
|
# We extend `local_database?` so that common VM IPs can be used.
|
307
426
|
coerce_tests! :test_ignores_remote_databases, :test_warning_for_remote_databases
|
@@ -395,12 +514,6 @@ class FinderTest < ActiveRecord::TestCase
|
|
395
514
|
end
|
396
515
|
end if defined? JRUBY_VERSION
|
397
516
|
|
398
|
-
coerce_tests! :test_string_sanitation
|
399
|
-
def test_string_sanitation_coerced
|
400
|
-
assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
|
401
|
-
assert_equal "N'something; select table'", ActiveRecord::Base.sanitize("something; select table")
|
402
|
-
end
|
403
|
-
|
404
517
|
coerce_tests! :test_take_and_first_and_last_with_integer_should_use_sql_limit
|
405
518
|
def test_take_and_first_and_last_with_integer_should_use_sql_limit_coerced
|
406
519
|
assert_sql(/OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY.* @0 = 3/) { Topic.take(3).entries }
|
@@ -485,7 +598,7 @@ class InheritanceTest < ActiveRecord::TestCase
|
|
485
598
|
coerce_tests! :test_eager_load_belongs_to_primary_key_quoting
|
486
599
|
def test_eager_load_belongs_to_primary_key_quoting_coerced
|
487
600
|
con = Account.connection
|
488
|
-
assert_sql(/\[companies\]\.\[id\] =
|
601
|
+
assert_sql(/\[companies\]\.\[id\] = \?/) do
|
489
602
|
Account.all.merge!(:includes => :firm).find(1)
|
490
603
|
end
|
491
604
|
end
|
@@ -538,6 +651,7 @@ end
|
|
538
651
|
|
539
652
|
|
540
653
|
|
654
|
+
require 'models/parrot'
|
541
655
|
require 'models/topic'
|
542
656
|
class PersistenceTest < ActiveRecord::TestCase
|
543
657
|
# We can not UPDATE identity columns.
|
@@ -547,14 +661,14 @@ class PersistenceTest < ActiveRecord::TestCase
|
|
547
661
|
coerce_tests! :test_update_all_doesnt_ignore_order
|
548
662
|
def test_update_all_doesnt_ignore_order_coerced
|
549
663
|
david, mary = authors(:david), authors(:mary)
|
550
|
-
david.id.must_equal 1
|
551
|
-
mary.id.must_equal 2
|
552
|
-
david.name.wont_equal mary.name
|
664
|
+
_(david.id).must_equal 1
|
665
|
+
_(mary.id).must_equal 2
|
666
|
+
_(david.name).wont_equal mary.name
|
553
667
|
assert_sql(/UPDATE.*\(SELECT \[authors\].\[id\] FROM \[authors\].*ORDER BY \[authors\].\[id\]/i) do
|
554
668
|
Author.where('[id] > 1').order(:id).update_all(name: 'Test')
|
555
669
|
end
|
556
|
-
david.reload.name.must_equal 'David'
|
557
|
-
mary.reload.name.must_equal 'Test'
|
670
|
+
_(david.reload.name).must_equal 'David'
|
671
|
+
_(mary.reload.name).must_equal 'Test'
|
558
672
|
end
|
559
673
|
|
560
674
|
# We can not UPDATE identity columns.
|
@@ -580,6 +694,19 @@ class PersistenceTest < ActiveRecord::TestCase
|
|
580
694
|
# assert_nothing_raised { topic.reload }
|
581
695
|
# assert_equal topic.title, Topic.find(1234).title
|
582
696
|
end
|
697
|
+
|
698
|
+
coerce_tests! :test_delete_new_record
|
699
|
+
def test_delete_new_record_coerced
|
700
|
+
client = Client.new(name: "37signals")
|
701
|
+
client.delete
|
702
|
+
assert_predicate client, :frozen?
|
703
|
+
|
704
|
+
assert_not client.save
|
705
|
+
assert_raise(ActiveRecord::RecordNotSaved) { client.save! }
|
706
|
+
|
707
|
+
assert_predicate client, :frozen?
|
708
|
+
assert_raise(FrozenError) { client.name = "something else" } # For some reason we get a FrozenError instead of a RuntimeError here
|
709
|
+
end
|
583
710
|
end
|
584
711
|
|
585
712
|
|
@@ -603,10 +730,19 @@ end
|
|
603
730
|
|
604
731
|
|
605
732
|
|
733
|
+
class PrimaryKeysTest < ActiveRecord::TestCase
|
734
|
+
# Gonna trust Rails core for this. We end up with 2 querys vs 3 asserted
|
735
|
+
# but as far as I can tell, this is only one for us anyway.
|
736
|
+
coerce_tests! :test_create_without_primary_key_no_extra_query
|
737
|
+
end
|
738
|
+
|
739
|
+
|
740
|
+
|
741
|
+
|
606
742
|
require 'models/task'
|
607
743
|
class QueryCacheTest < ActiveRecord::TestCase
|
608
|
-
coerce_tests! :
|
609
|
-
def
|
744
|
+
coerce_tests! :test_cache_does_not_wrap_results_in_arrays
|
745
|
+
def test_cache_does_not_wrap_results_in_arrays_coerced
|
610
746
|
Task.cache do
|
611
747
|
assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
|
612
748
|
end
|
@@ -621,16 +757,16 @@ class RelationTest < ActiveRecord::TestCase
|
|
621
757
|
# Use LEN vs LENGTH function.
|
622
758
|
coerce_tests! :test_reverse_order_with_function
|
623
759
|
def test_reverse_order_with_function_coerced
|
624
|
-
topics = Topic.order("LEN(title)").reverse_order
|
760
|
+
topics = Topic.order(Arel.sql("LEN(title)")).reverse_order
|
625
761
|
assert_equal topics(:second).title, topics.first.title
|
626
762
|
end
|
627
763
|
|
628
764
|
# Use LEN vs LENGTH function.
|
629
765
|
coerce_tests! :test_reverse_order_with_function_other_predicates
|
630
766
|
def test_reverse_order_with_function_other_predicates_coerced
|
631
|
-
topics = Topic.order("author_name, LEN(title), id").reverse_order
|
767
|
+
topics = Topic.order(Arel.sql("author_name, LEN(title), id")).reverse_order
|
632
768
|
assert_equal topics(:second).title, topics.first.title
|
633
|
-
topics = Topic.order("LEN(author_name), id, LEN(title)").reverse_order
|
769
|
+
topics = Topic.order(Arel.sql("LEN(author_name), id, LEN(title)")).reverse_order
|
634
770
|
assert_equal topics(:fifth).title, topics.first.title
|
635
771
|
end
|
636
772
|
|
@@ -646,6 +782,60 @@ class RelationTest < ActiveRecord::TestCase
|
|
646
782
|
# Leave it up to users to format selects/functions so HAVING works correctly.
|
647
783
|
coerce_tests! :test_multiple_where_and_having_clauses
|
648
784
|
coerce_tests! :test_having_with_binds_for_both_where_and_having
|
785
|
+
|
786
|
+
# Find any limit via our expression.
|
787
|
+
coerce_tests! %r{relations don't load all records in #inspect}
|
788
|
+
def test_relations_dont_load_all_records_in_inspect_coerced
|
789
|
+
assert_sql(/NEXT \? ROWS ONLY/) do
|
790
|
+
Post.all.inspect
|
791
|
+
end
|
792
|
+
end
|
793
|
+
|
794
|
+
# I wanted to add `.order("author_id")` scope to avoid error: Column "posts.id" is invalid in the ORDER BY
|
795
|
+
# However, this pull request on Rails core drops order on exists relation. https://github.com/rails/rails/pull/28699
|
796
|
+
# so we are skipping all together.
|
797
|
+
coerce_tests! :test_empty_complex_chained_relations
|
798
|
+
|
799
|
+
# Can't apply offset withour ORDER
|
800
|
+
coerce_tests! %r{using a custom table affects the wheres}
|
801
|
+
test 'using a custom table affects the wheres coerced' do
|
802
|
+
post = posts(:welcome)
|
803
|
+
|
804
|
+
assert_equal post, custom_post_relation.where!(title: post.title).order(:id).take
|
805
|
+
end
|
806
|
+
|
807
|
+
# Can't apply offset withour ORDER
|
808
|
+
coerce_tests! %r{using a custom table with joins affects the joins}
|
809
|
+
test 'using a custom table with joins affects the joins coerced' do
|
810
|
+
post = posts(:welcome)
|
811
|
+
|
812
|
+
assert_equal post, custom_post_relation.joins(:author).where!(title: post.title).order(:id).take
|
813
|
+
end
|
814
|
+
|
815
|
+
# Use LEN() vs length() function.
|
816
|
+
coerce_tests! :test_reverse_arel_assoc_order_with_function
|
817
|
+
def test_reverse_arel_assoc_order_with_function_coerced
|
818
|
+
topics = Topic.order(Arel.sql("LEN(title)") => :asc).reverse_order
|
819
|
+
assert_equal topics(:second).title, topics.first.title
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
class ActiveRecord::RelationTest < ActiveRecord::TestCase
|
824
|
+
coerce_tests! :test_relation_merging_with_merged_symbol_joins_is_aliased
|
825
|
+
def test_relation_merging_with_merged_symbol_joins_is_aliased__coerced
|
826
|
+
categorizations_with_authors = Categorization.joins(:author)
|
827
|
+
queries = capture_sql { Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(categorizations_with_authors).to_a }
|
828
|
+
|
829
|
+
nb_inner_join = queries.sum { |sql| sql.scan(/INNER\s+JOIN/i).size }
|
830
|
+
assert_equal 3, nb_inner_join, "Wrong amount of INNER JOIN in query"
|
831
|
+
|
832
|
+
# using `\W` as the column separator
|
833
|
+
query_matches = queries.any? do |sql|
|
834
|
+
%r[INNER\s+JOIN\s+#{Regexp.escape(Author.quoted_table_name)}\s+\Wauthors_categorizations\W]i.match?(sql)
|
835
|
+
end
|
836
|
+
|
837
|
+
assert query_matches, "Should be aliasing the child INNER JOINs in query"
|
838
|
+
end
|
649
839
|
end
|
650
840
|
|
651
841
|
|
@@ -677,9 +867,6 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
677
867
|
assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 38}, output
|
678
868
|
end
|
679
869
|
|
680
|
-
# This accidently returns the wrong number because of our tables too.
|
681
|
-
coerce_tests! :test_types_line_up
|
682
|
-
|
683
870
|
# This is a poorly written test and really does not catch the bottom'ness it is meant too. Ours throw it off.
|
684
871
|
coerce_tests! :test_foreign_keys_are_dumped_at_the_bottom_to_circumvent_dependency_issues
|
685
872
|
|
@@ -803,10 +990,55 @@ class DateTimePrecisionTest < ActiveRecord::TestCase
|
|
803
990
|
end
|
804
991
|
end
|
805
992
|
end
|
993
|
+
|
994
|
+
unless defined? JRUBY_VERSION
|
995
|
+
# datetime is rounded to increments of .000, .003, or .007 seconds
|
996
|
+
coerce_tests! :test_datetime_precision_is_truncated_on_assignment
|
997
|
+
def test_datetime_precision_is_truncated_on_assignment_coerced
|
998
|
+
@connection.create_table(:foos, force: true)
|
999
|
+
@connection.add_column :foos, :created_at, :datetime, precision: 0
|
1000
|
+
@connection.add_column :foos, :updated_at, :datetime, precision: 6
|
1001
|
+
|
1002
|
+
time = ::Time.now.change(nsec: 123456789)
|
1003
|
+
foo = Foo.new(created_at: time, updated_at: time)
|
1004
|
+
|
1005
|
+
assert_equal 0, foo.created_at.nsec
|
1006
|
+
assert_equal 123457000, foo.updated_at.nsec
|
1007
|
+
|
1008
|
+
foo.save!
|
1009
|
+
foo.reload
|
1010
|
+
|
1011
|
+
assert_equal 0, foo.created_at.nsec
|
1012
|
+
assert_equal 123457000, foo.updated_at.nsec
|
1013
|
+
end
|
1014
|
+
end
|
806
1015
|
end
|
807
1016
|
|
808
1017
|
|
809
1018
|
|
1019
|
+
class TimePrecisionTest < ActiveRecord::TestCase
|
1020
|
+
# datetime is rounded to increments of .000, .003, or .007 seconds
|
1021
|
+
coerce_tests! :test_time_precision_is_truncated_on_assignment
|
1022
|
+
def test_time_precision_is_truncated_on_assignment_coerced
|
1023
|
+
@connection.create_table(:foos, force: true)
|
1024
|
+
@connection.add_column :foos, :start, :time, precision: 0
|
1025
|
+
@connection.add_column :foos, :finish, :time, precision: 6
|
1026
|
+
|
1027
|
+
time = ::Time.now.change(nsec: 123456789)
|
1028
|
+
foo = Foo.new(start: time, finish: time)
|
1029
|
+
|
1030
|
+
assert_equal 0, foo.start.nsec
|
1031
|
+
assert_equal 123457000, foo.finish.nsec
|
1032
|
+
|
1033
|
+
foo.save!
|
1034
|
+
foo.reload
|
1035
|
+
|
1036
|
+
assert_equal 0, foo.start.nsec
|
1037
|
+
assert_equal 123457000, foo.finish.nsec
|
1038
|
+
end
|
1039
|
+
end unless defined? JRUBY_VERSION
|
1040
|
+
|
1041
|
+
|
810
1042
|
|
811
1043
|
class DefaultNumbersTest < ActiveRecord::TestCase
|
812
1044
|
# We do better with native types and do not return strings for everything.
|
@@ -843,3 +1075,151 @@ module ActiveRecord
|
|
843
1075
|
#coerce_tests! :test_find_does_not_use_statement_cache_if_table_name_is_changed
|
844
1076
|
end
|
845
1077
|
end
|
1078
|
+
|
1079
|
+
|
1080
|
+
|
1081
|
+
|
1082
|
+
module ActiveRecord
|
1083
|
+
module ConnectionAdapters
|
1084
|
+
class SchemaCacheTest < ActiveRecord::TestCase
|
1085
|
+
private
|
1086
|
+
# We need to give the full path for this to work.
|
1087
|
+
def schema_dump_path
|
1088
|
+
File.join ARTest::SQLServer.root_activerecord, 'test/assets/schema_dump_5_1.yml'
|
1089
|
+
end
|
1090
|
+
end
|
1091
|
+
end
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
class UnsafeRawSqlTest < ActiveRecord::TestCase
|
1095
|
+
coerce_tests! %r{always allows Arel}
|
1096
|
+
test 'order: always allows Arel' do
|
1097
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(Arel.sql("len(title)")).pluck(:title) }
|
1098
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(Arel.sql("len(title)")).pluck(:title) }
|
1099
|
+
|
1100
|
+
assert_equal ids_depr, ids_disabled
|
1101
|
+
end
|
1102
|
+
|
1103
|
+
test "pluck: always allows Arel" do
|
1104
|
+
values_depr = with_unsafe_raw_sql_deprecated { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
|
1105
|
+
values_disabled = with_unsafe_raw_sql_disabled { Post.includes(:comments).pluck(:title, Arel.sql("len(title)")) }
|
1106
|
+
|
1107
|
+
assert_equal values_depr, values_disabled
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
|
1111
|
+
coerce_tests! %r{order: disallows invalid Array arguments}
|
1112
|
+
test "order: disallows invalid Array arguments" do
|
1113
|
+
with_unsafe_raw_sql_disabled do
|
1114
|
+
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
1115
|
+
Post.order(["author_id", "len(title)"]).pluck(:id)
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
coerce_tests! %r{order: allows valid Array arguments}
|
1121
|
+
test "order: allows valid Array arguments" do
|
1122
|
+
ids_expected = Post.order(Arel.sql("author_id, len(title)")).pluck(:id)
|
1123
|
+
|
1124
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", Arel.sql("len(title)")]).pluck(:id) }
|
1125
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", Arel.sql("len(title)")]).pluck(:id) }
|
1126
|
+
|
1127
|
+
assert_equal ids_expected, ids_depr
|
1128
|
+
assert_equal ids_expected, ids_disabled
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
coerce_tests! %r{order: logs deprecation warning for unrecognized column}
|
1132
|
+
test "order: logs deprecation warning for unrecognized column" do
|
1133
|
+
with_unsafe_raw_sql_deprecated do
|
1134
|
+
assert_deprecated(/Dangerous query method/) do
|
1135
|
+
Post.order("len(title)")
|
1136
|
+
end
|
1137
|
+
end
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
coerce_tests! %r{pluck: disallows invalid column name}
|
1141
|
+
test "pluck: disallows invalid column name" do
|
1142
|
+
with_unsafe_raw_sql_disabled do
|
1143
|
+
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
1144
|
+
Post.pluck("len(title)")
|
1145
|
+
end
|
1146
|
+
end
|
1147
|
+
end
|
1148
|
+
|
1149
|
+
coerce_tests! %r{pluck: disallows invalid column name amongst valid names}
|
1150
|
+
test "pluck: disallows invalid column name amongst valid names" do
|
1151
|
+
with_unsafe_raw_sql_disabled do
|
1152
|
+
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
1153
|
+
Post.pluck(:title, "len(title)")
|
1154
|
+
end
|
1155
|
+
end
|
1156
|
+
end
|
1157
|
+
|
1158
|
+
coerce_tests! %r{pluck: disallows invalid column names with includes}
|
1159
|
+
test "pluck: disallows invalid column names with includes" do
|
1160
|
+
with_unsafe_raw_sql_disabled do
|
1161
|
+
assert_raises(ActiveRecord::UnknownAttributeReference) do
|
1162
|
+
Post.includes(:comments).pluck(:title, "len(title)")
|
1163
|
+
end
|
1164
|
+
end
|
1165
|
+
end
|
1166
|
+
|
1167
|
+
coerce_tests! %r{pluck: logs deprecation warning}
|
1168
|
+
test "pluck: logs deprecation warning" do
|
1169
|
+
with_unsafe_raw_sql_deprecated do
|
1170
|
+
assert_deprecated(/Dangerous query method/) do
|
1171
|
+
Post.includes(:comments).pluck(:title, "len(title)")
|
1172
|
+
end
|
1173
|
+
end
|
1174
|
+
end
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
|
1178
|
+
class ReservedWordTest < ActiveRecord::TestCase
|
1179
|
+
coerce_tests! :test_change_columns
|
1180
|
+
def test_change_columns_coerced
|
1181
|
+
assert_nothing_raised { @connection.change_column_default(:group, :order, "whatever") }
|
1182
|
+
assert_nothing_raised { @connection.change_column("group", "order", :text) }
|
1183
|
+
assert_nothing_raised { @connection.change_column_null("group", "order", true) }
|
1184
|
+
assert_nothing_raised { @connection.rename_column(:group, :order, :values) }
|
1185
|
+
end
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
|
1189
|
+
|
1190
|
+
class OptimisticLockingTest < ActiveRecord::TestCase
|
1191
|
+
# We do not allow updating identities, but we can test using a non-identity key
|
1192
|
+
coerce_tests! :test_update_with_dirty_primary_key
|
1193
|
+
def test_update_with_dirty_primary_key_coerced
|
1194
|
+
assert_raises(ActiveRecord::RecordNotUnique) do
|
1195
|
+
record = StringKeyObject.find('record1')
|
1196
|
+
record.id = 'record2'
|
1197
|
+
record.save!
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
record = StringKeyObject.find('record1')
|
1201
|
+
record.id = 'record42'
|
1202
|
+
record.save!
|
1203
|
+
|
1204
|
+
assert StringKeyObject.find('record42')
|
1205
|
+
assert_raises(ActiveRecord::RecordNotFound) do
|
1206
|
+
StringKeyObject.find('record1')
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
|
1212
|
+
|
1213
|
+
class RelationMergingTest < ActiveRecord::TestCase
|
1214
|
+
coerce_tests! :test_merging_with_order_with_binds
|
1215
|
+
def test_merging_with_order_with_binds_coerced
|
1216
|
+
relation = Post.all.merge(Post.order([Arel.sql("title LIKE ?"), "%suffix"]))
|
1217
|
+
assert_equal ["title LIKE N'%suffix'"], relation.order_values
|
1218
|
+
end
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
|
1222
|
+
class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
|
1223
|
+
# Temporarily coerce this test due to https://github.com/rails/rails/issues/34945
|
1224
|
+
coerce_tests! :test_eager_loading_too_may_ids
|
1225
|
+
end
|