activerecord-sqlserver-adapter 7.1.10 → 7.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +3 -3
  3. data/.github/workflows/ci.yml +11 -5
  4. data/CHANGELOG.md +5 -117
  5. data/Gemfile +4 -4
  6. data/README.md +40 -17
  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 +49 -34
  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 +4 -9
  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 +22 -9
  21. data/test/cases/active_schema_test_sqlserver.rb +6 -6
  22. data/test/cases/adapter_test_sqlserver.rb +17 -27
  23. data/test/cases/coerced_tests.rb +262 -190
  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/schema_test_sqlserver.rb +0 -4
  39. data/test/cases/showplan_test_sqlserver.rb +7 -7
  40. data/test/cases/specific_schema_test_sqlserver.rb +17 -13
  41. data/test/cases/view_test_sqlserver.rb +1 -9
  42. data/test/schema/sqlserver_specific_schema.rb +4 -4
  43. data/test/support/connection_reflection.rb +1 -1
  44. data/test/support/core_ext/query_cache.rb +2 -2
  45. data/test/support/query_assertions.rb +49 -0
  46. data/test/support/table_definition_sqlserver.rb +24 -0
  47. data/test/support/test_in_memory_oltp.rb +2 -2
  48. metadata +12 -13
  49. data/lib/active_record/sqlserver_base.rb +0 -13
  50. data/test/cases/scratchpad_test_sqlserver.rb +0 -8
  51. 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)
@@ -347,16 +347,12 @@ module ActiveRecord
347
347
 
348
348
  def columns_for_distinct(columns, orders)
349
349
  order_columns = orders.reject(&:blank?).map { |s|
350
- s = visitor.compile(s) unless s.is_a?(String)
350
+ s = s.to_sql unless s.is_a?(String)
351
351
  s.gsub(/\s+(?:ASC|DESC)\b/i, "")
352
352
  .gsub(/\s+NULLS\s+(?:FIRST|LAST)\b/i, "")
353
- }
354
- .reject(&:blank?)
355
- .reject { |s| columns.include?(s) }
353
+ }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" }
356
354
 
357
- order_columns_aliased = order_columns.map.with_index { |column, i| "#{column} AS alias_#{i}" }
358
-
359
- (order_columns_aliased << super).join(", ")
355
+ (order_columns << super).join(", ")
360
356
  end
361
357
 
362
358
  def update_table_definition(table_name, base)
@@ -685,7 +681,6 @@ module ActiveRecord
685
681
  s.split(/INSERT INTO/i)[1]
686
682
  .split(/OUTPUT INSERTED/i)[0]
687
683
  .split(/(DEFAULT)?\s+VALUES/i)[0]
688
- .split(/\bSELECT\b(?![^\[]*\])/i)[0]
689
684
  .match(/\s*([^(]*)/i)[0]
690
685
  elsif s.match?(/^\s*UPDATE\s+.*/i)
691
686
  s.match(/UPDATE\s+([^\(\s]+)\s*/i)[1]
@@ -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
@@ -52,6 +52,8 @@ module Arel
52
52
  end
53
53
 
54
54
  def delete_statement_using_join(o, collector)
55
+ collector.retryable = false
56
+
55
57
  collector << "DELETE "
56
58
  visit o.relation.left, collector
57
59
  collector << " FROM "
@@ -60,6 +62,8 @@ module Arel
60
62
  end
61
63
 
62
64
  def update_statement_using_join(o, collector)
65
+ collector.retryable = false
66
+
63
67
  collector << "UPDATE "
64
68
  visit o.relation.left, collector
65
69
  collect_nodes_for o.values, collector, " SET "
@@ -161,10 +165,12 @@ module Arel
161
165
  # github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
162
166
  table_name =
163
167
  begin
164
- if o.class.engine.connection.respond_to?(:sqlserver?) && o.class.engine.connection.database_prefix_remote_server?
165
- remote_server_table_name(o)
166
- else
167
- 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
168
174
  end
169
175
  rescue Exception
170
176
  quote_table_name(o.name)
@@ -233,6 +239,11 @@ module Arel
233
239
  collector
234
240
  end
235
241
 
242
+ def visit_Arel_Nodes_WithRecursive(o, collector)
243
+ collector << "WITH "
244
+ collect_ctes(o.children, collector)
245
+ end
246
+
236
247
  # SQLServer ToSql/Visitor (Additions)
237
248
 
238
249
  def visit_Arel_Nodes_SelectStatement_SQLServer_Lock(collector, options = {})
@@ -347,14 +358,16 @@ module Arel
347
358
  end
348
359
 
349
360
  def remote_server_table_name(o)
350
- ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
351
- "#{o.class.engine.connection.database_prefix}#{o.name}"
352
- ).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
353
366
  end
354
367
 
355
- # 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
356
369
  # returns error "The ORDER BY clause is invalid in views, inline functions, derived tables,
357
- # 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."
358
371
  def remove_invalid_ordering_from_select_statement(node)
359
372
  return unless Arel::Nodes::SelectStatement === node
360
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
@@ -581,13 +580,4 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
581
580
  end
582
581
  end
583
582
  end
584
-
585
- describe "distinct select query" do
586
- it "generated SQL does not contain unnecessary alias projection" do
587
- sqls = capture_sql do
588
- Post.includes(:comments).joins(:comments).first
589
- end
590
- assert_no_match(/AS alias_0/, sqls.first)
591
- end
592
- end
593
583
  end