activerecord-sqlserver-adapter 5.2.1 → 6.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/.editorconfig +9 -0
- data/.github/issue_template.md +23 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +6 -8
- data/CHANGELOG.md +38 -24
- data/{Dockerfile → Dockerfile.ci} +1 -1
- data/Gemfile +48 -41
- data/Guardfile +9 -8
- data/README.md +9 -30
- data/RUNNING_UNIT_TESTS.md +3 -0
- data/Rakefile +14 -16
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +25 -14
- data/appveyor.yml +24 -17
- data/docker-compose.ci.yml +7 -5
- data/guides/RELEASING.md +11 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +2 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +8 -7
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +36 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +88 -44
- data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +9 -12
- data/lib/active_record/connection_adapters/sqlserver/errors.rb +2 -3
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +46 -8
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +16 -5
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -7
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +190 -164
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_table.rb +4 -2
- data/lib/active_record/connection_adapters/sqlserver/showplan/printer_xml.rb +3 -1
- data/lib/active_record/connection_adapters/sqlserver/showplan.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +43 -44
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +7 -9
- data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/binary.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/boolean.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/char.rb +7 -4
- data/lib/active_record/connection_adapters/sqlserver/type/data.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +8 -8
- data/lib/active_record/connection_adapters/sqlserver/type/datetime2.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/decimal.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/float.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/json.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/type/money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/real.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/small_money.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/smalldatetime.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/time.rb +6 -6
- data/lib/active_record/connection_adapters/sqlserver/type/time_value_fractional.rb +8 -9
- data/lib/active_record/connection_adapters/sqlserver/type/timestamp.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/tiny_integer.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_char.rb +5 -4
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_string.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_text.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/unicode_varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/uuid.rb +4 -3
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varbinary_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type/varchar.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/type/varchar_max.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/type.rb +37 -35
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +10 -11
- data/lib/active_record/connection_adapters/sqlserver/version.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +128 -92
- data/lib/active_record/connection_adapters/sqlserver_column.rb +9 -5
- data/lib/active_record/sqlserver_base.rb +9 -1
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +28 -32
- data/lib/activerecord-sqlserver-adapter.rb +3 -1
- data/lib/arel/visitors/sqlserver.rb +58 -24
- data/lib/arel_sqlserver.rb +4 -2
- data/test/appveyor/dbsetup.ps1 +4 -4
- data/test/cases/adapter_test_sqlserver.rb +214 -171
- data/test/cases/change_column_null_test_sqlserver.rb +14 -12
- data/test/cases/coerced_tests.rb +631 -356
- data/test/cases/column_test_sqlserver.rb +283 -284
- data/test/cases/connection_test_sqlserver.rb +17 -20
- data/test/cases/execute_procedure_test_sqlserver.rb +20 -20
- data/test/cases/fetch_test_sqlserver.rb +16 -22
- data/test/cases/fully_qualified_identifier_test_sqlserver.rb +15 -19
- data/test/cases/helper_sqlserver.rb +15 -15
- data/test/cases/in_clause_test_sqlserver.rb +36 -0
- data/test/cases/index_test_sqlserver.rb +15 -15
- data/test/cases/json_test_sqlserver.rb +25 -25
- data/test/cases/migration_test_sqlserver.rb +25 -29
- data/test/cases/order_test_sqlserver.rb +53 -54
- data/test/cases/pessimistic_locking_test_sqlserver.rb +27 -33
- data/test/cases/rake_test_sqlserver.rb +33 -45
- data/test/cases/schema_dumper_test_sqlserver.rb +107 -109
- data/test/cases/schema_test_sqlserver.rb +20 -26
- data/test/cases/scratchpad_test_sqlserver.rb +4 -4
- data/test/cases/showplan_test_sqlserver.rb +28 -35
- data/test/cases/specific_schema_test_sqlserver.rb +68 -65
- data/test/cases/transaction_test_sqlserver.rb +18 -20
- data/test/cases/trigger_test_sqlserver.rb +14 -13
- data/test/cases/utils_test_sqlserver.rb +70 -70
- data/test/cases/uuid_test_sqlserver.rb +13 -14
- data/test/debug.rb +8 -6
- data/test/migrations/create_clients_and_change_column_null.rb +3 -1
- data/test/migrations/transaction_table/1_table_will_never_be_created.rb +4 -4
- data/test/models/sqlserver/booking.rb +3 -1
- data/test/models/sqlserver/customers_view.rb +3 -1
- data/test/models/sqlserver/datatype.rb +2 -0
- data/test/models/sqlserver/datatype_migration.rb +2 -0
- data/test/models/sqlserver/dollar_table_name.rb +3 -1
- data/test/models/sqlserver/edge_schema.rb +3 -3
- data/test/models/sqlserver/fk_has_fk.rb +3 -1
- data/test/models/sqlserver/fk_has_pk.rb +3 -1
- data/test/models/sqlserver/natural_pk_data.rb +4 -2
- data/test/models/sqlserver/natural_pk_int_data.rb +3 -1
- data/test/models/sqlserver/no_pk_data.rb +3 -1
- data/test/models/sqlserver/object_default.rb +3 -1
- data/test/models/sqlserver/quoted_table.rb +4 -2
- data/test/models/sqlserver/quoted_view_1.rb +3 -1
- data/test/models/sqlserver/quoted_view_2.rb +3 -1
- data/test/models/sqlserver/sst_memory.rb +3 -1
- data/test/models/sqlserver/string_default.rb +3 -1
- data/test/models/sqlserver/string_defaults_big_view.rb +3 -1
- data/test/models/sqlserver/string_defaults_view.rb +3 -1
- data/test/models/sqlserver/tinyint_pk.rb +3 -1
- data/test/models/sqlserver/trigger.rb +4 -2
- data/test/models/sqlserver/trigger_history.rb +3 -1
- data/test/models/sqlserver/upper.rb +3 -1
- data/test/models/sqlserver/uppered.rb +3 -1
- data/test/models/sqlserver/uuid.rb +3 -1
- data/test/schema/sqlserver_specific_schema.rb +22 -22
- data/test/support/coerceable_test_sqlserver.rb +15 -9
- data/test/support/connection_reflection.rb +3 -2
- data/test/support/core_ext/query_cache.rb +4 -1
- data/test/support/load_schema_sqlserver.rb +5 -5
- data/test/support/minitest_sqlserver.rb +3 -1
- data/test/support/paths_sqlserver.rb +11 -11
- data/test/support/rake_helpers.rb +13 -10
- data/test/support/sql_counter_sqlserver.rb +3 -4
- data/test/support/test_in_memory_oltp.rb +9 -7
- metadata +17 -7
|
@@ -1,147 +1,146 @@
|
|
|
1
|
-
|
|
2
|
-
require 'models/post'
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
require "cases/helper_sqlserver"
|
|
4
|
+
require "models/post"
|
|
5
5
|
|
|
6
|
+
class OrderTestSQLServer < ActiveRecord::TestCase
|
|
6
7
|
fixtures :posts
|
|
7
8
|
|
|
8
|
-
it
|
|
9
|
+
it "not mangel complex order clauses" do
|
|
9
10
|
xyz_order = "CASE WHEN [title] LIKE N'XYZ%' THEN 0 ELSE 1 END"
|
|
10
|
-
xyz_post = Post.create title:
|
|
11
|
+
xyz_post = Post.create title: "XYZ Post", body: "Test cased orders."
|
|
11
12
|
assert_equal xyz_post, Post.order(Arel.sql(xyz_order)).first
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
it
|
|
15
|
+
it "support column" do
|
|
15
16
|
order = "title"
|
|
16
|
-
post1 = Post.create title:
|
|
17
|
+
post1 = Post.create title: "AAA Post", body: "Test cased orders."
|
|
17
18
|
assert_equal post1, Post.order(order).first
|
|
18
19
|
end
|
|
19
20
|
|
|
20
|
-
it
|
|
21
|
+
it "support column ASC" do
|
|
21
22
|
order = "title ASC"
|
|
22
|
-
post1 = Post.create title:
|
|
23
|
+
post1 = Post.create title: "AAA Post", body: "Test cased orders."
|
|
23
24
|
assert_equal post1, Post.order(order).first
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
it
|
|
27
|
+
it "support column DESC" do
|
|
27
28
|
order = "title DESC"
|
|
28
|
-
post1 = Post.create title:
|
|
29
|
+
post1 = Post.create title: "ZZZ Post", body: "Test cased orders."
|
|
29
30
|
assert_equal post1, Post.order(order).first
|
|
30
31
|
end
|
|
31
32
|
|
|
32
|
-
it
|
|
33
|
+
it "support column as symbol" do
|
|
33
34
|
order = :title
|
|
34
|
-
post1 = Post.create title:
|
|
35
|
+
post1 = Post.create title: "AAA Post", body: "Test cased orders."
|
|
35
36
|
assert_equal post1, Post.order(order).first
|
|
36
37
|
end
|
|
37
38
|
|
|
38
|
-
it
|
|
39
|
+
it "support table and column" do
|
|
39
40
|
order = "posts.title"
|
|
40
|
-
post1 = Post.create title:
|
|
41
|
+
post1 = Post.create title: "AAA Post", body: "Test cased orders."
|
|
41
42
|
assert_equal post1, Post.order(order).first
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
it
|
|
45
|
+
it "support quoted column" do
|
|
45
46
|
order = "[title]"
|
|
46
|
-
post1 = Post.create title:
|
|
47
|
+
post1 = Post.create title: "AAA Post", body: "Test cased orders."
|
|
47
48
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
48
49
|
end
|
|
49
50
|
|
|
50
|
-
it
|
|
51
|
+
it "support quoted table and column" do
|
|
51
52
|
order = "[posts].[title]"
|
|
52
|
-
post1 = Post.create title:
|
|
53
|
+
post1 = Post.create title: "AAA Post", body: "Test cased orders."
|
|
53
54
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
54
55
|
end
|
|
55
56
|
|
|
56
|
-
it
|
|
57
|
+
it "support primary: column, secondary: column" do
|
|
57
58
|
order = "title DESC, body"
|
|
58
|
-
post1 = Post.create title:
|
|
59
|
-
post2 = Post.create title:
|
|
59
|
+
post1 = Post.create title: "ZZZ Post", body: "Test cased orders."
|
|
60
|
+
post2 = Post.create title: "ZZZ Post", body: "ZZZ Test cased orders."
|
|
60
61
|
assert_equal post1, Post.order(order).first
|
|
61
62
|
assert_equal post2, Post.order(order).second
|
|
62
63
|
end
|
|
63
64
|
|
|
64
|
-
it
|
|
65
|
+
it "support primary: table and column, secondary: column" do
|
|
65
66
|
order = "posts.title DESC, body"
|
|
66
|
-
post1 = Post.create title:
|
|
67
|
-
post2 = Post.create title:
|
|
67
|
+
post1 = Post.create title: "ZZZ Post", body: "Test cased orders."
|
|
68
|
+
post2 = Post.create title: "ZZZ Post", body: "ZZZ Test cased orders."
|
|
68
69
|
assert_equal post1, Post.order(order).first
|
|
69
70
|
assert_equal post2, Post.order(order).second
|
|
70
71
|
end
|
|
71
72
|
|
|
72
|
-
it
|
|
73
|
+
it "support primary: case expression, secondary: column" do
|
|
73
74
|
order = "(CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC, body"
|
|
74
|
-
post1 = Post.create title:
|
|
75
|
-
post2 = Post.create title:
|
|
75
|
+
post1 = Post.create title: "ZZZ Post", body: "Test cased orders."
|
|
76
|
+
post2 = Post.create title: "ZZZ Post", body: "ZZZ Test cased orders."
|
|
76
77
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
77
78
|
assert_equal post2, Post.order(Arel.sql(order)).second
|
|
78
79
|
end
|
|
79
80
|
|
|
80
|
-
it
|
|
81
|
+
it "support primary: quoted table and column, secondary: case expresion" do
|
|
81
82
|
order = "[posts].[body] DESC, (CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END) DESC"
|
|
82
|
-
post1 = Post.create title:
|
|
83
|
-
post2 = Post.create title:
|
|
83
|
+
post1 = Post.create title: "ZZZ Post", body: "ZZZ Test cased orders."
|
|
84
|
+
post2 = Post.create title: "ZZY Post", body: "ZZZ Test cased orders."
|
|
84
85
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
85
86
|
assert_equal post2, Post.order(Arel.sql(order)).second
|
|
86
87
|
end
|
|
87
88
|
|
|
88
|
-
it
|
|
89
|
+
it "support inline function" do
|
|
89
90
|
order = "LEN(title)"
|
|
90
|
-
post1 = Post.create title:
|
|
91
|
+
post1 = Post.create title: "A", body: "AAA Test cased orders."
|
|
91
92
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
92
93
|
end
|
|
93
94
|
|
|
94
|
-
it
|
|
95
|
+
it "support inline function with parameters" do
|
|
95
96
|
order = "SUBSTRING(title, 1, 3)"
|
|
96
|
-
post1 = Post.create title:
|
|
97
|
+
post1 = Post.create title: "AAA Post", body: "Test cased orders."
|
|
97
98
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
98
99
|
end
|
|
99
100
|
|
|
100
|
-
it
|
|
101
|
+
it "support inline function with parameters DESC" do
|
|
101
102
|
order = "SUBSTRING(title, 1, 3) DESC"
|
|
102
|
-
post1 = Post.create title:
|
|
103
|
+
post1 = Post.create title: "ZZZ Post", body: "Test cased orders."
|
|
103
104
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
104
105
|
end
|
|
105
106
|
|
|
106
|
-
it
|
|
107
|
+
it "support primary: inline function, secondary: column" do
|
|
107
108
|
order = "LEN(title), body"
|
|
108
|
-
post1 = Post.create title:
|
|
109
|
-
post2 = Post.create title:
|
|
109
|
+
post1 = Post.create title: "A", body: "AAA Test cased orders."
|
|
110
|
+
post2 = Post.create title: "A", body: "Test cased orders."
|
|
110
111
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
111
112
|
assert_equal post2, Post.order(Arel.sql(order)).second
|
|
112
113
|
end
|
|
113
114
|
|
|
114
|
-
it
|
|
115
|
+
it "support primary: inline function, secondary: column with direction" do
|
|
115
116
|
order = "LEN(title) ASC, body DESC"
|
|
116
|
-
post1 = Post.create title:
|
|
117
|
-
post2 = Post.create title:
|
|
117
|
+
post1 = Post.create title: "A", body: "ZZZ Test cased orders."
|
|
118
|
+
post2 = Post.create title: "A", body: "Test cased orders."
|
|
118
119
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
119
120
|
assert_equal post2, Post.order(Arel.sql(order)).second
|
|
120
121
|
end
|
|
121
122
|
|
|
122
|
-
it
|
|
123
|
+
it "support primary: column, secondary: inline function" do
|
|
123
124
|
order = "body DESC, LEN(title)"
|
|
124
|
-
post1 = Post.create title:
|
|
125
|
-
post2 = Post.create title:
|
|
125
|
+
post1 = Post.create title: "Post", body: "ZZZ Test cased orders."
|
|
126
|
+
post2 = Post.create title: "Longer Post", body: "ZZZ Test cased orders."
|
|
126
127
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
127
128
|
assert_equal post2, Post.order(Arel.sql(order)).second
|
|
128
129
|
end
|
|
129
130
|
|
|
130
|
-
it
|
|
131
|
+
it "support primary: case expression, secondary: inline function" do
|
|
131
132
|
order = "CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC, LEN(body) ASC"
|
|
132
|
-
post1 = Post.create title:
|
|
133
|
-
post2 = Post.create title:
|
|
133
|
+
post1 = Post.create title: "ZZZ Post", body: "Z"
|
|
134
|
+
post2 = Post.create title: "ZZZ Post", body: "Test cased orders."
|
|
134
135
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
135
136
|
assert_equal post2, Post.order(Arel.sql(order)).second
|
|
136
137
|
end
|
|
137
138
|
|
|
138
|
-
it
|
|
139
|
+
it "support primary: inline function, secondary: case expression" do
|
|
139
140
|
order = "LEN(body), CASE WHEN [title] LIKE N'ZZZ%' THEN title ELSE '' END DESC"
|
|
140
|
-
post1 = Post.create title:
|
|
141
|
-
post2 = Post.create title:
|
|
141
|
+
post1 = Post.create title: "ZZZ Post", body: "Z"
|
|
142
|
+
post2 = Post.create title: "Post", body: "Z"
|
|
142
143
|
assert_equal post1, Post.order(Arel.sql(order)).first
|
|
143
144
|
assert_equal post2, Post.order(Arel.sql(order)).second
|
|
144
145
|
end
|
|
145
|
-
|
|
146
|
-
|
|
147
146
|
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
require 'models/person'
|
|
3
|
-
require 'models/reader'
|
|
1
|
+
# frozen_string_literal: true
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
require "cases/helper_sqlserver"
|
|
4
|
+
require "models/person"
|
|
5
|
+
require "models/reader"
|
|
6
6
|
|
|
7
|
+
class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
7
8
|
fixtures :people, :readers
|
|
8
9
|
|
|
9
10
|
before do
|
|
@@ -11,15 +12,14 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
|
11
12
|
Reader.columns
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
it
|
|
15
|
+
it "uses with updlock by default" do
|
|
15
16
|
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\)| do
|
|
16
17
|
_(Person.lock(true).to_a).must_equal Person.all.to_a
|
|
17
18
|
end
|
|
18
19
|
end
|
|
19
20
|
|
|
20
|
-
describe
|
|
21
|
-
|
|
22
|
-
it 'lock with simple find' do
|
|
21
|
+
describe "For simple finds with default lock option" do
|
|
22
|
+
it "lock with simple find" do
|
|
23
23
|
assert_nothing_raised do
|
|
24
24
|
Person.transaction do
|
|
25
25
|
_(Person.lock(true).find(1)).must_equal Person.find(1)
|
|
@@ -27,7 +27,7 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
it
|
|
30
|
+
it "lock with scoped find" do
|
|
31
31
|
assert_nothing_raised do
|
|
32
32
|
Person.transaction do
|
|
33
33
|
Person.lock(true).scoping do
|
|
@@ -37,8 +37,8 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
it
|
|
41
|
-
|
|
40
|
+
it "lock with eager find" do
|
|
41
|
+
assert_nothing_raised do
|
|
42
42
|
Person.transaction do
|
|
43
43
|
person = Person.lock(true).includes(:readers).find(1)
|
|
44
44
|
_(person).must_equal Person.find(1)
|
|
@@ -46,62 +46,56 @@ class PessimisticLockingTestSQLServer < ActiveRecord::TestCase
|
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
it
|
|
49
|
+
it "can add a custom lock directive" do
|
|
50
50
|
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(HOLDLOCK, ROWLOCK\)| do
|
|
51
|
-
Person.lock(
|
|
51
|
+
Person.lock("WITH(HOLDLOCK, ROWLOCK)").load
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
describe
|
|
56
|
-
|
|
57
|
-
it 'joined tables use updlock by default' do
|
|
55
|
+
describe "joining tables" do
|
|
56
|
+
it "joined tables use updlock by default" do
|
|
58
57
|
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\) INNER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
|
|
59
58
|
Person.lock(true).joins(:readers).load
|
|
60
59
|
end
|
|
61
60
|
end
|
|
62
61
|
|
|
63
|
-
it
|
|
62
|
+
it "joined tables can use custom lock directive" do
|
|
64
63
|
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(
|
|
64
|
+
Person.lock("WITH(NOLOCK)").joins(:readers).load
|
|
66
65
|
end
|
|
67
66
|
end
|
|
68
67
|
|
|
69
|
-
it
|
|
68
|
+
it "left joined tables use updlock by default" do
|
|
70
69
|
assert_sql %r|SELECT \[people\]\.\* FROM \[people\] WITH\(UPDLOCK\) LEFT OUTER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\]\.\[person_id\] = \[people\]\.\[id\]| do
|
|
71
70
|
Person.lock(true).left_joins(:readers).load
|
|
72
71
|
end
|
|
73
72
|
end
|
|
74
73
|
|
|
75
|
-
it
|
|
74
|
+
it "left joined tables can use custom lock directive" do
|
|
76
75
|
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(
|
|
76
|
+
Person.lock("WITH(NOLOCK)").left_joins(:readers).load
|
|
78
77
|
end
|
|
79
78
|
end
|
|
80
|
-
|
|
81
79
|
end
|
|
82
|
-
|
|
83
80
|
end
|
|
84
81
|
|
|
85
|
-
describe
|
|
86
|
-
|
|
82
|
+
describe "For paginated finds" do
|
|
87
83
|
before do
|
|
88
84
|
Person.delete_all
|
|
89
85
|
20.times { |n| Person.create!(first_name: "Thing_#{n}") }
|
|
90
86
|
end
|
|
91
87
|
|
|
92
|
-
it
|
|
88
|
+
it "copes with eager loading un-locked paginated" do
|
|
93
89
|
eager_ids_sql = /SELECT\s+DISTINCT \[people\].\[id\] FROM \[people\] WITH\(UPDLOCK\) LEFT OUTER JOIN \[readers\] WITH\(UPDLOCK\)\s+ON \[readers\].\[person_id\] = \[people\].\[id\]\s+ORDER BY \[people\].\[id\] ASC OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY/
|
|
94
90
|
loader_sql = /SELECT.*FROM \[people\] WITH\(UPDLOCK\).*WHERE \[people\]\.\[id\] IN/
|
|
95
91
|
assert_sql(eager_ids_sql, loader_sql) do
|
|
96
92
|
people = Person.lock(true).limit(5).offset(10).includes(:readers).references(:readers).to_a
|
|
97
|
-
_(people[0].first_name).must_equal
|
|
98
|
-
_(people[1].first_name).must_equal
|
|
99
|
-
_(people[2].first_name).must_equal
|
|
100
|
-
_(people[3].first_name).must_equal
|
|
101
|
-
_(people[4].first_name).must_equal
|
|
93
|
+
_(people[0].first_name).must_equal "Thing_10"
|
|
94
|
+
_(people[1].first_name).must_equal "Thing_11"
|
|
95
|
+
_(people[2].first_name).must_equal "Thing_12"
|
|
96
|
+
_(people[3].first_name).must_equal "Thing_13"
|
|
97
|
+
_(people[4].first_name).must_equal "Thing_14"
|
|
102
98
|
end
|
|
103
99
|
end
|
|
104
|
-
|
|
105
100
|
end
|
|
106
|
-
|
|
107
101
|
end
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require "cases/helper_sqlserver"
|
|
4
4
|
|
|
5
|
+
class SQLServerRakeTest < ActiveRecord::TestCase
|
|
5
6
|
self.use_transactional_tests = false
|
|
6
7
|
|
|
7
8
|
cattr_accessor :azure_skip
|
|
8
9
|
self.azure_skip = connection_sqlserver_azure?
|
|
9
10
|
|
|
10
11
|
let(:db_tasks) { ActiveRecord::Tasks::DatabaseTasks }
|
|
11
|
-
let(:new_database) {
|
|
12
|
-
let(:default_configuration) { ARTest.connection_config[
|
|
13
|
-
let(:configuration) { default_configuration.merge(
|
|
12
|
+
let(:new_database) { "activerecord_unittest_tasks" }
|
|
13
|
+
let(:default_configuration) { ARTest.connection_config["arunit"] }
|
|
14
|
+
let(:configuration) { default_configuration.merge("database" => new_database) }
|
|
14
15
|
|
|
15
|
-
before { skip
|
|
16
|
+
before { skip "on azure" if azure_skip }
|
|
16
17
|
before { disconnect! unless azure_skip }
|
|
17
18
|
after { reconnect unless azure_skip }
|
|
18
19
|
|
|
@@ -25,7 +26,7 @@ class SQLServerRakeTest < ActiveRecord::TestCase
|
|
|
25
26
|
def reconnect
|
|
26
27
|
config = default_configuration
|
|
27
28
|
if connection_sqlserver_azure?
|
|
28
|
-
ActiveRecord::Base.establish_connection(config.merge(
|
|
29
|
+
ActiveRecord::Base.establish_connection(config.merge("database" => "master"))
|
|
29
30
|
connection.drop_database(new_database) rescue nil
|
|
30
31
|
disconnect!
|
|
31
32
|
ActiveRecord::Base.establish_connection(config)
|
|
@@ -34,57 +35,51 @@ class SQLServerRakeTest < ActiveRecord::TestCase
|
|
|
34
35
|
connection.drop_database(new_database) rescue nil
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
|
-
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
class SQLServerRakeCreateTest < SQLServerRakeTest
|
|
41
|
-
|
|
42
41
|
self.azure_skip = false
|
|
43
42
|
|
|
44
|
-
it
|
|
43
|
+
it "establishes connection to database after create " do
|
|
45
44
|
quietly { db_tasks.create configuration }
|
|
46
45
|
_(connection.current_database).must_equal(new_database)
|
|
47
46
|
end
|
|
48
47
|
|
|
49
|
-
it
|
|
48
|
+
it "creates database with default collation" do
|
|
50
49
|
quietly { db_tasks.create configuration }
|
|
51
|
-
_(connection.collation).must_equal
|
|
50
|
+
_(connection.collation).must_equal "SQL_Latin1_General_CP1_CI_AS"
|
|
52
51
|
end
|
|
53
52
|
|
|
54
|
-
it
|
|
55
|
-
quietly { db_tasks.create configuration.merge(
|
|
56
|
-
_(connection.collation).must_equal
|
|
53
|
+
it "creates database with given collation" do
|
|
54
|
+
quietly { db_tasks.create configuration.merge("collation" => "Latin1_General_CI_AS") }
|
|
55
|
+
_(connection.collation).must_equal "Latin1_General_CI_AS"
|
|
57
56
|
end
|
|
58
57
|
|
|
59
|
-
it
|
|
58
|
+
it "prints error message when database exists" do
|
|
60
59
|
quietly { db_tasks.create configuration }
|
|
61
60
|
message = capture(:stderr) { db_tasks.create configuration }
|
|
62
61
|
_(message).must_match %r{activerecord_unittest_tasks.*already exists}
|
|
63
62
|
end
|
|
64
|
-
|
|
65
63
|
end
|
|
66
64
|
|
|
67
65
|
class SQLServerRakeDropTest < SQLServerRakeTest
|
|
68
|
-
|
|
69
66
|
self.azure_skip = false
|
|
70
67
|
|
|
71
|
-
it
|
|
68
|
+
it "drops database and uses master" do
|
|
72
69
|
quietly do
|
|
73
70
|
db_tasks.create configuration
|
|
74
71
|
db_tasks.drop configuration
|
|
75
72
|
end
|
|
76
|
-
_(connection.current_database).must_equal
|
|
73
|
+
_(connection.current_database).must_equal "master"
|
|
77
74
|
end
|
|
78
75
|
|
|
79
|
-
it
|
|
80
|
-
message = capture(:stderr) { db_tasks.drop configuration.merge(
|
|
76
|
+
it "prints error message when database does not exist" do
|
|
77
|
+
message = capture(:stderr) { db_tasks.drop configuration.merge("database" => "doesnotexist") }
|
|
81
78
|
_(message).must_match %r{'doesnotexist' does not exist}
|
|
82
79
|
end
|
|
83
|
-
|
|
84
80
|
end
|
|
85
81
|
|
|
86
82
|
class SQLServerRakePurgeTest < SQLServerRakeTest
|
|
87
|
-
|
|
88
83
|
before do
|
|
89
84
|
quietly { db_tasks.create(configuration) }
|
|
90
85
|
connection.create_table :users, force: true do |t|
|
|
@@ -93,43 +88,37 @@ class SQLServerRakePurgeTest < SQLServerRakeTest
|
|
|
93
88
|
end
|
|
94
89
|
end
|
|
95
90
|
|
|
96
|
-
it
|
|
91
|
+
it "clears active connections, drops database, and recreates with established connection" do
|
|
97
92
|
_(connection.current_database).must_equal(new_database)
|
|
98
|
-
_(connection.tables).must_include
|
|
93
|
+
_(connection.tables).must_include "users"
|
|
99
94
|
quietly { db_tasks.purge(configuration) }
|
|
100
95
|
_(connection.current_database).must_equal(new_database)
|
|
101
|
-
_(connection.tables).wont_include
|
|
96
|
+
_(connection.tables).wont_include "users"
|
|
102
97
|
end
|
|
103
|
-
|
|
104
98
|
end
|
|
105
99
|
|
|
106
100
|
class SQLServerRakeCharsetTest < SQLServerRakeTest
|
|
107
|
-
|
|
108
101
|
before do
|
|
109
102
|
quietly { db_tasks.create(configuration) }
|
|
110
103
|
end
|
|
111
104
|
|
|
112
|
-
it
|
|
113
|
-
_(db_tasks.charset(configuration)).must_equal
|
|
105
|
+
it "retrieves charset" do
|
|
106
|
+
_(db_tasks.charset(configuration)).must_equal "iso_1"
|
|
114
107
|
end
|
|
115
|
-
|
|
116
108
|
end
|
|
117
109
|
|
|
118
110
|
class SQLServerRakeCollationTest < SQLServerRakeTest
|
|
119
|
-
|
|
120
111
|
before do
|
|
121
112
|
quietly { db_tasks.create(configuration) }
|
|
122
113
|
end
|
|
123
114
|
|
|
124
|
-
it
|
|
125
|
-
_(db_tasks.collation(configuration)).must_equal
|
|
115
|
+
it "retrieves collation" do
|
|
116
|
+
_(db_tasks.collation(configuration)).must_equal "SQL_Latin1_General_CP1_CI_AS"
|
|
126
117
|
end
|
|
127
|
-
|
|
128
118
|
end
|
|
129
119
|
|
|
130
120
|
class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
|
|
131
|
-
|
|
132
|
-
let(:filename) { File.join ARTest::SQLServer.migrations_root, 'structure.sql' }
|
|
121
|
+
let(:filename) { File.join ARTest::SQLServer.migrations_root, "structure.sql" }
|
|
133
122
|
let(:filedata) { File.read(filename) }
|
|
134
123
|
|
|
135
124
|
before do
|
|
@@ -146,8 +135,8 @@ class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
|
|
|
146
135
|
FileUtils.rm_rf(filename)
|
|
147
136
|
end
|
|
148
137
|
|
|
149
|
-
it
|
|
150
|
-
skip
|
|
138
|
+
it "dumps structure and accounts for defncopy oddities" do
|
|
139
|
+
skip "debug defncopy on windows later" if host_windows?
|
|
151
140
|
quietly { db_tasks.structure_dump configuration, filename }
|
|
152
141
|
_(filedata).wont_match %r{\AUSE.*\z}
|
|
153
142
|
_(filedata).wont_match %r{\AGO.*\z}
|
|
@@ -156,14 +145,13 @@ class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
|
|
|
156
145
|
_(filedata).must_match %r{background2\s+text\s+}
|
|
157
146
|
end
|
|
158
147
|
|
|
159
|
-
it
|
|
160
|
-
skip
|
|
148
|
+
it "can load dumped structure" do
|
|
149
|
+
skip "debug defncopy on windows later" if host_windows?
|
|
161
150
|
quietly { db_tasks.structure_dump configuration, filename }
|
|
162
151
|
_(filedata).must_match %r{CREATE TABLE dbo\.users}
|
|
163
152
|
db_tasks.purge(configuration)
|
|
164
|
-
_(connection.tables).wont_include
|
|
153
|
+
_(connection.tables).wont_include "users"
|
|
165
154
|
db_tasks.load_schema configuration, :sql, filename
|
|
166
|
-
_(connection.tables).must_include
|
|
155
|
+
_(connection.tables).must_include "users"
|
|
167
156
|
end
|
|
168
|
-
|
|
169
157
|
end
|