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
@@ -15,7 +15,7 @@ module ActiveRecord
15
15
  private
16
16
 
17
17
  def explicit_primary_key_default?(column)
18
- column.is_primary? && !column.is_identity?
18
+ column.type == :integer && !column.is_identity?
19
19
  end
20
20
 
21
21
  def schema_limit(column)
@@ -27,11 +27,17 @@ module ActiveRecord
27
27
  def schema_collation(column)
28
28
  return unless column.collation
29
29
 
30
- column.collation if column.collation != @connection.collation
30
+ # use inspect to ensure collation is dumped as string. Without this it's dumped as
31
+ # a constant ('collation: SQL_Latin1_General_CP1_CI_AS')
32
+ collation = column.collation.inspect
33
+ # use inspect to ensure string comparison
34
+ default_collation = @connection.collation.inspect
35
+
36
+ collation if collation != default_collation
31
37
  end
32
38
 
33
39
  def default_primary_key?(column)
34
- super && column.is_primary? && column.is_identity?
40
+ super && column.is_identity?
35
41
  end
36
42
  end
37
43
  end
@@ -27,7 +27,7 @@ module ActiveRecord
27
27
  end
28
28
  end
29
29
  if options[:if_exists] && @version_year < 2016
30
- execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #{quote(table_name)}) DROP TABLE #{quote_table_name(table_name)}"
30
+ execute "IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = #{quote(table_name)}) DROP TABLE #{quote_table_name(table_name)}", "SCHEMA"
31
31
  else
32
32
  super
33
33
  end
@@ -51,7 +51,7 @@ module ActiveRecord
51
51
  index[:index_keys].split(",").each do |column|
52
52
  column.strip!
53
53
 
54
- if column.ends_with?("(-)")
54
+ if column.end_with?("(-)")
55
55
  column.gsub! "(-)", ""
56
56
  orders[column] = :desc
57
57
  end
@@ -130,8 +130,9 @@ module ActiveRecord
130
130
  rename_table_indexes(table_name, new_name)
131
131
  end
132
132
 
133
- def remove_column(table_name, column_name, type = nil, options = {})
133
+ def remove_column(table_name, column_name, type = nil, **options)
134
134
  raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_name.is_a? Array
135
+ return if options[:if_exists] == true && !column_exists?(table_name, column_name)
135
136
 
136
137
  remove_check_constraints(table_name, column_name)
137
138
  remove_default_constraint(table_name, column_name)
@@ -156,6 +157,7 @@ module ActiveRecord
156
157
  end
157
158
  sql_commands << "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote_default_expression(options[:default], column_object)} WHERE #{quote_column_name(column_name)} IS NULL" if !options[:null].nil? && options[:null] == false && !options[:default].nil?
158
159
  alter_command = "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, limit: options[:limit], precision: options[:precision], scale: options[:scale])}"
160
+ alter_command += " COLLATE #{options[:collation]}" if options[:collation].present?
159
161
  alter_command += " NOT NULL" if !options[:null].nil? && options[:null] == false
160
162
  sql_commands << alter_command
161
163
  if without_constraints
@@ -190,7 +192,7 @@ module ActiveRecord
190
192
  end
191
193
 
192
194
  def rename_index(table_name, old_name, new_name)
193
- raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{allowed_index_name_length} characters" if new_name.length > allowed_index_name_length
195
+ raise ArgumentError, "Index name '#{new_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters" if new_name.length > index_name_length
194
196
 
195
197
  identifier = SQLServer::Utils.extract_identifiers("#{table_name}.#{old_name}")
196
198
  execute_procedure :sp_rename, identifier.quoted, new_name, "INDEX"
@@ -281,14 +283,33 @@ module ActiveRecord
281
283
  SQLServer::SchemaDumper.create(self, options)
282
284
  end
283
285
 
286
+ def create_schema(schema_name, authorization = nil)
287
+ sql = "CREATE SCHEMA [#{schema_name}]"
288
+ sql += " AUTHORIZATION [#{authorization}]" if authorization
289
+
290
+ execute sql
291
+ end
292
+
293
+ def change_table_schema(schema_name, table_name)
294
+ execute "ALTER SCHEMA [#{schema_name}] TRANSFER [#{table_name}]"
295
+ end
296
+
297
+ def drop_schema(schema_name)
298
+ execute "DROP SCHEMA [#{schema_name}]"
299
+ end
300
+
284
301
  private
