activerecord-jdbcsqlserver-adapter 50.0.0 → 52.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/.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
@@ -36,7 +36,7 @@ class ConnectionTestSQLServer < ActiveRecord::TestCase
|
|
36
36
|
describe 'Connection management' do
|
37
37
|
|
38
38
|
it 'set spid on connect' do
|
39
|
-
['Fixnum', 'Integer'].must_include connection.spid.class.name
|
39
|
+
_(['Fixnum', 'Integer']).must_include connection.spid.class.name
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'reset spid on disconnect!' do
|
@@ -46,7 +46,7 @@ class ConnectionTestSQLServer < ActiveRecord::TestCase
|
|
46
46
|
|
47
47
|
it 'reset the connection' do
|
48
48
|
connection.disconnect!
|
49
|
-
connection.raw_connection.must_be_nil
|
49
|
+
_(connection.raw_connection).must_be_nil
|
50
50
|
end unless defined? JRUBY_VERSION
|
51
51
|
|
52
52
|
it 'be able to disconnect and reconnect at will' do
|
@@ -36,11 +36,11 @@ class FetchTestSqlserver < ActiveRecord::TestCase
|
|
36
36
|
|
37
37
|
it 'gauntlet' do
|
38
38
|
Book.where(name:'Name-10').delete_all
|
39
|
-
Book.order(:name).limit(1).offset(1).map(&:name).must_equal ['Name-2']
|
40
|
-
Book.order(:name).limit(2).offset(2).map(&:name).must_equal ['Name-3', 'Name-4']
|
41
|
-
Book.order(:name).limit(2).offset(7).map(&:name).must_equal ['Name-8', 'Name-9']
|
42
|
-
Book.order(:name).limit(3).offset(7).map(&:name).must_equal ['Name-8', 'Name-9']
|
43
|
-
Book.order(:name).limit(3).offset(9).map(&:name).must_equal []
|
39
|
+
_(Book.order(:name).limit(1).offset(1).map(&:name)).must_equal ['Name-2']
|
40
|
+
_(Book.order(:name).limit(2).offset(2).map(&:name)).must_equal ['Name-3', 'Name-4']
|
41
|
+
_(Book.order(:name).limit(2).offset(7).map(&:name)).must_equal ['Name-8', 'Name-9']
|
42
|
+
_(Book.order(:name).limit(3).offset(7).map(&:name)).must_equal ['Name-8', 'Name-9']
|
43
|
+
_(Book.order(:name).limit(3).offset(9).map(&:name)).must_equal []
|
44
44
|
end
|
45
45
|
|
46
46
|
end
|
@@ -2,6 +2,7 @@ require 'support/paths_sqlserver'
|
|
2
2
|
require 'bundler/setup'
|
3
3
|
Bundler.require :default, :development
|
4
4
|
require 'pry'
|
5
|
+
require 'support/core_ext/query_cache'
|
5
6
|
require 'support/minitest_sqlserver'
|
6
7
|
require 'support/test_in_memory_oltp'
|
7
8
|
require 'cases/helper'
|
@@ -9,7 +10,7 @@ require 'support/load_schema_sqlserver'
|
|
9
10
|
require 'support/coerceable_test_sqlserver'
|
10
11
|
require 'support/sql_counter_sqlserver'
|
11
12
|
require 'support/connection_reflection'
|
12
|
-
require 'mocha/
|
13
|
+
require 'mocha/minitest'
|
13
14
|
|
14
15
|
module ActiveRecord
|
15
16
|
class TestCase < ActiveSupport::TestCase
|
@@ -23,9 +24,19 @@ module ActiveRecord
|
|
23
24
|
|
24
25
|
let(:logger) { ActiveRecord::Base.logger }
|
25
26
|
|
27
|
+
setup :ensure_clean_rails_env
|
28
|
+
setup :remove_backtrace_silencers
|
26
29
|
|
27
30
|
private
|
28
31
|
|
32
|
+
def ensure_clean_rails_env
|
33
|
+
Rails.instance_variable_set(:@_env, nil) if defined?(::Rails)
|
34
|
+
end
|
35
|
+
|
36
|
+
def remove_backtrace_silencers
|
37
|
+
Rails.backtrace_cleaner.remove_silencers!
|
38
|
+
end
|
39
|
+
|
29
40
|
def host_windows?
|
30
41
|
RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
|
31
42
|
end
|
@@ -12,20 +12,20 @@ class JsonTestSQLServer < ActiveRecord::TestCase
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'can return and save JSON data' do
|
15
|
-
SSTestDatatypeMigrationJson.find(@o1.id).json_col.must_equal({ 'a' => 'a', 'b' => 'b', 'c' => 'c' })
|
15
|
+
_(SSTestDatatypeMigrationJson.find(@o1.id).json_col).must_equal({ 'a' => 'a', 'b' => 'b', 'c' => 'c' })
|
16
16
|
@o1.json_col = { 'a' => 'a' }
|
17
|
-
@o1.json_col.must_equal({ 'a' => 'a' })
|
17
|
+
_(@o1.json_col).must_equal({ 'a' => 'a' })
|
18
18
|
@o1.save!
|
19
|
-
@o1.reload.json_col.must_equal({ 'a' => 'a' })
|
19
|
+
_(@o1.reload.json_col).must_equal({ 'a' => 'a' })
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'can use ISJSON function' do
|
23
|
-
SSTestDatatypeMigrationJson.where('ISJSON(json_col) > 0').count.must_equal 4
|
24
|
-
SSTestDatatypeMigrationJson.where('ISJSON(json_col) IS NULL').count.must_equal 1
|
23
|
+
_(SSTestDatatypeMigrationJson.where('ISJSON(json_col) > 0').count).must_equal 4
|
24
|
+
_(SSTestDatatypeMigrationJson.where('ISJSON(json_col) IS NULL').count).must_equal 1
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'can use JSON_VALUE function' do
|
28
|
-
SSTestDatatypeMigrationJson.where("JSON_VALUE(json_col, '$.b') = 'b'").count.must_equal 2
|
28
|
+
_(SSTestDatatypeMigrationJson.where("JSON_VALUE(json_col, '$.b') = 'b'").count).must_equal 2
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
@@ -20,12 +20,12 @@ class MigrationTestSQLServer < ActiveRecord::TestCase
|
|
20
20
|
it 'not create a tables if error in migrations' do
|
21
21
|
begin
|
22
22
|
migrations_dir = File.join ARTest::SQLServer.migrations_root, 'transaction_table'
|
23
|
-
quietly { ActiveRecord::
|
23
|
+
quietly { ActiveRecord::MigrationContext.new(migrations_dir).up }
|
24
24
|
rescue Exception => e
|
25
25
|
assert_match %r|this and all later migrations canceled|, e.message
|
26
26
|
end
|
27
|
-
connection.tables.wont_include @trans_test_table1
|
28
|
-
connection.tables.wont_include @trans_test_table2
|
27
|
+
_(connection.tables).wont_include @trans_test_table1
|
28
|
+
_(connection.tables).wont_include @trans_test_table2
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
@@ -41,6 +41,8 @@ class MigrationTestSQLServer < ActiveRecord::TestCase
|
|
41
41
|
lock_version_column = Person.columns_hash['lock_version']
|
42
42
|
assert_equal :string, lock_version_column.type
|
43
43
|
assert lock_version_column.default.nil?
|
44
|
+
assert_nothing_raised { connection.change_column 'people', 'lock_version', :integer }
|
45
|
+
Person.reset_column_information
|
44
46
|
end
|
45
47
|
|
46
48
|
it 'not drop the default contraint if just renaming' do
|
@@ -55,6 +57,14 @@ class MigrationTestSQLServer < ActiveRecord::TestCase
|
|
55
57
|
assert default_after
|
56
58
|
assert_equal default_before['constraint_keys'], default_after['constraint_keys']
|
57
59
|
end
|
60
|
+
|
61
|
+
it 'change limit' do
|
62
|
+
assert_nothing_raised { connection.change_column :people, :lock_version, :integer, limit: 8 }
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'change null and default' do
|
66
|
+
assert_nothing_raised { connection.change_column :people, :first_name, :text, null: true, default: nil }
|
67
|
+
end
|
58
68
|
|
59
69
|
end
|
60
70
|
|
@@ -44,13 +44,13 @@ class OrderTestSQLServer < ActiveRecord::TestCase
|
|
44
44
|
it 'support quoted column' do
|
45
45
|
order = "[title]"
|
46
46
|
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
47
|
-
assert_equal post1, Post.order(order).first
|
47
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'support quoted table and column' do
|
51
51
|
order = "[posts].[title]"
|
52
52
|
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
53
|
-
assert_equal post1, Post.order(order).first
|
53
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'support primary: column, secondary: column' do
|
@@ -73,74 +73,74 @@ class OrderTestSQLServer < ActiveRecord::TestCase
|
|
73
73
|
order = "(CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC, body"
|
74
74
|
post1 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
75
75
|
post2 = Post.create title: 'ZZZ Post', body: 'ZZZ Test cased orders.'
|
76
|
-
assert_equal post1, Post.order(order).first
|
77
|
-
assert_equal post2, Post.order(order).second
|
76
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
77
|
+
assert_equal post2, Post.order(Arel.sql(order)).second
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'support primary: quoted table and column, secondary: case expresion' do
|
81
81
|
order = "[posts].[body] DESC, (CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC"
|
82
82
|
post1 = Post.create title: 'ZZZ Post', body: 'ZZZ Test cased orders.'
|
83
83
|
post2 = Post.create title: 'ZZY Post', body: 'ZZZ Test cased orders.'
|
84
|
-
assert_equal post1, Post.order(order).first
|
85
|
-
assert_equal post2, Post.order(order).second
|
84
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
85
|
+
assert_equal post2, Post.order(Arel.sql(order)).second
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'support inline function' do
|
89
89
|
order = "LEN(title)"
|
90
90
|
post1 = Post.create title: 'A', body: 'AAA Test cased orders.'
|
91
|
-
assert_equal post1, Post.order(order).first
|
91
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'support inline function with parameters' do
|
95
95
|
order = "SUBSTRING(title, 1, 3)"
|
96
96
|
post1 = Post.create title: 'AAA Post', body: 'Test cased orders.'
|
97
|
-
assert_equal post1, Post.order(order).first
|
97
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
98
98
|
end
|
99
99
|
|
100
100
|
it 'support inline function with parameters DESC' do
|
101
101
|
order = "SUBSTRING(title, 1, 3) DESC"
|
102
102
|
post1 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
103
|
-
assert_equal post1, Post.order(order).first
|
103
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
104
104
|
end
|
105
105
|
|
106
106
|
it 'support primary: inline function, secondary: column' do
|
107
107
|
order = "LEN(title), body"
|
108
108
|
post1 = Post.create title: 'A', body: 'AAA Test cased orders.'
|
109
109
|
post2 = Post.create title: 'A', body: 'Test cased orders.'
|
110
|
-
assert_equal post1, Post.order(order).first
|
111
|
-
assert_equal post2, Post.order(order).second
|
110
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
111
|
+
assert_equal post2, Post.order(Arel.sql(order)).second
|
112
112
|
end
|
113
113
|
|
114
114
|
it 'support primary: inline function, secondary: column with direction' do
|
115
115
|
order = "LEN(title) ASC, body DESC"
|
116
116
|
post1 = Post.create title: 'A', body: 'ZZZ Test cased orders.'
|
117
117
|
post2 = Post.create title: 'A', body: 'Test cased orders.'
|
118
|
-
assert_equal post1, Post.order(order).first
|
119
|
-
assert_equal post2, Post.order(order).second
|
118
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
119
|
+
assert_equal post2, Post.order(Arel.sql(order)).second
|
120
120
|
end
|
121
121
|
|
122
122
|
it 'support primary: column, secondary: inline function' do
|
123
123
|
order = "body DESC, LEN(title)"
|
124
124
|
post1 = Post.create title: 'Post', body: 'ZZZ Test cased orders.'
|
125
125
|
post2 = Post.create title: 'Longer Post', body: 'ZZZ Test cased orders.'
|
126
|
-
assert_equal post1, Post.order(order).first
|
127
|
-
assert_equal post2, Post.order(order).second
|
126
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
127
|
+
assert_equal post2, Post.order(Arel.sql(order)).second
|
128
128
|
end
|
129
129
|
|
130
130
|
it 'support primary: case expression, secondary: inline function' do
|
131
131
|
order = "CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC, LEN(body) ASC"
|
132
132
|
post1 = Post.create title: 'ZZZ Post', body: 'Z'
|
133
133
|
post2 = Post.create title: 'ZZZ Post', body: 'Test cased orders.'
|
134
|
-
assert_equal post1, Post.order(order).first
|
135
|
-
assert_equal post2, Post.order(order).second
|
134
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
135
|
+
assert_equal post2, Post.order(Arel.sql(order)).second
|
136
136
|
end
|
137
137
|
|
138
138
|
it 'support primary: inline function, secondary: case expression' do
|
139
139
|
order = "LEN(body), CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC"
|
140
140
|
post1 = Post.create title: 'ZZZ Post', body: 'Z'
|
141
141
|
post2 = Post.create title: 'Post', body: 'Z'
|
142
|
-
assert_equal post1, Post.order(order).first
|
143
|
-
assert_equal post2, Post.order(order).second
|
142
|
+
assert_equal post1, Post.order(Arel.sql(order)).first
|
143
|
+
assert_equal post2, Post.order(Arel.sql(order)).second
|
144
144
|
end
|
145
145
|
|
146
146
|
|
@@ -13,7 +13,7 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
13
13
|
|
14
14
|
it 'uses with updlock by default' do
|
15
15
|
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\)| do
|
16
|
-
Person.lock(true).to_a.must_equal Person.all.to_a
|
16
|
+
_(Person.lock(true).to_a).must_equal Person.all.to_a
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -22,7 +22,7 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
22
22
|
it 'lock with simple find' do
|
23
23
|
assert_nothing_raised do
|
24
24
|
Person.transaction do
|
25
|
-
Person.lock(true).find(1).must_equal Person.find(1)
|
25
|
+
_(Person.lock(true).find(1)).must_equal Person.find(1)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -31,7 +31,7 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
31
31
|
assert_nothing_raised do
|
32
32
|
Person.transaction do
|
33
33
|
Person.lock(true).scoping do
|
34
|
-
Person.find(1).must_equal Person.find(1)
|
34
|
+
_(Person.find(1)).must_equal Person.find(1)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -41,18 +41,7 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
41
41
|
assert_nothing_raised do
|
42
42
|
Person.transaction do
|
43
43
|
person = Person.lock(true).includes(:readers).find(1)
|
44
|
-
person.must_equal Person.find(1)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'reload with lock when #lock! called' do
|
50
|
-
assert_nothing_raised do
|
51
|
-
Person.transaction do
|
52
|
-
person = Person.find 1
|
53
|
-
old, person.first_name = person.first_name, 'fooman'
|
54
|
-
person.lock!
|
55
|
-
assert_equal old, person.first_name
|
44
|
+
_(person).must_equal Person.find(1)
|
56
45
|
end
|
57
46
|
end
|
58
47
|
end
|
@@ -63,6 +52,34 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
63
52
|
end
|
64
53
|
end
|
65
54
|
|
55
|
+
describe 'joining tables' do
|
56
|
+
|
57
|
+
it 'joined tables use updlock by default' do
|
58
|
+
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\) INNER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
|
59
|
+
Person.lock(true).joins(:readers).load
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'joined tables can use custom lock directive' do
|
64
|
+
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(NOLOCK\) INNER JOIN \[readers\] WITH\(NOLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
|
65
|
+
Person.lock('WITH(NOLOCK)').joins(:readers).load
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'left joined tables use updlock by default' do
|
70
|
+
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\) LEFT OUTER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
|
71
|
+
Person.lock(true).left_joins(:readers).load
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'left joined tables can use custom lock directive' do
|
76
|
+
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(NOLOCK\) LEFT OUTER JOIN \[readers\] WITH\(NOLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
|
77
|
+
Person.lock('WITH(NOLOCK)').left_joins(:readers).load
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
66
83
|
end
|
67
84
|
|
68
85
|
describe 'For paginated finds' do
|
@@ -81,11 +98,11 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
81
98
|
loader_sql = /SELECT.*FROM \[people\] WITH\(UPDLOCK\).*WHERE \[people\]\.\[id\] IN/
|
82
99
|
assert_sql(eager_ids_sql, loader_sql) do
|
83
100
|
people = Person.lock(true).limit(5).offset(10).includes(:readers).references(:readers).to_a
|
84
|
-
people[0].first_name.must_equal 'Thing_10'
|
85
|
-
people[1].first_name.must_equal 'Thing_11'
|
86
|
-
people[2].first_name.must_equal 'Thing_12'
|
87
|
-
people[3].first_name.must_equal 'Thing_13'
|
88
|
-
people[4].first_name.must_equal 'Thing_14'
|
101
|
+
_(people[0].first_name).must_equal 'Thing_10'
|
102
|
+
_(people[1].first_name).must_equal 'Thing_11'
|
103
|
+
_(people[2].first_name).must_equal 'Thing_12'
|
104
|
+
_(people[3].first_name).must_equal 'Thing_13'
|
105
|
+
_(people[4].first_name).must_equal 'Thing_14'
|
89
106
|
end
|
90
107
|
end
|
91
108
|
|
@@ -43,23 +43,23 @@ class SQLServerRakeCreateTest < SQLServerRakeTest
|
|
43
43
|
|
44
44
|
it 'establishes connection to database after create ' do
|
45
45
|
quietly { db_tasks.create configuration }
|
46
|
-
connection.current_database.must_equal(new_database)
|
46
|
+
_(connection.current_database).must_equal(new_database)
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'creates database with default collation' do
|
50
50
|
quietly { db_tasks.create configuration }
|
51
|
-
connection.collation.must_equal 'SQL_Latin1_General_CP1_CI_AS'
|
51
|
+
_(connection.collation).must_equal 'SQL_Latin1_General_CP1_CI_AS'
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'creates database with given collation' do
|
55
55
|
quietly { db_tasks.create configuration.merge('collation' => 'Latin1_General_CI_AS') }
|
56
|
-
connection.collation.must_equal 'Latin1_General_CI_AS'
|
56
|
+
_(connection.collation).must_equal 'Latin1_General_CI_AS'
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'prints error message when database exists' do
|
60
60
|
quietly { db_tasks.create configuration }
|
61
61
|
message = capture(:stderr) { db_tasks.create configuration }
|
62
|
-
message.must_match %r{activerecord_unittest_tasks.*already exists}
|
62
|
+
_(message).must_match %r{activerecord_unittest_tasks.*already exists}
|
63
63
|
end
|
64
64
|
|
65
65
|
end
|
@@ -73,12 +73,12 @@ class SQLServerRakeDropTest < SQLServerRakeTest
|
|
73
73
|
db_tasks.create configuration
|
74
74
|
db_tasks.drop configuration
|
75
75
|
end
|
76
|
-
connection.current_database.must_equal 'master'
|
76
|
+
_(connection.current_database).must_equal 'master'
|
77
77
|
end
|
78
78
|
|
79
79
|
it 'prints error message when database does not exist' do
|
80
80
|
message = capture(:stderr) { db_tasks.drop configuration.merge('database' => 'doesnotexist') }
|
81
|
-
message.must_match %r{'doesnotexist' does not exist}
|
81
|
+
_(message).must_match %r{'doesnotexist' does not exist}
|
82
82
|
end
|
83
83
|
|
84
84
|
end
|
@@ -94,11 +94,11 @@ class SQLServerRakePurgeTest < SQLServerRakeTest
|
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'clears active connections, drops database, and recreates with established connection' do
|
97
|
-
connection.current_database.must_equal(new_database)
|
98
|
-
connection.tables.must_include 'users'
|
97
|
+
_(connection.current_database).must_equal(new_database)
|
98
|
+
_(connection.tables).must_include 'users'
|
99
99
|
quietly { db_tasks.purge(configuration) }
|
100
|
-
connection.current_database.must_equal(new_database)
|
101
|
-
connection.tables.wont_include 'users'
|
100
|
+
_(connection.current_database).must_equal(new_database)
|
101
|
+
_(connection.tables).wont_include 'users'
|
102
102
|
end
|
103
103
|
|
104
104
|
end
|
@@ -110,7 +110,7 @@ class SQLServerRakeCharsetTest < SQLServerRakeTest
|
|
110
110
|
end
|
111
111
|
|
112
112
|
it 'retrieves charset' do
|
113
|
-
db_tasks.charset(configuration).must_equal 'iso_1'
|
113
|
+
_(db_tasks.charset(configuration)).must_equal 'iso_1'
|
114
114
|
end
|
115
115
|
|
116
116
|
end
|
@@ -122,7 +122,7 @@ class SQLServerRakeCollationTest < SQLServerRakeTest
|
|
122
122
|
end
|
123
123
|
|
124
124
|
it 'retrieves collation' do
|
125
|
-
db_tasks.collation(configuration).must_equal 'SQL_Latin1_General_CP1_CI_AS'
|
125
|
+
_(db_tasks.collation(configuration)).must_equal 'SQL_Latin1_General_CP1_CI_AS'
|
126
126
|
end
|
127
127
|
|
128
128
|
end
|
@@ -149,21 +149,21 @@ class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
|
|
149
149
|
it 'dumps structure and accounts for defncopy oddities' do
|
150
150
|
skip 'debug defncopy on windows later' if host_windows?
|
151
151
|
quietly { db_tasks.structure_dump configuration, filename }
|
152
|
-
filedata.wont_match %r{\AUSE.*\z}
|
153
|
-
filedata.wont_match %r{\AGO.*\z}
|
154
|
-
filedata.must_match %r{email\s+nvarchar\(4000\)}
|
155
|
-
filedata.must_match %r{background1\s+nvarchar\(max\)}
|
156
|
-
filedata.must_match %r{background2\s+text\s+}
|
152
|
+
_(filedata).wont_match %r{\AUSE.*\z}
|
153
|
+
_(filedata).wont_match %r{\AGO.*\z}
|
154
|
+
_(filedata).must_match %r{email\s+nvarchar\(4000\)}
|
155
|
+
_(filedata).must_match %r{background1\s+nvarchar\(max\)}
|
156
|
+
_(filedata).must_match %r{background2\s+text\s+}
|
157
157
|
end
|
158
158
|
|
159
159
|
it 'can load dumped structure' do
|
160
160
|
skip 'debug defncopy on windows later' if host_windows?
|
161
161
|
quietly { db_tasks.structure_dump configuration, filename }
|
162
|
-
filedata.must_match %r{CREATE TABLE dbo\.users}
|
162
|
+
_(filedata).must_match %r{CREATE TABLE dbo\.users}
|
163
163
|
db_tasks.purge(configuration)
|
164
|
-
connection.tables.wont_include 'users'
|
164
|
+
_(connection.tables).wont_include 'users'
|
165
165
|
db_tasks.load_schema configuration, :sql, filename
|
166
|
-
connection.tables.must_include 'users'
|
166
|
+
_(connection.tables).must_include 'users'
|
167
167
|
end
|
168
168
|
|
169
169
|
end
|
@@ -34,21 +34,22 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
34
34
|
if connection_dblib_73?
|
35
35
|
assert_line :time_7, type: 'time', limit: nil, precision: 7, scale: nil, default: "04:20:00.2883215"
|
36
36
|
assert_line :time_2, type: 'time', limit: nil, precision: 2, scale: nil, default: nil
|
37
|
+
assert_line :time_default, type: 'time', limit: nil, precision: 7, scale: nil, default: "15:03:42.0621978"
|
37
38
|
end
|
38
39
|
# Character Strings
|
39
40
|
assert_line :char_10, type: 'char', limit: 10, precision: nil, scale: nil, default: "1234567890", collation: nil
|
40
41
|
assert_line :varchar_50, type: 'varchar', limit: 50, precision: nil, scale: nil, default: "test varchar_50", collation: nil
|
41
|
-
assert_line :varchar_max, type: 'varchar_max', limit:
|
42
|
-
assert_line :text, type: 'text_basic', limit:
|
42
|
+
assert_line :varchar_max, type: 'varchar_max', limit: nil, precision: nil, scale: nil, default: "test varchar_max", collation: nil
|
43
|
+
assert_line :text, type: 'text_basic', limit: nil, precision: nil, scale: nil, default: "test text", collation: nil
|
43
44
|
# Unicode Character Strings
|
44
45
|
assert_line :nchar_10, type: 'nchar', limit: 10, precision: nil, scale: nil, default: "12345678åå", collation: nil
|
45
46
|
assert_line :nvarchar_50, type: 'string', limit: 50, precision: nil, scale: nil, default: "test nvarchar_50 åå", collation: nil
|
46
|
-
assert_line :nvarchar_max, type: 'text', limit:
|
47
|
-
assert_line :ntext, type: 'ntext', limit:
|
47
|
+
assert_line :nvarchar_max, type: 'text', limit: nil, precision: nil, scale: nil, default: "test nvarchar_max åå", collation: nil
|
48
|
+
assert_line :ntext, type: 'ntext', limit: nil, precision: nil, scale: nil, default: "test ntext åå", collation: nil
|
48
49
|
# Binary Strings
|
49
50
|
assert_line :binary_49, type: 'binary_basic', limit: 49, precision: nil, scale: nil, default: nil
|
50
51
|
assert_line :varbinary_49, type: 'varbinary', limit: 49, precision: nil, scale: nil, default: nil
|
51
|
-
assert_line :varbinary_max, type: 'binary', limit:
|
52
|
+
assert_line :varbinary_max, type: 'binary', limit: nil, precision: nil, scale: nil, default: nil
|
52
53
|
# Other Data Types
|
53
54
|
assert_line :uniqueidentifier, type: 'uuid', limit: nil, precision: nil, scale: nil, default: -> { "newid()" }
|
54
55
|
assert_line :timestamp, type: 'ss_timestamp', limit: nil, precision: nil, scale: nil, default: nil
|
@@ -58,47 +59,47 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
58
59
|
columns = SSTestDatatypeMigration.columns_hash
|
59
60
|
generate_schema_for_table 'sst_datatypes_migration'
|
60
61
|
# Simple Rails conventions
|
61
|
-
columns['integer_col'].sql_type.must_equal 'int(4)'
|
62
|
-
columns['bigint_col'].sql_type.must_equal 'bigint(8)'
|
63
|
-
columns['boolean_col'].sql_type.must_equal 'bit'
|
64
|
-
columns['decimal_col'].sql_type.must_equal 'decimal(18,0)'
|
65
|
-
columns['float_col'].sql_type.must_equal 'float'
|
66
|
-
columns['string_col'].sql_type.must_equal 'nvarchar(4000)'
|
67
|
-
columns['text_col'].sql_type.must_equal 'nvarchar(max)'
|
68
|
-
columns['datetime_col'].sql_type.must_equal 'datetime'
|
69
|
-
columns['timestamp_col'].sql_type.must_equal 'datetime'
|
70
|
-
columns['time_col'].sql_type.must_equal 'time(7)'
|
71
|
-
columns['date_col'].sql_type.must_equal 'date'
|
72
|
-
columns['binary_col'].sql_type.must_equal 'varbinary(max)'
|
62
|
+
_(columns['integer_col'].sql_type).must_equal 'int(4)'
|
63
|
+
_(columns['bigint_col'].sql_type).must_equal 'bigint(8)'
|
64
|
+
_(columns['boolean_col'].sql_type).must_equal 'bit'
|
65
|
+
_(columns['decimal_col'].sql_type).must_equal 'decimal(18,0)'
|
66
|
+
_(columns['float_col'].sql_type).must_equal 'float'
|
67
|
+
_(columns['string_col'].sql_type).must_equal 'nvarchar(4000)'
|
68
|
+
_(columns['text_col'].sql_type).must_equal 'nvarchar(max)'
|
69
|
+
_(columns['datetime_col'].sql_type).must_equal 'datetime'
|
70
|
+
_(columns['timestamp_col'].sql_type).must_equal 'datetime'
|
71
|
+
_(columns['time_col'].sql_type).must_equal 'time(7)'
|
72
|
+
_(columns['date_col'].sql_type).must_equal 'date'
|
73
|
+
_(columns['binary_col'].sql_type).must_equal 'varbinary(max)'
|
73
74
|
assert_line :integer_col, type: 'integer', limit: nil, precision: nil, scale: nil, default: nil
|
74
75
|
assert_line :bigint_col, type: 'bigint', limit: nil, precision: nil, scale: nil, default: nil
|
75
76
|
assert_line :boolean_col, type: 'boolean', limit: nil, precision: nil, scale: nil, default: nil
|
76
77
|
assert_line :decimal_col, type: 'decimal', limit: nil, precision: 18, scale: 0, default: nil
|
77
78
|
assert_line :float_col, type: 'float', limit: nil, precision: nil, scale: nil, default: nil
|
78
79
|
assert_line :string_col, type: 'string', limit: nil, precision: nil, scale: nil, default: nil
|
79
|
-
assert_line :text_col, type: 'text', limit:
|
80
|
+
assert_line :text_col, type: 'text', limit: nil, precision: nil, scale: nil, default: nil
|
80
81
|
assert_line :datetime_col, type: 'datetime', limit: nil, precision: nil, scale: nil, default: nil
|
81
82
|
assert_line :timestamp_col, type: 'datetime', limit: nil, precision: nil, scale: nil, default: nil
|
82
83
|
assert_line :time_col, type: 'time', limit: nil, precision: 7, scale: nil, default: nil
|
83
84
|
assert_line :date_col, type: 'date', limit: nil, precision: nil, scale: nil, default: nil
|
84
|
-
assert_line :binary_col, type: 'binary', limit:
|
85
|
+
assert_line :binary_col, type: 'binary', limit: nil, precision: nil, scale: nil, default: nil
|
85
86
|
# Our type methods.
|
86
|
-
columns['real_col'].sql_type.must_equal 'real'
|
87
|
-
columns['money_col'].sql_type.must_equal 'money'
|
88
|
-
columns['smalldatetime_col'].sql_type.must_equal 'smalldatetime'
|
89
|
-
columns['datetime2_col'].sql_type.must_equal 'datetime2(7)'
|
90
|
-
columns['datetimeoffset'].sql_type.must_equal 'datetimeoffset(7)'
|
91
|
-
columns['smallmoney_col'].sql_type.must_equal 'smallmoney'
|
92
|
-
columns['char_col'].sql_type.must_equal 'char(1)'
|
93
|
-
columns['varchar_col'].sql_type.must_equal 'varchar(8000)'
|
94
|
-
columns['text_basic_col'].sql_type.must_equal 'text'
|
95
|
-
columns['nchar_col'].sql_type.must_equal 'nchar(1)'
|
96
|
-
columns['ntext_col'].sql_type.must_equal 'ntext'
|
97
|
-
columns['binary_basic_col'].sql_type.must_equal 'binary(1)'
|
98
|
-
columns['varbinary_col'].sql_type.must_equal 'varbinary(8000)'
|
99
|
-
columns['uuid_col'].sql_type.must_equal 'uniqueidentifier'
|
100
|
-
columns['sstimestamp_col'].sql_type.must_equal 'timestamp'
|
101
|
-
columns['json_col'].sql_type.must_equal 'nvarchar(max)'
|
87
|
+
_(columns['real_col'].sql_type).must_equal 'real'
|
88
|
+
_(columns['money_col'].sql_type).must_equal 'money'
|
89
|
+
_(columns['smalldatetime_col'].sql_type).must_equal 'smalldatetime'
|
90
|
+
_(columns['datetime2_col'].sql_type).must_equal 'datetime2(7)'
|
91
|
+
_(columns['datetimeoffset'].sql_type).must_equal 'datetimeoffset(7)'
|
92
|
+
_(columns['smallmoney_col'].sql_type).must_equal 'smallmoney'
|
93
|
+
_(columns['char_col'].sql_type).must_equal 'char(1)'
|
94
|
+
_(columns['varchar_col'].sql_type).must_equal 'varchar(8000)'
|
95
|
+
_(columns['text_basic_col'].sql_type).must_equal 'text'
|
96
|
+
_(columns['nchar_col'].sql_type).must_equal 'nchar(1)'
|
97
|
+
_(columns['ntext_col'].sql_type).must_equal 'ntext'
|
98
|
+
_(columns['binary_basic_col'].sql_type).must_equal 'binary(1)'
|
99
|
+
_(columns['varbinary_col'].sql_type).must_equal 'varbinary(8000)'
|
100
|
+
_(columns['uuid_col'].sql_type).must_equal 'uniqueidentifier'
|
101
|
+
_(columns['sstimestamp_col'].sql_type).must_equal 'timestamp'
|
102
|
+
_(columns['json_col'].sql_type).must_equal 'nvarchar(max)'
|
102
103
|
assert_line :real_col, type: 'real', limit: nil, precision: nil, scale: nil, default: nil
|
103
104
|
assert_line :money_col, type: 'money', limit: nil, precision: 19, scale: 4, default: nil
|
104
105
|
assert_line :smalldatetime_col, type: 'smalldatetime', limit: nil, precision: nil, scale: nil, default: nil
|
@@ -107,14 +108,14 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
107
108
|
assert_line :smallmoney_col, type: 'smallmoney', limit: nil, precision: 10, scale: 4, default: nil
|
108
109
|
assert_line :char_col, type: 'char', limit: 1, precision: nil, scale: nil, default: nil
|
109
110
|
assert_line :varchar_col, type: 'varchar', limit: nil, precision: nil, scale: nil, default: nil
|
110
|
-
assert_line :text_basic_col, type: 'text_basic', limit:
|
111
|
+
assert_line :text_basic_col, type: 'text_basic', limit: nil, precision: nil, scale: nil, default: nil
|
111
112
|
assert_line :nchar_col, type: 'nchar', limit: 1, precision: nil, scale: nil, default: nil
|
112
|
-
assert_line :ntext_col, type: 'ntext', limit:
|
113
|
+
assert_line :ntext_col, type: 'ntext', limit: nil, precision: nil, scale: nil, default: nil
|
113
114
|
assert_line :binary_basic_col, type: 'binary_basic', limit: 1, precision: nil, scale: nil, default: nil
|
114
115
|
assert_line :varbinary_col, type: 'varbinary', limit: nil, precision: nil, scale: nil, default: nil
|
115
116
|
assert_line :uuid_col, type: 'uuid', limit: nil, precision: nil, scale: nil, default: nil
|
116
117
|
assert_line :sstimestamp_col, type: 'ss_timestamp', limit: nil, precision: nil, scale: nil, default: nil
|
117
|
-
assert_line :json_col, type: 'text', limit:
|
118
|
+
assert_line :json_col, type: 'text', limit: nil, precision: nil, scale: nil, default: nil
|
118
119
|
end
|
119
120
|
|
120
121
|
# Special Cases
|
@@ -129,7 +130,7 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
129
130
|
|
130
131
|
it 'no id with model driven primary key' do
|
131
132
|
output = generate_schema_for_table 'sst_no_pk_data'
|
132
|
-
output.must_match %r{create_table "sst_no_pk_data".*id:\sfalse.*do}
|
133
|
+
_(output).must_match %r{create_table "sst_no_pk_data".*id:\sfalse.*do}
|
133
134
|
assert_line :name, type: 'string', limit: nil, default: nil, collation: nil
|
134
135
|
end
|
135
136
|
|
@@ -165,15 +166,15 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
165
166
|
expected = options[key]
|
166
167
|
message = "#{key.to_s.titleize} of #{expected.inspect} not found in:\n#{line}"
|
167
168
|
if expected.nil?
|
168
|
-
actual.must_be_nil message
|
169
|
+
_(actual).must_be_nil message
|
169
170
|
elsif expected.is_a?(Array)
|
170
171
|
actual.must_include expected, message
|
171
172
|
elsif expected.is_a?(Float)
|
172
|
-
actual.must_be_close_to expected, 0.001
|
173
|
+
_(actual).must_be_close_to expected, 0.001
|
173
174
|
elsif expected.is_a?(Proc)
|
174
|
-
actual.call.must_equal(expected.call)
|
175
|
+
_(actual.call).must_equal(expected.call)
|
175
176
|
else
|
176
|
-
actual.must_equal expected, message
|
177
|
+
_(actual).must_equal expected, message
|
177
178
|
end
|
178
179
|
end
|
179
180
|
end
|