activerecord-jdbcsqlserver-adapter 51.1.0 → 52.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +22 -39
  4. data/{Dockerfile → Dockerfile.ci} +0 -0
  5. data/Gemfile +1 -3
  6. data/README.md +5 -8
  7. data/VERSION +1 -1
  8. data/activerecord-jdbcsqlserver-adapter.gemspec +2 -3
  9. data/docker-compose.ci.yml +7 -5
  10. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +25 -29
  11. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +14 -18
  12. data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +43 -0
  13. data/lib/active_record/connection_adapters/sqlserver/core_ext/query_methods.rb +26 -0
  14. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +13 -2
  15. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +53 -10
  16. data/lib/active_record/connection_adapters/sqlserver/database_tasks.rb +1 -0
  17. data/lib/active_record/connection_adapters/sqlserver/jdbc_overrides.rb +5 -13
  18. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +2 -1
  19. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +2 -2
  20. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +43 -27
  21. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +3 -4
  22. data/lib/active_record/connection_adapters/sqlserver/type/json.rb +1 -1
  23. data/lib/active_record/connection_adapters/sqlserver/type/string.rb +7 -0
  24. data/lib/active_record/connection_adapters/sqlserver/type/time.rb +1 -0
  25. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +20 -14
  26. data/lib/active_record/tasks/sqlserver_database_tasks.rb +3 -1
  27. data/lib/activerecord-jdbcsqlserver-adapter.rb +3 -0
  28. data/lib/arel/visitors/sqlserver.rb +1 -1
  29. data/lib/arel_sqlserver.rb +0 -1
  30. data/test/bin/install-freetds.sh +18 -0
  31. data/test/cases/adapter_test_sqlserver.rb +29 -21
  32. data/test/cases/change_column_null_test_sqlserver.rb +42 -0
  33. data/test/cases/coerced_tests.rb +304 -30
  34. data/test/cases/column_test_sqlserver.rb +496 -462
  35. data/test/cases/connection_test_sqlserver.rb +2 -2
  36. data/test/cases/fetch_test_sqlserver.rb +5 -5
  37. data/test/cases/helper_sqlserver.rb +6 -0
  38. data/test/cases/json_test_sqlserver.rb +6 -6
  39. data/test/cases/migration_test_sqlserver.rb +13 -3
  40. data/test/cases/order_test_sqlserver.rb +19 -19
  41. data/test/cases/pessimistic_locking_test_sqlserver.rb +9 -9
  42. data/test/cases/rake_test_sqlserver.rb +20 -20
  43. data/test/cases/schema_dumper_test_sqlserver.rb +34 -33
  44. data/test/cases/schema_test_sqlserver.rb +2 -2
  45. data/test/cases/showplan_test_sqlserver.rb +25 -10
  46. data/test/cases/specific_schema_test_sqlserver.rb +11 -11
  47. data/test/cases/transaction_test_sqlserver.rb +9 -9
  48. data/test/cases/trigger_test_sqlserver.rb +8 -8
  49. data/test/cases/utils_test_sqlserver.rb +36 -36
  50. data/test/cases/uuid_test_sqlserver.rb +8 -8
  51. data/test/migrations/create_clients_and_change_column_null.rb +23 -0
  52. data/test/schema/datatypes/2012.sql +1 -0
  53. data/test/schema/sqlserver_specific_schema.rb +9 -1
  54. data/test/support/core_ext/query_cache.rb +29 -0
  55. metadata +19 -10
  56. data/BACKERS.md +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0fc70db649cdce388b0aa9682a6c67c425953238feed9db877e597edea9a887
4
- data.tar.gz: ae1c960295840fecfb6a6134d012e557f2ac61c2da7f1651cd10e9ceb2f23025
3
+ metadata.gz: c764412410f757d3f4ee0312e3950ba5eb3cd1b3f7e21645e2d081ce4974f7b2
4
+ data.tar.gz: 463f9a3245a8d95ff78d76fd2284a8cacbc64b8510bfb95915d55c2e2b50021f
5
5
  SHA512:
