Class: ActiveRecord::ConnectionAdapters::SQLServerAdapter

Constant Summary collapse

ADAPTER_NAME =
"SQLServer"
DEFAULT_TIME_PRECISION =
7
NATIVE_DATABASE_TYPES =
{
  primary_key: "bigint NOT NULL IDENTITY(1,1) PRIMARY KEY",
  primary_key_nonclustered: "bigint NOT NULL IDENTITY(1,1) PRIMARY KEY NONCLUSTERED",
  integer: {name: "int", limit: 4},
  bigint: {name: "bigint"},
  boolean: {name: "bit"},
  decimal: {name: "decimal"},
  money: {name: "money"},
  smallmoney: {name: "smallmoney"},
  float: {name: "float"},
  real: {name: "real"},
  date: {name: "date"},
  datetime: {name: "datetime"},
  datetime2: {name: "datetime2"},
  datetimeoffset: {name: "datetimeoffset"},
  smalldatetime: {name: "smalldatetime"},
  timestamp: {name: "datetime2(6)"},
  time: {name: "time"},
  char: {name: "char"},
  varchar: {name: "varchar", limit: 8000},
  varchar_max: {name: "varchar(max)"},
  text_basic: {name: "text"},
  nchar: {name: "nchar"},
  string: {name: "nvarchar", limit: 4000},
  text: {name: "nvarchar(max)"},
  ntext: {name: "ntext"},
  binary_basic: {name: "binary"},
  varbinary: {name: "varbinary", limit: 8000},
  binary: {name: "varbinary(max)"},
  uuid: {name: "uniqueidentifier"},
  ss_timestamp: {name: "timestamp"},
  json: {name: "nvarchar(max)"}
}
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_COLUMN_NAMES, ActiveRecord::ConnectionAdapters::SQLServer::Quoting::QUOTED_TABLE_NAMES

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

#fetch_type_metadata, #quote, #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

#affected_rows, #affected_rows_from_results_or_handle, #begin_db_transaction, #begin_isolated_db_transaction, #build_insert_sql, #build_sql_for_merge_insert, #case_sensitive_comparison, #cast_result, #commit_db_transaction, #exec_delete, #exec_rollback_db_transaction, #exec_update, #execute_procedure, #insert_fixtures_set, #internal_exec_sql_query, #merge_insert_values_list, #newid_function, #newsequentialid_function, #perform_query, #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

#add_timestamps, #build_change_column_default_definition, #build_change_column_definition, #change_column, #change_column_default, #change_column_null, #change_table_schema, #check_constraints, #columns, #columns_for_distinct, #create_schema, #create_schema_dumper, #create_table, #drop_schema, #drop_table, #extract_foreign_key_action, #extract_generated_type, #foreign_keys, #index_include_columns, #indexes, #new_column_from_field, #primary_keys, #primary_keys_select, #quoted_include_columns_for_index, #remove_column, #remove_index!, #rename_column, #rename_index, #rename_table, #schema_names, #type_to_sql, #update_table_definition

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

#index_name_length, #table_alias_length, #table_name_length

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

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

Methods included from ActiveRecord::ConnectionAdapters::SQLServer::Savepoints

#create_savepoint, #current_savepoint_name, #exec_rollback_to_savepoint, #release_savepoint

Constructor Details

#initializeSQLServerAdapter

Returns a new instance of SQLServerAdapter.



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 139

def initialize(...)
  super

  @config[:tds_version] = "7.3" unless @config[:tds_version]
  @config[:appname] = self.class.rails_application_name unless @config[:appname]
  @config[:login_timeout] = @config[:login_timeout].present? ? @config[:login_timeout].to_i : nil
  @config[:timeout] = @config[:timeout].present? ? @config[:timeout].to_i / 1000 : nil
  @config[:encoding] = @config[:encoding].present? ? @config[:encoding] : nil

  @connection_parameters ||= @config
end

Instance Attribute Details

#spidObject (readonly)

Returns the value of attribute spid.



53
54
55
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 53

def spid
  @spid
end

Class Method Details

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



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 100

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

  args += ["-d", config.database.to_s] if config.database
  args += ["-U", sqlserver_config[:username].to_s] if sqlserver_config[:username]
  args += ["-P", sqlserver_config[:password].to_s] if sqlserver_config[:password]
  args += ["-C"] if sqlserver_config[:trust_server_certificate]

  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

.native_database_typesObject

:nodoc:



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

def native_database_types # :nodoc:
  NATIVE_DATABASE_TYPES
end

.new_client(config) ⇒ Object



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

def new_client(config)
  TinyTds::Client.new(config)
rescue TinyTds::Error => error
  if /database .* does not exist/i.match?(error.message)
    raise ActiveRecord::NoDatabaseError
  else
    raise
  end
end

.rails_application_nameObject



128
129
130
131
132
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 128

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)


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

def active?
  if @raw_connection&.active?
    verified!
    true
  end
