activerecord-sqlserver-adapter 6.0.1 → 6.0.2
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/.github/workflows/ci.yml +26 -0
- data/CHANGELOG.md +18 -0
- data/README.md +19 -1
- data/RUNNING_UNIT_TESTS.md +1 -1
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +23 -3
- data/lib/active_record/connection_adapters/sqlserver/type.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +17 -2
- data/lib/arel/visitors/sqlserver.rb +52 -12
- data/test/cases/adapter_test_sqlserver.rb +34 -2
- data/test/cases/coerced_tests.rb +99 -33
- data/test/cases/column_test_sqlserver.rb +5 -2
- data/test/cases/lateral_test_sqlserver.rb +35 -0
- data/test/cases/migration_test_sqlserver.rb +44 -0
- data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
- data/test/cases/schema_dumper_test_sqlserver.rb +5 -3
- metadata +11 -6
- data/.travis.yml +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6cf80abcc5b46383279819d86c83c095b5aabcf4969e84bdb2ca3e101777b3a
|
4
|
+
data.tar.gz: e11e7d40bba8a4ce3c2d47e08002c5321f82c25b91fde75caa0f01b37a7f6e70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6f04caed7f5cc895fc185e8976d306901dc0563152b8867f40be0319f8572099495ef27bc205aad7733c8aac0e4baf451769cdc46719c2db248f50a802be324
|
7
|
+
data.tar.gz: 3c8f05837c093f0d44909d1a26bbc97010f8dc5ab07cd5d48bba94d09624c5fe2e5f21488915931c528207eb726860ae0d59b8ca229f353efe0846ff16f7a955
|
@@ -0,0 +1,26 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
name: Run test suite
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
|
10
|
+
env:
|
11
|
+
COMPOSE_FILE: docker-compose.ci.yml
|
12
|
+
|
13
|
+
strategy:
|
14
|
+
fail-fast: false
|
15
|
+
matrix:
|
16
|
+
ruby: [2.5.9, 2.6.7, 2.7.3, 3.0.1]
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- name: Checkout code
|
20
|
+
uses: actions/checkout@v2
|
21
|
+
|
22
|
+
- name: Build docker images
|
23
|
+
run: docker-compose build --build-arg TARGET_VERSION=${{ matrix.ruby }}
|
24
|
+
|
25
|
+
- name: Run tests
|
26
|
+
run: docker-compose run ci
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## v6.0.2
|
2
|
+
|
3
|
+
#### Fixed
|
4
|
+
|
5
|
+
- [#858](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/858) Allow table existence to be tested across database schemas.
|
6
|
+
|
7
|
+
#### Changed
|
8
|
+
|
9
|
+
- [#852](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/852) Updated the column name matchers to accept database and owner names
|
10
|
+
|
11
|
+
#### Added
|
12
|
+
|
13
|
+
- [#855](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/855) Add helpers to create/change/drop a schema.
|
14
|
+
- [#857](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/857) Included WAITFOR as read query type.
|
15
|
+
- [#865](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/865) Implemented optimizer hints.
|
16
|
+
- [#845](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/845) Add support for lateral using CROSS/OUTER APPLY.
|
17
|
+
- [#870](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/870) Added DecimalWithoutScale type
|
18
|
+
|
1
19
|
## v6.0.1
|
2
20
|
|
3
21
|
#### Fixed
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# ActiveRecord SQL Server Adapter. For SQL Server 2012 And Higher.
|
2
2
|
|
3
|
-
* [](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/actions/workflows/ci.yml) - CI
|
4
4
|
* [](https://ci.appveyor.com/project/rails-sqlserver/activerecord-sqlserver-adapter/branch/master) - Appveyor
|
5
5
|
* [](https://rubygems.org/gems/activerecord-sqlserver-adapter) - Gem Version
|
6
6
|
* [](https://gitter.im/rails-sqlserver/activerecord-sqlserver-adapter) - Community
|
@@ -52,6 +52,24 @@ Depending on your user and schema setup, it may be needed to use a table name pr
|
|
52
52
|
ActiveRecord::Base.table_name_prefix = 'dbo.'
|
53
53
|
```
|
54
54
|
|
55
|
+
It's also possible to create/change/drop a schema in the migration file as in the example below:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class CreateFooSchema < ActiveRecord::Migration[6.0]
|
59
|
+
def up
|
60
|
+
create_schema('foo')
|
61
|
+
|
62
|
+
# Or you could move a table to a different schema
|
63
|
+
|
64
|
+
change_table_schema('foo', 'dbo.admin')
|
65
|
+
end
|
66
|
+
|
67
|
+
def down
|
68
|
+
drop_schema('foo')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
55
73
|
|
56
74
|
#### Configure Connection & App Name
|
57
75
|
|
data/RUNNING_UNIT_TESTS.md
CHANGED
@@ -5,7 +5,7 @@ This process is much easier than it has been before!
|
|
5
5
|
|
6
6
|
## MS SQL SERVER
|
7
7
|
|
8
|
-
If you don't have easy access to MS SQL Server, you can set up a Vagrant/VirtualBox virtual machine with MS SQL Server. [Here's how](
|
8
|
+
If you don't have easy access to MS SQL Server, you can set up a Vagrant/VirtualBox virtual machine with MS SQL Server. [Here's how](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter-dev-box).
|
9
9
|
|
10
10
|
## TL;DR
|
11
11
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
6.0.
|
1
|
+
6.0.2
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters
|
5
5
|
module SQLServer
|
6
6
|
module DatabaseStatements
|
7
|
-
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :dbcc, :explain, :save, :select, :set, :rollback) # :nodoc:
|
7
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :dbcc, :explain, :save, :select, :set, :rollback, :waitfor) # :nodoc:
|
8
8
|
private_constant :READ_QUERY
|
9
9
|
|
10
10
|
def write_query?(sql) # :nodoc:
|
@@ -83,8 +83,8 @@ module ActiveRecord
|
|
83
83
|
\A
|
84
84
|
(
|
85
85
|
(?:
|
86
|
-
# [table_name].[column_name] | function(one or no argument)
|
87
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
86
|
+
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
|
87
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
88
88
|
)
|
89
89
|
(?:\s+AS\s+(?:\w+|\[\w+\]))?
|
90
90
|
)
|
@@ -96,8 +96,8 @@ module ActiveRecord
|
|
96
96
|
\A
|
97
97
|
(
|
98
98
|
(?:
|
99
|
-
# [table_name].[column_name] | function(one or no argument)
|
100
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
99
|
+
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
|
100
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
101
101
|
)
|
102
102
|
(?:\s+ASC|\s+DESC)?
|
103
103
|
(?:\s+NULLS\s+(?:FIRST|LAST))?
|
@@ -281,14 +281,33 @@ module ActiveRecord
|
|
281
281
|
SQLServer::SchemaDumper.create(self, options)
|
282
282
|
end
|
283
283
|
|
284
|
+
def create_schema(schema_name, authorization = nil)
|
285
|
+
sql = "CREATE SCHEMA [#{schema_name}]"
|
286
|
+
sql += " AUTHORIZATION [#{authorization}]" if authorization
|
287
|
+
|
288
|
+
execute sql
|
289
|
+
end
|
290
|
+
|
291
|
+
def change_table_schema(schema_name, table_name)
|
292
|
+
execute "ALTER SCHEMA [#{schema_name}] TRANSFER [#{table_name}]"
|
293
|
+
end
|
294
|
+
|
295
|
+
def drop_schema(schema_name)
|
296
|
+
execute "DROP SCHEMA [#{schema_name}]"
|
297
|
+
end
|
298
|
+
|
284
299
|
private
|
285
300
|
|
286
301
|
def data_source_sql(name = nil, type: nil)
|
287
302
|
scope = quoted_scope name, type: type
|
288
|
-
|
303
|
+
|
304
|
+
table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
|
305
|
+
database = scope[:database].present? ? "#{scope[:database]}." : ""
|
306
|
+
table_catalog = scope[:database].present? ? quote(scope[:database]) : "DB_NAME()"
|
307
|
+
|
289
308
|
sql = "SELECT #{table_name}"
|
290
|
-
sql += " FROM INFORMATION_SCHEMA.TABLES WITH (NOLOCK)"
|
291
|
-
sql += " WHERE TABLE_CATALOG =
|
309
|
+
sql += " FROM #{database}INFORMATION_SCHEMA.TABLES WITH (NOLOCK)"
|
310
|
+
sql += " WHERE TABLE_CATALOG = #{table_catalog}"
|
292
311
|
sql += " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
|
293
312
|
sql += " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
|
294
313
|
sql += " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
|
@@ -299,6 +318,7 @@ module ActiveRecord
|
|
299
318
|
def quoted_scope(name = nil, type: nil)
|
300
319
|
identifier = SQLServer::Utils.extract_identifiers(name)
|
301
320
|
{}.tap do |scope|
|
321
|
+
scope[:database] = identifier.database if identifier.database
|
302
322
|
scope[:schema] = identifier.schema || "dbo"
|
303
323
|
scope[:name] = identifier.object if identifier.object
|
304
324
|
scope[:type] = type if type
|
@@ -11,6 +11,7 @@ require "active_record/connection_adapters/sqlserver/type/small_integer"
|
|
11
11
|
require "active_record/connection_adapters/sqlserver/type/tiny_integer"
|
12
12
|
require "active_record/connection_adapters/sqlserver/type/boolean"
|
13
13
|
require "active_record/connection_adapters/sqlserver/type/decimal"
|
14
|
+
require "active_record/connection_adapters/sqlserver/type/decimal_without_scale"
|
14
15
|
require "active_record/connection_adapters/sqlserver/type/money"
|
15
16
|
require "active_record/connection_adapters/sqlserver/type/small_money"
|
16
17
|
# Approximate Numerics
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module SQLServer
|
6
|
+
module Type
|
7
|
+
class DecimalWithoutScale < ActiveRecord::Type::DecimalWithoutScale
|
8
|
+
def sqlserver_type
|
9
|
+
"decimal".yield_self do |type|
|
10
|
+
type += "(#{precision.to_i},0)" if precision
|
11
|
+
type
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def type_cast_for_schema(value)
|
16
|
+
value.is_a?(BigDecimal) ? value.to_s : value.inspect
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -152,6 +152,10 @@ module ActiveRecord
|
|
152
152
|
true
|
153
153
|
end
|
154
154
|
|
155
|
+
def supports_optimizer_hints?
|
156
|
+
true
|
157
|
+
end
|
158
|
+
|
155
159
|
def supports_lazy_transactions?
|
156
160
|
true
|
157
161
|
end
|
@@ -296,6 +300,7 @@ module ActiveRecord
|
|
296
300
|
|
297
301
|
def initialize_type_map(m = type_map)
|
298
302
|
m.register_type %r{.*}, SQLServer::Type::UnicodeString.new
|
303
|
+
|
299
304
|
# Exact Numerics
|
300
305
|
register_class_with_limit m, "bigint(8)", SQLServer::Type::BigInteger
|
301
306
|
m.alias_type "bigint", "bigint(8)"
|
@@ -308,16 +313,22 @@ module ActiveRecord
|
|
308
313
|
m.alias_type "tinyint", "tinyint(1)"
|
309
314
|
m.register_type "bit", SQLServer::Type::Boolean.new
|
310
315
|
m.register_type %r{\Adecimal}i do |sql_type|
|
311
|
-
scale
|
316
|
+
scale = extract_scale(sql_type)
|
312
317
|
precision = extract_precision(sql_type)
|
313
|
-
|
318
|
+
if scale == 0
|
319
|
+
SQLServer::Type::DecimalWithoutScale.new(precision: precision)
|
320
|
+
else
|
321
|
+
SQLServer::Type::Decimal.new(precision: precision, scale: scale)
|
322
|
+
end
|
314
323
|
end
|
315
324
|
m.alias_type %r{\Anumeric}i, "decimal"
|
316
325
|
m.register_type "money", SQLServer::Type::Money.new
|
317
326
|
m.register_type "smallmoney", SQLServer::Type::SmallMoney.new
|
327
|
+
|
318
328
|
# Approximate Numerics
|
319
329
|
m.register_type "float", SQLServer::Type::Float.new
|
320
330
|
m.register_type "real", SQLServer::Type::Real.new
|
331
|
+
|
321
332
|
# Date and Time
|
322
333
|
m.register_type "date", SQLServer::Type::Date.new
|
323
334
|
m.register_type %r{\Adatetime} do |sql_type|
|
@@ -337,11 +348,13 @@ module ActiveRecord
|
|
337
348
|
precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
|
338
349
|
SQLServer::Type::Time.new precision: precision
|
339
350
|
end
|
351
|
+
|
340
352
|
# Character Strings
|
341
353
|
register_class_with_limit m, %r{\Achar}i, SQLServer::Type::Char
|
342
354
|
register_class_with_limit m, %r{\Avarchar}i, SQLServer::Type::Varchar
|
343
355
|
m.register_type "varchar(max)", SQLServer::Type::VarcharMax.new
|
344
356
|
m.register_type "text", SQLServer::Type::Text.new
|
357
|
+
|
345
358
|
# Unicode Character Strings
|
346
359
|
register_class_with_limit m, %r{\Anchar}i, SQLServer::Type::UnicodeChar
|
347
360
|
register_class_with_limit m, %r{\Anvarchar}i, SQLServer::Type::UnicodeVarchar
|
@@ -349,10 +362,12 @@ module ActiveRecord
|
|
349
362
|
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
350
363
|
m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
|
351
364
|
m.register_type "ntext", SQLServer::Type::UnicodeText.new
|
365
|
+
|
352
366
|
# Binary Strings
|
353
367
|
register_class_with_limit m, %r{\Abinary}i, SQLServer::Type::Binary
|
354
368
|
register_class_with_limit m, %r{\Avarbinary}i, SQLServer::Type::Varbinary
|
355
369
|
m.register_type "varbinary(max)", SQLServer::Type::VarbinaryMax.new
|
370
|
+
|
356
371
|
# Other Data Types
|
357
372
|
m.register_type "uniqueidentifier", SQLServer::Type::Uuid.new
|
358
373
|
m.register_type "timestamp", SQLServer::Type::Timestamp.new
|
@@ -80,6 +80,16 @@ module Arel
|
|
80
80
|
@select_statement = nil
|
81
81
|
end
|
82
82
|
|
83
|
+
def visit_Arel_Nodes_SelectCore(o, collector)
|
84
|
+
collector = super
|
85
|
+
maybe_visit o.optimizer_hints, collector
|
86
|
+
end
|
87
|
+
|
88
|
+
def visit_Arel_Nodes_OptimizerHints(o, collector)
|
89
|
+
hints = o.expr.map { |v| sanitize_as_option_clause(v) }.join(", ")
|
90
|
+
collector << "OPTION (#{hints})"
|
91
|
+
end
|
92
|
+
|
83
93
|
def visit_Arel_Table o, collector
|
84
94
|
# Apparently, o.engine.connection can actually be a different adapter
|
85
95
|
# than sqlserver. Can be removed if fixed in ActiveRecord. See:
|
@@ -115,23 +125,33 @@ module Arel
|
|
115
125
|
end
|
116
126
|
|
117
127
|
def visit_Arel_Nodes_InnerJoin o, collector
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
if o.right
|
122
|
-
collector << " "
|
123
|
-
visit(o.right, collector)
|
128
|
+
if o.left.is_a?(Arel::Nodes::As) && o.left.left.is_a?(Arel::Nodes::Lateral)
|
129
|
+
collector << "CROSS "
|
130
|
+
visit o.left, collector
|
124
131
|
else
|
125
|
-
collector
|
132
|
+
collector << "INNER JOIN "
|
133
|
+
collector = visit o.left, collector
|
134
|
+
collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
|
135
|
+
if o.right
|
136
|
+
collector << " "
|
137
|
+
visit(o.right, collector)
|
138
|
+
else
|
139
|
+
collector
|
140
|
+
end
|
126
141
|
end
|
127
142
|
end
|
128
143
|
|
129
144
|
def visit_Arel_Nodes_OuterJoin o, collector
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
145
|
+
if o.left.is_a?(Arel::Nodes::As) && o.left.left.is_a?(Arel::Nodes::Lateral)
|
146
|
+
collector << "OUTER "
|
147
|
+
visit o.left, collector
|
148
|
+
else
|
149
|
+
collector << "LEFT OUTER JOIN "
|
150
|
+
collector = visit o.left, collector
|
151
|
+
collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
|
152
|
+
collector << " "
|
153
|
+
visit o.right, collector
|
154
|
+
end
|
135
155
|
end
|
136
156
|
|
137
157
|
def collect_in_clause(left, right, collector)
|
@@ -144,6 +164,10 @@ module Arel
|
|
144
164
|
super
|
145
165
|
end
|
146
166
|
|
167
|
+
def collect_optimizer_hints(o, collector)
|
168
|
+
collector
|
169
|
+
end
|
170
|
+
|
147
171
|
# SQLServer ToSql/Visitor (Additions)
|
148
172
|
|
149
173
|
def visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, options = {}
|
@@ -174,6 +198,18 @@ module Arel
|
|
174
198
|
collector
|
175
199
|
end
|
176
200
|
|
201
|
+
def visit_Arel_Nodes_Lateral o, collector
|
202
|
+
collector << "APPLY"
|
203
|
+
collector << " "
|
204
|
+
if o.expr.is_a?(Arel::Nodes::SelectStatement)
|
205
|
+
collector << "("
|
206
|
+
visit(o.expr, collector)
|
207
|
+
collector << ")"
|
208
|
+
else
|
209
|
+
visit(o.expr, collector)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
177
213
|
# SQLServer Helpers
|
178
214
|
|
179
215
|
def node_value(node)
|
@@ -247,6 +283,10 @@ module Arel
|
|
247
283
|
|
248
284
|
node.orders = [] unless node.offset || node.limit
|
249
285
|
end
|
286
|
+
|
287
|
+
def sanitize_as_option_clause(value)
|
288
|
+
value.gsub(%r{OPTION \s* \( (.+) \)}xi, "\\1")
|
289
|
+
end
|
250
290
|
end
|
251
291
|
end
|
252
292
|
end
|
@@ -6,6 +6,7 @@ require "models/task"
|
|
6
6
|
require "models/post"
|
7
7
|
require "models/subscriber"
|
8
8
|
require "models/minimalistic"
|
9
|
+
require "models/college"
|
9
10
|
|
10
11
|
class AdapterTestSQLServer < ActiveRecord::TestCase
|
11
12
|
fixtures :tasks
|
@@ -42,17 +43,48 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
42
43
|
assert connection.supports_ddl_transactions?
|
43
44
|
end
|
44
45
|
|
45
|
-
it "
|
46
|
+
it "table exists works if table name prefixed by schema and owner" do
|
46
47
|
begin
|
47
48
|
assert_equal "topics", Topic.table_name
|
48
49
|
assert Topic.table_exists?
|
50
|
+
|
51
|
+
# Test when owner included in table name.
|
49
52
|
Topic.table_name = "dbo.topics"
|
50
|
-
assert Topic.table_exists?, "
|
53
|
+
assert Topic.table_exists?, "Topics table name of 'dbo.topics' should return true for exists."
|
54
|
+
|
55
|
+
# Test when database and owner included in table name.
|
56
|
+
Topic.table_name = "#{ActiveRecord::Base.configurations["arunit"]['database']}.dbo.topics"
|
57
|
+
assert Topic.table_exists?, "Topics table name of '[DATABASE].dbo.topics' should return true for exists."
|
51
58
|
ensure
|
52
59
|
Topic.table_name = "topics"
|
53
60
|
end
|
54
61
|
end
|
55
62
|
|
63
|
+
it "test table existence across database schemas" do
|
64
|
+
arunit_connection = Topic.connection
|
65
|
+
arunit2_connection = College.connection
|
66
|
+
|
67
|
+
arunit_database = arunit_connection.pool.spec.config[:database]
|
68
|
+
arunit2_database = arunit2_connection.pool.spec.config[:database]
|
69
|
+
|
70
|
+
# Assert that connections use different default databases schemas.
|
71
|
+
assert_not_equal arunit_database, arunit2_database
|
72
|
+
|
73
|
+
# Assert that the Topics table exists when using the Topics connection.
|
74
|
+
assert arunit_connection.table_exists?('topics'), 'Topics table exists using table name'
|
75
|
+
assert arunit_connection.table_exists?('dbo.topics'), 'Topics table exists using owner and table name'
|
76
|
+
assert arunit_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using database, owner and table name'
|
77
|
+
|
78
|
+
# Assert that the Colleges table exists when using the Colleges connection.
|
79
|
+
assert arunit2_connection.table_exists?('colleges'), 'College table exists using table name'
|
80
|
+
assert arunit2_connection.table_exists?('dbo.colleges'), 'College table exists using owner and table name'
|
81
|
+
assert arunit2_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'College table exists using database, owner and table name'
|
82
|
+
|
83
|
+
# Assert that the tables exist when using each others connection.
|
84
|
+
assert arunit_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'Colleges table exists using Topics connection'
|
85
|
+
assert arunit2_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using Colleges connection'
|
86
|
+
end
|
87
|
+
|
56
88
|
it "return true to insert sql query for inserts only" do
|
57
89
|
assert connection.send(:insert_sql?, "INSERT...")
|
58
90
|
assert connection.send(:insert_sql?, "EXEC sp_executesql N'INSERT INTO [fk_test_has_fks] ([fk_id]) VALUES (@0); SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident', N'@0 int', @0 = 0")
|
data/test/cases/coerced_tests.rb
CHANGED
@@ -396,39 +396,6 @@ module ActiveRecord
|
|
396
396
|
end
|
397
397
|
|
398
398
|
class MigrationTest < ActiveRecord::TestCase
|
399
|
-
# We do not have do the DecimalWithoutScale type.
|
400
|
-
coerce_tests! :test_add_table_with_decimals
|
401
|
-
def test_add_table_with_decimals_coerced
|
402
|
-
Person.connection.drop_table :big_numbers rescue nil
|
403
|
-
assert !BigNumber.table_exists?
|
404
|
-
GiveMeBigNumbers.up
|
405
|
-
BigNumber.reset_column_information
|
406
|
-
assert BigNumber.create(
|
407
|
-
:bank_balance => 1586.43,
|
408
|
-
:big_bank_balance => BigDecimal("1000234000567.95"),
|
409
|
-
:world_population => 6000000000,
|
410
|
-
:my_house_population => 3,
|
411
|
-
:value_of_e => BigDecimal("2.7182818284590452353602875")
|
412
|
-
)
|
413
|
-
b = BigNumber.first
|
414
|
-
assert_not_nil b
|
415
|
-
assert_not_nil b.bank_balance
|
416
|
-
assert_not_nil b.big_bank_balance
|
417
|
-
assert_not_nil b.world_population
|
418
|
-
assert_not_nil b.my_house_population
|
419
|
-
assert_not_nil b.value_of_e
|
420
|
-
assert_kind_of BigDecimal, b.world_population
|
421
|
-
assert_equal "6000000000.0", b.world_population.to_s
|
422
|
-
assert_kind_of Integer, b.my_house_population
|
423
|
-
assert_equal 3, b.my_house_population
|
424
|
-
assert_kind_of BigDecimal, b.bank_balance
|
425
|
-
assert_equal BigDecimal("1586.43"), b.bank_balance
|
426
|
-
assert_kind_of BigDecimal, b.big_bank_balance
|
427
|
-
assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
|
428
|
-
GiveMeBigNumbers.down
|
429
|
-
assert_raise(ActiveRecord::StatementInvalid) { BigNumber.first }
|
430
|
-
end
|
431
|
-
|
432
399
|
# For some reason our tests set Rails.@_env which breaks test env switching.
|
433
400
|
coerce_tests! :test_internal_metadata_stores_environment_when_other_data_exists
|
434
401
|
coerce_tests! :test_internal_metadata_stores_environment
|
@@ -982,6 +949,21 @@ class RelationTest < ActiveRecord::TestCase
|
|
982
949
|
end
|
983
950
|
end
|
984
951
|
|
952
|
+
module ActiveRecord
|
953
|
+
class RelationTest < ActiveRecord::TestCase
|
954
|
+
# Skipping this test. SQL Server doesn't support optimizer hint as comments
|
955
|
+
coerce_tests! :test_relation_with_optimizer_hints_filters_sql_comment_delimiters
|
956
|
+
|
957
|
+
coerce_tests! :test_does_not_duplicate_optimizer_hints_on_merge
|
958
|
+
def test_does_not_duplicate_optimizer_hints_on_merge_coerced
|
959
|
+
escaped_table = Post.connection.quote_table_name("posts")
|
960
|
+
expected = "SELECT #{escaped_table}.* FROM #{escaped_table} OPTION (OMGHINT)"
|
961
|
+
query = Post.optimizer_hints("OMGHINT").merge(Post.optimizer_hints("OMGHINT")).to_sql
|
962
|
+
assert_equal expected, query
|
963
|
+
end
|
964
|
+
end
|
965
|
+
end
|
966
|
+
|
985
967
|
require "models/post"
|
986
968
|
class SanitizeTest < ActiveRecord::TestCase
|
987
969
|
# Use nvarchar string (N'') in assert
|
@@ -1243,7 +1225,11 @@ module ActiveRecord
|
|
1243
1225
|
end
|
1244
1226
|
end
|
1245
1227
|
|
1228
|
+
require "models/post"
|
1229
|
+
require "models/comment"
|
1246
1230
|
class UnsafeRawSqlTest < ActiveRecord::TestCase
|
1231
|
+
fixtures :posts
|
1232
|
+
|
1247
1233
|
# Use LEN() vs length() function.
|
1248
1234
|
coerce_tests! %r{order: always allows Arel}
|
1249
1235
|
test "order: always allows Arel" do
|
@@ -1273,6 +1259,86 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase
|
|
1273
1259
|
assert_equal ids_expected, ids_depr
|
1274
1260
|
assert_equal ids_expected, ids_disabled
|
1275
1261
|
end
|
1262
|
+
|
1263
|
+
test "order: allows string column names that are quoted" do
|
1264
|
+
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1265
|
+
|
1266
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order("[id]").pluck(:id) }
|
1267
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[id]").pluck(:id) }
|
1268
|
+
|
1269
|
+
assert_equal ids_expected, ids_depr
|
1270
|
+
assert_equal ids_expected, ids_disabled
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
test "order: allows string column names that are quoted with table" do
|
1274
|
+
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1275
|
+
|
1276
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order("[posts].[id]").pluck(:id) }
|
1277
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[posts].[id]").pluck(:id) }
|
1278
|
+
|
1279
|
+
assert_equal ids_expected, ids_depr
|
1280
|
+
assert_equal ids_expected, ids_disabled
|
1281
|
+
end
|
1282
|
+
|
1283
|
+
test "order: allows string column names that are quoted with table and user" do
|
1284
|
+
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1285
|
+
|
1286
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order("[dbo].[posts].[id]").pluck(:id) }
|
1287
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[dbo].[posts].[id]").pluck(:id) }
|
1288
|
+
|
1289
|
+
assert_equal ids_expected, ids_depr
|
1290
|
+
assert_equal ids_expected, ids_disabled
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
test "order: allows string column names that are quoted with table, user and database" do
|
1294
|
+
ids_expected = Post.order(Arel.sql("id")).pluck(:id)
|
1295
|
+
|
1296
|
+
ids_depr = with_unsafe_raw_sql_deprecated { Post.order("[activerecord_unittest].[dbo].[posts].[id]").pluck(:id) }
|
1297
|
+
ids_disabled = with_unsafe_raw_sql_disabled { Post.order("[activerecord_unittest].[dbo].[posts].[id]").pluck(:id) }
|
1298
|
+
|
1299
|
+
assert_equal ids_expected, ids_depr
|
1300
|
+
assert_equal ids_expected, ids_disabled
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
test "pluck: allows string column name that are quoted" do
|
1304
|
+
titles_expected = Post.pluck(Arel.sql("title"))
|
1305
|
+
|
1306
|
+
titles_depr = with_unsafe_raw_sql_deprecated { Post.pluck("[title]") }
|
1307
|
+
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[title]") }
|
1308
|
+
|
1309
|
+
assert_equal titles_expected, titles_depr
|
1310
|
+
assert_equal titles_expected, titles_disabled
|
1311
|
+
end
|
1312
|
+
|
1313
|
+
test "pluck: allows string column name that are quoted with table" do
|
1314
|
+
titles_expected = Post.pluck(Arel.sql("title"))
|
1315
|
+
|
1316
|
+
titles_depr = with_unsafe_raw_sql_deprecated { Post.pluck("[posts].[title]") }
|
1317
|
+
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[posts].[title]") }
|
1318
|
+
|
1319
|
+
assert_equal titles_expected, titles_depr
|
1320
|
+
assert_equal titles_expected, titles_disabled
|
1321
|
+
end
|
1322
|
+
|
1323
|
+
test "pluck: allows string column name that are quoted with table and user" do
|
1324
|
+
titles_expected = Post.pluck(Arel.sql("title"))
|
1325
|
+
|
1326
|
+
titles_depr = with_unsafe_raw_sql_deprecated { Post.pluck("[dbo].[posts].[title]") }
|
1327
|
+
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[dbo].[posts].[title]") }
|
1328
|
+
|
1329
|
+
assert_equal titles_expected, titles_depr
|
1330
|
+
assert_equal titles_expected, titles_disabled
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
test "pluck: allows string column name that are quoted with table, user and database" do
|
1334
|
+
titles_expected = Post.pluck(Arel.sql("title"))
|
1335
|
+
|
1336
|
+
titles_depr = with_unsafe_raw_sql_deprecated { Post.pluck("[activerecord_unittest].[dbo].[posts].[title]") }
|
1337
|
+
titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("[activerecord_unittest].[dbo].[posts].[title]") }
|
1338
|
+
|
1339
|
+
assert_equal titles_expected, titles_depr
|
1340
|
+
assert_equal titles_expected, titles_disabled
|
1341
|
+
end
|
1276
1342
|
end
|
1277
1343
|
|
1278
1344
|
class ReservedWordTest < ActiveRecord::TestCase
|
@@ -157,13 +157,16 @@ class ColumnTestSQLServer < ActiveRecord::TestCase
|
|
157
157
|
_(col.default).must_equal BigDecimal("191")
|
158
158
|
_(obj.numeric_18_0).must_equal BigDecimal("191")
|
159
159
|
_(col.default_function).must_be_nil
|
160
|
+
|
160
161
|
type = connection.lookup_cast_type_from_column(col)
|
161
|
-
_(type).must_be_instance_of Type::
|
162
|
+
_(type).must_be_instance_of Type::DecimalWithoutScale
|
162
163
|
_(type.limit).must_be_nil
|
163
164
|
_(type.precision).must_equal 18
|
164
|
-
_(type.scale).
|
165
|
+
_(type.scale).must_be_nil
|
166
|
+
|
165
167
|
obj.numeric_18_0 = "192.1"
|
166
168
|
_(obj.numeric_18_0).must_equal BigDecimal("192")
|
169
|
+
|
167
170
|
obj.save!
|
168
171
|
_(obj.reload.numeric_18_0).must_equal BigDecimal("192")
|
169
172
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cases/helper_sqlserver"
|
4
|
+
require "models/post"
|
5
|
+
require "models/author"
|
6
|
+
|
7
|
+
class LateralTestSQLServer < ActiveRecord::TestCase
|
8
|
+
fixtures :posts, :authors
|
9
|
+
|
10
|
+
it 'uses OUTER APPLY for OUTER JOIN LATERAL' do
|
11
|
+
post = Arel::Table.new(:posts)
|
12
|
+
author = Arel::Table.new(:authors)
|
13
|
+
subselect = post.project(Arel.star).take(1).where(post[:author_id].eq(author[:id])).where(post[:id].eq(42))
|
14
|
+
|
15
|
+
one = Arel::Nodes::Quoted.new(1)
|
16
|
+
eq = Arel::Nodes::Equality.new(one, one)
|
17
|
+
|
18
|
+
sql = author.project(Arel.star).where(author[:name].matches("David")).outer_join(subselect.lateral.as("bar")).on(eq).to_sql
|
19
|
+
results = ActiveRecord::Base.connection.exec_query sql
|
20
|
+
assert_equal sql, "SELECT * FROM [authors] OUTER APPLY (SELECT * FROM [posts] WHERE [posts].[author_id] = [authors].[id] AND [posts].[id] = 42 ORDER BY [posts].[id] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) AS bar WHERE [authors].[name] LIKE N'David'"
|
21
|
+
assert_equal results.length, 1
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'uses CROSS APPLY for INNER JOIN LATERAL' do
|
25
|
+
post = Arel::Table.new(:posts)
|
26
|
+
author = Arel::Table.new(:authors)
|
27
|
+
subselect = post.project(Arel.star).take(1).where(post[:author_id].eq(author[:id])).where(post[:id].eq(42))
|
28
|
+
|
29
|
+
sql = author.project(Arel.star).where(author[:name].matches("David")).join(subselect.lateral.as("bar")).to_sql
|
30
|
+
results = ActiveRecord::Base.connection.exec_query sql
|
31
|
+
|
32
|
+
assert_equal sql, "SELECT * FROM [authors] CROSS APPLY (SELECT * FROM [posts] WHERE [posts].[author_id] = [authors].[id] AND [posts].[id] = 42 ORDER BY [posts].[id] ASC OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) AS bar WHERE [authors].[name] LIKE N'David'"
|
33
|
+
assert_equal results.length, 0
|
34
|
+
end
|
35
|
+
end
|
@@ -64,4 +64,48 @@ class MigrationTestSQLServer < ActiveRecord::TestCase
|
|
64
64
|
assert_nothing_raised { connection.change_column :people, :first_name, :text, null: true, default: nil }
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
describe "#create_schema" do
|
69
|
+
it "creates a new schema" do
|
70
|
+
connection.create_schema("some schema")
|
71
|
+
|
72
|
+
schemas = connection.exec_query("select name from sys.schemas").to_a
|
73
|
+
|
74
|
+
assert_includes schemas, { "name" => "some schema" }
|
75
|
+
end
|
76
|
+
|
77
|
+
it "creates a new schema with an owner" do
|
78
|
+
connection.create_schema("some schema", :guest)
|
79
|
+
|
80
|
+
schemas = connection.exec_query("select name, principal_id from sys.schemas").to_a
|
81
|
+
|
82
|
+
assert_includes schemas, { "name" => "some schema", "principal_id" => 2 }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#change_table_schema" do
|
87
|
+
before { connection.create_schema("foo") }
|
88
|
+
|
89
|
+
it "transfer the given table to the given schema" do
|
90
|
+
connection.change_table_schema("foo", "orders")
|
91
|
+
|
92
|
+
assert connection.data_source_exists?("foo.orders")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#drop_schema" do
|
97
|
+
before { connection.create_schema("some schema") }
|
98
|
+
|
99
|
+
it "drops a schema" do
|
100
|
+
schemas = connection.exec_query("select name from sys.schemas").to_a
|
101
|
+
|
102
|
+
assert_includes schemas, { "name" => "some schema" }
|
103
|
+
|
104
|
+
connection.drop_schema("some schema")
|
105
|
+
|
106
|
+
schemas = connection.exec_query("select name from sys.schemas").to_a
|
107
|
+
|
108
|
+
refute_includes schemas, { "name" => "some schema" }
|
109
|
+
end
|
110
|
+
end
|
67
111
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cases/helper_sqlserver"
|
4
|
+
require "models/company"
|
5
|
+
|
6
|
+
class OptimizerHitsTestSQLServer < ActiveRecord::TestCase
|
7
|
+
fixtures :companies
|
8
|
+
|
9
|
+
it "apply optimizations" do
|
10
|
+
assert_sql(%r{\ASELECT .+ FROM .+ OPTION \(HASH GROUP\)\z}) do
|
11
|
+
companies = Company.optimizer_hints("HASH GROUP")
|
12
|
+
companies = companies.distinct.select("firm_id")
|
13
|
+
assert_includes companies.explain, "| Hash Match | Aggregate |"
|
14
|
+
end
|
15
|
+
|
16
|
+
assert_sql(%r{\ASELECT .+ FROM .+ OPTION \(ORDER GROUP\)\z}) do
|
17
|
+
companies = Company.optimizer_hints("ORDER GROUP")
|
18
|
+
companies = companies.distinct.select("firm_id")
|
19
|
+
assert_includes companies.explain, "| Stream Aggregate | Aggregate |"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "apply multiple optimizations" do
|
24
|
+
assert_sql(%r{\ASELECT .+ FROM .+ OPTION \(HASH GROUP, FAST 1\)\z}) do
|
25
|
+
companies = Company.optimizer_hints("HASH GROUP", "FAST 1")
|
26
|
+
companies = companies.distinct.select("firm_id")
|
27
|
+
assert_includes companies.explain, "| Hash Match | Flow Distinct |"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "support subqueries" do
|
32
|
+
assert_sql(%r{.*'SELECT COUNT\(count_column\) FROM \(SELECT .*\) subquery_for_count OPTION \(MAXDOP 2\)'.*}) do
|
33
|
+
companies = Company.optimizer_hints("MAXDOP 2")
|
34
|
+
companies = companies.select(:id).where(firm_id: [0, 1]).limit(3)
|
35
|
+
assert_equal 3, companies.count
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "sanitize values" do
|
40
|
+
assert_sql(%r{\ASELECT .+ FROM .+ OPTION \(HASH GROUP\)\z}) do
|
41
|
+
companies = Company.optimizer_hints("OPTION (HASH GROUP)")
|
42
|
+
companies = companies.distinct.select("firm_id")
|
43
|
+
companies.to_a
|
44
|
+
end
|
45
|
+
|
46
|
+
assert_sql(%r{\ASELECT .+ FROM .+ OPTION \(HASH GROUP\)\z}) do
|
47
|
+
companies = Company.optimizer_hints("OPTION(HASH GROUP)")
|
48
|
+
companies = companies.distinct.select("firm_id")
|
49
|
+
companies.to_a
|
50
|
+
end
|
51
|
+
|
52
|
+
assert_sql(%r{\ASELECT .+ FROM .+ OPTION \(TABLE HINT \(\[companies\], INDEX\(1\)\)\)\z}) do
|
53
|
+
companies = Company.optimizer_hints("OPTION(TABLE HINT ([companies], INDEX(1)))")
|
54
|
+
companies = companies.distinct.select("firm_id")
|
55
|
+
companies.to_a
|
56
|
+
end
|
57
|
+
|
58
|
+
assert_sql(%r{\ASELECT .+ FROM .+ OPTION \(HASH GROUP\)\z}) do
|
59
|
+
companies = Company.optimizer_hints("Option(HASH GROUP)")
|
60
|
+
companies = companies.distinct.select("firm_id")
|
61
|
+
companies.to_a
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "skip optimization after unscope" do
|
66
|
+
assert_sql("SELECT DISTINCT [companies].[firm_id] FROM [companies]") do
|
67
|
+
companies = Company.optimizer_hints("HASH GROUP")
|
68
|
+
companies = companies.distinct.select("firm_id")
|
69
|
+
companies.unscope(:optimizer_hints).load
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -16,7 +16,7 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
16
16
|
assert_line :tinyint, type: "integer", limit: 1, precision: nil, scale: nil, default: 42
|
17
17
|
assert_line :bit, type: "boolean", limit: nil, precision: nil, scale: nil, default: true
|
18
18
|
assert_line :decimal_9_2, type: "decimal", limit: nil, precision: 9, scale: 2, default: 12345.01
|
19
|
-
assert_line :numeric_18_0, type: "decimal", limit: nil, precision: 18, scale:
|
19
|
+
assert_line :numeric_18_0, type: "decimal", limit: nil, precision: 18, scale: nil, default: 191
|
20
20
|
assert_line :numeric_36_2, type: "decimal", limit: nil, precision: 36, scale: 2, default: 12345678901234567890.01
|
21
21
|
assert_line :money, type: "money", limit: nil, precision: 19, scale: 4, default: 4.2
|
22
22
|
assert_line :smallmoney, type: "smallmoney", limit: nil, precision: 10, scale: 4, default: 4.2
|
@@ -75,7 +75,7 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
75
75
|
assert_line :integer_col, type: "integer", limit: nil, precision: nil, scale: nil, default: nil
|
76
76
|
assert_line :bigint_col, type: "bigint", limit: nil, precision: nil, scale: nil, default: nil
|
77
77
|
assert_line :boolean_col, type: "boolean", limit: nil, precision: nil, scale: nil, default: nil
|
78
|
-
assert_line :decimal_col, type: "decimal", limit: nil, precision: 18, scale:
|
78
|
+
assert_line :decimal_col, type: "decimal", limit: nil, precision: 18, scale: nil, default: nil
|
79
79
|
assert_line :float_col, type: "float", limit: nil, precision: nil, scale: nil, default: nil
|
80
80
|
assert_line :string_col, type: "string", limit: nil, precision: nil, scale: nil, default: nil
|
81
81
|
assert_line :text_col, type: "text", limit: nil, precision: nil, scale: nil, default: nil
|
@@ -166,13 +166,15 @@ class SchemaDumperTestSQLServer < ActiveRecord::TestCase
|
|
166
166
|
|
167
167
|
def assert_line(column_name, options = {})
|
168
168
|
line = line(column_name)
|
169
|
-
assert line, "
|
169
|
+
assert line, "Could not find line with column name: #{column_name.inspect} in schema:\n#{schema}"
|
170
|
+
|
170
171
|
[:type, :limit, :precision, :scale, :collation, :default].each do |key|
|
171
172
|
next unless options.key?(key)
|
172
173
|
|
173
174
|
actual = key == :type ? line.send(:type_method) : line.send(key)
|
174
175
|
expected = options[key]
|
175
176
|
message = "#{key.to_s.titleize} of #{expected.inspect} not found in:\n#{line}"
|
177
|
+
|
176
178
|
if expected.nil?
|
177
179
|
_(actual).must_be_nil message
|
178
180
|
elsif expected.is_a?(Array)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-sqlserver-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ken Collins
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2021-
|
17
|
+
date: 2021-04-12 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: activerecord
|
@@ -54,9 +54,9 @@ extra_rdoc_files: []
|
|
54
54
|
files:
|
55
55
|
- ".editorconfig"
|
56
56
|
- ".github/issue_template.md"
|
57
|
+
- ".github/workflows/ci.yml"
|
57
58
|
- ".gitignore"
|
58
59
|
- ".rubocop.yml"
|
59
|
-
- ".travis.yml"
|
60
60
|
- CHANGELOG.md
|
61
61
|
- CODE_OF_CONDUCT.md
|
62
62
|
- Dockerfile.ci
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/active_record/connection_adapters/sqlserver/type/datetime2.rb
|
105
105
|
- lib/active_record/connection_adapters/sqlserver/type/datetimeoffset.rb
|
106
106
|
- lib/active_record/connection_adapters/sqlserver/type/decimal.rb
|
107
|
+
- lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb
|
107
108
|
- lib/active_record/connection_adapters/sqlserver/type/float.rb
|
108
109
|
- lib/active_record/connection_adapters/sqlserver/type/integer.rb
|
109
110
|
- lib/active_record/connection_adapters/sqlserver/type/json.rb
|
@@ -154,7 +155,9 @@ files:
|
|
154
155
|
- test/cases/in_clause_test_sqlserver.rb
|
155
156
|
- test/cases/index_test_sqlserver.rb
|
156
157
|
- test/cases/json_test_sqlserver.rb
|
158
|
+
- test/cases/lateral_test_sqlserver.rb
|
157
159
|
- test/cases/migration_test_sqlserver.rb
|
160
|
+
- test/cases/optimizer_hints_test_sqlserver.rb
|
158
161
|
- test/cases/order_test_sqlserver.rb
|
159
162
|
- test/cases/pessimistic_locking_test_sqlserver.rb
|
160
163
|
- test/cases/rake_test_sqlserver.rb
|
@@ -214,8 +217,8 @@ licenses:
|
|
214
217
|
- MIT
|
215
218
|
metadata:
|
216
219
|
bug_tracker_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues
|
217
|
-
changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v6.0.
|
218
|
-
source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v6.0.
|
220
|
+
changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v6.0.2/CHANGELOG.md
|
221
|
+
source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v6.0.2
|
219
222
|
post_install_message:
|
220
223
|
rdoc_options: []
|
221
224
|
require_paths:
|
@@ -231,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
234
|
- !ruby/object:Gem::Version
|
232
235
|
version: '0'
|
233
236
|
requirements: []
|
234
|
-
rubygems_version: 3.
|
237
|
+
rubygems_version: 3.1.4
|
235
238
|
signing_key:
|
236
239
|
specification_version: 4
|
237
240
|
summary: ActiveRecord SQL Server Adapter.
|
@@ -253,7 +256,9 @@ test_files:
|
|
253
256
|
- test/cases/in_clause_test_sqlserver.rb
|
254
257
|
- test/cases/index_test_sqlserver.rb
|
255
258
|
- test/cases/json_test_sqlserver.rb
|
259
|
+
- test/cases/lateral_test_sqlserver.rb
|
256
260
|
- test/cases/migration_test_sqlserver.rb
|
261
|
+
- test/cases/optimizer_hints_test_sqlserver.rb
|
257
262
|
- test/cases/order_test_sqlserver.rb
|
258
263
|
- test/cases/pessimistic_locking_test_sqlserver.rb
|
259
264
|
- test/cases/rake_test_sqlserver.rb
|
data/.travis.yml
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
sudo: required
|
2
|
-
cache: bundler
|
3
|
-
services:
|
4
|
-
- docker
|
5
|
-
env:
|
6
|
-
global:
|
7
|
-
- COMPOSE_FILE: docker-compose.ci.yml
|
8
|
-
before_install:
|
9
|
-
- sudo rm /usr/local/bin/docker-compose
|
10
|
-
- sudo curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
11
|
-
- sudo chmod +x /usr/local/bin/docker-compose
|
12
|
-
install:
|
13
|
-
- docker-compose build --build-arg TARGET_VERSION=$TARGET_VERSION
|
14
|
-
script:
|
15
|
-
- docker-compose run ci
|
16
|
-
matrix:
|
17
|
-
include:
|
18
|
-
- name: 2.5.8
|
19
|
-
env: TARGET_VERSION=2.5.8
|
20
|
-
- name: 2.6.6
|
21
|
-
env: TARGET_VERSION=2.6.6
|
22
|
-
- name: 2.7.1
|
23
|
-
env: TARGET_VERSION=2.7.1
|