activerecord-jdbcsqlserver-adapter 50.1.0 → 51.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.travis.yml +4 -5
  4. data/BACKERS.md +32 -0
  5. data/CHANGELOG.md +21 -87
  6. data/README.md +2 -3
  7. data/VERSION +1 -1
  8. data/activerecord-jdbcsqlserver-adapter.gemspec +3 -2
  9. data/appveyor.yml +1 -1
  10. data/lib/active_record/connection_adapters/sqlserver/core_ext/active_record.rb +3 -1
  11. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +3 -1
  12. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +55 -0
  13. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +4 -2
  14. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain_subscriber.rb +5 -3
  15. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +41 -18
  16. data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +2 -12
  17. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -0
  18. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +21 -0
  19. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +72 -52
  20. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +15 -7
  21. data/lib/active_record/connection_adapters/sqlserver/type/big_integer.rb +0 -4
  22. data/lib/active_record/connection_adapters/sqlserver/type/data.rb +5 -0
  23. data/lib/active_record/connection_adapters/sqlserver/type/datetime.rb +3 -6
  24. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +27 -10
  25. data/lib/active_record/tasks/sqlserver_database_tasks.rb +2 -2
  26. data/lib/activerecord-jdbcsqlserver-adapter.rb +1 -1
  27. data/lib/arel/visitors/sqlserver.rb +16 -3
  28. data/test/bin/setup.sh +19 -0
  29. data/test/cases/adapter_test_sqlserver.rb +17 -20
  30. data/test/cases/coerced_tests.rb +117 -11
  31. data/test/cases/column_test_sqlserver.rb +1 -1
  32. data/test/cases/helper_sqlserver.rb +6 -1
  33. data/test/cases/pessimistic_locking_test_sqlserver.rb +28 -11
  34. data/test/cases/schema_dumper_test_sqlserver.rb +10 -10
  35. data/test/cases/specific_schema_test_sqlserver.rb +0 -6
  36. data/test/cases/trigger_test_sqlserver.rb +31 -0
  37. data/test/config.yml +2 -2
  38. data/test/models/sqlserver/trigger.rb +7 -0
  39. data/test/models/sqlserver/trigger_history.rb +3 -0
  40. data/test/schema/sqlserver_specific_schema.rb +39 -5
  41. data/test/support/sql_counter_sqlserver.rb +3 -2
  42. metadata +23 -16
  43. data/RAILS5-TODO.md +0 -5
  44. data/lib/jdbc_mssql_driver_loader.rb +0 -22
  45. data/test/models/sqlserver/dot_table_name.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a5acd7cd424c10d62f5c2c1b71c8375fd736ed7ec7793c85a3fd6dc0f0f23f6
4
- data.tar.gz: 597ccc6cfb6d8533555dda1eb7598132cd932f80c78f936b85b69daef9545271
3
+ metadata.gz: 0741df1e5631f4906252da7155f1132211b7013a5af28c67acaa5842904fb00f
4
+ data.tar.gz: 766c6e44c12e5a068fc86120af09ac60e1435c22fa6ad645bd66298711aca79d
5
5
  SHA512:
6
- metadata.gz: c55e61e720f4de8c51cd94a34be67eb16b3d9d1c34888471e8eb14e3fc1f590eb404b90f7cc19a16534a135ab3665dc57ea1551e78c49777ff3d678816d888e9
7
- data.tar.gz: a731bb86cac95cb46e1876b65ff7740f855c0759fd0751ee08fcb7f4f5497247ad8e6633671d7ab468289770bea319656a64ce8934f42b0b9b512bb8171fa91b
6
+ metadata.gz: 73fefebc26abc9047a08237f423619cc5b0b3b5e44151e684441e4533f3fcec6d29ed424be8355698d157fa64e8e9d81d547889a3fa1f07c13050c48e6545dfe
7
+ data.tar.gz: fb6d2c239737a9417a0969e5806c78e1e1d9b0d7ce4fe39bb1e81052e9425f2a9e7f9943d1ffa2021c2d8642d2fbe71440d3b56a1b0e141287b3012201ba14f3
data/.gitignore CHANGED
@@ -9,7 +9,9 @@ Gemfile.lock
9
9
  test/profile/output/*
10
10
  .rvmrc
11
11
  .rbenv-version
12
+ .tool-versions
12
13
  .idea
13
14
  coverage/*
14
15
  .flooignore
15
- .floo
16
+ .floo
17
+ .byebug_history
data/.travis.yml CHANGED
@@ -4,8 +4,8 @@ services:
4
4
  - docker
5
5
  env:
6
6
  global:
7
- - COMPOSE_FILE=docker-compose.ci.yml
8
- #- ARJDBC_BRANCH=mssql-support
7
+ - COMPOSE_FILE: docker-compose.ci.yml
8
+ - ARJDBC_BRANCH=51-stable
9
9
  matrix:
10
10
  - TARGET_VERSION=9.1
11
11
  - TARGET_VERSION=9.2
@@ -17,11 +17,10 @@ before_install:
17
17
  - 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
18
18
  - sudo chmod +x /usr/local/bin/docker-compose
19
19
  install:
20
- - docker-compose build --build-arg TARGET_VERSION=$TARGET_VERSION-jdk-alpine
21
- #- docker-compose build --build-arg TARGET_VERSION=$TARGET_VERSION-jdk-alpine --build-arg TARGET_ARJDBC_BRANCH=$ARJDBC_BRANCH
20
+ #- docker-compose build --build-arg TARGET_VERSION=$TARGET_VERSION-jdk-alpine
21
+ - docker-compose build --build-arg TARGET_VERSION=$TARGET_VERSION-jdk-alpine --build-arg TARGET_ARJDBC_BRANCH=$ARJDBC_BRANCH
22
22
  script:
23
23
  - docker-compose run ci
24
24
  matrix:
25
25
  allow_failures:
26
26
  - env: TARGET_VERSION=9.1
27
-
data/BACKERS.md ADDED
@@ -0,0 +1,32 @@
1
+ # Backers
2
+
3
+ You can join in supporting TinyTDS and the Rails SQL Server Adapter development by [pledging on Patreon](https://www.patreon.com/metaskills)! Backers in the same pledge level appear in the order of pledge date.
4
+
5
+ ### $2000
6
+
7
+ [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611218)
8
+
9
+
10
+ ### $500
11
+
12
+ [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611209)
13
+
14
+
15
+ ### $250
16
+
17
+ [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611199)
18
+
19
+
20
+ ### $100
21
+
22
+ [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611196)
23
+
24
+
25
+ ### $50+
26
+
27
+ [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611186)
28
+
29
+
30
+ ### $10+
31
+
32
+ [It could be you!](https://www.patreon.com/bePatron?c=765225&rid=1611149)
data/CHANGELOG.md CHANGED
@@ -1,124 +1,58 @@
1
- ## v50.0.0
1
+ ## v51.0.0
2
2
 
3
3
  * Forked original gem to provide JRuby support
4
4
 
5
- ## v5.0.8
6
-
7
- * Memorized SQL Server Version to prevent a flood of SELECT @@version queries. Fixes #632
8
-
9
- ## v5.0.7
10
-
11
- * Add `WITH NO_INFOMSGS` to `user_options` method. Fixes #580
12
-
13
-
14
- ## v5.0.6
15
-
16
- #### Fixed
17
-
18
- * Performance w/inserts. Check binds & use schema cache for id inserts.
19
- Fixes #572. Thanks @noelr.
20
- * Add smalldatetime type for migrations. Fixes #507
21
-
22
- #### Changed
23
-
24
- * Misc index enhancements or testing. Fixes #570
25
- Enable `supports_index_sort_order?`, test `supports_partial_index?`, test how expression indexes work.
5
+ ## v5.1.6
26
6
 
27
7
  #### Added
28
8
 
29
- * New `primary_key_nonclustered` type for easy In-Memory table creation.
30
- * Examples for an In-Memory table.
31
-
32
- ```ruby
33
- create_table :in_memory_table, id: false,
34
- options: 'WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)' do |t|
35
- t.primary_key_nonclustered :id
36
- t.string :name
37
- t.timestamps
38
- end
39
- ```
40
-
41
- * Enable supports_json? Fixes #577.
42
-
43
- ```ruby
44
- create_table :users do |t|
45
- t.string :name, :email
46
- t.json :data # Creates a nvarchar(max) column.
47
- end
48
-
49
- class Users < ActiveRecord::Base
50
- attribute :data, ActiveRecord::Type::SQLServer::Json.new
51
- end
52
-
53
- User.create! name: 'Ken Collins', data: { 'admin' => true, 'foo' => 'bar' }
9
+ * Use lock hint when joining table in query.
54
10
 
55
- admin = User.where("JSON_VALUE(data, '$.admin') = CAST(1 AS BIT)").first
56
- admin.data['foo'] # => "bar"
57
- ```
58
11
 
12
+ ## v5.1.5
59
13
 
60
- ## v5.0.5
61
-
62
- #### Changed
14
+ #### Fixed
63
15
 
64
- * Add TinyTDS as a runtime dependency.
16
+ * Memoize `@@version` queries. Fixes #632
65
17
 
66
18
 
67
- ## v5.0.4
19
+ ## v5.1.4
68
20
 
69
21
  #### Fixed
70
22
 
71
- * Allow `datetimeoffset` to be used in migrations and represented in schema.
72
- * Using transactions and resetting isolation level correctly when `READ_COMMITTED_SNAPSHOT` is set to `ON` Fixes #520
23
+ * Add case insensitive comparison for better performance with CI collations. Fixes #624
73
24
 
74
25
 
75
- ## v5.0.3
26
+ ## v5.1.3
76
27
 
77
- #### Changed
28
+ #### Fixed
78
29
 
79
- * Reduce view information reflection to per table vs. column. Fixes #552
80
- * The `user_options` parsing. Works for hash/array. Fixes #535
81
- * Pass the `:contained` option to TinyTDS. Fixes #527
30
+ * Use bigint type in sqlserver_type when needed. Fixes #616
82
31
 
83
32
 
84
- ## v5.0.2
33
+ ## v5.1.2
85
34
 
86
35
  #### Fixed
87
36
 
88
- * Filter table constraints with matching table schema to column. Fixes #478
89
-
37
+ * The `fast_string_to_time` method when zone local. Fixes #609 #614 #620
38
+ * Patched `Relation#build_count_subquery`. Fixes #613.
39
+ * Inserts to tables with triggers using default `OUTPUT INSERTED` style. Fixes #595.
90
40
 
91
- ## v5.0.1
92
-
93
- #### Changed
94
41
 
95
- * Set `tds_version` fallback to `7.3`.
42
+ ## v5.1.1
96
43
 
97
44
  #### Fixed
98
45
 
99
- * Support 2014, 2012 drop table statement.
46
+ * Use `ActiveSupport.on_load` to hook into ActiveRecord Fixes #588 #598
100
47
 
101
48
 
102
- ## v5.0.0
103
-
104
- #### Added
105
-
106
- * Support for `supports_datetime_with_precision`.
107
- * Support for `unprepared_statement` blocks on the connection.
49
+ ## v5.1.0
108
50
 
109
51
  #### Changed
110
52
 
111
- * Major refactoring of all type objects. Especially time types.
112
-
113
- #### Deprecated
53
+ * The `drop_table` with force cascade option now mimics in via pure SQL for us.
114
54
 
115
- * Support for a handful of standard Rails deprecations in 5-0-stable suite.
116
-
117
- #### Removed
118
-
119
- * ODBC connection mode. Not been maintained since Rails 4.0.
120
- * View table name detection in `with_identity_insert_enabled` method for fixtures. Perf hit.
55
+ #### Added
121
56
 
122
- #### Fixed
57
+ * Support MismatchedForeignKey exception.
123
58
 
124
- * Do not output column collation in schema when same as database.
data/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  [![Gem Version](http://img.shields.io/gem/v/activerecord-jdbcsqlserver-adapter.svg)](https://rubygems.org/gems/activerecord-jdbcsqlserver-adapter) - Gem Version
4
4
 
5
-
6
- The JDBC SQL Server adapter for ActiveRecord v5.0 using SQL Server 2012 or higher.
5
+ The JDBC SQL Server adapter for ActiveRecord v5.1 using SQL Server 2012 or higher.
7
6
 
8
7
  We currently support JRuby 9.2+. Older versions may work but they are not tested and there is a known date issue with JRuby 9.1.
9
8
 
@@ -61,7 +60,7 @@ If the bug/feature is JRuby or specific to this gem, please submit patches to: h
61
60
  Many many people have contributed. If you do not see your name here and it should be let us know. Also, many thanks go out to those that have pledged financial contributions.
62
61
 
63
62
 
64
- ## Contributers
63
+ ## Contributors
65
64
 
66
65
  Up-to-date list of contributors: http://github.com/rails-sqlserver/activerecord-sqlserver-adapter/contributors
67
66
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 50.1.0
1
+ 51.0.0
@@ -15,7 +15,8 @@ Gem::Specification.new do |spec|
15
15
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ['lib']
18
- spec.add_dependency 'activerecord', '~> 5.0.0', '>= 5.0.6'
19
- spec.add_dependency 'activerecord-jdbc-adapter' , '~> 50.8'
18
+
19
+ spec.add_dependency 'activerecord', '~> 5.1.0', '>= 5.1.7'
20
+ spec.add_dependency 'activerecord-jdbc-adapter' , '~> 51.5'
20
21
  spec.add_dependency 'jdbc-mssql', '>= 0.6.0'
21
22
  end
data/appveyor.yml CHANGED
@@ -2,7 +2,7 @@ init:
2
2
  - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
3
3
  - SET PATH=C:\MinGW\msys\1.0\bin;%PATH%
4
4
  - SET RAKEOPT=-rdevkit
5
- - SET TINYTDS_VERSION=1.3.0
5
+ - SET TINYTDS_VERSION=2.1.0
6
6
  clone_depth: 5
7
7
  skip_tags: true
8
8
  matrix:
@@ -24,4 +24,6 @@ module ActiveRecord
24
24
  end
25
25
  end
26
26
 
27
- ActiveRecord::Base.send :include, ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::ActiveRecord
27
+ ActiveSupport.on_load(:active_record) do
28
+ include ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::ActiveRecord
29
+ end
@@ -22,4 +22,6 @@ module ActiveRecord
22
22
  end
23
23
  end
24
24
 
25
- ActiveRecord::Base.send :include, ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::AttributeMethods
25
+ ActiveSupport.on_load(:active_record) do
26
+ include ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::AttributeMethods
27
+ end
@@ -0,0 +1,55 @@
1
+ require 'active_record/relation'
2
+ require 'active_record/version'
3
+
4
+ module ActiveRecord
5
+ module ConnectionAdapters
6
+ module SQLServer
7
+ module CoreExt
8
+ module Calculations
9
+
10
+ # @Override
11
+ # If we are ordering a subquery for a count, we have to artificially add the offset bind parameter
12
+ def bound_attributes
13
+ attrs = super
14
+ if @_setting_offset_for_count
15
+ @_setting_offset_for_count = false
16
+ attrs << Attribute.with_cast_value('OFFSET'.freeze, 0, ::ActiveRecord::Type.default_value)
17
+ end
18
+ attrs
19
+ end
20
+
21
+ private
22
+
23
+ # @Override
24
+ def build_count_subquery(relation, column_name, distinct)
25
+
26
+ # For whatever reason, mssql requires an offset if an ORDER BY is included in a subquery
27
+ if distinct && !has_limit_or_offset? && !relation.orders.empty?
28
+ relation = relation.offset(0)
29
+
30
+ # This is purely to appease activerecord/test/cases/calculations_test.rb @ line 258 CalculationsTest#test_distinct_count_all_with_custom_select_and_order
31
+ # hopefully nobody tries to do anything too crazy in a literal...
32
+ if relation.projections.length == 1 && relation.projections.first.is_a?(::Arel::Nodes::SqlLiteral)
33
+ relation.projections[0] = ::Arel::Nodes::SqlLiteral.new(relation.projections.first + ' as some_name_that_hopefully_never_exists123')
34
+ end
35
+
36
+ @_setting_offset_for_count = true
37
+ end
38
+
39
+ super
40
+
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ ActiveSupport.on_load(:active_record) do
49
+ if ActiveRecord::VERSION::MAJOR == 5 &&
50
+ ActiveRecord::VERSION::MINOR == 1 &&
51
+ ActiveRecord::VERSION::TINY >= 4
52
+ mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Calculations
53
+ ActiveRecord::Relation.prepend(mod)
54
+ end
55
+ end
@@ -43,5 +43,7 @@ module ActiveRecord
43
43
  end
44
44
  end
45
45
 
46
- ActiveRecord::Base.extend ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Explain
47
- ActiveRecord::Relation.send :include, ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Explain
46
+ ActiveSupport.on_load(:active_record) do
47
+ extend ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Explain
48
+ ActiveRecord::Relation.include(ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Explain)
49
+ end
@@ -1,4 +1,6 @@
1
- silence_warnings do
2
- # Already defined in Rails
3
- ActiveRecord::ExplainSubscriber::EXPLAINED_SQLS = /(select|update|delete|insert)\b/i
1
+ ActiveSupport.on_load(:active_record) do
2
+ silence_warnings do
3
+ # Already defined in Rails
4
+ ActiveRecord::ExplainSubscriber::EXPLAINED_SQLS = /(select|update|delete|insert)\b/i
5
+ end
4
6
  end
@@ -3,10 +3,6 @@ module ActiveRecord
3
3
  module SQLServer
4
4
  module DatabaseStatements
5
5
 
6
- def select_rows(sql, name = nil, binds = [])
7
- sp_executesql sql, name, binds, fetch: :rows
8
- end
9
-
10
6
  def execute(sql, name = nil)
11
7
  if id_insert_table_name = query_requires_identity_insert?(sql)
12
8
  with_identity_insert_enabled(id_insert_table_name) { do_execute(sql, name) }
@@ -19,22 +15,22 @@ module ActiveRecord
19
15
  sp_executesql(sql, name, binds, prepare: prepare)
20
16
  end
21
17
 
22
- def exec_insert(sql, name, binds, pk = nil, _sequence_name = nil)
18
+ def exec_insert(sql, name = nil, binds = [], pk = nil, _sequence_name = nil)
23
19
  if id_insert_table_name = exec_insert_requires_identity?(sql, pk, binds)
24
- with_identity_insert_enabled(id_insert_table_name) { exec_query(sql, name, binds) }
20
+ with_identity_insert_enabled(id_insert_table_name) { super(sql, name, binds, pk) }
25
21
  else
26
- exec_query(sql, name, binds)
22
+ super(sql, name, binds, pk)
27
23
  end
28
24
  end
29
25
 
30
26
  def exec_delete(sql, name, binds)
31
- sql << '; SELECT @@ROWCOUNT AS AffectedRows'
32
- super.rows.first.first
27
+ sql = sql.dup << '; SELECT @@ROWCOUNT AS AffectedRows'
28
+ super(sql, name, binds).rows.first.first
33
29
  end
34
30
 
35
31
  def exec_update(sql, name, binds)
36
- sql << '; SELECT @@ROWCOUNT AS AffectedRows'
37
- super.rows.first.first
32
+ sql = sql.dup << '; SELECT @@ROWCOUNT AS AffectedRows'
33
+ super(sql, name, binds).rows.first.first
38
34
  end
39
35
 
40
36
  def supports_statement_cache?
@@ -80,7 +76,7 @@ module ActiveRecord
80
76
  end
81
77
 
82
78
  def case_sensitive_comparison(table, attribute, column, value)
83
- if value && value.acts_like?(:string)
79
+ if column.collation && !column.case_sensitive?
84
80
  table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
85
81
  else
86
82
  super
@@ -88,7 +84,7 @@ module ActiveRecord
88
84
  end
89
85
 
90
86
  def can_perform_case_insensitive_comparison_for?(column)
91
- column.type == :string
87
+ column.type == :string && (!column.collation || column.case_sensitive?)
92
88
  end
93
89
  private :can_perform_case_insensitive_comparison_for?
94
90
 
@@ -196,9 +192,20 @@ module ActiveRecord
196
192
  table_name = query_requires_identity_insert?(sql)
197
193
  pk = primary_key(table_name)
198
194
  end
199
- sql = if pk && self.class.use_output_inserted && !database_prefix_remote_server?
195
+ sql = if pk && use_output_inserted? && !database_prefix_remote_server?
200
196
  quoted_pk = SQLServer::Utils.extract_identifiers(pk).quoted
201
- sql.insert sql.index(/ (DEFAULT )?VALUES/), " OUTPUT INSERTED.#{quoted_pk}"
197
+ table_name ||= get_table_name(sql)
198
+ exclude_output_inserted = exclude_output_inserted_table_name?(table_name, sql)
199
+ if exclude_output_inserted
200
+ id_sql_type = exclude_output_inserted.is_a?(TrueClass) ? 'bigint' : exclude_output_inserted
201
+ <<-SQL.strip_heredoc
202
+ DECLARE @ssaIdInsertTable table (#{quoted_pk} #{id_sql_type});
203
+ #{sql.dup.insert sql.index(/ (DEFAULT )?VALUES/), " OUTPUT INSERTED.#{quoted_pk} INTO @ssaIdInsertTable"}
204
+ SELECT CAST(#{quoted_pk} AS #{id_sql_type}) FROM @ssaIdInsertTable
205
+ SQL
206
+ else
207
+ sql.dup.insert sql.index(/ (DEFAULT )?VALUES/), " OUTPUT INSERTED.#{quoted_pk}"
208
+ end
202
209
  else
203
210
  "#{sql}; SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident"
204
211
  end
@@ -241,7 +248,7 @@ module ActiveRecord
241
248
  return attr.type.sqlserver_type if attr.type.respond_to?(:sqlserver_type)
242
249
  case value = attr.value_for_database
243
250
  when Numeric
244
- 'int'.freeze
251
+ value > 2_147_483_647 ? 'bigint'.freeze : 'int'.freeze
245
252
  else
246
253
  'nvarchar(max)'.freeze
247
254
  end
@@ -261,7 +268,7 @@ module ActiveRecord
261
268
  if name == 'EXPLAIN'
262
269
  params.each.with_index do |param, index|
263
270
  substitute_at_finder = /(@#{index})(?=(?:[^']|'[^']*')*$)/ # Finds unquoted @n values.
264
- sql.sub! substitute_at_finder, param.to_s
271
+ sql = sql.sub substitute_at_finder, param.to_s
265
272
  end
266
273
  else
267
274
  types = quote(types.join(', '))
@@ -283,6 +290,21 @@ module ActiveRecord
283
290
 
284
291
  # === SQLServer Specific (Identity Inserts) ===================== #
285
292
 
293
+ def use_output_inserted?
294
+ self.class.use_output_inserted
295
+ end
296
+
297
+ def exclude_output_inserted_table_names?
298
+ !self.class.exclude_output_inserted_table_names.empty?
299
+ end
300
+
301
+ def exclude_output_inserted_table_name?(table_name, sql)
302
+ return false unless exclude_output_inserted_table_names?
303
+ table_name ||= get_table_name(sql)
304
+ return false unless table_name
305
+ self.class.exclude_output_inserted_table_names[table_name]
306
+ end
307
+
286
308
  def exec_insert_requires_identity?(sql, pk, binds)
287
309
  query_requires_identity_insert?(sql) if pk && binds.map(&:name).include?(pk)
288
310
  end
@@ -291,7 +313,8 @@ module ActiveRecord
291
313
  if insert_sql?(sql)
292
314
  table_name = get_table_name(sql)
293
315
  id_column = identity_columns(table_name).first
294
- id_column && sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)[^(]+\([^)]*\b(#{id_column.name})\b,?[^)]*\)/i ? quote_table_name(table_name) : false
316
+ # id_column && sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)[^(]+\([^)]*\b(#{id_column.name})\b,?[^)]*\)/i ? quote_table_name(table_name) : false
317
+ id_column && sql =~ /^\s*(INSERT|EXEC sp_executesql N'INSERT)[^(]+\([^)]*\b(#{id_column.name})\b,?[^)]*\)/i ? table_name : false
295
318
  else
296
319
  false
297
320
  end