6
- metadata.gz: 4d17bb43ed779b8dbb7b27c12d64e00666368dd1aa7eec19a1b2ef19db4c7202dd2f4a81058ade3dcc4c4977630a4109e952f43cec683f728fcc05cc3939055c
7
- data.tar.gz: bd361d607277b673f3e2f83428024730c9aa86a08b38cf5e01677dbd2b0ba7e817338c58efff22bf33ca9a915f0ae8030624f5d93bfb84a3053d04a81e05c7f1
6
+ metadata.gz: 703e10527b9d65e5e237dde6b5cdc381cb2f398f8fcd3cad780f64567694c193e9922ac58f5b4e591611157cb480ed405c75093d314e535c00210ad2ccbaeb99
7
+ data.tar.gz: f229972c054e17396b5aa1f6f554ae0a661a4e8d69ca9cb8e9ed52e4c7c3afef0f2d0eeb3e217f3e8b9c0323140329c16aa1e0986e2bc2b57da7817524a0232e
@@ -5,7 +5,7 @@ services:
5
5
  env:
6
6
  global:
7
7
  - COMPOSE_FILE: docker-compose.ci.yml
8
- - ARJDBC_BRANCH=51-stable
8
+ - ARJDBC_BRANCH: 52-stable
9
9
  matrix:
10
10
  - TARGET_VERSION=9.1
11
11
  - TARGET_VERSION=9.2
@@ -1,62 +1,45 @@
1
- ## v51.1.0
2
1
 
3
- * Updated activerecord-jdbc-adapter dependecy to fix an issue with inserts on tables with composite primary keys
4
- * Changed how the jdbc driver is loaded so that other drivers can be used if needed
2
+ ## v52.0.0
5
3
 
6
- ## v51.0.0
4
+ - Forked to support JRuby
7
5
 
8
- * Forked original gem to provide JRuby support
9
-
10
- ## v5.1.6
11
-
12
- #### Added
13
-
14
- * Use lock hint when joining table in query.
15
-
16
-
17
- ## v5.1.5
6
+ ## v5.2.1
18
7
 
19
8
  #### Fixed
20
9
 
