activerecord-sqlserver-adapter 6.1.0.0 → 6.1.1.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/CHANGELOG.md +14 -0
- data/README.md +1 -1
- data/VERSION +1 -1
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +5 -1
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +14 -5
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +0 -1
- data/lib/active_record/connection_adapters/sqlserver_column.rb +74 -35
- data/lib/arel/visitors/sqlserver.rb +15 -2
- data/test/cases/adapter_test_sqlserver.rb +2 -2
- data/test/cases/coerced_tests.rb +13 -0
- data/test/cases/column_test_sqlserver.rb +4 -0
- data/test/cases/fetch_test_sqlserver.rb +18 -0
- data/test/cases/rake_test_sqlserver.rb +35 -0
- data/test/models/sqlserver/composite_pk.rb +9 -0
- data/test/schema/sqlserver_specific_schema.rb +18 -0
- metadata +7 -6
- data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f481c462cbdd16314d87172f78c7a63f63f4c4f7f81df1ca84f110adcb3b6da8
|
4
|
+
data.tar.gz: cc79ad659b39244a0df7c37774922f22a537adf736adc9ba6344cdac6643c686
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0b3f273dfa36cc20e15d52384d8ba8d145f23c5816e7592b5c96324314a5204ea7d76879f6e27bd028cccf1be0411e0f7cbc60009f22b34831ff9383776b252
|
7
|
+
data.tar.gz: 6f34b2de7d27af451a8376501a46c65780ab960710632dceb939a4dbb39ac3a7754f48cf84da58e4f15064570d07792f8b779dde036720df74d483c462a7a5ed
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,23 @@
|
|
1
|
+
## v6.1.1.0
|
2
|
+
|
3
|
+
[Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.0.0...v6.1.1.0)
|
4
|
+
|
5
|
+
#### Fixed
|
6
|
+
|
7
|
+
- [#933](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/933) Conditionally apply SQL Server monkey patches to ActiveRecord so that it is safe to use this gem alongside other database adapters (e.g. PostgreSQL) in a multi-database Rails app
|
8
|
+
- [#935](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/935) Fix schema cache generation
|
9
|
+
(**breaking change**)
|
10
|
+
- [#936](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/936) Fix deteministic fetch when table has a composite primary key
|
11
|
+
- [#938](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/938) Fix date columns serialization for range values
|
12
|
+
|
1
13
|
## v6.1.0.0
|
2
14
|
|
3
15
|
- No changes
|
4
16
|
|
5
17
|
## v6.1.0.0.rc1
|
6
18
|
|
19
|
+
[Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/6-0-stable...v6.1.0.0.rc1)
|
20
|
+
|
7
21
|
#### Fixed
|
8
22
|
|
9
23
|
- [#872](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/872) Use native String#start_with
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ Interested in older versions? We follow a rational versioning policy that tracks
|
|
13
13
|
|
14
14
|
| Adapter Version | Rails Version | Support |
|
15
15
|
| --------------- | ------------- | ------------------------------------------------------------------------------------------- |
|
16
|
-
| `6.1.
|
16
|
+
| `6.1.1.0` | `6.1.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main) |
|
17
17
|
| `6.0.2` | `6.0.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable) |
|
18
18
|
| `5.2.1` | `5.2.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-2-stable) |
|
19
19
|
| `5.1.6` | `5.1.x` | [ended](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-1-stable) |
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
6.1.
|
1
|
+
6.1.1.0
|
@@ -10,6 +10,8 @@ module ActiveRecord
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def attributes_for_update(attribute_names)
|
13
|
+
return super unless self.class.connection.adapter_name == "SQLServer"
|
14
|
+
|
13
15
|
super.reject do |name|
|
14
16
|
column = self.class.columns_hash[name]
|
15
17
|
column && column.respond_to?(:is_identity?) && column.is_identity?
|
@@ -10,6 +10,8 @@ module ActiveRecord
|
|
10
10
|
module Calculations
|
11
11
|
# Same as original except we don't perform PostgreSQL hack that removes ordering.
|
12
12
|
def calculate(operation, column_name)
|
13
|
+
return super unless klass.connection.adapter_name == "SQLServer"
|
14
|
+
|
13
15
|
if has_include?(column_name)
|
14
16
|
relation = apply_join_dependency
|
15
17
|
|
@@ -29,6 +31,8 @@ module ActiveRecord
|
|
29
31
|
private
|
30
32
|
|
31
33
|
def build_count_subquery(relation, column_name, distinct)
|
34
|
+
return super unless klass.connection.adapter_name == "SQLServer"
|
35
|
+
|
32
36
|
super(relation.unscope(:order), column_name, distinct)
|
33
37
|
end
|
34
38
|
end
|
@@ -39,5 +43,5 @@ end
|
|
39
43
|
|
40
44
|
ActiveSupport.on_load(:active_record) do
|
41
45
|
mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Calculations
|
42
|
-
ActiveRecord::Relation.
|
46
|
+
ActiveRecord::Relation.include(mod)
|
43
47
|
end
|
@@ -9,6 +9,8 @@ module ActiveRecord
|
|
9
9
|
SQLSERVER_STATEMENT_REGEXP = /N'(.+)', N'(.+)', (.+)/
|
10
10
|
|
11
11
|
def exec_explain(queries)
|
12
|
+
return super unless connection.adapter_name == "SQLServer"
|
13
|
+
|
12
14
|
unprepared_queries = queries.map do |(sql, binds)|
|
13
15
|
[unprepare_sqlserver_statement(sql, binds), binds]
|
14
16
|
end
|
@@ -12,6 +12,8 @@ module ActiveRecord
|
|
12
12
|
|
13
13
|
# Same as original except we order by values in distinct select if present.
|
14
14
|
def construct_relation_for_exists(conditions)
|
15
|
+
return super unless klass.connection.adapter_name == "SQLServer"
|
16
|
+
|
15
17
|
conditions = sanitize_forbidden_attributes(conditions)
|
16
18
|
|
17
19
|
if distinct_value && offset_value
|
@@ -10,6 +10,8 @@ module ActiveRecord
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def records_for(ids)
|
13
|
+
return super unless klass.connection.adapter_name == "SQLServer"
|
14
|
+
|
13
15
|
ids.each_slice(in_clause_length).flat_map do |slice|
|
14
16
|
scope.where(association_key_name => slice).load do |record|
|
15
17
|
# Processing only the first owner
|
@@ -17,7 +17,8 @@ module ActiveRecord
|
|
17
17
|
precision: cast_type.precision,
|
18
18
|
scale: cast_type.scale
|
19
19
|
)
|
20
|
-
|
20
|
+
|
21
|
+
SQLServer::TypeMetadata.new(simple_type, **sqlserver_options)
|
21
22
|
end
|
22
23
|
|
23
24
|
def quote_string(s)
|
@@ -84,7 +84,7 @@ module ActiveRecord
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def new_column(name, default, sql_type_metadata, null, default_function = nil, collation = nil, comment = nil, sqlserver_options = {})
|
87
|
-
|
87
|
+
SQLServer::Column.new(
|
88
88
|
name,
|
89
89
|
default,
|
90
90
|
sql_type_metadata,
|
@@ -8,24 +8,33 @@ module ActiveRecord
|
|
8
8
|
|
9
9
|
include Deduplicable
|
10
10
|
|
11
|
-
attr_reader :
|
11
|
+
attr_reader :is_identity, :is_primary, :table_name, :ordinal_position
|
12
12
|
|
13
|
-
def initialize(type_metadata,
|
13
|
+
def initialize(type_metadata, is_identity: nil, is_primary: nil, table_name: nil, ordinal_position: nil)
|
14
14
|
super(type_metadata)
|
15
|
-
@
|
15
|
+
@is_identity = is_identity
|
16
|
+
@is_primary = is_primary
|
17
|
+
@table_name = table_name
|
18
|
+
@ordinal_position = ordinal_position
|
16
19
|
end
|
17
20
|
|
18
21
|
def ==(other)
|
19
22
|
other.is_a?(TypeMetadata) &&
|
20
23
|
__getobj__ == other.__getobj__ &&
|
21
|
-
|
24
|
+
is_identity == other.is_identity &&
|
25
|
+
is_primary == other.is_primary &&
|
26
|
+
table_name == other.table_name &&
|
27
|
+
ordinal_position == other.ordinal_position
|
22
28
|
end
|
23
29
|
alias eql? ==
|
24
30
|
|
25
31
|
def hash
|
26
32
|
TypeMetadata.hash ^
|
27
33
|
__getobj__.hash ^
|
28
|
-
|
34
|
+
is_identity.hash ^
|
35
|
+
is_primary.hash ^
|
36
|
+
table_name.hash ^
|
37
|
+
ordinal_position.hash
|
29
38
|
end
|
30
39
|
|
31
40
|
private
|
@@ -10,7 +10,6 @@ require "active_record/connection_adapters/sqlserver/core_ext/explain"
|
|
10
10
|
require "active_record/connection_adapters/sqlserver/core_ext/explain_subscriber"
|
11
11
|
require "active_record/connection_adapters/sqlserver/core_ext/attribute_methods"
|
12
12
|
require "active_record/connection_adapters/sqlserver/core_ext/finder_methods"
|
13
|
-
require "active_record/connection_adapters/sqlserver/core_ext/query_methods"
|
14
13
|
require "active_record/connection_adapters/sqlserver/core_ext/preloader"
|
15
14
|
require "active_record/connection_adapters/sqlserver/version"
|
16
15
|
require "active_record/connection_adapters/sqlserver/type"
|
@@ -2,48 +2,87 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
super
|
9
|
-
end
|
5
|
+
module SQLServer
|
6
|
+
class Column < ConnectionAdapters::Column
|
7
|
+
delegate :is_identity, :is_primary, :table_name, :ordinal_position, to: :sql_type_metadata
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
def initialize(*, is_identity: nil, is_primary: nil, table_name: nil, ordinal_position: nil, **)
|
10
|
+
super
|
11
|
+
@is_identity = is_identity
|
12
|
+
@is_primary = is_primary
|
13
|
+
@table_name = table_name
|
14
|
+
@ordinal_position = ordinal_position
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
def is_identity?
|
18
|
+
is_identity
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
def is_primary?
|
22
|
+
is_primary
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
def is_utf8?
|
26
|
+
sql_type =~ /nvarchar|ntext|nchar/i
|
27
|
+
end
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
def case_sensitive?
|
30
|
+
collation && collation.match(/_CS/)
|
31
|
+
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
33
|
+
def init_with(coder)
|
34
|
+
@is_identity = coder["is_identity"]
|
35
|
+
@is_primary = coder["is_primary"]
|
36
|
+
@table_name = coder["table_name"]
|
37
|
+
@ordinal_position = coder["ordinal_position"]
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
41
|
+
def encode_with(coder)
|
42
|
+
coder["is_identity"] = @is_identity
|
43
|
+
coder["is_primary"] = @is_primary
|
44
|
+
coder["table_name"] = @table_name
|
45
|
+
coder["ordinal_position"] = @ordinal_position
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def ==(other)
|
50
|
+
other.is_a?(Column) &&
|
51
|
+
super &&
|
52
|
+
is_identity? == other.is_identity? &&
|
53
|
+
is_primary? == other.is_primary? &&
|
54
|
+
table_name == other.table_name &&
|
55
|
+
ordinal_position == other.ordinal_position
|
56
|
+
end
|
57
|
+
alias :eql? :==
|
58
|
+
|
59
|
+
def hash
|
60
|
+
Column.hash ^
|
61
|
+
super.hash ^
|
62
|
+
is_identity?.hash ^
|
63
|
+
is_primary?.hash ^
|
64
|
+
table_name.hash ^
|
65
|
+
ordinal_position.hash
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# In the Rails version of this method there is an assumption that the `default` value will always be a
|
71
|
+
# `String` class, which must be true for the MySQL/PostgreSQL/SQLite adapters. However, in the SQL Server
|
72
|
+
# adapter the `default` value can also be Boolean/Date/Time/etc. Changed the implementation of this method
|
73
|
+
# to handle non-String `default` objects.
|
74
|
+
def deduplicated
|
75
|
+
@name = -name
|
76
|
+
@sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata
|
77
|
+
@default = (default.is_a?(String) ? -default : default.dup.freeze) if default
|
78
|
+
@default_function = -default_function if default_function
|
79
|
+
@collation = -collation if collation
|
80
|
+
@comment = -comment if comment
|
81
|
+
freeze
|
82
|
+
end
|
46
83
|
end
|
84
|
+
|
85
|
+
SQLServerColumn = SQLServer::Column
|
47
86
|
end
|
48
87
|
end
|
49
88
|
end
|
@@ -296,8 +296,21 @@ module Arel
|
|
296
296
|
def primary_Key_From_Table(t)
|
297
297
|
return unless t
|
298
298
|
|
299
|
-
|
300
|
-
|
299
|
+
primary_keys = @connection.schema_cache.primary_keys(t.name)
|
300
|
+
column_name = nil
|
301
|
+
|
302
|
+
case primary_keys
|
303
|
+
when NilClass
|
304
|
+
column_name = @connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
|
305
|
+
when String
|
306
|
+
column_name = primary_keys
|
307
|
+
when Array
|
308
|
+
candidate_columns = @connection.schema_cache.columns_hash(t.name).slice(*primary_keys).values
|
309
|
+
candidate_column = candidate_columns.find(&:is_identity?)
|
310
|
+
candidate_column ||= candidate_columns.first
|
311
|
+
column_name = candidate_column.try(:name)
|
312
|
+
end
|
313
|
+
|
301
314
|
column_name ? t[column_name] : nil
|
302
315
|
end
|
303
316
|
|
@@ -377,7 +377,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
377
377
|
assert !SSTestCustomersView.columns.blank?
|
378
378
|
assert_equal columns.size, SSTestCustomersView.columns.size
|
379
379
|
columns.each do |colname|
|
380
|
-
assert_instance_of ActiveRecord::ConnectionAdapters::
|
380
|
+
assert_instance_of ActiveRecord::ConnectionAdapters::SQLServer::Column,
|
381
381
|
SSTestCustomersView.columns_hash[colname],
|
382
382
|
"Column name #{colname.inspect} was not found in these columns #{SSTestCustomersView.columns.map(&:name).inspect}"
|
383
383
|
end
|
@@ -404,7 +404,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
|
|
404
404
|
assert !SSTestStringDefaultsView.columns.blank?
|
405
405
|
assert_equal columns.size, SSTestStringDefaultsView.columns.size
|
406
406
|
columns.each do |colname|
|
407
|
-
assert_instance_of ActiveRecord::ConnectionAdapters::
|
407
|
+
assert_instance_of ActiveRecord::ConnectionAdapters::SQLServer::Column,
|
408
408
|
SSTestStringDefaultsView.columns_hash[colname],
|
409
409
|
"Column name #{colname.inspect} was not found in these columns #{SSTestStringDefaultsView.columns.map(&:name).inspect}"
|
410
410
|
end
|
data/test/cases/coerced_tests.rb
CHANGED
@@ -1521,6 +1521,7 @@ module ActiveRecord
|
|
1521
1521
|
|
1522
1522
|
original_test_statement_cache_values_differ
|
1523
1523
|
ensure
|
1524
|
+
Book.where(author_id: nil, name: 'my book').delete_all
|
1524
1525
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1525
1526
|
end
|
1526
1527
|
end
|
@@ -1748,6 +1749,7 @@ class EnumTest < ActiveRecord::TestCase
|
|
1748
1749
|
|
1749
1750
|
send(:'original_enums are distinct per class')
|
1750
1751
|
ensure
|
1752
|
+
Book.where(author_id: nil, name: nil).delete_all
|
1751
1753
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1752
1754
|
end
|
1753
1755
|
|
@@ -1758,6 +1760,7 @@ class EnumTest < ActiveRecord::TestCase
|
|
1758
1760
|
|
1759
1761
|
send(:'original_creating new objects with enum scopes')
|
1760
1762
|
ensure
|
1763
|
+
Book.where(author_id: nil, name: nil).delete_all
|
1761
1764
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1762
1765
|
end
|
1763
1766
|
|
@@ -1768,6 +1771,7 @@ class EnumTest < ActiveRecord::TestCase
|
|
1768
1771
|
|
1769
1772
|
send(:'original_enums are inheritable')
|
1770
1773
|
ensure
|
1774
|
+
Book.where(author_id: nil, name: nil).delete_all
|
1771
1775
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1772
1776
|
end
|
1773
1777
|
|
@@ -1778,6 +1782,7 @@ class EnumTest < ActiveRecord::TestCase
|
|
1778
1782
|
|
1779
1783
|
send(:'original_declare multiple enums at a time')
|
1780
1784
|
ensure
|
1785
|
+
Book.where(author_id: nil, name: nil).delete_all
|
1781
1786
|
Book.connection.add_index(:books, [:author_id, :name], unique: true)
|
1782
1787
|
end
|
1783
1788
|
end
|
@@ -1843,6 +1848,14 @@ class LogSubscriberTest < ActiveRecord::TestCase
|
|
1843
1848
|
def test_vebose_query_logs_coerced
|
1844
1849
|
original_test_vebose_query_logs
|
1845
1850
|
end
|
1851
|
+
|
1852
|
+
# Bindings logged slightly differently.
|
1853
|
+
coerce_tests! :test_where_in_binds_logging_include_attribute_names
|
1854
|
+
def test_where_in_binds_logging_include_attribute_names_coerced
|
1855
|
+
Developer.where(id: [1, 2, 3, 4, 5]).load
|
1856
|
+
wait
|
1857
|
+
assert_match(%{@0 = 1, @1 = 2, @2 = 3, @3 = 4, @4 = 5 [["id", nil], ["id", nil], ["id", nil], ["id", nil], ["id", nil]]}, @logger.logged(:debug).last)
|
1858
|
+
end
|
1846
1859
|
end
|
1847
1860
|
|
1848
1861
|
class ActiveRecordSchemaTest < ActiveRecord::TestCase
|
@@ -299,6 +299,8 @@ class ColumnTestSQLServer < ActiveRecord::TestCase
|
|
299
299
|
_(obj.date).must_equal Date.civil(0001, 4, 1)
|
300
300
|
obj.reload
|
301
301
|
_(obj.date).must_equal Date.civil(0001, 4, 1)
|
302
|
+
# Can filter by date range
|
303
|
+
_(obj).must_equal obj.class.where(date: obj.date..Date::Infinity.new).first
|
302
304
|
# Can keep and return assigned date.
|
303
305
|
assert_obj_set_and_save :date, Date.civil(1972, 04, 14)
|
304
306
|
# Can accept and cast time objects.
|
@@ -333,6 +335,8 @@ class ColumnTestSQLServer < ActiveRecord::TestCase
|
|
333
335
|
obj.reload
|
334
336
|
_(obj.datetime).must_equal time, "Microseconds were <#{obj.datetime.usec}> vs <3000>"
|
335
337
|
_(obj).must_equal obj.class.where(datetime: time).first
|
338
|
+
# Can filter by datetime range
|
339
|
+
_(obj).must_equal obj.class.where(datetime: time..DateTime::Infinity.new).first
|
336
340
|
# Will cast to true DB value on attribute write, save and return again.
|
337
341
|
time = Time.utc 2010, 04, 01, 12, 34, 56, 234567
|
338
342
|
time2 = Time.utc 2010, 04, 01, 12, 34, 56, 233000
|
@@ -49,3 +49,21 @@ class FetchTestSqlserver < ActiveRecord::TestCase
|
|
49
49
|
@books = (1..10).map { |i| Book.create! name: "Name-#{i}" }
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
class DeterministicFetchWithCompositePkTestSQLServer < ActiveRecord::TestCase
|
54
|
+
it "orders by the identity column if table has one" do
|
55
|
+
SSCompositePkWithIdentity.delete_all
|
56
|
+
SSCompositePkWithIdentity.create(pk_col_two: 2)
|
57
|
+
SSCompositePkWithIdentity.create(pk_col_two: 1)
|
58
|
+
|
59
|
+
_(SSCompositePkWithIdentity.take(1).map(&:pk_col_two)).must_equal [2]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "orders by the first column if table has no identity column" do
|
63
|
+
SSCompositePkWithoutIdentity.delete_all
|
64
|
+
SSCompositePkWithoutIdentity.create(pk_col_one: 2, pk_col_two: 2)
|
65
|
+
SSCompositePkWithoutIdentity.create(pk_col_one: 1, pk_col_two: 1)
|
66
|
+
|
67
|
+
_(SSCompositePkWithoutIdentity.take(1).map(&:pk_col_two)).must_equal [1]
|
68
|
+
end
|
69
|
+
end
|
@@ -156,3 +156,38 @@ class SQLServerRakeStructureDumpLoadTest < SQLServerRakeTest
|
|
156
156
|
_(connection.tables).must_include "users"
|
157
157
|
end
|
158
158
|
end
|
159
|
+
|
160
|
+
class SQLServerRakeSchemaCacheDumpLoadTest < SQLServerRakeTest
|
161
|
+
let(:filename) { File.join ARTest::SQLServer.test_root_sqlserver, "schema_cache.yml" }
|
162
|
+
let(:filedata) { File.read(filename) }
|
163
|
+
|
164
|
+
before do
|
165
|
+
quietly { db_tasks.create(configuration) }
|
166
|
+
|
167
|
+
connection.create_table :users, force: true do |t|
|
168
|
+
t.string :name, null: false
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
after do
|
173
|
+
FileUtils.rm_rf(filename)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "dumps schema cache with SQL Server metadata" do
|
177
|
+
quietly { db_tasks.dump_schema_cache connection, filename }
|
178
|
+
|
179
|
+
schema_cache = YAML.load(File.read(filename))
|
180
|
+
|
181
|
+
col_id, col_name = connection.schema_cache.columns("users")
|
182
|
+
|
183
|
+
assert col_id.is_identity
|
184
|
+
assert col_id.is_primary
|
185
|
+
assert_equal col_id.ordinal_position, 1
|
186
|
+
assert_equal col_id.table_name, "users"
|
187
|
+
|
188
|
+
assert_not col_name.is_identity
|
189
|
+
assert_not col_name.is_primary
|
190
|
+
assert_equal col_name.ordinal_position, 2
|
191
|
+
assert_equal col_name.table_name, "users"
|
192
|
+
end
|
193
|
+
end
|
@@ -294,4 +294,22 @@ ActiveRecord::Schema.define do
|
|
294
294
|
CONSTRAINT PK_UNIQUE_KEY PRIMARY KEY (id)
|
295
295
|
);
|
296
296
|
SQLSERVERUNIQUEKEYS
|
297
|
+
|
298
|
+
execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sst_composite_without_identity') DROP TABLE sst_composite_without_identity"
|
299
|
+
execute <<-COMPOSITE_WITHOUT_IDENTITY
|
300
|
+
CREATE TABLE sst_composite_without_identity (
|
301
|
+
pk_col_one int NOT NULL,
|
302
|
+
pk_col_two int NOT NULL,
|
303
|
+
CONSTRAINT PK_sst_composite_without_identity PRIMARY KEY (pk_col_one, pk_col_two)
|
304
|
+
);
|
305
|
+
COMPOSITE_WITHOUT_IDENTITY
|
306
|
+
|
307
|
+
execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sst_composite_with_identity') DROP TABLE sst_composite_with_identity"
|
308
|
+
execute <<-COMPOSITE_WITH_IDENTITY
|
309
|
+
CREATE TABLE sst_composite_with_identity (
|
310
|
+
pk_col_one int IDENTITY NOT NULL,
|
311
|
+
pk_col_two int NOT NULL,
|
312
|
+
CONSTRAINT PK_sst_composite_with_identity PRIMARY KEY (pk_col_one, pk_col_two)
|
313
|
+
);
|
314
|
+
COMPOSITE_WITH_IDENTITY
|
297
315
|
end
|
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.1.
|
4
|
+
version: 6.1.1.0
|
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-08-11 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: activerecord
|
@@ -78,7 +78,6 @@ files:
|
|
78
78
|
- lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb
|
79
79
|
- lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb
|
80
80
|
- lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb
|
81
|
-
- lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb
|
82
81
|
- lib/active_record/connection_adapters/sqlserver/database_limits.rb
|
83
82
|
- lib/active_record/connection_adapters/sqlserver/database_statements.rb
|
84
83
|
- lib/active_record/connection_adapters/sqlserver/database_tasks.rb
|
@@ -180,6 +179,7 @@ files:
|
|
180
179
|
- test/migrations/create_clients_and_change_column_null.rb
|
181
180
|
- test/migrations/transaction_table/1_table_will_never_be_created.rb
|
182
181
|
- test/models/sqlserver/booking.rb
|
182
|
+
- test/models/sqlserver/composite_pk.rb
|
183
183
|
- test/models/sqlserver/customers_view.rb
|
184
184
|
- test/models/sqlserver/datatype.rb
|
185
185
|
- test/models/sqlserver/datatype_migration.rb
|
@@ -224,8 +224,8 @@ licenses:
|
|
224
224
|
- MIT
|
225
225
|
metadata:
|
226
226
|
bug_tracker_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues
|
227
|
-
changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v6.1.
|
228
|
-
source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v6.1.
|
227
|
+
changelog_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/v6.1.1.0/CHANGELOG.md
|
228
|
+
source_code_uri: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/v6.1.1.0
|
229
229
|
post_install_message:
|
230
230
|
rdoc_options: []
|
231
231
|
require_paths:
|
@@ -241,7 +241,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
241
241
|
- !ruby/object:Gem::Version
|
242
242
|
version: '0'
|
243
243
|
requirements: []
|
244
|
-
rubygems_version: 3.2.
|
244
|
+
rubygems_version: 3.2.22
|
245
245
|
signing_key:
|
246
246
|
specification_version: 4
|
247
247
|
summary: ActiveRecord SQL Server Adapter.
|
@@ -288,6 +288,7 @@ test_files:
|
|
288
288
|
- test/migrations/create_clients_and_change_column_null.rb
|
289
289
|
- test/migrations/transaction_table/1_table_will_never_be_created.rb
|
290
290
|
- test/models/sqlserver/booking.rb
|
291
|
+
- test/models/sqlserver/composite_pk.rb
|
291
292
|
- test/models/sqlserver/customers_view.rb
|
292
293
|
- test/models/sqlserver/datatype.rb
|
293
294
|
- test/models/sqlserver/datatype_migration.rb
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_record/relation"
|
4
|
-
require "active_record/version"
|
5
|
-
|
6
|
-
module ActiveRecord
|
7
|
-
module ConnectionAdapters
|
8
|
-
module SQLServer
|
9
|
-
module CoreExt
|
10
|
-
module QueryMethods
|
11
|
-
private
|
12
|
-
|
13
|
-
# Copy of original from Rails master.
|
14
|
-
# This patch can be removed when adapter supports Rails version greater than 6.0.2.2
|
15
|
-
def table_name_matches?(from)
|
16
|
-
table_name = Regexp.escape(table.name)
|
17
|
-
quoted_table_name = Regexp.escape(connection.quote_table_name(table.name))
|
18
|
-
/(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
ActiveSupport.on_load(:active_record) do
|
27
|
-
ActiveRecord::Relation.include(ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::QueryMethods)
|
28
|
-
end
|