activerecord-sqlserver-adapter 7.1.7 → 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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +3 -3
  3. data/.github/workflows/ci.yml +10 -4
  4. data/CHANGELOG.md +5 -99
  5. data/Gemfile +4 -4
  6. data/README.md +43 -19
  7. data/VERSION +1 -1
  8. data/activerecord-sqlserver-adapter.gemspec +2 -2
  9. data/lib/active_record/connection_adapters/sqlserver/core_ext/attribute_methods.rb +6 -4
  10. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +6 -5
  11. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +7 -4
  12. data/lib/active_record/connection_adapters/sqlserver/core_ext/finder_methods.rb +6 -4
  13. data/lib/active_record/connection_adapters/sqlserver/core_ext/preloader.rb +14 -12
  14. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +50 -32
  15. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +44 -46
  16. data/lib/active_record/connection_adapters/sqlserver/savepoints.rb +2 -0
  17. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +1 -1
  18. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +2 -5
  19. data/lib/active_record/tasks/sqlserver_database_tasks.rb +38 -32
  20. data/lib/arel/visitors/sqlserver.rb +57 -12
  21. data/test/cases/active_schema_test_sqlserver.rb +6 -6
  22. data/test/cases/adapter_test_sqlserver.rb +17 -18
  23. data/test/cases/coerced_tests.rb +279 -167
  24. data/test/cases/disconnected_test_sqlserver.rb +9 -3
  25. data/test/cases/eager_load_too_many_ids_test_sqlserver.rb +1 -1
  26. data/test/cases/enum_test_sqlserver.rb +1 -1
  27. data/test/cases/execute_procedure_test_sqlserver.rb +9 -5
  28. data/test/cases/helper_sqlserver.rb +11 -5
  29. data/test/cases/index_test_sqlserver.rb +8 -6
  30. data/test/cases/json_test_sqlserver.rb +1 -1
  31. data/test/cases/lateral_test_sqlserver.rb +2 -2
  32. data/test/cases/migration_test_sqlserver.rb +1 -1
  33. data/test/cases/optimizer_hints_test_sqlserver.rb +12 -12
  34. data/test/cases/pessimistic_locking_test_sqlserver.rb +8 -7
  35. data/test/cases/primary_keys_test_sqlserver.rb +2 -2
  36. data/test/cases/rake_test_sqlserver.rb +8 -4
  37. data/test/cases/schema_dumper_test_sqlserver.rb +4 -5
  38. data/test/cases/showplan_test_sqlserver.rb +7 -7
  39. data/test/cases/specific_schema_test_sqlserver.rb +17 -13
  40. data/test/cases/view_test_sqlserver.rb +1 -1
  41. data/test/schema/sqlserver_specific_schema.rb +4 -4
  42. data/test/support/connection_reflection.rb +1 -1
  43. data/test/support/core_ext/query_cache.rb +2 -2
  44. data/test/support/query_assertions.rb +49 -0
  45. data/test/support/table_definition_sqlserver.rb +24 -0
  46. data/test/support/test_in_memory_oltp.rb +2 -2
  47. metadata +12 -13
  48. data/lib/active_record/sqlserver_base.rb +0 -13
  49. data/test/cases/scratchpad_test_sqlserver.rb +0 -8
  50. data/test/support/sql_counter_sqlserver.rb +0 -14
@@ -4,9 +4,53 @@ module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module SQLServer
6
6
  module Quoting
7
+ extend ActiveSupport::Concern
8
+
7
9
  QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
8
10
  QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
9
11
 
