activerecord-sqlserver-adapter 6.0.1 → 6.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
* [![
|
3
|
+
* [![CI](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/actions/workflows/ci.yml/badge.svg)](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/actions/workflows/ci.yml) - CI
|
4
4
|
* [![Build Status](https://ci.appveyor.com/api/projects/status/mtgbx8f57vr7k2qa/branch/master?svg=true)](https://ci.appveyor.com/project/rails-sqlserver/activerecord-sqlserver-adapter/branch/master) - Appveyor
|
5
5
|
* [![Gem Version](http://img.shields.io/gem/v/activerecord-sqlserver-adapter.svg)](https://rubygems.org/gems/activerecord-sqlserver-adapter) - Gem Version
|
6
6
|
* [![Gitter chat](https://img.shields.io/badge/%E2%8A%AA%20GITTER%20-JOIN%20CHAT%20%E2%86%92-brightgreen.svg?style=flat)](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
|