Class: ActiveRecord::ConnectionAdapters::SQLServerAdapter

Constant Summary collapse

ADAPTER_NAME =
"SQLServer".freeze
DEFAULT_TIME_PRECISION =
7
TYPE_MAP =
Type::TypeMap.new.tap { |m| initialize_type_map(m) }

Constants included from ActiveRecord::ConnectionAdapters::SQLServer::Version

ActiveRecord::ConnectionAdapters::SQLServer::Version::VERSION

Constants included from ActiveRecord::ConnectionAdapters::SQLServer::Quoting

ActiveRecord::ConnectionAdapters::SQLServer::Quoting::QUOTED_FALSE, ActiveRecord::ConnectionAdapters::SQLServer::Quoting::QUOTED_STRING_PREFIX, ActiveRecord::ConnectionAdapters::SQLServer::Quoting::QUOTED_TRUE

Constants included from ActiveRecord::ConnectionAdapters::SQLServer::Showplan

ActiveRecord::ConnectionAdapters::SQLServer::Showplan::OPTIONS, ActiveRecord::ConnectionAdapters::SQLServer::Showplan::OPTION_ALL, ActiveRecord::ConnectionAdapters::SQLServer::Showplan::OPTION_TEXT, ActiveRecord::ConnectionAdapters::SQLServer::Showplan::OPTION_XML

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveRecord::ConnectionAdapters::SQLServer::Quoting

#column_name_matcher, #column_name_with_order_matcher, #fetch_type_metadata, #quote, #quote_column_name, #quote_default_expression, #quote_string, #quote_string_single, #quote_string_single_national, #quoted_date, #quoted_false, #quoted_true, #type_cast, #unquoted_false, #unquoted_true

Methods included from ActiveRecord::ConnectionAdapters::SQLServer::DatabaseStatements

#begin_db_transaction, #begin_isolated_db_transaction, #build_insert_sql, #case_sensitive_comparison, #commit_db_transaction, #create_savepoint, #exec_delete, #exec_insert, #exec_query, #exec_rollback_db_transaction, #exec_rollback_to_savepoint, #exec_update, #execute, #execute_procedure, #insert_fixtures_set, #newid_function, #newsequentialid_function, #release_savepoint, #set_transaction_isolation_level, #transaction_isolation_levels, #use_database, #user_options, #user_options_dateformat, #user_options_isolation_level, #user_options_language, #with_identity_insert_enabled, #write_query?

Methods included from ActiveRecord::ConnectionAdapters::SQLServer::Showplan

#explain

Methods included from ActiveRecord::ConnectionAdapters::SQLServer::SchemaStatements

#change_column, #change_column_default, #change_column_null, #change_table_schema, #columns, #columns_for_distinct, #create_schema, #create_schema_dumper, #create_table, #drop_schema, #drop_table, #extract_foreign_key_action, #foreign_keys, #indexes, #native_database_types, #new_column, #primary_keys, #primary_keys_select, #remove_column, #remove_index!, #rename_column, #rename_index, #rename_table, #type_to_sql, #update_table_definition

Methods included from ActiveRecord::ConnectionAdapters::SQLServer::DatabaseLimits

#column_name_length, #columns_per_multicolumn_index, #columns_per_table, #index_name_length, #indexes_per_table, #joins_per_query, #sql_query_length, #table_alias_length, #table_name_length

Methods included from ActiveRecord::ConnectionAdapters::SQLServer::DatabaseTasks

#charset, #collation, #create_database, #current_database, #drop_database

Constructor Details

#initialize(connection, logger, _connection_options, config) ⇒ SQLServerAdapter

Returns a new instance of SQLServerAdapter.



157
158
159
160
161
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 157

def initialize(connection, logger, _connection_options, config)
  super(connection, logger, config)
  @connection_options = config
  perform_connection_configuration
end

Instance Attribute Details

#spidObject (readonly)

Returns the value of attribute spid.



49
50
51
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 49

def spid
  @spid
end

Class Method Details

.config_appname(config) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 124

def config_appname(config)
  if instance_methods.include?(:configure_application_name)
    ActiveSupport::Deprecation.warn <<~MSG.squish
    Configuring the application name used by TinyTDS by overriding the
    `ActiveRecord::ConnectionAdapters::SQLServerAdapter#configure_application_name`
    instance method is no longer supported. The application name should configured
    using the `appname` setting in the `database.yml` file instead. Consult the
    README for further information."
    MSG
  end

  config[:appname] || rails_application_name
end

.config_encoding(config) ⇒ Object



152
153
154
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 152

def config_encoding(config)
  config[:encoding].present? ? config[:encoding] : nil
end

.config_login_timeout(config) ⇒ Object



144
145
146
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 144

def (config)
  config[:login_timeout].present? ? config[:login_timeout].to_i : nil
end

.config_timeout(config) ⇒ Object



148
149
150
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 148

def config_timeout(config)
  config[:timeout].present? ? config[:timeout].to_i / 1000 : nil
end

.database_exists?(config) ⇒ Boolean

Returns:

  • (Boolean)


177
178
179
180
181
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 177