21
- * Memoize `@@version` queries. Fixes #632
22
-
10
+ - [#691](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/691) Fix constraints bug
11
+ - [#700](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/700) SET SINGLE_USER before dropping the database
12
+ - [#733](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/733) Calculate should not remove ordering for MSSQL
13
+ - [#735](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/735) Order by selected items when using distinct exists
14
+ - [#737](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/737) Use default precision for 'time' column type
15
+ - [#744](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/744) Adapter does not use prepared statement cache
16
+ - [#743](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/743) Set default time precision when registering time type
17
+ - [#745](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/745) Quoted table names containing square brackets need to be regex escaped
23
18
 
24
- ## v5.1.4
19
+ ## v5.2.0
25
20
 
26
21
  #### Fixed
27
22
 
28
- * Add case insensitive comparison for better performance with CI collations. Fixes #624
23
+ - [#686](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/686) sql_for_insert set table name in case when pk is not nil
29
24
 
30
-
31
- ## v5.1.3
25
+ ## v5.2.0.rc2
32
26
 
33
27
  #### Fixed
34
28
 
35
- * Use bigint type in sqlserver_type when needed. Fixes #616
36
-
29
+ - [#681](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/681) change_column_null should not clear other column attributes. Fixes #582.
30
+ - [#684](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/684) Fix explain with array conditions. Fixes #673.
37
31
 
38
- ## v5.1.2
32
+ ## v5.2.0.rc1
39
33
 
40
34
  #### Fixed
41
35
 
42
- * The `fast_string_to_time` method when zone local. Fixes #609 #614 #620
43
- * Patched `Relation#build_count_subquery`. Fixes #613.
44
- * Inserts to tables with triggers using default `OUTPUT INSERTED` style. Fixes #595.
45
-
46
-
47
- ## v5.1.1
48
-
49
- #### Fixed
50
-
51
- * Use `ActiveSupport.on_load` to hook into ActiveRecord Fixes #588 #598
52
-
53
-
54
- ## v5.1.0
36
+ - [#638](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/638) Don't disable referential integrity for the same table twice.
37
+ - [#646](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/646) Make String equality check work for Type::Data values. Fixes #645.
38
+ - [#671](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/671) Fix tinyint columns schema migration. Fixes #670.
55
39
 
56
40
  #### Changed
57
41
 
58
- * The `drop_table` with force cascade option now mimics in via pure SQL for us.
42
+ - [#642](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/642) Added with (nolock) hint to information_schema.views.
59
43
 
60
- #### Added
61
44
 
62
- * Support MismatchedForeignKey exception.
45
+ Please check [5-1-stable-jdbc](https://github.com/jruby/activerecord-jdbcsqlserver-adapter/blob/5-1-stable-jdbc/CHANGELOG.md) for previous changes.
File without changes
data/Gemfile CHANGED
@@ -2,9 +2,7 @@ require 'openssl'
2
2
  source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
- gem 'rb-readline', platform: :mri
6
- gem 'sqlite3', platform: :mri
7
- gem 'minitest', '< 5.3.4'
5
+ gem 'sqlite3', '~> 1.3.6', platform: :mri
8
6
  gem 'bcrypt'
9
7
  gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
10
8
 
data/README.md CHANGED
@@ -1,18 +1,16 @@
1
- # ActiveRecord SQL Server Adapter. For SQL Server 2012 And Higher.
1
+ # ActiveRecord JDBC SQL Server Adapter. For SQL Server 2012 And Higher.
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
- The JDBC SQL Server adapter for ActiveRecord v5.1 using SQL Server 2012 or higher.
5
+ ## About The Adapter
6
+
7
+ The JDBC SQL Server adapter for ActiveRecord v5.2 using SQL Server 2012 or higher.
6
8
 
7
9
  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.
8
10
 
9
11
  For older versions see [activerecord-jdbcmssql-adapter](https://rubygems.org/gems/activerecord-jdbcmssql-adapter)
10
12
 
11
13
 
12
- #### Native Data Type Support
13
-
14
- The Rails v5 adapter supports ActiveRecord's `datetime_with_precision` setting. This means that passing `:precision` to a datetime column is supported. Using a pecision with the `:datetime` type will signal the adapter to use the `datetime2` type under the hood.
15
-
16
14
  #### Schemas & Users
17
15
 
18
16
  Depending on your user and schema setup, it may be needed to use a table name prefix of `dbo.`. So something like this in your initializer file for ActiveRecord or the adapter.
@@ -48,7 +46,7 @@ gem 'activerecord-jdbcsqlserver-adapter'
48
46
 
49
47
  ## Contributing
50
48
 
51
- If you would like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Gitter, or post a ticket on github issues. Second, make sure there are tests! We will not accept any patch that is not tested. Please read the `RUNNING_UNIT_TESTS` file for the details of how to run the unit tests.
49
+ If you would like to contribute a feature or bugfix, thanks! To make sure your fix/feature has a high chance of being added, please read the following guidelines. First, ask on the Gitter, or post a ticket on github issues. Second, make sure there are tests! We will not accept any patch that is not tested. Please read the [`RUNNING_UNIT_TESTS`](RUNNING_UNIT_TESTS.md) file for the details of how to run the unit tests.
52
50
 
53
51
  This is a fork of the activerecord-sqlserver-adapter. If you find a bug in the base code, please submit patches to: http://github.com/rails-sqlserver/activerecord-sqlserver-adapter
54
52
 
@@ -89,4 +87,3 @@ JDBC version of the gem:
89
87
  ## License
90
88
 
91
89
  Copyright © 2008-2019. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
92
-
data/VERSION CHANGED
@@ -1 +1 @@
1
- 51.1.0
1
+ 52.0.0
@@ -15,8 +15,7 @@ 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
-
19
- spec.add_dependency 'activerecord', '~> 5.1.0', '>= 5.1.7'
20
- spec.add_dependency 'activerecord-jdbc-adapter' , '~> 51.8'
18
+ spec.add_dependency 'activerecord', '~> 5.2.0', '>= 5.2.3'
19
+ spec.add_dependency 'activerecord-jdbc-adapter' , '~> 52.7'
21
20
  spec.add_dependency 'jdbc-mssql', '>= 0.6.0'
22
21
  end
@@ -1,11 +1,13 @@
1
1
  version: "2.2"
2
2
  services:
3
- database:
3
+ sqlserver:
4
4
  image: metaskills/mssql-server-linux-rails
5
5
  ci:
6
6
  environment:
7
- - ACTIVERECORD_UNITTEST_HOST=database
8
- build: .
9
- command: test/bin/wait-for.sh database:1433 -- bundle exec rake test
7
+ - ACTIVERECORD_UNITTEST_HOST=sqlserver
8
+ build:
9
+ context: .
10
+ dockerfile: Dockerfile.ci
11
+ command: test/bin/wait-for.sh sqlserver:1433 -- bundle exec rake test
10
12
  depends_on:
11
- - "database"
13
+ - "sqlserver"
@@ -7,37 +7,37 @@ module ActiveRecord
7
7
  module CoreExt
8
8
  module Calculations
9
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)
10
+ # Same as original except we don't perform PostgreSQL hack that removes ordering.
11
+ def calculate(operation, column_name)
12
+ if has_include?(column_name)
13
+ relation = apply_join_dependency
14
+
15
+ if operation.to_s.downcase == "count"
16
+ unless distinct_value || distinct_select?(column_name || select_for_count)
17
+ relation.distinct!
18
+ relation.select_values = [ klass.primary_key || table[Arel.star] ]
19
+ end
20
+ end
21
+
22
+ relation.calculate(operation, column_name)
23
+ else
24
+ perform_calculation(operation, column_name)
17
25
  end
18
- attrs
19
26
  end
20
27
 
21
28
  private
22
29
 
23
- # @Override
24
30
  def build_count_subquery(relation, column_name, distinct)
31
+ super(relation.unscope(:order), column_name, distinct)
32
+ end
25
33
 
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
34
+ def type_cast_calculated_value(value, type, operation = nil)
35
+ case operation
36
+ when "count" then value.to_i
37
+ when "sum" then type.deserialize(value || 0)
38
+ when "average" then value&.respond_to?(:to_d) ? value.to_d : value
39
+ else type.deserialize(value)
37
40
  end
38
-
39
- super
40
-
41
41
  end
42
42
  end
43
43
  end
@@ -46,10 +46,6 @@ module ActiveRecord
46
46
  end
47
47
 
48
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
49
+ mod = ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::Calculations
50
+ ActiveRecord::Relation.prepend(mod)
55
51
  end
@@ -5,12 +5,11 @@ module ActiveRecord
5
5
  module Explain
6
6
 
7
7
  SQLSERVER_STATEMENT_PREFIX = 'EXEC sp_executesql '.freeze
8
- SQLSERVER_PARAM_MATCHER = /@\d+ = (.*)/
9
- SQLSERVER_NATIONAL_STRING_MATCHER = /N'(.*)'/m
8
+ SQLSERVER_STATEMENT_REGEXP = /N'(.+)', N'(.+)', (.+)/
10
9
 
11
10
  def exec_explain(queries)
12
11
  unprepared_queries = queries.map do |(sql, binds)|
13
- [unprepare_sqlserver_statement(sql), binds]
12
+ [unprepare_sqlserver_statement(sql, binds), binds]
14
13
  end
15
14
  super(unprepared_queries)
16
15
  end
@@ -19,22 +18,19 @@ module ActiveRecord
19
18
 
20
19
  # This is somewhat hacky, but it should reliably reformat our prepared sql statment
21
20
  # which uses sp_executesql to just the first argument, then unquote it. Likewise our
22
- # `sp_executesql` method should substitude the @n args withe the quoted values.
23
- def unprepare_sqlserver_statement(sql)
24
- if sql.starts_with?(SQLSERVER_STATEMENT_PREFIX)
25
- executesql = sql.from(SQLSERVER_STATEMENT_PREFIX.length)
26
- args = executesql.split(', ')
27
- unprepared_sql = args.shift.strip.match(SQLSERVER_NATIONAL_STRING_MATCHER)[1]
28
- unprepared_sql = Utils.unquote_string(unprepared_sql)
29
- args = args.from(args.length / 2)
30
- args.each_with_index do |arg, index|
31
- value = arg.match(SQLSERVER_PARAM_MATCHER)[1]
32
- unprepared_sql.sub! "@#{index}", value
33
- end
34
- unprepared_sql
35
- else
36
- sql
21
+ # `sp_executesql` method should substitude the @n args with the quoted values.
22
+ def unprepare_sqlserver_statement(sql, binds)
23
+ return sql unless sql.starts_with?(SQLSERVER_STATEMENT_PREFIX)
24
+
25
+ executesql = sql.from(SQLSERVER_STATEMENT_PREFIX.length)
26
+ executesql = executesql.match(SQLSERVER_STATEMENT_REGEXP).to_a[1]
27
+
28
+ binds.each_with_index do |bind, index|
29
+ value = connection.quote(bind)
30
+ executesql = executesql.sub("@#{index}", value)
37
31
  end
32
+
33
+ executesql
38
34
  end
39
35
 
40
36
  end
@@ -0,0 +1,43 @@
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 FinderMethods
9
+
10
+ private
11
+
12
+ # Same as original except we order by values in distinct select if present.
13
+ def construct_relation_for_exists(conditions)
14
+ if distinct_value && offset_value
15
+ relation = limit!(1)
16
+
17
+ if select_values.present?
18
+ relation = relation.order(*select_values)
19
+ else
20
+ relation = relation.except(:order)
21
+ end
22
+ else
23
+ relation = except(:select, :distinct, :order)._select!(::ActiveRecord::FinderMethods::ONE_AS_ONE).limit!(1)
24
+ end
25
+
26
+ case conditions
27
+ when Array, Hash
28
+ relation.where!(conditions) unless conditions.empty?
29
+ else
30
+ relation.where!(primary_key => conditions) unless conditions == :none
31
+ end
32
+
33
+ relation
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ ActiveSupport.on_load(:active_record) do
42
+ ActiveRecord::Relation.include(ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::FinderMethods)
43
+ end
@@ -0,0 +1,26 @@
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 QueryMethods
9
+
10
+ private
11
+
12
+ # Copy of original from Rails master. This patch can be removed when adapter supports Rails 6.
13
+ def table_name_matches?(from)
14
+ table_name = Regexp.escape(table.name)
15
+ quoted_table_name = Regexp.escape(connection.quote_table_name(table.name))
16
+ /(?:\A|(?<!FROM)\s)(?:\b#{table_name}\b|#{quoted_table_name})(?!\.)/i.match?(from.to_s)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ ActiveSupport.on_load(:active_record) do
25
+ ActiveRecord::Relation.include(ActiveRecord::ConnectionAdapters::SQLServer::CoreExt::QueryMethods)
26
+ end
@@ -2,7 +2,6 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module SQLServer
4
4
  module DatabaseLimits
5
-
6
5
  def table_alias_length
7
6
  128
8
7
  end
@@ -32,7 +31,7 @@ module ActiveRecord
32
31
  end
33
32
 
34
33
  def in_clause_length
35
- 65_536
34
+ 10_000
36
35
  end
37
36
 
38
37
  def sql_query_length
@@ -43,6 +42,18 @@ module ActiveRecord
43
42
  256
44
43
  end
45
44
 
45
+ private
46
+
47
+ # The max number of binds is 2100, but because sp_executesql takes
48
+ # the first 2 params as the query string and the list of types,
49
+ # we have only 2098 spaces left
50
+ def bind_params_length
51
+ 2_098
52
+ end
53
+
54
+ def insert_rows_length
55
+ 1_000
56
+ end
46
57
  end
47
58
  end
48
59
  end
@@ -33,10 +33,6 @@ module ActiveRecord
33
33
  super(sql, name, binds).rows.first.first
34
34
  end
35
35
 
36
- def supports_statement_cache?
37
- true
38
- end
39
-
40
36
  def begin_db_transaction
41
37
  do_execute 'BEGIN TRANSACTION'
42
38
  end
@@ -77,17 +73,55 @@ module ActiveRecord
77
73
 
78
74
  def case_sensitive_comparison(table, attribute, column, value)
79
75
  if column.collation && !column.case_sensitive?
80
- table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new))
76
+ table[attribute].eq(Arel::Nodes::Bin.new(value))
81
77
  else
82
78
  super
83
79
  end
84
80
  end
85
81
 
82
+ # We should propose this change to Rails team
83
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
84
+ fixture_inserts = []
85
+
86
+ fixture_set.each do |table_name, fixtures|
87
+ fixtures.each_slice(insert_rows_length) do |batch|
88
+ fixture_inserts << build_fixture_sql(batch, table_name)
89
+ end
90
+ end
91
+
92
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
93
+ total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
94
+
95
+ disable_referential_integrity do
96
+ transaction(requires_new: true) do
97
+ total_sql.each do |sql|
98
+ execute sql, "Fixtures Load"
99
+ yield if block_given?
100
+ end
101
+ end
102
+ end
103
+ end
104
+
86
105
  def can_perform_case_insensitive_comparison_for?(column)
87
106
  column.type == :string && (!column.collation || column.case_sensitive?)
88
107
  end
89
108
  private :can_perform_case_insensitive_comparison_for?
90
109
 
110
+ def combine_multi_statements(total_sql)
111
+ total_sql
112
+ end
113
+ private :combine_multi_statements
114
+
115
+ def default_insert_value(column)
116
+ if column.is_identity?
117
+ table_name = quote(quote_table_name(column.table_name))
118
+ Arel.sql("IDENT_CURRENT(#{table_name}) + IDENT_INCR(#{table_name})")
119
+ else
120
+ super
121
+ end
122
+ end
123
+ private :default_insert_value
124
+
91
125
  # === SQLServer Specific ======================================== #
92
126
 
93
127
  def execute_procedure(proc_name, *variables)
@@ -238,6 +272,8 @@ module ActiveRecord
238
272
  def sp_executesql_types_and_parameters(binds)
239
273
  types, params = [], []
240
274
  binds.each_with_index do |attr, index|
275
+ attr = attr.value if attr.is_a?(Arel::Nodes::BindParam)
276
+
241
277
  types << "@#{index} #{sp_executesql_sql_type(attr)}"
242
278
  params << sp_executesql_sql_param(attr)
243
279
  end
@@ -255,12 +291,12 @@ module ActiveRecord
255
291
  end
256
292
 
257
293
  def sp_executesql_sql_param(attr)
258
- case attr.value_for_database
294
+ case value = attr.value_for_database
259
295
  when Type::Binary::Data,
260
296
  ActiveRecord::Type::SQLServer::Data
261
- quote(attr.value_for_database)
297
+ quote(value)
262
298
  else
263
- quote(type_cast(attr.value_for_database))
299
+ quote(type_cast(value))
264
300
  end
265
301
  end
266
302
 
@@ -282,7 +318,14 @@ module ActiveRecord
282
318
  def raw_connection_do(sql)
283
319
  case @connection_options[:mode]
284
320
  when :dblib
285
- @connection.execute(sql).do
321
+ result = @connection.execute(sql)
322
+
323
+ # TinyTDS returns false instead of raising an exception if connection fails.
324
+ # Getting around this by raising an exception ourselves while this PR
325
+ # https://github.com/rails-sqlserver/tiny_tds/pull/469 is not released.
326
+ raise TinyTds::Error, "failed to execute statement" if result.is_a?(FalseClass)
327
+
328
+ result.do
286
329
  end
287
330
  ensure
288
331
  @update_sql = false
@@ -306,7 +349,7 @@ module ActiveRecord
306
349
  end
307
350
 
308
351
  def exec_insert_requires_identity?(sql, pk, binds)
309
- query_requires_identity_insert?(sql) if pk && binds.map(&:name).include?(pk)
352
+ query_requires_identity_insert?(sql)
310
353
  end
311
354
 
312
355
  def query_requires_identity_insert?(sql)