285
302
 
286
303
  def data_source_sql(name = nil, type: nil)
287
304
  scope = quoted_scope name, type: type
288
- table_name = lowercase_schema_reflection_sql "TABLE_NAME"
305
+
306
+ table_name = lowercase_schema_reflection_sql 'TABLE_NAME'
307
+ database = scope[:database].present? ? "#{scope[:database]}." : ""
308
+ table_catalog = scope[:database].present? ? quote(scope[:database]) : "DB_NAME()"
309
+
289
310
  sql = "SELECT #{table_name}"
290
- sql += " FROM INFORMATION_SCHEMA.TABLES WITH (NOLOCK)"
291
- sql += " WHERE TABLE_CATALOG = DB_NAME()"
311
+ sql += " FROM #{database}INFORMATION_SCHEMA.TABLES WITH (NOLOCK)"
312
+ sql += " WHERE TABLE_CATALOG = #{table_catalog}"
292
313
  sql += " AND TABLE_SCHEMA = #{quote(scope[:schema])}"
293
314
  sql += " AND TABLE_NAME = #{quote(scope[:name])}" if scope[:name]
294
315
  sql += " AND TABLE_TYPE = #{quote(scope[:type])}" if scope[:type]
@@ -299,6 +320,7 @@ module ActiveRecord
299
320
  def quoted_scope(name = nil, type: nil)
300
321
  identifier = SQLServer::Utils.extract_identifiers(name)
301
322
  {}.tap do |scope|
323
+ scope[:database] = identifier.database if identifier.database
302
324
  scope[:schema] = identifier.schema || "dbo"
303
325
  scope[:name] = identifier.object if identifier.object
304
326
  scope[:type] = type if type
@@ -310,7 +332,7 @@ module ActiveRecord
310
332
  def initialize_native_database_types
