activerecord-sqlserver-adapter 6.0.0.rc2 → 6.1.0.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 (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
@@ -27,6 +27,23 @@ module ActiveRecord
27
27
  def case_sensitive?
28
28
  collation && collation.match(/_CS/)
29
29
  end
30
+
31
+ private
32
+
33
+ # In the Rails version of this method there is an assumption that the `default` value will always be a
34
+ # `String` class, which must be true for the MySQL/PostgreSQL/SQLite adapters. However, in the SQL Server
35
+ # adapter the `default` value can also be Boolean/Date/Time/etc. Changed the implementation of this method
36
+ # to handle non-String `default` objects.
37
+ def deduplicated
38
+ @name = -name
39
+ @sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata
40
+ @default = (default.is_a?(String) ? -default : default.dup.freeze) if default
41
+ @default_function = -default_function if default_function
42
+ @collation = -collation if collation
43
+ @comment = -comment if comment
44
+
45
+ freeze
46
+ end
30
47
  end
31
48
  end
32
49
  end
@@ -4,21 +4,15 @@ module ActiveRecord
4
4
  module ConnectionHandling
5
5
  def sqlserver_connection(config) #:nodoc:
6
6
  config = config.symbolize_keys
7
- config.reverse_merge! mode: :dblib
8
- mode = config[:mode].to_s.downcase.underscore.to_sym
9
- case mode
10
- when :dblib
11
- require "tiny_tds"
12
- else
13
- raise ArgumentError, "Unknown connection mode in #{config.inspect}."
14
- end
15
- ConnectionAdapters::SQLServerAdapter.new(nil, nil, config.merge(mode: mode))
16
- rescue TinyTds::Error => e
17
- if e.message.match(/database .* does not exist/i)
18
- raise ActiveRecord::NoDatabaseError
19
- else
20
- raise
21
- end
7
+ config.reverse_merge!(mode: :dblib)
8
+ config[:mode] = config[:mode].to_s.downcase.underscore.to_sym
9
+
10
+ ConnectionAdapters::SQLServerAdapter.new(
11
+ ConnectionAdapters::SQLServerAdapter.new_client(config),
12
+ logger,
13
+ nil,
14
+ config
15
+ )
22
16
  end
23
17
  end
24
18
  end
@@ -13,13 +13,18 @@ module ActiveRecord
13
13
  delegate :connection, :establish_connection, :clear_active_connections!,
14
14
  to: ActiveRecord::Base
15
15
 
16
+ def self.using_database_configurations?
17
+ true
18
+ end
19
+
16
20
  def initialize(configuration)
17
21
  @configuration = configuration
22
+ @configuration_hash = @configuration.configuration_hash
18
23
  end
19
24
 
20
25
  def create(master_established = false)
21
26
  establish_master_connection unless master_established
22
- connection.create_database configuration["database"], configuration.merge("collation" => default_collation)
27
+ connection.create_database configuration.database, configuration_hash.merge(collation: default_collation)
23
28
  establish_connection configuration
24
29
  rescue ActiveRecord::StatementInvalid => e
25
30
  if /database .* already exists/i === e.message
@@ -31,7 +36,7 @@ module ActiveRecord
31
36
 
32
37
  def drop
33
38
  establish_master_connection
34
- connection.drop_database configuration["database"]
39
+ connection.drop_database configuration.database
35
40
  end
36
41
 
37
42
  def charset
@@ -49,14 +54,14 @@ module ActiveRecord
49
54
  end
50
55
 
51
56
  def structure_dump(filename, extra_flags)
52
- server_arg = "-S #{Shellwords.escape(configuration['host'])}"
53
- server_arg += ":#{Shellwords.escape(configuration['port'])}" if configuration["port"]
57
+ server_arg = "-S #{Shellwords.escape(configuration_hash[:host])}"
58
+ server_arg += ":#{Shellwords.escape(configuration_hash[:port])}" if configuration_hash[:port]
54
59
  command = [
55
60
  "defncopy-ttds",
56
61
  server_arg,
57
- "-D #{Shellwords.escape(configuration['database'])}",
58
- "-U #{Shellwords.escape(configuration['username'])}",
59
- "-P #{Shellwords.escape(configuration['password'])}",
62
+ "-D #{Shellwords.escape(configuration_hash[:database])}",
63
+ "-U #{Shellwords.escape(configuration_hash[:username])}",
64
+ "-P #{Shellwords.escape(configuration_hash[:password])}",
60
65
  "-o #{Shellwords.escape(filename)}",
61
66
  ]
62
67
  table_args = connection.tables.map { |t| Shellwords.escape(t) }
@@ -80,16 +85,14 @@ module ActiveRecord
80
85
 
81
86
  private
82
87
 
83
- def configuration
84
- @configuration
85
- end
88
+ attr_reader :configuration, :configuration_hash
86
89
 
87
90
  def default_collation
88
- configuration["collation"] || DEFAULT_COLLATION
91
+ configuration_hash[:collation] || DEFAULT_COLLATION
89
92
  end
90
93
 
91
94
  def establish_master_connection
92
- establish_connection configuration.merge("database" => "master")
95
+ establish_connection configuration_hash.merge(database: "master")
93
96
  end
94
97
  end
95
98
 
@@ -110,9 +113,9 @@ module ActiveRecord
110
113
  end
111
114
 
112
115
  def configuration_host_ip(configuration)
113
- return nil unless configuration["host"]
116
+ return nil unless configuration.host
114
117
 
115
- Socket::getaddrinfo(configuration["host"], "echo", Socket::AF_INET)[0][3]
118
+ Socket::getaddrinfo(configuration.host, "echo", Socket::AF_INET)[0][3]
116
119
  end
117
120
 
118
121
  def local_ipaddr?(host_ip)
@@ -11,13 +11,14 @@ module Arel
11
11
 
12
12
  private
13
13
 
14
- # SQLServer ToSql/Visitor (Overides)
14
+ # SQLServer ToSql/Visitor (Overrides)
15
15
 
16
- def visit_Arel_Nodes_BindParam o, collector
17
- collector.add_bind(o.value) { |i| "@#{i - 1}" }
18
- end
16
+ BIND_BLOCK = proc { |i| "@#{i - 1}" }
17
+ private_constant :BIND_BLOCK
18
+
19
+ def bind_block; BIND_BLOCK; end
19
20
 
20
- def visit_Arel_Nodes_Bin o, collector
21
+ def visit_Arel_Nodes_Bin(o, collector)
21
22
  visit o.expr, collector
22
23
  collector << " #{ActiveRecord::ConnectionAdapters::SQLServerAdapter.cs_equality_operator} "
23
24
  end
@@ -28,26 +29,26 @@ module Arel
28
29
  visit o.right, collector
29
30
  end
30
31
 
31
- def visit_Arel_Nodes_UpdateStatement(o, a)
32
+ def visit_Arel_Nodes_UpdateStatement(o, collector)
32
33
  if o.orders.any? && o.limit.nil?
33
34
  o.limit = Nodes::Limit.new(9_223_372_036_854_775_807)
34
35
  end
35
36
  super
36
37
  end
37
38
 
38
- def visit_Arel_Nodes_Lock o, collector
39
+ def visit_Arel_Nodes_Lock(o, collector)
39
40
  o.expr = Arel.sql("WITH(UPDLOCK)") if o.expr.to_s =~ /FOR UPDATE/
40
41
  collector << " "
41
42
  visit o.expr, collector
42
43
  end
43
44
 
44
- def visit_Arel_Nodes_Offset o, collector
45
+ def visit_Arel_Nodes_Offset(o, collector)
45
46
  collector << OFFSET
46
47
  visit o.expr, collector
47
48
  collector << ROWS
48
49
  end
49
50
 
50
- def visit_Arel_Nodes_Limit o, collector
51
+ def visit_Arel_Nodes_Limit(o, collector)
51
52
  if node_value(o) == 0
52
53
  collector << FETCH0
53
54
  collector << ROWS_ONLY
@@ -63,7 +64,38 @@ module Arel
63
64
  super
64
65
  end
65
66
 
66
- def visit_Arel_Nodes_SelectStatement o, collector
67
+ def visit_Arel_Nodes_HomogeneousIn(o, collector)
68
+ collector.preparable = false
69
+
70
+ collector << quote_table_name(o.table_name) << "." << quote_column_name(o.column_name)
71
+
72
+ if o.type == :in
73
+ collector << " IN ("
74
+ else
75
+ collector << " NOT IN ("
76
+ end
77
+
78
+ values = o.casted_values
79
+
80
+ if values.empty?
81
+ collector << @connection.quote(nil)
82
+ elsif @connection.prepared_statements
83
+ # Monkey-patch start. Add query attribute bindings rather than just values.
84
+ column_name = o.column_name
85
+ column_type = o.attribute.relation.type_for_attribute(o.column_name)
86
+ attrs = values.map { |value| ActiveRecord::Relation::QueryAttribute.new(column_name, value, column_type) }
87
+
88
+ collector.add_binds(attrs, &bind_block)
89
+ # Monkey-patch end.
90
+ else
91
+ collector.add_binds(values, &bind_block)
92
+ end
93
+
94
+ collector << ")"
95
+ collector
96
+ end
97
+
98
+ def visit_Arel_Nodes_SelectStatement(o, collector)
67
99
  @select_statement = o
68
100
  distinct_One_As_One_Is_So_Not_Fetch o
69
101
  if o.with
@@ -80,7 +112,17 @@ module Arel
80
112
  @select_statement = nil
81
113
  end
82
114
 
83
- def visit_Arel_Table o, collector
115
+ def visit_Arel_Nodes_SelectCore(o, collector)
116
+ collector = super
117
+ maybe_visit o.optimizer_hints, collector
118
+ end
119
+
120
+ def visit_Arel_Nodes_OptimizerHints(o, collector)
121
+ hints = o.expr.map { |v| sanitize_as_option_clause(v) }.join(", ")
122
+ collector << "OPTION (#{hints})"
123
+ end
124
+
125
+ def visit_Arel_Table(o, collector)
84
126
  # Apparently, o.engine.connection can actually be a different adapter
85
127
  # than sqlserver. Can be removed if fixed in ActiveRecord. See:
86
128
  # github.com/rails-sqlserver/activerecord-sqlserver-adapter/issues/450
@@ -102,7 +144,7 @@ module Arel
102
144
  end
103
145
  end
104
146
 
105
- def visit_Arel_Nodes_JoinSource o, collector
147
+ def visit_Arel_Nodes_JoinSource(o, collector)
106
148
  if o.left
107
149
  collector = visit o.left, collector
108
150
  collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector
@@ -114,39 +156,53 @@ module Arel
114
156
  collector
115
157
  end
116
158
 
117
- def visit_Arel_Nodes_InnerJoin o, collector
118
- collector << "INNER JOIN "
119
- collector = visit o.left, collector
120
- collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
121
- if o.right
122
- collector << " "
123
- visit(o.right, collector)
159
+ def visit_Arel_Nodes_InnerJoin(o, collector)
160
+ if o.left.is_a?(Arel::Nodes::As) && o.left.left.is_a?(Arel::Nodes::Lateral)
161
+ collector << "CROSS "
162
+ visit o.left, collector
124
163
  else
125
- collector
164
+ collector << "INNER JOIN "
165
+ collector = visit o.left, collector
166
+ collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
167
+ if o.right
168
+ collector << " "
169
+ visit(o.right, collector)
170
+ else
171
+ collector
172
+ end
126
173
  end
127
174
  end
128
175
 
129
- def visit_Arel_Nodes_OuterJoin o, collector
130
- collector << "LEFT OUTER JOIN "
131
- collector = visit o.left, collector
132
- collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
133
- collector << " "
134
- visit o.right, collector
176
+ def visit_Arel_Nodes_OuterJoin(o, collector)
177
+ if o.left.is_a?(Arel::Nodes::As) && o.left.left.is_a?(Arel::Nodes::Lateral)
178
+ collector << "OUTER "
179
+ visit o.left, collector
180
+ else
181
+ collector << "LEFT OUTER JOIN "
182
+ collector = visit o.left, collector
183
+ collector = visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, space: true
184
+ collector << " "
185
+ visit o.right, collector
186
+ end
135
187
  end
136
188
 
137
- def collect_in_clause(left, right, collector)
138
- if Array === right
139
- right.each { |node| remove_invalid_ordering_from_select_statement(node) }
189
+ def visit_Arel_Nodes_In(o, collector)
190
+ if Array === o.right
191
+ o.right.each { |node| remove_invalid_ordering_from_select_statement(node) }
140
192
  else
141
- remove_invalid_ordering_from_select_statement(right)
193
+ remove_invalid_ordering_from_select_statement(o.right)
142
194
  end
143
195
 
144
196
  super
145
197
  end
146
198
 
199
+ def collect_optimizer_hints(o, collector)
200
+ collector
201
+ end
202
+
147
203
  # SQLServer ToSql/Visitor (Additions)
148
204
 
149
- def visit_Arel_Nodes_SelectStatement_SQLServer_Lock collector, options = {}
205
+ def visit_Arel_Nodes_SelectStatement_SQLServer_Lock(collector, options = {})
150
206
  if select_statement_lock?
151
207
  collector = visit @select_statement.lock, collector
152
208
  collector << " " if options[:space]
@@ -154,7 +210,7 @@ module Arel
154
210
  collector
155
211
  end
156
212
 
157
- def visit_Orders_And_Let_Fetch_Happen o, collector
213
+ def visit_Orders_And_Let_Fetch_Happen(o, collector)
158
214
  make_Fetch_Possible_And_Deterministic o
159
215
  unless o.orders.empty?
160
216
  collector << " ORDER BY "
@@ -167,13 +223,25 @@ module Arel
167
223
  collector
168
224
  end
169
225
 
170
- def visit_Make_Fetch_Happen o, collector
226
+ def visit_Make_Fetch_Happen(o, collector)
171
227
  o.offset = Nodes::Offset.new(0) if o.limit && !o.offset
172
228
  collector = visit o.offset, collector if o.offset
173
229
  collector = visit o.limit, collector if o.limit
174
230
  collector
175
231
  end
176
232
 
233
+ def visit_Arel_Nodes_Lateral(o, collector)
234
+ collector << "APPLY"
235
+ collector << " "
236
+ if o.expr.is_a?(Arel::Nodes::SelectStatement)
237
+ collector << "("
238
+ visit(o.expr, collector)
239
+ collector << ")"
240
+ else
241
+ visit(o.expr, collector)
242
+ end
243
+ end
244
+
177
245
  # SQLServer Helpers
178
246
 
179
247
  def node_value(node)
@@ -190,7 +258,7 @@ module Arel
190
258
  @select_statement && @select_statement.lock
191
259
  end
192
260
 
193
- def make_Fetch_Possible_And_Deterministic o
261
+ def make_Fetch_Possible_And_Deterministic(o)
194
262
  return if o.limit.nil? && o.offset.nil?
195
263
 
196
264
  t = table_From_Statement o
@@ -203,7 +271,7 @@ module Arel
203
271
  end
204
272
  end
205
273
 
206
- def distinct_One_As_One_Is_So_Not_Fetch o
274
+ def distinct_One_As_One_Is_So_Not_Fetch(o)
207
275
  core = o.cores.first
208
276
  distinct = Nodes::Distinct === core.set_quantifier
209
277
  oneasone = core.projections.all? { |x| x == ActiveRecord::FinderMethods::ONE_AS_ONE }
@@ -214,7 +282,7 @@ module Arel
214
282
  end
215
283
  end
216
284
 
217
- def table_From_Statement o
285
+ def table_From_Statement(o)
218
286
  core = o.cores.first
219
287
  if Arel::Table === core.from
220
288
  core.from
@@ -225,15 +293,15 @@ module Arel
225
293
  end
226
294
  end
227
295
 
228
- def primary_Key_From_Table t
296
+ def primary_Key_From_Table(t)
229
297
  return unless t
230
298
 
231
299
  column_name = @connection.schema_cache.primary_keys(t.name) ||
232
- @connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
300
+ @connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
233
301
  column_name ? t[column_name] : nil
234
302
  end
235
303
 
236
- def remote_server_table_name o
304
+ def remote_server_table_name(o)
237
305
  ActiveRecord::ConnectionAdapters::SQLServer::Utils.extract_identifiers(
238
306
  "#{o.class.engine.connection.database_prefix}#{o.name}"
239
307
  ).quoted
@@ -247,6 +315,10 @@ module Arel
247
315
 
248
316
  node.orders = [] unless node.offset || node.limit
249
317
  end
318
+
319
+ def sanitize_as_option_clause(value)
320
+ value.gsub(%r{OPTION \s* \( (.+) \)}xi, "\\1")
321
+ end
250
322
  end
251
323
  end
252
324
  end
@@ -6,6 +6,7 @@ require "models/task"
6
6
  require "models/post"
7
7
  require "models/subscriber"
8
8
  require "models/minimalistic"
9
+ require "models/college"
9
10
 
10
11
  class AdapterTestSQLServer < ActiveRecord::TestCase
11
12
  fixtures :tasks
@@ -42,17 +43,49 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
42
43
  assert connection.supports_ddl_transactions?
43
44
  end
44
45
 
45
- it "allow owner table name prefixs like dbo to still allow table exists to return true" do
46
+ it "table exists works if table name prefixed by schema and owner" do
46
47
  begin
47
48
  assert_equal "topics", Topic.table_name
48
49
  assert Topic.table_exists?
50
+
51
+ # Test when owner included in table name.
49
52
  Topic.table_name = "dbo.topics"
50
- assert Topic.table_exists?, "Tasks table name of dbo.topics should return true for exists."
53
+ assert Topic.table_exists?, "Topics table name of 'dbo.topics' should return true for exists."
54
+
55
+ # Test when database and owner included in table name.
56
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
57
+ Topic.table_name = "#{db_config.database}.dbo.topics"
58
+ assert Topic.table_exists?, "Topics table name of '[DATABASE].dbo.topics' should return true for exists."
51
59
  ensure
52
60
  Topic.table_name = "topics"
53
61
  end
54
62
  end
55
63
 
64
+ it "test table existence across database schemas" do
65
+ arunit_connection = Topic.connection
66
+ arunit2_connection = College.connection
67
+
68
+ arunit_database = arunit_connection.pool.db_config.database
69
+ arunit2_database = arunit2_connection.pool.db_config.database
70
+
71
+ # Assert that connections use different default databases schemas.
72
+ assert_not_equal arunit_database, arunit2_database
73
+
74
+ # Assert that the Topics table exists when using the Topics connection.
75
+ assert arunit_connection.table_exists?('topics'), 'Topics table exists using table name'
76
+ assert arunit_connection.table_exists?('dbo.topics'), 'Topics table exists using owner and table name'
77
+ assert arunit_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using database, owner and table name'
78
+
79
+ # Assert that the Colleges table exists when using the Colleges connection.
80
+ assert arunit2_connection.table_exists?('colleges'), 'College table exists using table name'
81
+ assert arunit2_connection.table_exists?('dbo.colleges'), 'College table exists using owner and table name'
82
+ assert arunit2_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'College table exists using database, owner and table name'
83
+
84
+ # Assert that the tables exist when using each others connection.
85
+ assert arunit_connection.table_exists?("#{arunit2_database}.dbo.colleges"), 'Colleges table exists using Topics connection'
86
+ assert arunit2_connection.table_exists?("#{arunit_database}.dbo.topics"), 'Topics table exists using Colleges connection'
87
+ end
88
+
56
89
  it "return true to insert sql query for inserts only" do
57
90
  assert connection.send(:insert_sql?, "INSERT...")
58
91
  assert connection.send(:insert_sql?, "EXEC sp_executesql N'INSERT INTO [fk_test_has_fks] ([fk_id]) VALUES (@0); SELECT CAST(SCOPE_IDENTITY() AS bigint) AS Ident', N'@0 int', @0 = 0")
@@ -68,21 +101,23 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
68
101
 
69
102
  it "test bad connection" do
70
103
  assert_raise ActiveRecord::NoDatabaseError do
71
- config = ActiveRecord::Base.configurations["arunit"].merge(database: "inexistent_activerecord_unittest")
72
- ActiveRecord::Base.sqlserver_connection config
104
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
105
+ configuration = db_config.configuration_hash.merge(database: "inexistent_activerecord_unittest")
106
+ ActiveRecord::Base.sqlserver_connection configuration
73
107
  end
74
108
  end
75
109
 
76
110
  it "test database exists returns false if database does not exist" do
77
- config = ActiveRecord::Base.configurations["arunit"].merge(database: "inexistent_activerecord_unittest")
78
- assert_not ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config),
111
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
112
+ configuration = db_config.configuration_hash.merge(database: "inexistent_activerecord_unittest")
113
+ assert_not ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(configuration),
79
114
  "expected database to not exist"