12
+ module ClassMethods
13
+ def column_name_matcher
14
+ /
15
+ \A
16
+ (
17
+ (?:
18
+ # [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
19
+ ((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
20
+ )
21
+ (?:\s+AS\s+(?:\w+|\[\w+\]))?
22
+ )
23
+ (?:\s*,\s*\g<1>)*
24
+ \z
25
+ /ix
26
+ end
27
+
28
+ def column_name_with_order_matcher
29
+ /
30
+ \A
31
+ (
32
+ (?:
33
+ # [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
34
+ ((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
35
+ )
36
+ (?:\s+COLLATE\s+\w+)?
37
+ (?:\s+ASC|\s+DESC)?
38
+ (?:\s+NULLS\s+(?:FIRST|LAST))?
39
+ )
40
+ (?:\s*,\s*\g<1>)*
41
+ \z
42
+ /ix
43
+ end
44
+
45
+ def quote_column_name(name)
46
+ QUOTED_COLUMN_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
47
+ end
48
+
49
+ def quote_table_name(name)
50
+ QUOTED_TABLE_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
51
+ end
52
+ end
53
+
10
54
  def fetch_type_metadata(sql_type, sqlserver_options = {})
11
55
  cast_type = lookup_cast_type(sql_type)
12
56
 
@@ -33,14 +77,6 @@ module ActiveRecord
33
77
  SQLServer::Utils.quote_string_single_national(s)
34
78
  end
35
79
 
36
- def quote_column_name(name)
37
- QUOTED_COLUMN_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
38
- end
39
-
40
- def quote_table_name(name)
41
- QUOTED_TABLE_NAMES[name] ||= SQLServer::Utils.extract_identifiers(name).quoted
42
- end
43
-
44
80
  def quote_default_expression(value, column)
45
81
  cast_type = lookup_cast_type(column.sql_type)
46
82
  if cast_type.type == :uuid && value.is_a?(String) && value.include?('()')
@@ -76,44 +112,6 @@ module ActiveRecord
76
112
  end
77
113
  end
78
114
 
79
- def column_name_matcher
80
- COLUMN_NAME
81
- end
82
-
83
- def column_name_with_order_matcher
84
- COLUMN_NAME_WITH_ORDER
85
- end
86
-
87
- COLUMN_NAME = /
88
- \A
89
- (
90
- (?:
91
- # [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
92
- ((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
93
- )
94
- (?:\s+AS\s+(?:\w+|\[\w+\]))?
95
- )
96
- (?:\s*,\s*\g<1>)*
97
- \z
98
- /ix
99
-
100
- COLUMN_NAME_WITH_ORDER = /
101
- \A
102
- (
103
- (?:
104
- # [database_name].[database_owner].[table_name].[column_name] | function(one or no argument)
105
- ((?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+\.|\[\w+\]\.)?(?:\w+|\[\w+\]) | \w+\((?:|\g<2>)\))
106
- )
107
- (?:\s+COLLATE\s+\w+)?
108
- (?:\s+ASC|\s+DESC)?
109
- (?:\s+NULLS\s+(?:FIRST|LAST))?
110
- )
111
- (?:\s*,\s*\g<1>)*
112
- \z
113
- /ix
114
-
115
- private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
116
-
117
115
  def quote(value)
118
116
  case value
119
117
  when Type::Binary::Data
@@ -16,6 +16,8 @@ module ActiveRecord
16
16
  internal_execute("ROLLBACK TRANSACTION #{name}", "TRANSACTION")
17
17
  end
18
18
 
19
+ # SQL Server does require save-points to be explicitly released.
20
+ # See https://stackoverflow.com/questions/3101312/sql-server-2008-no-release-savepoint-for-current-transaction
19
21
  def release_savepoint(_name)
20
22
  end
21
23
  end
@@ -132,7 +132,7 @@ module ActiveRecord
132
132
  schema_cache.clear_data_source_cache!(table_name.to_s)
133
133
  schema_cache.clear_data_source_cache!(new_name.to_s)
134
134
  execute "EXEC sp_rename '#{table_name}', '#{new_name}'"
135
- rename_table_indexes(table_name, new_name)
135
+ rename_table_indexes(table_name, new_name, **options)
136
136
  end
137
137
 
138
138
  def remove_column(table_name, column_name, type = nil, **options)
@@ -29,12 +29,13 @@ require "active_record/connection_adapters/sqlserver/showplan"
29
29
  require "active_record/connection_adapters/sqlserver/table_definition"
30
30
  require "active_record/connection_adapters/sqlserver/quoting"
31
31
  require "active_record/connection_adapters/sqlserver/utils"
32
- require "active_record/sqlserver_base"
33
32
  require "active_record/connection_adapters/sqlserver_column"
34
33
  require "active_record/tasks/sqlserver_database_tasks"
35
34
 
36
35
  module ActiveRecord
37
36
  module ConnectionAdapters
37
+ register "sqlserver", "ActiveRecord::ConnectionAdapters::SQLServerAdapter", "active_record/connection_adapters/sqlserver_adapter"
38
+
38
39
  class SQLServerAdapter < AbstractAdapter
39
40
  include SQLServer::Version,
40
41
  SQLServer::Quoting,
@@ -324,10 +325,6 @@ module ActiveRecord
324
325
  self.class::VERSION
325
326
  end
326
327
 
327
- def inspect
328
- "#<#{self.class} version: #{version}, azure: #{sqlserver_azure?.inspect}>"
329
- end
330
-
331
328
  def combine_bind_parameters(from_clause: [], join_clause: [], where_clause: [], having_clause: [], limit: nil, offset: nil)
332
329
  result = from_clause + join_clause + where_clause + having_clause
333
330
  result << offset if offset
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  class SQLServerDatabaseTasks
11
11
  DEFAULT_COLLATION = "SQL_Latin1_General_CP1_CI_AS"
12
12
 
13
- delegate :connection, :establish_connection, to: ActiveRecord::Base
13
+ delegate :with_connection, :establish_connection, to: ActiveRecord::Base
14
14
 
15
15
  def self.using_database_configurations?
16
16
  true
@@ -23,8 +23,10 @@ module ActiveRecord
23
23
 
24
24
  def create(master_established = false)
25
25
  establish_master_connection unless master_established
26
- connection.create_database configuration.database, configuration_hash.merge(collation: default_collation)
27
- establish_connection configuration
26
+ with_connection do |connection|
27
+ connection.create_database(configuration.database, configuration_hash.merge(collation: default_collation))
28
+ end
29
+ establish_connection(configuration)
28
30
  rescue ActiveRecord::StatementInvalid => e
29
31
  if /database .* already exists/i === e.message
30
32
  raise DatabaseAlreadyExists
@@ -35,15 +37,15 @@ module ActiveRecord
35
37
 
36
38
  def drop
37
39
  establish_master_connection
38
- connection.drop_database configuration.database
40
+ with_connection { |connection| connection.drop_database(configuration.database) }
39
41
  end
40
42
 
41
43
  def charset
42
- connection.charset
44
+ with_connection { |connection| connection.charset }
43
45
  end
44
46
 
45
47
  def collation
46
- connection.collation
48
+ with_connection { |connection| connection.collation }
47
49
  end
48
50
 
49
51
  def purge
@@ -56,34 +58,38 @@ module ActiveRecord
56
58
  ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
57
59
  end
58
60
 
59
- def structure_dump(filename, extra_flags)
60
- server_arg = "-S #{Shellwords.escape(configuration_hash[:host])}"
61
- server_arg += ":#{Shellwords.escape(configuration_hash[:port])}" if configuration_hash[:port]
62
- command = [
63
- "defncopy-ttds",
64
- server_arg,
65
- "-D #{Shellwords.escape(configuration_hash[:database])}",
66
- "-U #{Shellwords.escape(configuration_hash[:username])}",
67
- "-P #{Shellwords.escape(configuration_hash[:password])}",
68
- "-o #{Shellwords.escape(filename)}",
69
- ]
70
- table_args = connection.tables.map { |t| Shellwords.escape(t) }
71
- command.concat(table_args)
72
- view_args = connection.views.map { |v| Shellwords.escape(v) }
73
- command.concat(view_args)
74
- raise "Error dumping database" unless Kernel.system(command.join(" "))
75
-
76
- dump = File.read(filename)
77
- dump.gsub!(/^USE .*$\nGO\n/, "") # Strip db USE statements
78
- dump.gsub!(/^GO\n/, "") # Strip db GO statements
79
- dump.gsub!(/nvarchar\(8000\)/, "nvarchar(4000)") # Fix nvarchar(8000) column defs
80
- dump.gsub!(/nvarchar\(-1\)/, "nvarchar(max)") # Fix nvarchar(-1) column defs
81
- dump.gsub!(/text\(\d+\)/, "text") # Fix text(16) column defs
82
- File.open(filename, "w") { |file| file.puts dump }
61
+ def structure_dump(filename, _extra_flags)
62
+ with_connection do |connection|
63
+ server_arg = "-S #{Shellwords.escape(configuration_hash[:host])}"
64
+ server_arg += ":#{Shellwords.escape(configuration_hash[:port])}" if configuration_hash[:port]
65
+ command = [
66
+ "defncopy-ttds",
67
+ server_arg,
68
+ "-D #{Shellwords.escape(configuration_hash[:database])}",
69
+ "-U #{Shellwords.escape(configuration_hash[:username])}",
70
+ "-P #{Shellwords.escape(configuration_hash[:password])}",
71
+ "-o #{Shellwords.escape(filename)}",
72
+ ]
73
+ table_args = connection.tables.map { |t| Shellwords.escape(t) }
74
+ command.concat(table_args)
75
+ view_args = connection.views.map { |v| Shellwords.escape(v) }
76
+ command.concat(view_args)
77
+ raise "Error dumping database" unless Kernel.system(command.join(" "))
78
+
79
+ dump = File.read(filename)
80
+ dump.gsub!(/^USE .*$\nGO\n/, "") # Strip db USE statements
81
+ dump.gsub!(/^GO\n/, "") # Strip db GO statements
82
+ dump.gsub!(/nvarchar\(8000\)/, "nvarchar(4000)") # Fix nvarchar(8000) column defs
83
+ dump.gsub!(/nvarchar\(-1\)/, "nvarchar(max)") # Fix nvarchar(-1) column defs
84
+ dump.gsub!(/text\(\d+\)/, "text") # Fix text(16) column defs
85
+ File.open(filename, "w") { |file| file.puts dump }
86
+ end
83
87
  end
84
88
 
85
- def structure_load(filename, extra_flags)
86
- connection.execute File.read(filename)
89
+ def structure_load(filename, _extra_flags)
90
+ with_connection do |connection|
91
+ connection.execute File.read(filename)
92
+ end
87
93
  end
88
94
 
89
95
  private
@@ -30,10 +30,46 @@ module Arel
30
30
  end
31
31
 
32
32
  def visit_Arel_Nodes_UpdateStatement(o, collector)
33
- if o.orders.any? && o.limit.nil?
34
- o.limit = Nodes::Limit.new(9_223_372_036_854_775_807)
33
+ if has_join_and_composite_primary_key?(o)
34
+ update_statement_using_join(o, collector)
35
+ else
36
+ o.limit = Nodes::Limit.new(9_223_372_036_854_775_807) if o.orders.any? && o.limit.nil?
37
+
38
+ super
35
39
  end
36
- super
40
+ end
41
+
42
+ def visit_Arel_Nodes_DeleteStatement(o, collector)
43
+ if has_join_and_composite_primary_key?(o)
44
+ delete_statement_using_join(o, collector)
45
+ else
46
+ super
47
+ end
48
+ end
49
+
50
+ def has_join_and_composite_primary_key?(o)
51
+ has_join_sources?(o) && o.relation.left.instance_variable_get(:@klass).composite_primary_key?
52
+ end
53
+
54
+ def delete_statement_using_join(o, collector)
55
+ collector.retryable = false
56
+
57
+ collector << "DELETE "
58
+ visit o.relation.left, collector
59
+ collector << " FROM "
60
+ visit o.relation, collector
61
+ collect_nodes_for o.wheres, collector, " WHERE ", " AND "
62
+ end
63
+
64
+ def update_statement_using_join(o, collector)
65
+ collector.retryable = false
66
+
67
+ collector << "UPDATE "
68
+ visit o.relation.left, collector
69
+ collect_nodes_for o.values, collector, " SET "
70
+ collector << " FROM "
71
+ visit o.relation, collector
72
+ collect_nodes_for o.wheres, collector, " WHERE ", " AND "
37
73
  end
38
74
 
39
75
  def visit_Arel_Nodes_Lock(o, collector)
@@ -129,10 +165,12 @@ module Arel
129
165
  # github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
130
166
  table_name =
131
167
  begin
132
- if o.class.engine.connection.respond_to?(:sqlserver?) && o.class.engine.connection.database_prefix_remote_server?
133
- remote_server_table_name(o)
134
- else
135
- quote_table_name(o.name)
168
+ o.class.engine.with_connection do |connection|
169
+ if connection.respond_to?(:sqlserver?) && connection.database_prefix_remote_server?
170
+ remote_server_table_name(o)
171
+ else
172
+ quote_table_name(o.name)
173
+ end
136
174
  end
137
175
  rescue Exception
138
176
  quote_table_name(o.name)
@@ -201,6 +239,11 @@ module Arel
201
239
  collector
202
240
  end
203
241
 
242
+ def visit_Arel_Nodes_WithRecursive(o, collector)
243
+ collector << "WITH "
244
+ collect_ctes(o.children, collector)
245
+ end
246
+
204
247
  # SQLServer ToSql/Visitor (Additions)
205
248
 
206
249
  def visit_Arel_Nodes_SelectStatement_SQLServer_Lock(collector, options = {})
@@ -315,14 +358,16 @@ module Arel
315
358
  end
316
359
 
317
360
  def remote_server_table_name(o)
318
- ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
319
- "#{o.class.engine.connection.database_prefix}#{o.name}"
320
- ).quoted
361
+ o.class.engine.with_connection do |connection|
362
+ ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
363
+ "#{connection.database_prefix}#{o.name}"
364
+ ).quoted
365
+ end
321
366
  end
322
367
 
323
- # Need to remove ordering from subqueries unless TOP/OFFSET also used. Otherwise, SQLServer
368
+ # Need to remove ordering from sub-queries unless TOP/OFFSET also used. Otherwise, SQLServer
324
369
  # returns error "The ORDER BY clause is invalid in views, inline functions, derived tables,
325
- # subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified."
370
+ # sub-queries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified."
326
371
  def remove_invalid_ordering_from_select_statement(node)
327
372
  return unless Arel::Nodes::SelectStatement === node
328
373
 
@@ -16,38 +16,38 @@ class ActiveSchemaTestSQLServer < ActiveRecord::TestCase
16
16
  end
17
17
 
18
18
  it 'default index' do
19
- assert_sql('CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
19
+ assert_queries_match('CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
20
20
  connection.add_index :schema_test_table, "foo"
21
21
  end
22
22
  end
23
23
 
24
24
  it 'unique index' do
25
- assert_sql('CREATE UNIQUE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
25
+ assert_queries_match('CREATE UNIQUE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
26
26
  connection.add_index :schema_test_table, "foo", unique: true
27
27
  end
28
28
  end
29
29
 
30
30
  it 'where condition on index' do
31
- assert_sql("CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo]) WHERE state = 'active'") do
31
+ assert_queries_match("CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo]) WHERE state = 'active'") do
32
32
  connection.add_index :schema_test_table, "foo", where: "state = 'active'"
33
33
  end
34
34
  end
35
35
 
36
36
  it 'if index does not exist' do
37
- assert_sql("IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = 'index_schema_test_table_on_foo') " \
37
+ assert_queries_match("IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = 'index_schema_test_table_on_foo') " \
38
38
  "CREATE INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])") do
39
39
  connection.add_index :schema_test_table, "foo", if_not_exists: true
40
40
  end
41
41
  end
42
42
 
43
43
  it 'clustered index' do
44
- assert_sql('CREATE CLUSTERED INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
44
+ assert_queries_match('CREATE CLUSTERED INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
45
45
  connection.add_index :schema_test_table, "foo", type: :clustered
46
46
  end
47
47
  end
48
48
 
49
49
  it 'nonclustered index' do
50
- assert_sql('CREATE NONCLUSTERED INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
50
+ assert_queries_match('CREATE NONCLUSTERED INDEX [index_schema_test_table_on_foo] ON [schema_test_table] ([foo])') do
51
51
  connection.add_index :schema_test_table, "foo", type: :nonclustered
52
52
  end
53
53
  end
@@ -18,8 +18,6 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
18
18
  it "has basic and non-sensitive information in the adapters inspect method" do
19
19
  string = connection.inspect
20
20
  _(string).must_match %r{ActiveRecord::ConnectionAdapters::SQLServerAdapter}
21
- _(string).must_match %r{version\: \d.\d}
22
- _(string).must_match %r{azure: (true|false)}
23
21
  _(string).wont_match %r{host}
24
22
  _(string).wont_match %r{password}
25
23
  _(string).wont_match %r{username}
@@ -31,7 +29,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
31
29
  end
32
30
 
33
31
  it "raises invalid statement error for bad SQL" do
34
- assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.update("UPDATE XXX") }
32
+ assert_raise(ActiveRecord::StatementInvalid) { Topic.lease_connection.update("UPDATE XXX") }
35
33
  end
36
34
 
37
35
  it "is has our adapter_name" do
@@ -61,8 +59,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
61
59
  end
62
60
 
63
61
  it "test table existence across database schemas" do
64
- arunit_connection = Topic.connection
65
- arunit2_connection = College.connection
62
+ arunit_connection = Topic.lease_connection
63
+ arunit2_connection = College.lease_connection
66
64
 
67
65
  arunit_database = arunit_connection.pool.db_config.database
68
66
  arunit2_database = arunit2_connection.pool.db_config.database
@@ -102,8 +100,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
102
100
  assert_raise ActiveRecord::NoDatabaseError do
103
101
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
104
102
  configuration = db_config.configuration_hash.merge(database: "nonexistent_activerecord_unittest")
105
-
106
- connection = ActiveRecord::Base.sqlserver_connection configuration
103
+ connection = ActiveRecord::ConnectionAdapters::SQLServerAdapter.new(configuration)
107
104
  connection.exec_query("SELECT 1")
108
105
  end
109
106
  end
@@ -285,23 +282,25 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
285
282
  end
286
283
 
287
284
  it "NOT ALLOW by default the deletion of a referenced parent" do
288
- SSTestHasPk.connection.disable_referential_integrity {}
285
+ SSTestHasPk.lease_connection.disable_referential_integrity {}
289
286
  assert_raise(ActiveRecord::StatementInvalid) { @parent.destroy }
290
287
  end
291
288
 
292
289
  it "ALLOW deletion of referenced parent using #disable_referential_integrity block" do
293
- SSTestHasPk.connection.disable_referential_integrity { @parent.destroy }
290
+ assert_difference("SSTestHasPk.count", -1) do
291
+ SSTestHasPk.lease_connection.disable_referential_integrity { @parent.destroy }
292
+ end
294
293
  end
295
294
 
296
295
  it "again NOT ALLOW deletion of referenced parent after #disable_referential_integrity block" do
297
296
  assert_raise(ActiveRecord::StatementInvalid) do
298
- SSTestHasPk.connection.disable_referential_integrity {}
297
+ SSTestHasPk.lease_connection.disable_referential_integrity {}
299
298
  @parent.destroy
300
299
  end
301
300
  end
302
301
 
303
302
  it "not disable referential integrity for the same table twice" do
304
- tables = SSTestHasPk.connection.tables_with_referential_integrity
303
+ tables = SSTestHasPk.lease_connection.tables_with_referential_integrity
305
304
  assert_equal tables.size, tables.uniq.size
306
305
  end
307
306
  end
@@ -396,7 +395,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
396
395
 
397
396
  it "allows connection#view_information to work across databases when using qualified object names" do
398
397
  # College is defined in activerecord_unittest2 database.
399
- view_info = College.connection.send(:view_information, "[activerecord_unittest].[dbo].[sst_customers_view]")
398
+ view_info = College.lease_connection.send(:view_information, "[activerecord_unittest].[dbo].[sst_customers_view]")
400
399
  assert_equal("sst_customers_view", view_info["TABLE_NAME"])
401
400
  assert_match(/CREATE VIEW sst_customers_view/, view_info["VIEW_DEFINITION"])
402
401
  end
@@ -407,8 +406,8 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
407
406
  end
408
407
 
409
408
  it "allow the connection#view_table_name method to return true table_name for the view for other connections" do
410
- assert_equal "customers", College.connection.send(:view_table_name, "[activerecord_unittest].[dbo].[sst_customers_view]")
411
- assert_equal "topics", College.connection.send(:view_table_name, "topics"), "No view here, the same table name should come back."
409
+ assert_equal "customers", College.lease_connection.send(:view_table_name, "[activerecord_unittest].[dbo].[sst_customers_view]")
410
+ assert_equal "topics", College.lease_connection.send(:view_table_name, "topics"), "No view here, the same table name should come back."
412
411
  end
413
412
  # With same column names
414
413
 
@@ -434,7 +433,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
434
433
  end
435
434
 
436
435
  it "respond true to data_source_exists?" do
437
- assert SSTestCustomersView.connection.data_source_exists?(SSTestCustomersView.table_name)
436
+ assert SSTestCustomersView.lease_connection.data_source_exists?(SSTestCustomersView.table_name)
438
437
  end
439
438
 
440
439
  # With aliased column names
@@ -462,7 +461,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
462
461
  end
463
462
 
464
463
  it "respond true to data_source_exists?" do
465
- assert SSTestStringDefaultsView.connection.data_source_exists?(SSTestStringDefaultsView.table_name)
464
+ assert SSTestStringDefaultsView.lease_connection.data_source_exists?(SSTestStringDefaultsView.table_name)
466
465
  end
467
466
 
468
467
  # That have more than 4000 chars for their defintion
@@ -508,7 +507,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
508
507
 
509
508
  describe "block writes to a database" do
510
509
  def setup
511
- @conn = ActiveRecord::Base.connection
510
+ @conn = ActiveRecord::Base.lease_connection
512
511
  end
513
512
 
514
513
  def test_errors_when_an_insert_query_is_called_while_preventing_writes
@@ -557,7 +556,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
557
556
 
558
557
  it 'records can be inserted using SQL' do
559
558
  assert_difference("Alien.count", 2) do
560
- Alien.connection.exec_insert("insert into [test].[aliens] (id, name) VALUES(1, 'Trisolarans'), (2, 'Xenomorph')")
559
+ Alien.lease_connection.exec_insert("insert into [test].[aliens] (id, name) VALUES(1, 'Trisolarans'), (2, 'Xenomorph')")
561
560
  end
562
561
  end
563
562
  end