activerecord-sqlserver-adapter 6.0.0.rc2 → 6.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +26 -0
  3. data/CHANGELOG.md +20 -41
  4. data/README.md +32 -3
  5. data/RUNNING_UNIT_TESTS.md +1 -1
  6. data/VERSION +1 -1
  7. data/activerecord-sqlserver-adapter.gemspec +1 -1
  8. data/lib/active_record/connection_adapters/sqlserver/core_ext/calculations.rb +0 -9
  9. data/lib/active_record/connection_adapters/sqlserver/core_ext/explain.rb +7 -2
  10. data/lib/active_record/connection_adapters/sqlserver/database_limits.rb +0 -4
  11. data/lib/active_record/connection_adapters/sqlserver/database_statements.rb +28 -16
  12. data/lib/active_record/connection_adapters/sqlserver/quoting.rb +7 -7
  13. data/lib/active_record/connection_adapters/sqlserver/schema_creation.rb +22 -1
  14. data/lib/active_record/connection_adapters/sqlserver/schema_dumper.rb +9 -3
  15. data/lib/active_record/connection_adapters/sqlserver/schema_statements.rb +31 -8
  16. data/lib/active_record/connection_adapters/sqlserver/sql_type_metadata.rb +27 -7
  17. data/lib/active_record/connection_adapters/sqlserver/table_definition.rb +0 -1
  18. data/lib/active_record/connection_adapters/sqlserver/transaction.rb +2 -2
  19. data/lib/active_record/connection_adapters/sqlserver/type.rb +1 -0
  20. data/lib/active_record/connection_adapters/sqlserver/type/decimal_without_scale.rb +22 -0
  21. data/lib/active_record/connection_adapters/sqlserver/utils.rb +1 -1
  22. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +100 -68
  23. data/lib/active_record/connection_adapters/sqlserver_column.rb +17 -0
  24. data/lib/active_record/sqlserver_base.rb +9 -15
  25. data/lib/active_record/tasks/sqlserver_database_tasks.rb +17 -14
  26. data/lib/arel/visitors/sqlserver.rb +111 -39
  27. data/test/cases/adapter_test_sqlserver.rb +48 -14
  28. data/test/cases/change_column_collation_test_sqlserver.rb +33 -0
  29. data/test/cases/coerced_tests.rb +598 -78
  30. data/test/cases/column_test_sqlserver.rb +5 -2
  31. data/test/cases/disconnected_test_sqlserver.rb +39 -0
  32. data/test/cases/execute_procedure_test_sqlserver.rb +9 -0
  33. data/test/cases/in_clause_test_sqlserver.rb +27 -0
  34. data/test/cases/lateral_test_sqlserver.rb +35 -0
  35. data/test/cases/migration_test_sqlserver.rb +51 -0
  36. data/test/cases/optimizer_hints_test_sqlserver.rb +72 -0
  37. data/test/cases/order_test_sqlserver.rb +7 -0
  38. data/test/cases/primary_keys_test_sqlserver.rb +103 -0
  39. data/test/cases/rake_test_sqlserver.rb +3 -2
  40. data/test/cases/schema_dumper_test_sqlserver.rb +20 -3
  41. data/test/migrations/create_clients_and_change_column_collation.rb +19 -0
  42. data/test/models/sqlserver/sst_string_collation.rb +3 -0
  43. data/test/schema/sqlserver_specific_schema.rb +17 -0
  44. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic.dump +0 -0
  45. data/test/support/marshal_compatibility_fixtures/SQLServer/rails_6_0_topic_associations.dump +0 -0
  46. data/test/support/sql_counter_sqlserver.rb +14 -12
  47. metadata +32 -13
  48. data/.travis.yml +0 -23
@@ -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