activerecord-sqlserver-adapter 6.0.1 → 6.1.1.0
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 +29 -46
- data/README.md +32 -3
- data/RUNNING_UNIT_TESTS.md +1 -1
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +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 -10
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +9 -2
- 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/database_limits.rb +0 -4
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +28 -16
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +8 -7
- data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -1
- data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -3
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +31 -9
- data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +36 -7
- data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +0 -1
- data/lib/active_record/connection_adapters/sqlserver/transaction.rb +2 -2
- data/lib/active_record/connection_adapters/sqlserver/type.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver/type/date.rb +2 -1
- data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
- data/lib/active_record/connection_adapters/sqlserver/utils.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +100 -69
- data/lib/active_record/connection_adapters/sqlserver_column.rb +75 -19
- data/lib/active_record/sqlserver_base.rb +9 -15
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +17 -14
- data/lib/arel/visitors/sqlserver.rb +125 -40
- data/test/cases/adapter_test_sqlserver.rb +50 -16
- data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
- data/test/cases/coerced_tests.rb +611 -78
- data/test/cases/column_test_sqlserver.rb +9 -2
- data/test/cases/disconnected_test_sqlserver.rb +39 -0
- data/test/cases/execute_procedure_test_sqlserver.rb +9 -0
- data/test/cases/fetch_test_sqlserver.rb +18 -0
- data/test/cases/in_clause_test_sqlserver.rb +27 -0
- data/test/cases/lateral_test_sqlserver.rb +35 -0
- data/test/cases/migration_test_sqlserver.rb +51 -0
- data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
- data/test/cases/order_test_sqlserver.rb +7 -0
- data/test/cases/primary_keys_test_sqlserver.rb +103 -0
- data/test/cases/rake_test_sqlserver.rb +38 -2
- data/test/cases/schema_dumper_test_sqlserver.rb +14 -3
- data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
- data/test/models/sqlserver/composite_pk.rb +9 -0
- data/test/models/sqlserver/sst_string_collation.rb +3 -0
- data/test/schema/sqlserver_specific_schema.rb +25 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
- data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
- data/test/support/sql_counter_sqlserver.rb +14 -12
- metadata +29 -9
- data/.travis.yml +0 -23
- 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
|
@@ -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,60 +1,43 @@
|
|
1
|
-
## v6.
|
1
|
+
## v6.1.1.0
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
- [#851](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/851) Updated 'column_definitions_sql' to ensure that only primary key key constraints are queried for
|
6
|
-
|
7
|
-
## v6.0.0
|
8
|
-
|
9
|
-
**No Changes**
|
10
|
-
|
11
|
-
## v6.0.0.rc2
|
3
|
+
[Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/v6.1.0.0...v6.1.1.0)
|
12
4
|
|
13
5
|
#### Fixed
|
14
6
|
|
15
|
-
- [#
|
16
|
-
- [#
|
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
|
17
12
|
|
18
|
-
|
13
|
+
## v6.1.0.0
|
14
|
+
|
15
|
+
- No changes
|
19
16
|
|
20
|
-
|
21
|
-
- [#827](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/827) Rubocop: Enable Layout/EmptyLinesAroundClassBody cop
|
22
|
-
- [#828](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/828) Rubocop: Enable Layout/EmptyLines cop
|
23
|
-
- [#829](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/829) Rubocop: Enable Layout/Layout/EmptyLinesAround* cops
|
24
|
-
- [#830](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/830) Rubocop: Enable Layout/IndentationWidth and Layout/TrailingWhitespace cops
|
25
|
-
- [#831](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/831) Rubocop: Enable Spacing cops
|
26
|
-
- [#832](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/832) Rubocop: Enable Bundler cops
|
27
|
-
- [#833](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/833) Rubocop: Enable Layout/* cops
|
28
|
-
- [#834](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/834) Rubocop: Enable Lint/UselessAssignment cop
|
29
|
-
- [#835](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/835) Rubocop: Configure Naming cops
|
17
|
+
## v6.1.0.0.rc1
|
30
18
|
|
31
|
-
|
19
|
+
[Full changelog](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/compare/6-0-stable...v6.1.0.0.rc1)
|
32
20
|
|
33
21
|
#### Fixed
|
34
22
|
|
35
|
-
- [#
|
36
|
-
- [#
|
37
|
-
- [#
|
38
|
-
- [#
|
39
|
-
- [#
|
40
|
-
- [#
|
41
|
-
- [#
|
42
|
-
- [#
|
43
|
-
- [#
|
23
|
+
- [#872](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/872) Use native String#start_with
|
24
|
+
- [#876](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/876) Use native String#end_with
|
25
|
+
- [#873](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/873) Various fixes to get the tests running for Rails 6.1
|
26
|
+
- [#874](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/874) Deduplicate schema cache structures
|
27
|
+
- [#875](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/875) Handle default boolean column values when deduplicating
|
28
|
+
- [#879](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/879) Added visit method for HomogeneousIn
|
29
|
+
- [#880](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/880) Handle any default column class when deduplicating
|
30
|
+
- [#861](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/861) Fix Rails 6.1 database config
|
31
|
+
- [#890](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/890) Fix removal of invalid ordering from select statements
|
32
|
+
- [#881](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/881) Dump column collation to schema.rb and allow collation changes using column_change
|
33
|
+
- [#891](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/891) Add support for if_not_exists to indexes
|
34
|
+
- [#892](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/892) Add support for if_exists on remove_column
|
35
|
+
- [#883](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/885) Fix quoting of ActiveRecord::Relation::QueryAttribute and ActiveModel::Attributes
|
36
|
+
- [#893](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/893) Add Active Record Marshal forward compatibility tests
|
37
|
+
- [#903](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/903) Raise ActiveRecord::ConnectionNotEstablished on calls to execute with a disconnected connection
|
44
38
|
|
45
39
|
#### Changed
|
46
40
|
|
47
|
-
- [#
|
48
|
-
- [#763](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/763) Refactor columns introspection query to make it faster
|
49
|
-
- [#783](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/783) Update test matrix
|
50
|
-
- [#820](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/820) Enable frozen strings for tests
|
51
|
-
- [#821](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/821) Enable frozen strings - part 1
|
52
|
-
- [#822](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/822) Enable frozen strings - part 2
|
53
|
-
- [#823](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/823) Enable frozen strings - final
|
54
|
-
- [#824](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/824) Tidy up Gemfile
|
55
|
-
|
56
|
-
#### Added
|
57
|
-
|
58
|
-
- [#726](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/726) How to Develop ActiveRecord SQL Server Adapter with Pre-Installed MS SQL
|
41
|
+
- [#917](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/917) Refactored to use new_client connection pattern
|
59
42
|
|
60
|
-
Please check [
|
43
|
+
Please check [6-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/6-0-stable/CHANGELOG.md) for previous changes.
|
data/README.md
CHANGED
@@ -1,15 +1,26 @@
|
|
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
|
7
7
|
|
8
8
|
## About The Adapter
|
9
9
|
|
10
|
-
The SQL Server adapter for ActiveRecord
|
10
|
+
The SQL Server adapter for ActiveRecord using SQL Server 2012 or higher.
|
11
11
|
|
12
|
-
Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our
|
12
|
+
Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 6.x version of the adapter is only for the latest 6.x version of Rails. If you need the adapter for SQL Server 2008 or 2005, you are still in the right spot. Just install the latest 3.2.x to 4.1.x version of the adapter that matches your Rails version. We also have stable branches for each major/minor release of ActiveRecord.
|
13
|
+
|
14
|
+
| Adapter Version | Rails Version | Support |
|
15
|
+
| --------------- | ------------- | ------------------------------------------------------------------------------------------- |
|
16
|
+
| `6.1.1.0` | `6.1.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main) |
|
17
|
+
| `6.0.2` | `6.0.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable) |
|
18
|
+
| `5.2.1` | `5.2.x` | [active](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-2-stable) |
|
19
|
+
| `5.1.6` | `5.1.x` | [ended](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-1-stable) |
|
20
|
+
| `4.2.18` | `4.2.x` | [ended](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/4-2-stable) |
|
21
|
+
| `4.1.8` | `4.1.x` | [ended](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/4-1-stable) |
|
22
|
+
|
23
|
+
For older versions, please check their stable branches.
|
13
24
|
|
14
25
|
#### Native Data Type Support
|
15
26
|
|
@@ -52,6 +63,24 @@ Depending on your user and schema setup, it may be needed to use a table name pr
|
|
52
63
|
ActiveRecord::Base.table_name_prefix = 'dbo.'
|
53
64
|
```
|
54
65
|
|
66
|
+
It's also possible to create/change/drop a schema in the migration file as in the example below:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
class CreateFooSchema < ActiveRecord::Migration[6.0]
|
70
|
+
def up
|
71
|
+
create_schema('foo')
|
72
|
+
|
73
|
+
# Or you could move a table to a different schema
|
74
|
+
|
75
|
+
change_table_schema('foo', 'dbo.admin')
|
76
|
+
end
|
77
|
+
|
78
|
+
def down
|
79
|
+
drop_schema('foo')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
55
84
|
|
56
85
|
#### Configure Connection & App Name
|
57
86
|
|
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.
|
1
|
+
6.1.1.0
|
@@ -27,6 +27,6 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
-
spec.add_dependency "activerecord", "~> 6.
|
30
|
+
spec.add_dependency "activerecord", "~> 6.1.0"
|
31
31
|
spec.add_dependency "tiny_tds"
|
32
32
|
end
|
@@ -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,16 +31,9 @@ module ActiveRecord
|
|
29
31
|
private
|
30
32
|
|
31
33
|
def build_count_subquery(relation, column_name, distinct)
|
32
|
-
super
|
33
|
-
end
|
34
|
+
return super unless klass.connection.adapter_name == "SQLServer"
|
34
35
|
|
35
|
-
|
36
|
-
case operation
|
37
|
-
when "count" then value.to_i
|
38
|
-
when "sum" then type.deserialize(value || 0)
|
39
|
-
when "average" then value&.respond_to?(:to_d) ? value.to_d : value
|
40
|
-
else type.deserialize(value)
|
41
|
-
end
|
36
|
+
super(relation.unscope(:order), column_name, distinct)
|
42
37
|
end
|
43
38
|
end
|
44
39
|
end
|
@@ -48,5 +43,5 @@ end
|
|
48
43
|
|
49
44
|
ActiveSupport.on_load(:active_record) do
|
50
45
|
mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Calculations
|
51
|
-
ActiveRecord::Relation.
|
46
|
+
ActiveRecord::Relation.include(mod)
|
52
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
|
@@ -21,13 +23,18 @@ module ActiveRecord
|
|
21
23
|
# which uses sp_executesql to just the first argument, then unquote it. Likewise our
|
22
24
|
# `sp_executesql` method should substitude the @n args with the quoted values.
|
23
25
|
def unprepare_sqlserver_statement(sql, binds)
|
24
|
-
return sql unless sql.
|
26
|
+
return sql unless sql.start_with?(SQLSERVER_STATEMENT_PREFIX)
|
25
27
|
|
26
28
|
executesql = sql.from(SQLSERVER_STATEMENT_PREFIX.length)
|
27
29
|
executesql = executesql.match(SQLSERVER_STATEMENT_REGEXP).to_a[1]
|
28
30
|
|
29
31
|
binds.each_with_index do |bind, index|
|
30
|
-
|
32
|
+
|
33
|
+
value = if bind.is_a?(::ActiveModel::Attribute) then
|
34
|
+
connection.quote(bind.value_for_database)
|
35
|
+
else
|
36
|
+
connection.quote(bind)
|
37
|
+
end
|
31
38
|
executesql = executesql.sub("@#{index}", value)
|
32
39
|
end
|
33
40
|
|
@@ -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
|
@@ -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:
|
@@ -17,6 +17,7 @@ module ActiveRecord
|
|
17
17
|
end
|
18
18
|
|
19
19
|
materialize_transactions
|
20
|
+
mark_transaction_written_if_write(sql)
|
20
21
|
|
21
22
|
if id_insert_table_name = query_requires_identity_insert?(sql)
|
22
23
|
with_identity_insert_enabled(id_insert_table_name) { do_execute(sql, name) }
|
@@ -31,6 +32,7 @@ module ActiveRecord
|
|
31
32
|
end
|
32
33
|
|
33
34
|
materialize_transactions
|
35
|
+
mark_transaction_written_if_write(sql)
|
34
36
|
|
35
37
|
sp_executesql(sql, name, binds, prepare: prepare)
|
36
38
|
end
|
@@ -54,7 +56,7 @@ module ActiveRecord
|
|
54
56
|
end
|
55
57
|
|
56
58
|
def begin_db_transaction
|
57
|
-
do_execute "BEGIN TRANSACTION"
|
59
|
+
do_execute "BEGIN TRANSACTION", "TRANSACTION"
|
58
60
|
end
|
59
61
|
|
60
62
|
def transaction_isolation_levels
|
@@ -67,25 +69,25 @@ module ActiveRecord
|
|
67
69
|
end
|
68
70
|
|
69
71
|
def set_transaction_isolation_level(isolation_level)
|
70
|
-
do_execute "SET TRANSACTION ISOLATION LEVEL #{isolation_level}"
|
72
|
+
do_execute "SET TRANSACTION ISOLATION LEVEL #{isolation_level}", "TRANSACTION"
|
71
73
|
end
|
72
74
|
|
73
75
|
def commit_db_transaction
|
74
|
-
do_execute "COMMIT TRANSACTION"
|
76
|
+
do_execute "COMMIT TRANSACTION", "TRANSACTION"
|
75
77
|
end
|
76
78
|
|
77
79
|
def exec_rollback_db_transaction
|
78
|
-
do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
|
80
|
+
do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION", "TRANSACTION"
|
79
81
|
end
|
80
82
|
|
81
83
|
include Savepoints
|
82
84
|
|
83
85
|
def create_savepoint(name = current_savepoint_name)
|
84
|
-
do_execute "SAVE TRANSACTION #{name}"
|
86
|
+
do_execute "SAVE TRANSACTION #{name}", "TRANSACTION"
|
85
87
|
end
|
86
88
|
|
87
89
|
def exec_rollback_to_savepoint(name = current_savepoint_name)
|
88
|
-
do_execute "ROLLBACK TRANSACTION #{name}"
|
90
|
+
do_execute "ROLLBACK TRANSACTION #{name}", "TRANSACTION"
|
89
91
|
end
|
90
92
|
|
91
93
|
def release_savepoint(name = current_savepoint_name)
|
@@ -165,7 +167,7 @@ module ActiveRecord
|
|
165
167
|
log(sql, name) do
|
166
168
|
case @connection_options[:mode]
|
167
169
|
when :dblib
|
168
|
-
result =
|
170
|
+
result = ensure_established_connection! { dblib_execute(sql) }
|
169
171
|
options = { as: :hash, cache_rows: true, timezone: ActiveRecord::Base.default_timezone || :utc }
|
170
172
|
result.each(options) do |row|
|
171
173
|
r = row.with_indifferent_access
|
@@ -291,6 +293,7 @@ module ActiveRecord
|
|
291
293
|
|
292
294
|
def do_execute(sql, name = "SQL")
|
293
295
|
materialize_transactions
|
296
|
+
mark_transaction_written_if_write(sql)
|
294
297
|
|
295
298
|
log(sql, name) { raw_connection_do(sql) }
|
296
299
|
end
|
@@ -354,13 +357,7 @@ module ActiveRecord
|
|
354
357
|
def raw_connection_do(sql)
|
355
358
|
case @connection_options[:mode]
|
356
359
|
when :dblib
|
357
|
-
result =
|
358
|
-
|
359
|
-
# TinyTDS returns false instead of raising an exception if connection fails.
|
360
|
-
# Getting around this by raising an exception ourselves while this PR
|
361
|
-
# https://github.com/rails-sqlserver/tiny_tds/pull/469 is not released.
|
362
|
-
raise TinyTds::Error, "failed to execute statement" if result.is_a?(FalseClass)
|
363
|
-
|
360
|
+
result = ensure_established_connection! { dblib_execute(sql) }
|
364
361
|
result.do
|
365
362
|
end
|
366
363
|
ensure
|
@@ -425,7 +422,7 @@ module ActiveRecord
|
|
425
422
|
def raw_connection_run(sql)
|
426
423
|
case @connection_options[:mode]
|
427
424
|
when :dblib
|
428
|
-
|
425
|
+
ensure_established_connection! { dblib_execute(sql) }
|
429
426
|
end
|
430
427
|
end
|
431
428
|
|
@@ -459,6 +456,21 @@ module ActiveRecord
|
|
459
456
|
end
|
460
457
|
handle
|
461
458
|
end
|
459
|
+
|
460
|
+
def dblib_execute(sql)
|
461
|
+
@connection.execute(sql).tap do |result|
|
462
|
+
# TinyTDS returns false instead of raising an exception if connection fails.
|
463
|
+
# Getting around this by raising an exception ourselves while this PR
|
464
|
+
# https://github.com/rails-sqlserver/tiny_tds/pull/469 is not released.
|
465
|
+
raise TinyTds::Error, "failed to execute statement" if result.is_a?(FalseClass)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
def ensure_established_connection!
|
470
|
+
raise TinyTds::Error, 'SQL Server client is not connected' unless @connection
|
471
|
+
|
472
|
+
yield
|
473
|
+
end
|
462
474
|
end
|
463
475
|
end
|
464
476
|
end
|
@@ -10,14 +10,15 @@ module ActiveRecord
|
|
10
10
|
|
11
11
|
def fetch_type_metadata(sql_type, sqlserver_options = {})
|
12
12
|
cast_type = lookup_cast_type(sql_type)
|
13
|
-
|
13
|
+
simple_type = SqlTypeMetadata.new(
|
14
14
|
sql_type: sql_type,
|
15
15
|
type: cast_type.type,
|
16
16
|
limit: cast_type.limit,
|
17
17
|
precision: cast_type.precision,
|
18
|
-
scale: cast_type.scale
|
19
|
-
sqlserver_options: sqlserver_options
|
18
|
+
scale: cast_type.scale
|
20
19
|
)
|
20
|
+
|
21
|
+
SQLServer::TypeMetadata.new(simple_type, **sqlserver_options)
|
21
22
|
end
|
22
23
|
|
23
24
|
def quote_string(s)
|
@@ -83,8 +84,8 @@ module ActiveRecord
|
|
83
84
|
\A
|
84
85
|
(
|
85
86
|
(?:
|
86
|
-
# [table_name].[column_name] | function(one or no argument)
|
87
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
87
|
+
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
|
88
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
88
89
|
)
|
89
90
|
(?:\s+AS\s+(?:\w+|\[\w+\]))?
|
90
91
|
)
|
@@ -96,8 +97,8 @@ module ActiveRecord
|
|
96
97
|
\A
|
97
98
|
(
|
98
99
|
(?:
|
99
|
-
# [table_name].[column_name] | function(one or no argument)
|
100
|
-
((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
100
|
+
# [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
|
101
|
+
((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
|
101
102
|
)
|
102
103
|
(?:\s+ASC|\s+DESC)?
|
103
104
|
(?:\s+NULLS\s+(?:FIRST|LAST))?
|