activerecord-sqlserver-adapter 7.1.8 → 7.2.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/.devcontainer/Dockerfile +3 -3
- data/.github/workflows/ci.yml +11 -5
- data/CHANGELOG.md +5 -105
- data/Gemfile +4 -4
- data/README.md +40 -17
- data/VERSION +1 -1
- data/activerecord-sqlserver-adapter.gemspec +2 -2
- data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +6 -5
- data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +7 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +6 -4
- data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +14 -12
- data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +49 -34
- data/lib/active_record/connection_adapters/sqlserver/quoting.rb +44 -46
- data/lib/active_record/connection_adapters/sqlserver/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +2 -5
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +38 -32
- data/lib/arel/visitors/sqlserver.rb +22 -9
- data/test/cases/active_schema_test_sqlserver.rb +6 -6
- data/test/cases/adapter_test_sqlserver.rb +17 -18
- data/test/cases/coerced_tests.rb +262 -190
- data/test/cases/disconnected_test_sqlserver.rb +9 -3
- data/test/cases/eager_load_too_many_ids_test_sqlserver.rb +1 -1
- data/test/cases/enum_test_sqlserver.rb +1 -1
- data/test/cases/execute_procedure_test_sqlserver.rb +9 -5
- data/test/cases/helper_sqlserver.rb +11 -5
- data/test/cases/index_test_sqlserver.rb +8 -6
- data/test/cases/json_test_sqlserver.rb +1 -1
- data/test/cases/lateral_test_sqlserver.rb +2 -2
- data/test/cases/migration_test_sqlserver.rb +1 -1
- data/test/cases/optimizer_hints_test_sqlserver.rb +12 -12
- data/test/cases/pessimistic_locking_test_sqlserver.rb +8 -7
- data/test/cases/primary_keys_test_sqlserver.rb +2 -2
- data/test/cases/rake_test_sqlserver.rb +8 -4
- data/test/cases/schema_dumper_test_sqlserver.rb +4 -5
- data/test/cases/showplan_test_sqlserver.rb +7 -7
- data/test/cases/specific_schema_test_sqlserver.rb +17 -13
- data/test/cases/view_test_sqlserver.rb +1 -9
- data/test/schema/sqlserver_specific_schema.rb +4 -4
- data/test/support/connection_reflection.rb +1 -1
- data/test/support/core_ext/query_cache.rb +2 -2
- data/test/support/query_assertions.rb +49 -0
- data/test/support/table_definition_sqlserver.rb +24 -0
- data/test/support/test_in_memory_oltp.rb +2 -2
- metadata +11 -12
- data/lib/active_record/sqlserver_base.rb +0 -13
- data/test/cases/scratchpad_test_sqlserver.rb +0 -8
- data/test/support/sql_counter_sqlserver.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6356803690516019929168fed2c356f3250eb5ec8a9894b8117fc35db84b8c1
|
4
|
+
data.tar.gz: dbedbedb583e766c526d959459166edd195516700fb6f0b1be2769ea1d947233
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5079fd8e88a8e67b91f11de2f9ec158d686afe121461f2b2050ebdd1072f1ac0fc86356dd81da507e99b72b8f9266aa5a59031d886dcb8d119715cab4cbef1c8
|
7
|
+
data.tar.gz: d1a8f37563ba09c443242e83f75098b2cc74bd269c9b11b9c6834a5e2fa23c7791f93083c7884ec1d22acdeca3bdf75f752153bde565fa0d92c3988a6653565c
|
data/.devcontainer/Dockerfile
CHANGED
@@ -6,9 +6,9 @@ FROM mcr.microsoft.com/devcontainers/ruby:${VARIANT}
|
|
6
6
|
|
7
7
|
# TinyTDS
|
8
8
|
RUN apt-get -y install libc6-dev \
|
9
|
-
&& wget http://www.freetds.org/files/stable/freetds-1.
|
10
|
-
&& tar -xzf freetds-1.
|
11
|
-
&& cd freetds-1.
|
9
|
+
&& wget http://www.freetds.org/files/stable/freetds-1.4.14.tar.gz \
|
10
|
+
&& tar -xzf freetds-1.4.14.tar.gz \
|
11
|
+
&& cd freetds-1.4.14 \
|
12
12
|
&& ./configure --prefix=/usr/local --with-tdsver=7.3 \
|
13
13
|
&& make \
|
14
14
|
&& make install
|
data/.github/workflows/ci.yml
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
name: CI
|
2
2
|
|
3
|
-
on:
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ main ]
|
8
|
+
schedule:
|
9
|
+
- cron: '0 18 * * *'
|
4
10
|
|
5
11
|
jobs:
|
6
12
|
test:
|
7
13
|
name: Run test suite
|
8
|
-
runs-on: ubuntu-
|
14
|
+
runs-on: ubuntu-latest
|
9
15
|
|
10
16
|
env:
|
11
17
|
COMPOSE_FILE: docker-compose.ci.yml
|
@@ -14,9 +20,9 @@ jobs:
|
|
14
20
|
fail-fast: false
|
15
21
|
matrix:
|
16
22
|
ruby:
|
17
|
-
- 3.
|
18
|
-
- 3.
|
19
|
-
- 3.
|
23
|
+
- 3.1.6
|
24
|
+
- 3.2.4
|
25
|
+
- 3.3.2
|
20
26
|
|
21
27
|
steps:
|
22
28
|
- name: Checkout code
|
data/CHANGELOG.md
CHANGED
@@ -1,112 +1,12 @@
|
|
1
|
-
##
|
2
|
-
|
3
|
-
#### Fixed
|
4
|
-
|
5
|
-
- [#1232](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1232) Enable identity insert on view's base table
|
6
|
-
|
7
|
-
## v7.1.7
|
8
|
-
|
9
|
-
#### Fixed
|
10
|
-
|
11
|
-
- [#1210](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1210) Handle blank SQL when parsing table name
|
12
|
-
|
13
|
-
## v7.1.6
|
14
|
-
|
15
|
-
#### Fixed
|
16
|
-
|
17
|
-
- [#1208](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1208) Exclude "guest" schema in schema dumper
|
18
|
-
|
19
|
-
## v7.1.5
|
20
|
-
|
21
|
-
#### Added
|
22
|
-
|
23
|
-
- [#1201](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1201) Support non-dbo schemas in schema dumper
|
24
|
-
- [#1206](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1206) Support table names containing spaces
|
25
|
-
|
26
|
-
## v7.1.4
|
27
|
-
|
28
|
-
#### Fixed
|
29
|
-
|
30
|
-
- [#1164](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1164) Fix composite primary key with different data type with triggers
|
31
|
-
|
32
|
-
#### Changed
|
33
|
-
|
34
|
-
- [#1199](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1199) Remove ActiveRecord::Relation#calculate patch
|
35
|
-
|
36
|
-
## v7.1.3
|
37
|
-
|
38
|
-
#### Fixed
|
39
|
-
|
40
|
-
- [#1152](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1152) Fix Composite Key Inserts with Triggers
|
41
|
-
|
42
|
-
## v7.1.2
|
43
|
-
|
44
|
-
#### Fixed
|
45
|
-
|
46
|
-
- [#1151](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1151) FROM subquery should work if order provided
|
47
|
-
|
48
|
-
## v7.1.1
|
49
|
-
|
50
|
-
#### Fixed
|
51
|
-
|
52
|
-
- [#1145](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1145) Ensure correct order of COLLATE and NOT NULL in CREATE TABLE statements
|
53
|
-
- [#1144](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1144) Fix precision handling in time migration
|
54
|
-
- [#1143](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1143) Fix precision handling for datetimeoffset migration
|
55
|
-
|
56
|
-
## v7.1.0
|
57
|
-
|
58
|
-
#### Added
|
59
|
-
|
60
|
-
- [#1141](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1141) Added support for check constraints.
|
61
|
-
|
62
|
-
## v7.1.0.rc2
|
63
|
-
|
64
|
-
#### Added
|
65
|
-
|
66
|
-
- [#1136](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1136) Prevent marking broken connections as verified
|
67
|
-
- [#1138](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1138) Cache quoted names
|
68
|
-
|
69
|
-
## v7.1.0.rc1
|
1
|
+
## Unreleased
|
70
2
|
|
71
3
|
#### Added
|
72
4
|
|
73
|
-
|
74
|
-
|
75
|
-
The adapter supports new Rails 7.1 features such as composite primary keys. See the
|
76
|
-
[Rails 7.1 release notes](https://guides.rubyonrails.org/7_1_release_notes.html) for more information.
|
5
|
+
- [#1178](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1178) Support encrypting binary columns
|
77
6
|
|
78
7
|
#### Changed
|
79
8
|
|
80
|
-
|
81
|
-
|
82
|
-
If you require additional connection configuration you now need to call `super` within the `configure_connection`
|
83
|
-
method so that the default configuration is also applied.
|
84
|
-
|
85
|
-
v7.1.x adapter:
|
86
|
-
```ruby
|
87
|
-
module ActiveRecord
|
88
|
-
module ConnectionAdapters
|
89
|
-
class SQLServerAdapter < AbstractAdapter
|
90
|
-
def configure_connection
|
91
|
-
super
|
92
|
-
raw_connection_do "SET TEXTSIZE #{64.megabytes}"
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
```
|
98
|
-
|
99
|
-
v7.0.x adapter:
|
100
|
-
```ruby
|
101
|
-
module ActiveRecord
|
102
|
-
module ConnectionAdapters
|
103
|
-
class SQLServerAdapter < AbstractAdapter
|
104
|
-
def configure_connection
|
105
|
-
raw_connection_do "SET TEXTSIZE #{64.megabytes}"
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
```
|
9
|
+
- [#1153](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1153) Only support Ruby v3.1+
|
10
|
+
- [#1196](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/1196) Use default inspect for database adapter
|
111
11
|
|
112
|
-
Please check [7-
|
12
|
+
Please check [7-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/7-1-stable/CHANGELOG.md) for previous changes.
|
data/Gemfile
CHANGED
@@ -8,16 +8,16 @@ gemspec
|
|
8
8
|
|
9
9
|
gem "bcrypt"
|
10
10
|
gem "pg", ">= 0.18.0"
|
11
|
-
gem "sqlite3", "
|
11
|
+
gem "sqlite3", ">= 1.6.6"
|
12
12
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
13
13
|
gem "benchmark-ips"
|
14
|
-
gem "minitest", ">= 5.15.0"
|
14
|
+
gem "minitest", ">= 5.15.0"
|
15
15
|
gem "msgpack", ">= 1.7.0"
|
16
16
|
|
17
17
|
if ENV["RAILS_SOURCE"]
|
18
18
|
gemspec path: ENV["RAILS_SOURCE"]
|
19
|
-
elsif ENV["
|
20
|
-
gem "rails", github: "rails/rails", branch:
|
19
|
+
elsif ENV["RAILS_BRANCH"]
|
20
|
+
gem "rails", github: "rails/rails", branch: ENV["RAILS_BRANCH"]
|
21
21
|
else
|
22
22
|
# Need to get rails source because the gem doesn't include tests
|
23
23
|
version = ENV["RAILS_VERSION"] || begin
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# ActiveRecord SQL Server Adapter. For SQL Server 2012 And Higher.
|
2
2
|
|
3
3
|
* [](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/actions/workflows/ci.yml) - CI
|
4
|
-
* [](https://ci.appveyor.com/project/rails-sqlserver/activerecord-sqlserver-adapter/branch/master) - Appveyor
|
5
4
|
* [](https://rubygems.org/gems/activerecord-sqlserver-adapter) - Gem Version
|
6
5
|
* [](https://gitter.im/rails-sqlserver/activerecord-sqlserver-adapter) - Community
|
7
6
|
|
@@ -9,22 +8,25 @@
|
|
9
8
|
|
10
9
|
The SQL Server adapter for ActiveRecord using SQL Server 2012 or higher.
|
11
10
|
|
12
|
-
Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 7.x version
|
11
|
+
Interested in older versions? We follow a rational versioning policy that tracks Rails. That means that our 7.x version
|
12
|
+
of the adapter is only for the latest 7.x version of Rails. If you need the adapter for SQL Server 2008 or 2005, you
|
13
|
+
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
|
14
|
+
version. We also have stable branches for each major/minor release of ActiveRecord. For older versions, please check
|
15
|
+
their stable branches.
|
13
16
|
|
14
|
-
|
15
|
-
|
16
|
-
|
|
17
|
-
|-----------------|---------------|---------|--------------------------------------------------------------------------------------------------|
|
17
|
+
| Adapter Version | Rails Version | Support | Branch |
|
18
|
+
|-----------------|---------------|----------------|-------------------------------------------------------------------------------------------------|
|
19
|
+
| `7.2.x` | `7.2.x` | Active | [main](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/main) |
|
18
20
|
| `7.1.x` | `7.1.x` | Active | [7-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/7-1-stable) |
|
19
|
-
| `7.0.x` | `7.0.x` |
|
20
|
-
| `6.1.x` | `6.1.x` |
|
21
|
-
| `6.0.x` | `6.0.x` | Ended
|
22
|
-
| `5.2.x` | `5.2.x` | Ended
|
23
|
-
| `5.1.x` | `5.1.x` | Ended
|
24
|
-
| `4.2.x` | `4.2.x` | Ended
|
25
|
-
| `4.1.x` | `4.1.x` | Ended
|
21
|
+
| `7.0.x` | `7.0.x` | Active | [7-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/7-0-stable) |
|
22
|
+
| `6.1.x` | `6.1.x` | Active | [6-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-1-stable) |
|
23
|
+
| `6.0.x` | `6.0.x` | Ended | [6-0-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/6-0-stable) |
|
24
|
+
| `5.2.x` | `5.2.x` | Ended | [5-2-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-2-stable) |
|
25
|
+
| `5.1.x` | `5.1.x` | Ended | [5-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/5-1-stable) |
|
26
|
+
| `4.2.x` | `4.2.x` | Ended | [4-2-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/4-2-stable) |
|
27
|
+
| `4.1.x` | `4.1.x` | Ended | [4-1-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/tree/4-1-stable) |
|
26
28
|
|
27
|
-
|
29
|
+
See [Rubygems](https://rubygems.org/gems/activerecord-sqlserver-adapter/versions) for the latest version of the adapter for each Rails release.
|
28
30
|
|
29
31
|
#### Native Data Type Support
|
30
32
|
|
@@ -169,14 +171,35 @@ ActiveRecord::ConnectionAdapters::SQLServerAdapter.showplan_option = 'SHOWPLAN_X
|
|
169
171
|
|
170
172
|
## New Rails Applications
|
171
173
|
|
172
|
-
When creating a new Rails application you
|
174
|
+
When creating a new Rails application you need to perform the following steps to connect a Rails application to a
|
175
|
+
SQL Server instance.
|
176
|
+
|
177
|
+
1. Create new Rails application, the database defaults to `sqlite`.
|
173
178
|
|
179
|
+
```bash
|
180
|
+
rails new my_app
|
174
181
|
```
|
175
|
-
|
182
|
+
|
183
|
+
2. Update the Gemfile to install the adapter instead of the SQLite adapter. Remove the `sqlite3` gem from the Gemfile.
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
gem 'activerecord-sqlserver-adapter'
|
176
187
|
```
|
177
188
|
|
178
|
-
|
189
|
+
3. Connect the application to your SQL Server instance by editing the `config/database.yml` file with the username,
|
190
|
+
password and host of your SQL Server instance.
|
179
191
|
|
192
|
+
Example:
|
193
|
+
|
194
|
+
```yaml
|
195
|
+
development:
|
196
|
+
adapter: sqlserver
|
197
|
+
host: 'localhost'
|
198
|
+
port: 1433
|
199
|
+
database: my_app_development
|
200
|
+
username: 'frank_castle'
|
201
|
+
password: 'secret'
|
202
|
+
```
|
180
203
|
|
181
204
|
## Installation
|
182
205
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
7.
|
1
|
+
7.2.0
|
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.version = version
|
9
9
|
|
10
|
-
spec.required_ruby_version = ">=
|
10
|
+
spec.required_ruby_version = ">= 3.1.0"
|
11
11
|
|
12
12
|
spec.license = "MIT"
|
13
13
|
spec.authors = ["Ken Collins", "Anna Carey", "Will Bond", "Murray Steele", "Shawn Balestracci", "Joe Rafaniello", "Tom Ward", "Aidan Haran"]
|
@@ -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", "~> 7.
|
30
|
+
spec.add_dependency "activerecord", "~> 7.2.0"
|
31
31
|
spec.add_dependency "tiny_tds"
|
32
32
|
end
|
@@ -10,11 +10,13 @@ module ActiveRecord
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def attributes_for_update(attribute_names)
|
13
|
-
|
13
|
+
self.class.with_connection do |connection|
|
14
|
+
return super(attribute_names) unless connection.sqlserver?
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
super(attribute_names).reject do |name|
|
17
|
+
column = self.class.columns_hash[name]
|
18
|
+
column && column.respond_to?(:is_identity?) && column.is_identity?
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -8,13 +8,14 @@ module ActiveRecord
|
|
8
8
|
module SQLServer
|
9
9
|
module CoreExt
|
10
10
|
module Calculations
|
11
|
-
|
12
|
-
private
|
13
11
|
|
12
|
+
private
|
13
|
+
|
14
14
|
def build_count_subquery(relation, column_name, distinct)
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
klass.with_connection do |connection|
|
16
|
+
relation = relation.unscope(:order) if connection.sqlserver?
|
17
|
+
super(relation, column_name, distinct)
|
18
|
+
end
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -9,12 +9,15 @@ module ActiveRecord
|
|
9
9
|
SQLSERVER_STATEMENT_REGEXP = /N'(.+)', N'(.+)', (.+)/
|
10
10
|
|
11
11
|
def exec_explain(queries, options = [])
|
12
|
-
|
12
|
+
with_connection do |connection|
|
13
|
+
return super(queries, options) unless connection.sqlserver?
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
unprepared_queries = queries.map do |(sql, binds)|
|
16
|
+
[unprepare_sqlserver_statement(sql, binds), binds]
|
17
|
+
end
|
18
|
+
|
19
|
+
super(unprepared_queries, options)
|
16
20
|
end
|
17
|
-
super(unprepared_queries, options)
|
18
21
|
end
|
19
22
|
|
20
23
|
private
|
@@ -11,10 +11,12 @@ module ActiveRecord
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def construct_relation_for_exists(conditions)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
klass.with_connection do |connection|
|
15
|
+
if connection.sqlserver?
|
16
|
+
_construct_relation_for_exists(conditions)
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
@@ -8,23 +8,25 @@ module ActiveRecord
|
|
8
8
|
module CoreExt
|
9
9
|
module LoaderQuery
|
10
10
|
def load_records_for_keys(keys, &block)
|
11
|
-
|
11
|
+
scope.with_connection do |connection|
|
12
|
+
return super unless connection.sqlserver?
|
12
13
|
|
13
|
-
|
14
|
+
return [] if keys.empty?
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
if association_key_name.is_a?(Array)
|
17
|
+
query_constraints = Hash.new { |hsh, key| hsh[key] = Set.new }
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
keys.each_with_object(query_constraints) do |values_set, constraints|
|
20
|
+
association_key_name.zip(values_set).each do |key_name, value|
|
21
|
+
constraints[key_name] << value
|
22
|
+
end
|
21
23
|
end
|
22
|
-
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
scope.where(query_constraints).load(&block)
|
26
|
+
else
|
27
|
+
keys.each_slice(in_clause_length).flat_map do |slice|
|
28
|
+
scope.where(association_key_name => slice).load(&block).records
|
29
|
+
end
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
@@ -14,9 +14,7 @@ module ActiveRecord
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
|
17
|
-
|
18
|
-
|
19
|
-
log(sql, name, async: async) do
|
17
|
+
log(sql, name, async: async) do |notification_payload|
|
20
18
|
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
|
21
19
|
result = if id_insert_table_name = query_requires_identity_insert?(sql)
|
22
20
|
with_identity_insert_enabled(id_insert_table_name, conn) { internal_raw_execute(sql, conn, perform_do: true) }
|
@@ -24,14 +22,13 @@ module ActiveRecord
|
|
24
22
|
internal_raw_execute(sql, conn, perform_do: true)
|
25
23
|
end
|
26
24
|
verified!
|
25
|
+
notification_payload[:row_count] = result
|
26
|
+
result
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
30
|
-
result
|
31
29
|
end
|
32
30
|
|
33
|
-
def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false)
|
34
|
-
result = nil
|
31
|
+
def internal_exec_query(sql, name = "SQL", binds = [], prepare: false, async: false, allow_retry: false)
|
35
32
|
sql = transform_query(sql)
|
36
33
|
|
37
34
|
check_if_write_query(sql)
|
@@ -42,23 +39,21 @@ module ActiveRecord
|
|
42
39
|
sql = sp_executesql_sql(sql, types, params, name)
|
43
40
|
end
|
44
41
|
|
45
|
-
log(sql, name, binds, async: async) do
|
42
|
+
log(sql, name, binds, async: async) do |notification_payload|
|
46
43
|
with_raw_connection do |conn|
|
47
|
-
if id_insert_table_name = query_requires_identity_insert?(sql)
|
48
|
-
|
49
|
-
|
44
|
+
result = if id_insert_table_name = query_requires_identity_insert?(sql)
|
45
|
+
with_identity_insert_enabled(id_insert_table_name, conn) do
|
46
|
+
internal_exec_sql_query(sql, conn)
|
47
|
+
end
|
48
|
+
else
|
49
|
+
internal_exec_sql_query(sql, conn)
|
50
|
+
end
|
50
51
|
|
51
|
-
with_identity_insert_enabled(id_insert_table_name, conn) do
|
52
|
-
result = internal_exec_sql_query(sql, conn)
|
53
|
-
end
|
54
|
-
else
|
55
|
-
result = internal_exec_sql_query(sql, conn)
|
56
|
-
end
|
57
52
|
verified!
|
53
|
+
notification_payload[:row_count] = result.count
|
54
|
+
result
|
58
55
|
end
|
59
56
|
end
|
60
|
-
|
61
|
-
result
|
62
57
|
end
|
63
58
|
|
64
59
|
def internal_exec_sql_query(sql, conn)
|
@@ -156,10 +151,10 @@ module ActiveRecord
|
|
156
151
|
|
157
152
|
if returning = insert.send(:insert_all).returning
|
158
153
|
returning_sql = if returning.is_a?(String)
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
154
|
+
returning
|
155
|
+
else
|
156
|
+
returning.map { |column| "INSERTED.#{quote_column_name(column)}" }.join(", ")
|
157
|
+
end
|
163
158
|
sql << " OUTPUT #{returning_sql}"
|
164
159
|
end
|
165
160
|
|
@@ -177,7 +172,7 @@ module ActiveRecord
|
|
177
172
|
end.join(", ")
|
178
173
|
sql = "EXEC #{proc_name} #{vars}".strip
|
179
174
|
|
180
|
-
log(sql, "Execute Procedure") do
|
175
|
+
log(sql, "Execute Procedure") do |notification_payload|
|
181
176
|
with_raw_connection do |conn|
|
182
177
|
result = internal_raw_execute(sql, conn)
|
183
178
|
verified!
|
@@ -188,10 +183,11 @@ module ActiveRecord
|
|
188
183
|
yield(r) if block_given?
|
189
184
|
end
|
190
185
|
|
191
|
-
result.each.map { |row| row.is_a?(Hash) ? row.with_indifferent_access : row }
|
186
|
+
result = result.each.map { |row| row.is_a?(Hash) ? row.with_indifferent_access : row }
|
187
|
+
notification_payload[:row_count] = result.count
|
188
|
+
result
|
192
189
|
end
|
193
190
|
end
|
194
|
-
|
195
191
|
end
|
196
192
|
|
197
193
|
def with_identity_insert_enabled(table_name, conn)
|
@@ -332,11 +328,17 @@ module ActiveRecord
|
|
332
328
|
end
|
333
329
|
|
334
330
|
def sp_executesql_sql_type(attr)
|
335
|
-
|
336
|
-
|
331
|
+
if attr.respond_to?(:type)
|
332
|
+
return attr.type.sqlserver_type if attr.type.respond_to?(:sqlserver_type)
|
337
333
|
|
338
|
-
|
339
|
-
|
334
|
+
if attr.type.is_a?(ActiveRecord::Encryption::EncryptedAttributeType) && attr.type.instance_variable_get(:@cast_type).respond_to?(:sqlserver_type)
|
335
|
+
return attr.type.instance_variable_get(:@cast_type).sqlserver_type
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
value = basic_attribute_type?(attr) ? attr : attr.value_for_database
|
340
|
+
|
341
|
+
if value.is_a?(Numeric)
|
340
342
|
value > 2_147_483_647 ? "bigint".freeze : "int".freeze
|
341
343
|
else
|
342
344
|
"nvarchar(max)".freeze
|
@@ -344,17 +346,26 @@ module ActiveRecord
|
|
344
346
|
end
|
345
347
|
|
346
348
|
def sp_executesql_sql_param(attr)
|
347
|
-
return quote(attr) if
|
349
|
+
return quote(attr) if basic_attribute_type?(attr)
|
348
350
|
|
349
351
|
case value = attr.value_for_database
|
350
|
-
when Type::Binary::Data,
|
351
|
-
ActiveRecord::Type::SQLServer::Data
|
352
|
+
when Type::Binary::Data, ActiveRecord::Type::SQLServer::Data
|
352
353
|
quote(value)
|
353
354
|
else
|
354
355
|
quote(type_cast(value))
|
355
356
|
end
|
356
357
|
end
|
357
358
|
|
359
|
+
def basic_attribute_type?(type)
|
360
|
+
type.is_a?(Symbol) ||
|
361
|
+
type.is_a?(String) ||
|
362
|
+
type.is_a?(Numeric) ||
|
363
|
+
type.is_a?(Time) ||
|
364
|
+
type.is_a?(TrueClass) ||
|
365
|
+
type.is_a?(FalseClass) ||
|
366
|
+
type.is_a?(NilClass)
|
367
|
+
end
|
368
|
+
|
358
369
|
def sp_executesql_sql(sql, types, params, name)
|
359
370
|
if name == "EXPLAIN"
|
360
371
|
params.each.with_index do |param, index|
|
@@ -427,7 +438,11 @@ module ActiveRecord
|
|
427
438
|
qo[:as] = (options[:ar_result] || options[:fetch] == :rows) ? :array : :hash
|
428
439
|
end
|
429
440
|
results = handle.each(query_options)
|
430
|
-
|
441
|
+
|
442
|
+
columns = handle.fields
|
443
|
+
# If query returns multiple result sets, only return the columns of the last one.
|
444
|
+
columns = columns.last if columns.any? && columns.all? { |e| e.is_a?(Array) }
|
445
|
+
columns = columns.map(&:downcase) if lowercase_schema_reflection
|
431
446
|
|
432
447
|
options[:ar_result] ? ActiveRecord::Result.new(columns, results) : results
|
433
448
|
end
|