def self.database_exists?(config)
  !!ActiveRecord::Base.sqlserver_connection(config)
rescue ActiveRecord::NoDatabaseError
  false
end

.dbconsole(config, options = {}) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 62

def dbconsole(config, options = {})
  sqlserver_config = config.configuration_hash
  args = []

  args += ["-d", "#{config.database}"] if config.database
  args += ["-U", "#{sqlserver_config[:username]}"] if sqlserver_config[:username]
  args += ["-P", "#{sqlserver_config[:password]}"] if sqlserver_config[:password]

  if sqlserver_config[:host]
    host_arg = +"tcp:#{sqlserver_config[:host]}"
    host_arg << ",#{sqlserver_config[:port]}" if sqlserver_config[:port]
    args += ["-S", host_arg]
  end

  find_cmd_and_exec("sqlcmd", *args)
end

.dblib_connect(config) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 89

def dblib_connect(config)
  TinyTds::Client.new(
    dataserver:    config[:dataserver],
    host:          config[:host],
    port:          config[:port],
    username:      config[:username],
    password:      config[:password],
    database:      config[:database],
    tds_version:   config[:tds_version] || "7.3",
    appname:       config_appname(config),
    login_timeout: (config),
    timeout:       config_timeout(config),
    encoding:      config_encoding(config),
    azure:         config[:azure],
    contained:     config[:contained]
  ).tap do |client|
    if config[:azure]
      client.execute("SET ANSI_NULLS ON").do
      client.execute("SET ANSI_NULL_DFLT_ON ON").do
      client.execute("SET ANSI_PADDING ON").do
      client.execute("SET ANSI_WARNINGS ON").do
    else
      client.execute("SET ANSI_DEFAULTS ON").do
    end
    client.execute("SET QUOTED_IDENTIFIER ON").do
    client.execute("SET CURSOR_CLOSE_ON_COMMIT OFF").do
    client.execute("SET IMPLICIT_TRANSACTIONS OFF").do
    client.execute("SET TEXTSIZE 2147483647").do
    client.execute("SET CONCAT_NULL_YIELDS_NULL ON").do
  end
rescue TinyTds::Error => e
  raise ActiveRecord::NoDatabaseError if e.message.match(/database .* does not exist/i)
  raise e
end

.new_client(config) ⇒ Object



79
80
81
82
83
84
85
86
87
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 79

def new_client(config)
  case config[:mode]
  when :dblib
    require "tiny_tds"
    dblib_connect(config)
  else
    raise ArgumentError, "Unknown connection mode in #{config.inspect}."
  end
end

.rails_application_nameObject



138
139
140
141
142
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 138

def rails_application_name
  Rails.application.class.name.split("::").first
rescue
  nil # Might not be in a Rails context so we fallback to `nil`.
end

Instance Method Details

#active?Boolean

Abstract Adapter (Connection Management) ================== #

Returns:

  • (Boolean)


285
286
287
288
289
290
291
292
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 285

def active?
  return false unless @connection

  raw_connection_do "SELECT 1"
  true
rescue *connection_errors
  false
end

#arel_visitorObject

Abstract Adapter ========================================== #



165
166
167
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 165

def arel_visitor
  Arel::Visitors::SQLServer.new self
end

#clear_cache!Object



311
312
313
314
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 311

def clear_cache!
  @view_information = nil
  super
end

#combine_bind_parameters(from_clause: [], join_clause: [], where_clause: [], having_clause: [], limit: nil, offset: nil) ⇒ Object



378
379
380
381
382
383
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 378

def combine_bind_parameters(from_clause: [], join_clause: [], where_clause: [], having_clause: [], limit: nil, offset: nil)
  result = from_clause + join_clause + where_clause + having_clause
  result << offset if offset
  result << limit if limit
  result
end

#database_prefixObject



358
359
360
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 358

def database_prefix
  @connection_options[:database_prefix]
end

#database_prefix_identifier(name) ⇒ Object



362
363
364
365
366
367
368
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 362

def database_prefix_identifier(name)
  if database_prefix_remote_server?
    SQLServer::Utils.extract_identifiers("#{database_prefix}#{name}")
  else
    SQLServer::Utils.extract_identifiers(name)
  end
end

#database_prefix_remote_server?Boolean

Returns:

  • (Boolean)


351
352
353
354
355
356
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 351

def database_prefix_remote_server?
  return false if database_prefix.blank?

  name = SQLServer::Utils.extract_identifiers(database_prefix)
  name.fully_qualified? && name.object.blank?
end

#disable_referential_integrityObject



275
276
277
278
279
280
281
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 275

def disable_referential_integrity
  tables = tables_with_referential_integrity
  tables.each { |t| do_execute "ALTER TABLE #{quote_table_name(t)} NOCHECK CONSTRAINT ALL" }
  yield
ensure
  tables.each { |t| do_execute "ALTER TABLE #{quote_table_name(t)} CHECK CONSTRAINT ALL" }
end

#disconnect!Object



300
301
302
303
304
305
306
307
308
309
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 300

def disconnect!
  super
  case @connection_options[:mode]
  when :dblib
    @connection.close rescue nil
  end
  @connection = nil
  @spid = nil
  @collation = nil
