activerecord-sqlserver-adapter 6.0.0.rc2 → 6.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +26 -0
  3. data/CHANGELOG.md +20 -41
  4. data/README.md +32 -3
  5. data/RUNNING_UNIT_TESTS.md +1 -1
  6. data/VERSION +1 -1
  7. data/activerecord-sqlserver-adapter.gemspec +1 -1
  8. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +0 -9
  9. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +7 -2
  10. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -4
  11. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +28 -16
  12. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +7 -7
  13. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -1
  14. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -3
  15. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +31 -8
  16. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +27 -7
  17. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +0 -1
  18. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +2 -2
  19. data/lib/active_record/connection_adapters/sqlserver/type.rb +1 -0
  20. data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
  21. data/lib/active_record/connection_adapters/sqlserver/utils.rb +1 -1
  22. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +100 -68
  23. data/lib/active_record/connection_adapters/sqlserver_column.rb +17 -0
  24. data/lib/active_record/sqlserver_base.rb +9 -15
  25. data/lib/active_record/tasks/sqlserver_database_tasks.rb +17 -14
  26. data/lib/arel/visitors/sqlserver.rb +111 -39
  27. data/test/cases/adapter_test_sqlserver.rb +48 -14
  28. data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
  29. data/test/cases/coerced_tests.rb +598 -78
  30. data/test/cases/column_test_sqlserver.rb +5 -2
  31. data/test/cases/disconnected_test_sqlserver.rb +39 -0
  32. data/test/cases/execute_procedure_test_sqlserver.rb +9 -0
  33. data/test/cases/in_clause_test_sqlserver.rb +27 -0
  34. data/test/cases/lateral_test_sqlserver.rb +35 -0
  35. data/test/cases/migration_test_sqlserver.rb +51 -0
  36. data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
  37. data/test/cases/order_test_sqlserver.rb +7 -0
  38. data/test/cases/primary_keys_test_sqlserver.rb +103 -0
  39. data/test/cases/rake_test_sqlserver.rb +3 -2
  40. data/test/cases/schema_dumper_test_sqlserver.rb +20 -3
  41. data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
  42. data/test/models/sqlserver/sst_string_collation.rb +3 -0
  43. data/test/schema/sqlserver_specific_schema.rb +17 -0
  44. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
  45. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
  46. data/test/support/sql_counter_sqlserver.rb +14 -12
  47. metadata +32 -13
  48. data/.travis.yml +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae90a6f8498d914a0cff5b47bf56fe4eacf67fa771b4f89b06fb3c97683cf6ec
4
- data.tar.gz: 3bcba233d32f874bc4914886d257f32cb45b06eec83a395cec9d0d4876c59bbb
3
+ metadata.gz: cb745869999fcde64e516e7a09aae4c0405396bb36f8fe3c57f8b01ff4b2e5b8
4
+ data.tar.gz: ad90fcd48bd9141986cdb5b9e5ea364c08c7a045545ef88e24030d1bed1b6e54
5
5
  SHA512:
6
- metadata.gz: 8fda1468adae0fe9a8de40c33abbcd34c4364b441e3ea55724130c1a871999e2985e7c7183a03534c0361b8d89f7f150be17ca30f98a3d4ac1d36dbe956e8174
7
- data.tar.gz: a893c81ab5b00204c9014aba27cab25bee3513001043e71132e00938534d7c0ca0b7ea1cd1b8b10b347c97ece39e29a30ebdfbf85ed748f983b159573f0e1836
6
+ metadata.gz: 3f1becc13785706f0074d5ca4339a21531c3b4bcffe4582f8858dace5d75100a20e60518963effcd6edd933a7d3c434aeb4c16d62c5b518aa7e29e4d7bf79ddf
7
+ data.tar.gz: 02b54c72e7abf889b1f51e77b86e7a70d47657991a21cdb27cdd42334eb06040a15f8c5a936bae70c399baba5d699c766f4b46030e27844f569fe98d12e11080
@@ -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,50 +1,29 @@
1
- ## v6.0.0.rc2
1
+ ## v6.1.0.0
2
2
 