rescue *connection_errors
  false
end

#arel_visitorObject

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



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

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

#check_versionObject

:nodoc:



389
390
391
392
393
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 389

def check_version # :nodoc:
  if schema_cache.database_version < 2012
    raise "Your version of SQL Server (#{database_version}) is too old. SQL Server Active Record supports 2012 or higher."
  end
end

#clear_cache!Object



322
323
324
325
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 322

def clear_cache!(...)
  @view_information = nil
  super
end

#database_prefixObject



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

def database_prefix
  @connection_parameters[:database_prefix]
end

#database_prefix_identifier(name) ⇒ Object



373
374
375
376
377
378
379
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 373

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)


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

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



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

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

#disconnect!Object



309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 309

def disconnect!
  super

  begin
    @raw_connection&.close
  rescue
    nil
  end
  @raw_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

#pk_and_sequence_for(table_name) ⇒ Object



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

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

#reconnectObject



296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 296

def reconnect
  begin
    @raw_connection&.close
  rescue
    nil
  end
  @raw_connection = nil
  @spid = nil
  @collation = nil

  connect
end

#reset!Object



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

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

#return_value_after_insert?(column) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


273
274
275
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 273

def return_value_after_insert?(column) # :nodoc:
  column.is_primary? || column.is_identity?
end

#schema_creationObject



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

def schema_creation
  SQLServer::SchemaCreation.new(self)
end

#sqlserver?Boolean

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

Returns:

  • (Boolean)


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

def sqlserver?
  true
end

#sqlserver_azure?Boolean

Returns:

  • (Boolean)


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

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

#supports_advisory_locks?Boolean

Returns:

  • (Boolean)


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

def supports_advisory_locks?
  false
end

#supports_bulk_alter?Boolean

Returns:

  • (Boolean)


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

def supports_bulk_alter?
  false
end

#supports_check_constraints?Boolean

Returns:

  • (Boolean)


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

def supports_check_constraints?
  true
end

#supports_comments?Boolean

Returns:

  • (Boolean)


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

def supports_comments?
  false
end

#supports_comments_in_create?Boolean

Returns:

  • (Boolean)


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

def supports_comments_in_create?
  false
end

#supports_common_table_expressions?Boolean

Returns:

  • (Boolean)


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

def supports_common_table_expressions?
  true
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


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

def supports_datetime_with_precision?
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


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

def supports_ddl_transactions?
  true
end

#supports_explain?Boolean

Returns:

  • (Boolean)


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

def supports_explain?
  true
end

#supports_expression_index?Boolean

Returns:

  • (Boolean)


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

def supports_expression_index?
  false
end

#supports_foreign_keys?Boolean

Returns:

  • (Boolean)


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

def supports_foreign_keys?
  true
end

#supports_in_memory_oltp?Boolean

Returns:

  • (Boolean)


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

def supports_in_memory_oltp?
  version_year >= 2014
end

#supports_index_include?Boolean

Returns:

  • (Boolean)


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

def supports_index_include?
  true
end

#supports_index_sort_order?Boolean

Returns:

  • (Boolean)


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

def supports_index_sort_order?
  true
end

#supports_indexes_in_create?Boolean

Returns:

  • (Boolean)


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

def supports_indexes_in_create?
  false
end

#supports_insert_conflict_target?Boolean

Returns:

  • (Boolean)


265
266
267
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 265

def supports_insert_conflict_target?
  false
end

#supports_insert_on_duplicate_skip?Boolean

Returns:

  • (Boolean)


257
258
259
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 257

def supports_insert_on_duplicate_skip?
  true
end

#supports_insert_on_duplicate_update?Boolean

Returns:

  • (Boolean)


261
262
263
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 261

def supports_insert_on_duplicate_update?
  true
end

#supports_insert_returning?Boolean

Returns:

  • (Boolean)


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

def supports_insert_returning?
  true
end

#supports_json?Boolean

Returns:

  • (Boolean)


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

def supports_json?
  version_year >= 2016
end

#supports_lazy_transactions?Boolean

Returns:

  • (Boolean)


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

def supports_lazy_transactions?
  true
end

#supports_optimizer_hints?Boolean

Returns:

  • (Boolean)


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

def supports_optimizer_hints?
  true
end

#supports_partial_index?Boolean

Returns:

  • (Boolean)


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

def supports_partial_index?
  true
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


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

def supports_savepoints?
  true
end

#supports_transaction_isolation?Boolean

Returns:

  • (Boolean)


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

def supports_transaction_isolation?
  true
end

#supports_views?Boolean

Returns:

  • (Boolean)


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

def supports_views?
  true
end

#supports_virtual_columns?Boolean

Returns:

  • (Boolean)


269
270
271
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 269

def supports_virtual_columns?
  true
end

#tables_with_referential_integrityObject

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



334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 334

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)


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

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

#versionObject



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

def version
  self.class::VERSION
end