311
333
  {
312
334
  primary_key: "bigint NOT NULL IDENTITY(1,1) PRIMARY KEY",
313
- primary_key_nonclustered: "int NOT NULL IDENTITY(1,1) PRIMARY KEY NONCLUSTERED",
335
+ primary_key_nonclustered: "bigint NOT NULL IDENTITY(1,1) PRIMARY KEY NONCLUSTERED",
314
336
  integer: { name: "int", limit: 4 },
315
337
  bigint: { name: "bigint" },
316
338
  boolean: { name: "bit" },
@@ -472,6 +494,7 @@ module ActiveRecord
472
494
  AND c.default_object_id = d.object_id
473
495
  LEFT OUTER JOIN #{database}.sys.key_constraints k
474
496
  ON c.object_id = k.parent_object_id
497
+ AND k.type = 'PK'
475
498
  LEFT OUTER JOIN #{database}.sys.index_columns ic
476
499
  ON k.parent_object_id = ic.object_id
477
500
  AND k.unique_index_id = ic.index_id
@@ -3,16 +3,36 @@
3
3
  module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module SQLServer
6
- class SqlTypeMetadata < ActiveRecord::ConnectionAdapters::SqlTypeMetadata
7
- def initialize(**kwargs)
8
- @sqlserver_options = kwargs.extract!(:sqlserver_options)
9
- super(**kwargs)
6
+ class TypeMetadata < DelegateClass(SqlTypeMetadata)
7
+ undef to_yaml if method_defined?(:to_yaml)
8
+
9
+ include Deduplicable
10
+
11
+ attr_reader :sqlserver_options
12
+
13
+ def initialize(type_metadata, sqlserver_options: nil)
14
+ super(type_metadata)
15
+ @sqlserver_options = sqlserver_options
16
+ end
17
+
18
+ def ==(other)
19
+ other.is_a?(TypeMetadata) &&
20
+ __getobj__ == other.__getobj__ &&
21
+ sqlserver_options == other.sqlserver_options
22
+ end
23
+ alias eql? ==
24
+
25
+ def hash
26
+ TypeMetadata.hash ^
27
+ __getobj__.hash ^
28
+ sqlserver_options.hash
10
29
  end
11
30
 
12
- protected
31
+ private
13
32
 
14
- def attributes_for_hash
15
- super + [@sqlserver_options]
33
+ def deduplicated
34
+ __setobj__(__getobj__.deduplicate)
35
+ super
16
36
  end
17
37
  end
18
38
  end
@@ -9,7 +9,6 @@ module ActiveRecord
9
9
  options[:is_identity] = true unless options.key?(:default)
10
10
  elsif type == :uuid
11
11
  options[:default] = options.fetch(:default, "NEWID()")
12
- options[:primary_key] = true
13
12
  end
14
13
  super
15
14
  end
@@ -31,9 +31,9 @@ module ActiveRecord
31
31
  module SQLServerRealTransaction
32
32
  attr_reader :starting_isolation_level
33
33
 
34
- def initialize(connection, options, **args)
34
+ def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
35
35
  @connection = connection
36
- @starting_isolation_level = current_isolation_level if options[:isolation]
36
+ @starting_isolation_level = current_isolation_level if isolation
37
37
  super
38
38
  end
39
39
 
@@ -11,6 +11,7 @@ require "active_record/connection_adapters/sqlserver/type/small_integer"
11
11
  require "active_record/connection_adapters/sqlserver/type/tiny_integer"
12
12
  require "active_record/connection_adapters/sqlserver/type/boolean"
13
13
  require "active_record/connection_adapters/sqlserver/type/decimal"
14
+ require "active_record/connection_adapters/sqlserver/type/decimal_without_scale"
14
15
  require "active_record/connection_adapters/sqlserver/type/money"
15
16
  require "active_record/connection_adapters/sqlserver/type/small_money"
16
17
  # Approximate Numerics
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters
5
+ module SQLServer
6
+ module Type
7
+ class DecimalWithoutScale < ActiveRecord::Type::DecimalWithoutScale
8
+ def sqlserver_type
9
+ "decimal".yield_self do |type|
10
+ type += "(#{precision.to_i},0)" if precision
11
+ type
12
+ end
13
+ end
14
+
15
+ def type_cast_for_schema(value)
16
+ value.is_a?(BigDecimal) ? value.to_s : value.inspect
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -92,7 +92,7 @@ module ActiveRecord
92
92
  @schema = @parts.first
93
93
  end
94
94
  rest = scanner.rest
95
- rest = rest.starts_with?(".") ? rest[1..-1] : rest[0..-1]
95
+ rest = rest.start_with?(".") ? rest[1..-1] : rest[0..-1]
96
96
  @object = unquote(rest)
97
97
  @parts << @object
98
98
  end
@@ -59,13 +59,73 @@ module ActiveRecord
59
59
  self.use_output_inserted = true
60
60
  self.exclude_output_inserted_table_names = Concurrent::Map.new { false }
61
61
 
62
- def initialize(connection, logger = nil, config = {})
62
+ class << self
63
+ def new_client(config)
64
+ case config[:mode]
65
+ when :dblib
66
+ require "tiny_tds"
67
+ dblib_connect(config)
68
+ else
69
+ raise ArgumentError, "Unknown connection mode in #{config.inspect}."
70
+ end
71
+ end
72
+
73
+ def dblib_connect(config)
74
+ TinyTds::Client.new(
75
+ dataserver: config[:dataserver],
76
+ host: config[:host],
77
+ port: config[:port],
78
+ username: config[:username],
79
+ password: config[:password],
80
+ database: config[:database],
81
+ tds_version: config[:tds_version] || "7.3",
82
+ appname: config_appname(config),
83
+ login_timeout: config_login_timeout(config),
84
+ timeout: config_timeout(config),
85
+ encoding: config_encoding(config),
86
+ azure: config[:azure],
87
+ contained: config[:contained]
88
+ ).tap do |client|
89
+ if config[:azure]
90
+ client.execute("SET ANSI_NULLS ON").do
91
+ client.execute("SET ANSI_NULL_DFLT_ON ON").do
92
+ client.execute("SET ANSI_PADDING ON").do
93
+ client.execute("SET ANSI_WARNINGS ON").do
94
+ else
95
+ client.execute("SET ANSI_DEFAULTS ON").do
96
+ end
97
+ client.execute("SET QUOTED_IDENTIFIER ON").do
98
+ client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
99
+ client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
100
+ client.execute("SET TEXTSIZE 2147483647").do
101
+ client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
102
+ end
103
+ rescue TinyTds::Error => e
104
+ raise ActiveRecord::NoDatabaseError if e.message.match(/database .* does not exist/i)
105
+ raise e
106
+ end
107
+
108
+ def config_appname(config)
109
+ config[:appname] || configure_application_name || Rails.application.class.name.split("::").first rescue nil
110
+ end
111
+
112
+ def config_login_timeout(config)
113
+ config[:login_timeout].present? ? config[:login_timeout].to_i : nil
114
+ end
115
+
116
+ def config_timeout(config)
117
+ config[:timeout].present? ? config[:timeout].to_i / 1000 : nil
118
+ end
119
+
120
+ def config_encoding(config)
121
+ config[:encoding].present? ? config[:encoding] : nil
122
+ end
123
+ end
124
+
125
+ def initialize(connection, logger, _connection_options, config)
63
126
  super(connection, logger, config)
64
- # Our Responsibility
65
127
  @connection_options = config
66
- connect
67
- initialize_dateformatter
68
- use_database
128
+ configure_connection
69
129
  end
70
130
 
71
131
  # === Abstract Adapter ========================================== #
@@ -152,6 +212,10 @@ module ActiveRecord
152
212
  true
153
213
  end
154
214
 
215
+ def supports_optimizer_hints?
216
+ true
217
+ end
218
+
155
219
  def supports_lazy_transactions?
156
220
  true
157
221
  end
@@ -222,6 +286,14 @@ module ActiveRecord
222
286
  do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
223
287
  end
224
288
 
289
+ def configure_connection
290
+ @spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
291
+ @version_year = version_year
292
+
293
+ initialize_dateformatter
294
+ use_database
295
+ end
296
+
225
297
  # === Abstract Adapter (Misc Support) =========================== #
226
298
 
227
299
  def tables_with_referential_integrity
@@ -296,6 +368,7 @@ module ActiveRecord
296
368
 
297
369
  def initialize_type_map(m = type_map)
298
370
  m.register_type %r{.*}, SQLServer::Type::UnicodeString.new
371
+
299
372
  # Exact Numerics
300
373
  register_class_with_limit m, "bigint(8)", SQLServer::Type::BigInteger
301
374
  m.alias_type "bigint", "bigint(8)"
@@ -308,16 +381,22 @@ module ActiveRecord
308
381
  m.alias_type "tinyint", "tinyint(1)"
309
382
  m.register_type "bit", SQLServer::Type::Boolean.new
310
383
  m.register_type %r{\Adecimal}i do |sql_type|
311
- scale = extract_scale(sql_type)
384
+ scale = extract_scale(sql_type)
312
385
  precision = extract_precision(sql_type)
313
- SQLServer::Type::Decimal.new precision: precision, scale: scale
386
+ if scale == 0
387
+ SQLServer::Type::DecimalWithoutScale.new(precision: precision)
388
+ else
389
+ SQLServer::Type::Decimal.new(precision: precision, scale: scale)
390
+ end
314
391
  end
315
392
  m.alias_type %r{\Anumeric}i, "decimal"
316
393
  m.register_type "money", SQLServer::Type::Money.new
317
394
  m.register_type "smallmoney", SQLServer::Type::SmallMoney.new
395
+
318
396
  # Approximate Numerics
319
397
  m.register_type "float", SQLServer::Type::Float.new
320
398
  m.register_type "real", SQLServer::Type::Real.new
399
+
321
400
  # Date and Time
322
401
  m.register_type "date", SQLServer::Type::Date.new
323
402
  m.register_type %r{\Adatetime} do |sql_type|
@@ -337,11 +416,13 @@ module ActiveRecord
337
416
  precision = extract_precision(sql_type) || DEFAULT_TIME_PRECISION
338
417
  SQLServer::Type::Time.new precision: precision
339
418
  end
419
+
340
420
  # Character Strings
341
421
  register_class_with_limit m, %r{\Achar}i, SQLServer::Type::Char
342
422
  register_class_with_limit m, %r{\Avarchar}i, SQLServer::Type::Varchar
343
423
  m.register_type "varchar(max)", SQLServer::Type::VarcharMax.new
344
424
  m.register_type "text", SQLServer::Type::Text.new
425
+
345
426
  # Unicode Character Strings
346
427
  register_class_with_limit m, %r{\Anchar}i, SQLServer::Type::UnicodeChar
347
428
  register_class_with_limit m, %r{\Anvarchar}i, SQLServer::Type::UnicodeVarchar
@@ -349,10 +430,12 @@ module ActiveRecord
349
430
  m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
350
431
  m.register_type "nvarchar(max)", SQLServer::Type::UnicodeVarcharMax.new
351
432
  m.register_type "ntext", SQLServer::Type::UnicodeText.new
433
+
352
434
  # Binary Strings
353
435
  register_class_with_limit m, %r{\Abinary}i, SQLServer::Type::Binary
354
436
  register_class_with_limit m, %r{\Avarbinary}i, SQLServer::Type::Varbinary
355
437
  m.register_type "varbinary(max)", SQLServer::Type::VarbinaryMax.new
438
+
356
439
  # Other Data Types
357
440
  m.register_type "uniqueidentifier", SQLServer::Type::Uuid.new
358
441
  m.register_type "timestamp", SQLServer::Type::Timestamp.new
@@ -360,6 +443,8 @@ module ActiveRecord
360
443
 
361
444
  def translate_exception(e, message:, sql:, binds:)
362
445
  case message
446
+ when /(SQL Server client is not connected)|(failed to execute statement)/i
447
+ ConnectionNotEstablished.new(message)
363
448
  when /(cannot insert duplicate key .* with unique index) | (violation of unique key constraint)/i
364
449
  RecordNotUnique.new(message, sql: sql, binds: binds)
365
450
  when /(conflicted with the foreign key constraint) | (The DELETE statement conflicted with the REFERENCE constraint)/i
@@ -393,78 +478,18 @@ module ActiveRecord
393
478
 
394
479
  # === SQLServer Specific (Connection Management) ================ #
395
480
 
396
- def connect
397
- config = @connection_options
398
- @connection = case config[:mode]
399
- when :dblib
400
- dblib_connect(config)
401
- end
402
- @spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
403
- @version_year = version_year
404
- configure_connection
405
- end
406
-
407
481
  def connection_errors
408
482
  @connection_errors ||= [].tap do |errors|
409
483
  errors << TinyTds::Error if defined?(TinyTds::Error)
410
484
  end
411
485
  end
412
486
 
413
- def dblib_connect(config)
414
- TinyTds::Client.new(
415
- dataserver: config[:dataserver],
416
- host: config[:host],
417
- port: config[:port],
418
- username: config[:username],
419
- password: config[:password],
420
- database: config[:database],
421
- tds_version: config[:tds_version] || "7.3",
422
- appname: config_appname(config),
423
- login_timeout: config_login_timeout(config),
424
- timeout: config_timeout(config),
425
- encoding: config_encoding(config),
426
- azure: config[:azure],
427
- contained: config[:contained]
428
- ).tap do |client|
429
- if config[:azure]
430
- client.execute("SET ANSI_NULLS ON").do
431
- client.execute("SET ANSI_NULL_DFLT_ON ON").do
432
- client.execute("SET ANSI_PADDING ON").do
433
- client.execute("SET ANSI_WARNINGS ON").do
434
- else
435
- client.execute("SET ANSI_DEFAULTS ON").do
436
- end
437
- client.execute("SET QUOTED_IDENTIFIER ON").do
438
- client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
439
- client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
440
- client.execute("SET TEXTSIZE 2147483647").do
441
- client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
442
- end
443
- end
444
-
445
- def config_appname(config)
446
- config[:appname] || configure_application_name || Rails.application.class.name.split("::").first rescue nil
447
- end
448
-
449
- def config_login_timeout(config)
450
- config[:login_timeout].present? ? config[:login_timeout].to_i : nil
451
- end
452
-
453
- def config_timeout(config)
454
- config[:timeout].present? ? config[:timeout].to_i / 1000 : nil
455
- end
456
-
457
- def config_encoding(config)
458
- config[:encoding].present? ? config[:encoding] : nil
459
- end
460
-
461
- def configure_connection; end
462
-
463
487
  def configure_application_name; end
464
488
 
465
489
  def initialize_dateformatter
466
490
  @database_dateformat = user_options_dateformat
467
491
  a, b, c = @database_dateformat.each_char.to_a
492
+
468
493
  [a, b, c].each { |f| f.upcase! if f == "y" }
469
494
  dateformat = "%#{a}-%#{b}-%#{c}"
470
495
  ::Date::DATE_FORMATS[:_sqlserver_dateformat] = dateformat
@@ -487,6 +512,13 @@ module ActiveRecord
487
512
  def sqlserver_version
488
513
  @sqlserver_version ||= _raw_select("SELECT @@version", fetch: :rows).first.first.to_s
489
514
  end
515
+
516
+ private
517
+
518
+ def connect
519
+ @connection = self.class.new_client(@connection_options)
520
+ configure_connection
521
+ end
490
522
  end
491
523
  end
492
524
  end