80
115
  end
81
116
 
82
117
  it "test database exists returns true when the database exists" do
83
- config = ActiveRecord::Base.configurations["arunit"]
84
- assert ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(config),
85
- "expected database #{config[:database]} to exist"
118
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
119
+ assert ActiveRecord::ConnectionAdapters::SQLServerAdapter.database_exists?(db_config.configuration_hash),
120
+ "expected database #{db_config.database} to exist"
86
121
  end
87
122
 
88
123
  describe "with different language" do
@@ -434,12 +469,11 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
434
469
  describe "block writes to a database" do
435
470
  def setup
436
471
  @conn = ActiveRecord::Base.connection
437
- @connection_handler = ActiveRecord::Base.connection_handler
438
472
  end
439
473
 
440
474
  def test_errors_when_an_insert_query_is_called_while_preventing_writes
441
475
  assert_raises(ActiveRecord::ReadOnlyError) do
442
- @connection_handler.while_preventing_writes do
476
+ ActiveRecord::Base.while_preventing_writes do
443
477
  @conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
444
478
  end
445
479
  end
@@ -449,7 +483,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
449
483
  @conn.insert("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
450
484
 
451
485
  assert_raises(ActiveRecord::ReadOnlyError) do
452
- @connection_handler.while_preventing_writes do
486
+ ActiveRecord::Base.while_preventing_writes do
453
487
  @conn.update("UPDATE [subscribers] SET [subscribers].[name] = 'Aidan' WHERE [subscribers].[nick] = 'aido'")
454
488
  end
455
489
  end
@@ -459,7 +493,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
459
493
  @conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
460
494
 
461
495
  assert_raises(ActiveRecord::ReadOnlyError) do
462
- @connection_handler.while_preventing_writes do
496
+ ActiveRecord::Base.while_preventing_writes do
463
497
  @conn.execute("DELETE FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
464
498
  end
465
499
  end
@@ -468,7 +502,7 @@ class AdapterTestSQLServer < ActiveRecord::TestCase
468
502
  def test_doesnt_error_when_a_select_query_is_called_while_preventing_writes
469
503
  @conn.execute("INSERT INTO [subscribers] ([nick]) VALUES ('aido')")
470
504
 
471
- @connection_handler.while_preventing_writes do
505
+ ActiveRecord::Base.while_preventing_writes do
472
506
  assert_equal 1, @conn.execute("SELECT * FROM [subscribers] WHERE [subscribers].[nick] = 'aido'")
473
507
  end
474
508
  end