3
- #### Fixed
4
-
5
- - [#639](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/639) Primary key should be lowercase if schema forced to lowercase
6
- - [#720](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/720) quoted_date doesn't work for Type::DateTime
7
-
8
- #### Changed
3
+ - No changes
9
4
 
10
- - [#826](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/826) Rubocop: Enable Style/StringLiterals cop
11
- - [#827](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/827) Rubocop: Enable Layout/EmptyLinesAroundClassBody cop
12
- - [#828](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/828) Rubocop: Enable Layout/EmptyLines cop
13
- - [#829](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/829) Rubocop: Enable Layout/Layout/EmptyLinesAround* cops
14
- - [#830](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/830) Rubocop: Enable Layout/IndentationWidth and Layout/TrailingWhitespace cops
15
- - [#831](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/831) Rubocop: Enable Spacing cops
16
- - [#832](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/832) Rubocop: Enable Bundler cops
17
- - [#833](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/833) Rubocop: Enable Layout/* cops
18
- - [#834](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/834) Rubocop: Enable Lint/UselessAssignment cop
19
- - [#835](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/835) Rubocop: Configure Naming cops
20
-
21
- ## v6.0.0.rc1
5
+ ## v6.1.0.0.rc1
22
6
 
23
7
  #### Fixed
24
8
 
25
- - [#690](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/690) Rails 6 support
26
- - [#805](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/805) Rails 6: Fix database tasks tests for SQL Server
27
- - [#807](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/807) Rails 6: Skip binary fixtures test on Windows
28
- - [#809](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/809) Rails 6: Coerce reaper test using fork
29
- - [#810](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/810) Rails 6: Fix randomly failing tests due to schema load
30
- - [#812](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/812) Rails 6: Coerce ReloadModelsTest test on Windows
31
- - [#818](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/818) Handle false return by TinyTDS if connection fails and fixed CI
32
- - [#819](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/819) Fix Ruby 2.7 kwargs warnings
33
- - [#825](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/825) Adjust error message when connection is dead
9
+ - [#872](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/872) Use native String#start_with
10
+ - [#876](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/876) Use native String#end_with
11
+ - [#873](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/873) Various fixes to get the tests running for Rails 6.1
12
+ - [#874](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/874) Deduplicate schema cache structures
13
+ - [#875](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/875) Handle default boolean column values when deduplicating
14
+ - [#879](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/879) Added visit method for HomogeneousIn
15
+ - [#880](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/880) Handle any default column class when deduplicating
16
+ - [#861](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/861) Fix Rails 6.1 database config
17
+ - [#890](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/890) Fix removal of invalid ordering from select statements
18
+ - [#881](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/881) Dump column collation to schema.rb and allow collation changes using column_change
19
+ - [#891](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/891) Add support for if_not_exists to indexes
20
+ - [#892](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/892) Add support for if_exists on remove_column
21
+ - [#883](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/885) Fix quoting of ActiveRecord::Relation::QueryAttribute and ActiveModel::Attributes
22
+ - [#893](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/893) Add Active Record Marshal forward compatibility tests
23
+ - [#903](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/903) Raise ActiveRecord::ConnectionNotEstablished on calls to execute with a disconnected connection
34
24
 
35
25
  #### Changed
36
26
 
37
- - [#716](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/716) Translate the connection timed out error
38
- - [#763](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/763) Refactor columns introspection query to make it faster
39
- - [#783](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/783) Update test matrix
40
- - [#820](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/820) Enable frozen strings for tests
41
- - [#821](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/821) Enable frozen strings - part 1
42
- - [#822](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/822) Enable frozen strings - part 2
43
- - [#823](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/823) Enable frozen strings - final
44
- - [#824](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/824) Tidy up Gemfile
45
-
46
- #### Added
47
-
48
- - [#726](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/726) How to Develop ActiveRecord SQL Server Adapter with Pre-Installed MS SQL
27
+ - [#917](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/pull/917) Refactored to use new_client connection pattern
49
28
 
50
- Please check [5-2-stable](https://github.com/rails-sqlserver/activerecord-sqlserver-adapter/blob/5-2-stable/CHANGELOG.md) for previous changes.
29
+ 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
- * [![TravisCI](https://travis-ci.org/rails-sqlserver/activerecord-sqlserver-adapter.svg?branch=master)](https://travis-ci.org/rails-sqlserver/activerecord-sqlserver-adapter) - TravisCI
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 v6.0 using SQL Server 2012 or higher.
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 5.2.x version of the adapter is only for the latest 5.2 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.
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.0.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
 
@@ -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](/https://github.com/rails-sqlserver/activerecord-sqlserver-adapter-dev-box).
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.0.0.rc2
1
+ 6.1.0.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.0.0"
30
+ spec.add_dependency "activerecord", "~> 6.1.0"
31
31
  spec.add_dependency "tiny_tds"
32
32
  end
@@ -31,15 +31,6 @@ module ActiveRecord
31
31
  def build_count_subquery(relation, column_name, distinct)
32
32
  super(relation.unscope(:order), column_name, distinct)
33
33
  end
34
-
35
- def type_cast_calculated_value(value, type, operation = nil)
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
42
- end
43
34
  end
44
35
  end
45
36
  end
@@ -21,13 +21,18 @@ module ActiveRecord
21
21
  # which uses sp_executesql to just the first argument, then unquote it. Likewise our
22
22
  # `sp_executesql` method should substitude the @n args with the quoted values.
23
23
  def unprepare_sqlserver_statement(sql, binds)
24
- return sql unless sql.starts_with?(SQLSERVER_STATEMENT_PREFIX)
24
+ return sql unless sql.start_with?(SQLSERVER_STATEMENT_PREFIX)
25
25
 
26
26
  executesql = sql.from(SQLSERVER_STATEMENT_PREFIX.length)
27
27
  executesql = executesql.match(SQLSERVER_STATEMENT_REGEXP).to_a[1]
28
28
 
29
29
  binds.each_with_index do |bind, index|
30
- value = connection.quote(bind)
30
+
31
+ value = if bind.is_a?(::ActiveModel::Attribute) then
32
+ connection.quote(bind.value_for_database)
33
+ else
34
+ connection.quote(bind)
35
+ end
31
36
  executesql = executesql.sub("@#{index}", value)
32
37
  end
33
38
 
@@ -37,10 +37,6 @@ module ActiveRecord
37
37
  end
38
38
  deprecate :columns_per_multicolumn_index
39
39
 
40
- def in_clause_length
41
- 10_000
42
- end
43
-
44
40
  def sql_query_length
45
41
  65_536 * 4_096
46
42
  end
@@ -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 = @connection.execute(sql)
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 = @connection.execute(sql)
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
- @connection.execute(sql)
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,14 @@ module ActiveRecord
10
10
 
11
11
  def fetch_type_metadata(sql_type, sqlserver_options = {})
12
12
  cast_type = lookup_cast_type(sql_type)
13
- SQLServer::SqlTypeMetadata.new(
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
+ SQLServer::TypeMetadata.new(simple_type, sqlserver_options: sqlserver_options)
21
21
  end
22
22
 
23
23
  def quote_string(s)
@@ -83,8 +83,8 @@ module ActiveRecord
83
83
  \A
84
84
  (
85
85
  (?:
86
- # [table_name].[column_name] | function(one or no argument)
87
- ((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
86
+ # [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
87
+ ((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
88
88
  )
89
89
  (?:\s+AS\s+(?:\w+|\[\w+\]))?
90
90
  )
@@ -96,8 +96,8 @@ module ActiveRecord
96
96
  \A
97
97
  (
98
98
  (?:
99
- # [table_name].[column_name] | function(one or no argument)
100
- ((?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
99
+ # [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
100
+ ((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\])) | \w+\((?:|\g<2>)\)
101
101
  )
102
102
  (?:\s+ASC|\s+DESC)?
103
103
  (?:\s+NULLS\s+(?:FIRST|LAST))?
@@ -3,9 +3,13 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module SQLServer
6
- class SchemaCreation < AbstractAdapter::SchemaCreation
6
+ class SchemaCreation < SchemaCreation
7
7
  private
8
8
 
9
+ def supports_index_using?
10
+ false
11
+ end
12
+
9
13
  def visit_TableDefinition(o)
10
14
  if_not_exists = o.if_not_exists
11
15
 
@@ -29,11 +33,28 @@ module ActiveRecord
29
33
  sql
30
34
  end
31
35
 
36
+ def visit_CreateIndexDefinition(o)
37
+ if_not_exists = o.if_not_exists
38
+
39
+ o.if_not_exists = false
40
+
41
+ sql = super
42
+
43
+ if if_not_exists
44
+ sql = "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '#{o.index.name}') #{sql}"
45
+ end
46
+
47
+ sql
48
+ end
49
+
32
50
  def add_column_options!(sql, options)
33
51
  sql << " DEFAULT #{quote_default_expression(options[:default], options[:column])}" if options_include_default?(options)
34
52
  if options[:null] == false
35
53
  sql << " NOT NULL"
36
54
  end
55
+ if options[:collation].present?
56
+ sql << " COLLATE #{options[:collation]}"
57
+ end
37
58
  if options[:is_identity] == true
38
59
  sql << " IDENTITY(1,1)"
39
60
  end