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.



140
141
142
143
144
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 140

def initialize(connection, logger, _connection_options, config)
  super(connection, logger, config)
  @connection_options = config
  configure_connection
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



107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 107

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



135
136
137
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 135

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

.config_login_timeout(config) ⇒ Object



127
128
129
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 127

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

.config_timeout(config) ⇒ Object



131
132
133
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 131

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

.database_exists?(config) ⇒ Boolean

Returns:

  • (Boolean)


160
161
162
163
164
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 160

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

.dblib_connect(config) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 72

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



62
63
64
65
66
67
68
69
70
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 62

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



121
122
123
124
125
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 121

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)


268
269
270
271
272
273
274
275
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 268

def active?
  return false unless @connection

  raw_connection_do "SELECT 1"
  true
rescue *connection_errors
  false
end

#arel_visitorObject

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



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

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

#clear_cache!Object



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

def clear_cache!
  @view_information = nil
  super
end

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



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

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

#configure_connectionObject



304
305
306
307
308
309
310
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 304

def configure_connection
  @spid = _raw_select("SELECT @@SPID", fetch: :rows).first.first
  @version_year = version_year

  initialize_dateformatter
  use_database
end

#database_prefixObject



349
350
351
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 349

def database_prefix
  @connection_options[:database_prefix]
end

#database_prefix_identifier(name) ⇒ Object



353
354
355
356
357
358
359
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 353

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)


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

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



258
259
260
261
262
263
264
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 258

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



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

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:



376
377
378
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 376

def get_database_version # :nodoc:
  version_year
end

#inspectObject



365
366
367
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 365

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

#pk_and_sequence_for(table_name) ⇒ Object



327
328
329
330
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 327

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

#reconnect!Object



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

def reconnect!
  super
  disconnect!
  connect
end

#reset!Object



299
300
301
302
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 299

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

#schema_creationObject



156
157
158
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 156

def schema_creation
  SQLServer::SchemaCreation.new self
end

#sqlserver?Boolean

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

Returns:

  • (Boolean)


334
335
336
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 334

def sqlserver?
  true
end

#sqlserver_azure?Boolean

Returns:

  • (Boolean)


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

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

#supports_advisory_locks?Boolean

Returns:

  • (Boolean)


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

def supports_advisory_locks?
  false
end

#supports_bulk_alter?Boolean

Returns:

  • (Boolean)


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

def supports_bulk_alter?
  false
end

#supports_comments?Boolean

Returns:

  • (Boolean)


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

def supports_comments?
  false
end

#supports_comments_in_create?Boolean

Returns:

  • (Boolean)


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

def supports_comments_in_create?
  false
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


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

def supports_datetime_with_precision?
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


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

def supports_ddl_transactions?
  true
end

#supports_explain?Boolean

Returns:

  • (Boolean)


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

def supports_explain?
  true
end

#supports_expression_index?Boolean

Returns:

  • (Boolean)


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

def supports_expression_index?
  false
end

#supports_foreign_keys?Boolean

Returns:

  • (Boolean)


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

def supports_foreign_keys?
  true
end

#supports_in_memory_oltp?Boolean

Returns:

  • (Boolean)


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

def supports_in_memory_oltp?
  @version_year >= 2014
end

#supports_index_sort_order?Boolean

Returns:

  • (Boolean)


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

def supports_index_sort_order?
  true
end

#supports_indexes_in_create?Boolean

Returns:

  • (Boolean)


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

def supports_indexes_in_create?
  false
end

#supports_insert_conflict_target?Boolean

Returns:

  • (Boolean)


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

def supports_insert_conflict_target?
  false
end

#supports_insert_on_duplicate_skip?Boolean

Returns:

  • (Boolean)


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

def supports_insert_on_duplicate_skip?
  false
end

#supports_insert_on_duplicate_update?Boolean

Returns:

  • (Boolean)


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

def supports_insert_on_duplicate_update?
  false
end

#supports_insert_returning?Boolean

Returns:

  • (Boolean)


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

def supports_insert_returning?
  true
end

#supports_json?Boolean

Returns:

  • (Boolean)


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

def supports_json?
  @version_year >= 2016
end

#supports_lazy_transactions?Boolean

Returns:

  • (Boolean)


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

def supports_lazy_transactions?
  true
end

#supports_optimizer_hints?Boolean

Returns:

  • (Boolean)


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

def supports_optimizer_hints?
  true
end

#supports_partial_index?Boolean

Returns:

  • (Boolean)


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

def supports_partial_index?
  true
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


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

def supports_savepoints?
  true
end

#supports_transaction_isolation?Boolean

Returns:

  • (Boolean)


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

def supports_transaction_isolation?
  true
end

#supports_views?Boolean

Returns:

  • (Boolean)


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

def supports_views?
  true
end

#tables_with_referential_integrityObject

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



314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 314

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)


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

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

#versionObject



361
362
363
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 361

def version
  self.class::VERSION
end