end

#get_database_versionObject

:nodoc:



385
386
387
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 385

def get_database_version # :nodoc:
  version_year
end

#inspectObject



374
375
376
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 374

def inspect
  "#<#{self.class} version: #{version}, mode: #{@connection_options[:mode]}, azure: #{sqlserver_azure?.inspect}>"
end

#pk_and_sequence_for(table_name) ⇒ Object



336
337
338
339
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 336

def pk_and_sequence_for(table_name)
  pk = primary_key(table_name)
  pk ? [pk, nil] : nil
end

#reconnect!Object



294
295
296
297
298
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 294

def reconnect!
  super
  disconnect!
  connect
end

#reset!Object



316
317
318
319
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 316

def reset!
  reset_transaction
  do_execute "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
end

#schema_creationObject



173
174
175
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 173

def schema_creation
  SQLServer::SchemaCreation.new self
end

#sqlserver?Boolean

SQLServer Specific (DB Reflection) ======================== #

Returns:

  • (Boolean)


343
344
345
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 343

def sqlserver?
  true
end

#sqlserver_azure?Boolean

Returns:

  • (Boolean)


347
348
349
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 347

def sqlserver_azure?
  !!(sqlserver_version =~ /Azure/i)
end

#supports_advisory_locks?Boolean

Returns:

  • (Boolean)


191
192
193
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 191

def supports_advisory_locks?
  false
end

#supports_bulk_alter?Boolean

Returns:

  • (Boolean)


187
188
189
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 187

def supports_bulk_alter?
  false
end

#supports_comments?Boolean

Returns:

  • (Boolean)


235
236
237
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 235

def supports_comments?
  false
end

#supports_comments_in_create?Boolean

Returns:

  • (Boolean)


239
240
241
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 239

def supports_comments_in_create?
  false
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


227
228
229
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 227

def supports_datetime_with_precision?
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


183
184
185
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 183

def supports_ddl_transactions?
  true
end

#supports_explain?Boolean

Returns:

  • (Boolean)


207
208
209
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 207

def supports_explain?
  true
end

#supports_expression_index?Boolean

Returns:

  • (Boolean)


203
204
205
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 203

def supports_expression_index?
  false
end

#supports_foreign_keys?Boolean

Returns:

  • (Boolean)


219
220
221
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 219

def supports_foreign_keys?
  true
end

#supports_in_memory_oltp?Boolean

Returns:

  • (Boolean)


255
256
257
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 255

def supports_in_memory_oltp?
  @version_year >= 2014
end

#supports_index_sort_order?Boolean

Returns:

  • (Boolean)


195
196
197
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 195

def supports_index_sort_order?
  true
end

#supports_indexes_in_create?Boolean

Returns:

  • (Boolean)


215
216
217
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 215

def supports_indexes_in_create?
  false
end

#supports_insert_conflict_target?Boolean

Returns:

  • (Boolean)


271
272
273
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 271

def supports_insert_conflict_target?
  false
end

#supports_insert_on_duplicate_skip?Boolean

Returns:

  • (Boolean)


263
264
265
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 263

def supports_insert_on_duplicate_skip?
  false
end

#supports_insert_on_duplicate_update?Boolean

Returns:

  • (Boolean)


267
268
269
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 267

def supports_insert_on_duplicate_update?
  false
end

#supports_insert_returning?Boolean

Returns:

  • (Boolean)


259
260
261
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 259

def supports_insert_returning?
  true
end

#supports_json?Boolean

Returns:

  • (Boolean)


231
232
233
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 231

def supports_json?
  @version_year >= 2016
end

#supports_lazy_transactions?Boolean

Returns:

  • (Boolean)


251
252
253
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 251

def supports_lazy_transactions?
  true
end

#supports_optimizer_hints?Boolean

Returns:

  • (Boolean)


247
248
249
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 247

def supports_optimizer_hints?
  true
end

#supports_partial_index?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 199

def supports_partial_index?
  true
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


243
244
245
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 243

def supports_savepoints?
  true
end

#supports_transaction_isolation?Boolean

Returns:

  • (Boolean)


211
212
213
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 211

def supports_transaction_isolation?
  true
end

#supports_views?Boolean

Returns:

  • (Boolean)


223
224
225
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 223

def supports_views?
  true
end

#tables_with_referential_integrityObject

Abstract Adapter (Misc Support) =========================== #



323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 323

def tables_with_referential_integrity
  schemas_and_tables = select_rows <<~SQL.squish
    SELECT DISTINCT s.name, o.name
    FROM sys.foreign_keys i
    INNER JOIN sys.objects o ON i.parent_object_id = o.OBJECT_ID
    INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
  SQL
  schemas_and_tables.map do |schema_table|
    schema, table = schema_table
    "#{SQLServer::Utils.quoted_raw(schema)}.#{SQLServer::Utils.quoted_raw(table)}"
  end
end

#valid_type?(type) ⇒ Boolean

Returns:

  • (Boolean)


169
170
171
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 169

def valid_type?(type)
  !native_database_types[type].nil?
end

#versionObject



370
371
372
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 370

def version
  self.class::VERSION
end