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
@@ -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
|