Class: ActiveRecord::ConnectionAdapters::SQLite3Adapter

Inherits:
AbstractAdapter show all
Includes:
ActiveRecord::ConnectionAdapters::SQLite3::DatabaseStatements, ActiveRecord::ConnectionAdapters::SQLite3::Quoting, ActiveRecord::ConnectionAdapters::SQLite3::SchemaStatements
Defined in:
lib/active_record/connection_adapters/sqlite3_adapter.rb

Overview

Active Record SQLite3 Adapter

The SQLite3 adapter works with the sqlite3-ruby drivers (available as gem from rubygems.org/gems/sqlite3).

Options:

  • :database - Path to the database file.

Defined Under Namespace

Classes: SQLite3Integer, StatementPool

Constant Summary collapse

ADAPTER_NAME =
"SQLite"
NATIVE_DATABASE_TYPES =
{
  primary_key:  "integer PRIMARY KEY AUTOINCREMENT NOT NULL",
  string:       { name: "varchar" },
  text:         { name: "text" },
  integer:      { name: "integer" },
  float:        { name: "float" },
  decimal:      { name: "decimal" },
  datetime:     { name: "datetime" },
  time:         { name: "time" },
  date:         { name: "date" },
  binary:       { name: "blob" },
  boolean:      { name: "boolean" },
  json:         { name: "json" },
}
DEFAULT_PRAGMAS =
{
  "foreign_keys"        => true,
  "journal_mode"        => :wal,
  "synchronous"         => :normal,
  "mmap_size"           => 134217728, # 128 megabytes
  "journal_size_limit"  => 67108864, # 64 megabytes
  "cache_size"          => 2000
}
VIRTUAL_TABLE_REGEX =
/USING\s+(\w+)\s*\((.+)\)/i
FK_REGEX =
/.*FOREIGN KEY\s+\("(\w+)"\)\s+REFERENCES\s+"(\w+)"\s+\("(\w+)"\)/
DEFERRABLE_REGEX =
/DEFERRABLE INITIALLY (\w+)/
TYPE_MAP =
Type::TypeMap.new.tap { |m| initialize_type_map(m) }
EXTENDED_TYPE_MAPS =
Concurrent::Map.new

Constants included from ActiveRecord::ConnectionAdapters::SQLite3::Quoting

ActiveRecord::ConnectionAdapters::SQLite3::Quoting::QUOTED_COLUMN_NAMES, ActiveRecord::ConnectionAdapters::SQLite3::Quoting::QUOTED_TABLE_NAMES

Constants inherited from AbstractAdapter

AbstractAdapter::COMMENT_REGEX, AbstractAdapter::SIMPLE_INT

Constants included from QueryCache

QueryCache::DEFAULT_SIZE

Instance Attribute Summary

Attributes inherited from AbstractAdapter

#lock, #logger, #owner, #pool, #visitor

Attributes included from QueryCache

#query_cache

Attributes included from DatabaseStatements

#transaction_manager

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveRecord::ConnectionAdapters::SQLite3::DatabaseStatements

#begin_db_transaction, #begin_deferred_transaction, #begin_isolated_db_transaction, #commit_db_transaction, #exec_rollback_db_transaction, #execute, #explain, #high_precision_current_timestamp, #reset_isolation_level, #write_query?

Methods included from ActiveRecord::ConnectionAdapters::SQLite3::SchemaStatements

#add_check_constraint, #add_foreign_key, #check_constraints, #create_schema_dumper, #indexes, #remove_check_constraint, #remove_foreign_key, #schema_creation, #virtual_table_exists?

Methods included from ActiveRecord::ConnectionAdapters::SQLite3::Quoting

#quote_default_expression, #quote_string, #quote_table_name_for_assignment, #quoted_binary, #quoted_false, #quoted_time, #quoted_true, #type_cast, #unquoted_false, #unquoted_true

Methods inherited from AbstractAdapter

#adapter_name, #add_enum_value, #advisory_locks_enabled?, #async_enabled?, build_read_query_regexp, #case_insensitive_comparison, #case_sensitive_comparison, #check_if_write_query, #clean!, #clear_cache!, #close, #connect!, #connection_class, #connection_retries, #create_enum, database_exists?, #database_version, #default_index_type?, #default_timezone, #default_uniqueness_comparison, #disable_extension, #discard!, #drop_enum, #enable_extension, #expire, extended_type_map, #extensions, find_cmd_and_exec, #get_advisory_lock, #index_algorithms, #inspect, #lease, #lock_thread=, #prefetch_primary_key?, #prepared_statements?, #prepared_statements_disabled_cache, #preventing_writes?, #raw_connection, #reconnect!, register_class_with_precision, #release_advisory_lock, #rename_enum, #rename_enum_value, #replica?, #retry_deadline, #return_value_after_insert?, #role, #savepoint_errors_invalidate_transactions?, #schema_cache, #schema_version, #seconds_idle, #shard, #steal!, #supports_advisory_locks?, #supports_bulk_alter?, #supports_comments?, #supports_comments_in_create?, #supports_exclusion_constraints?, #supports_extensions?, #supports_foreign_tables?, #supports_index_include?, #supports_indexes_in_create?, #supports_materialized_views?, #supports_nulls_not_distinct?, #supports_optimizer_hints?, #supports_partitioned_indexes?, #supports_restart_db_transaction?, #supports_unique_constraints?, #supports_validate_constraints?, #throw_away!, type_cast_config_to_boolean, type_cast_config_to_integer, #unprepared_statement, #valid_type?, validate_default_timezone, #verify!, #with_instrumenter

Methods included from Savepoints

#create_savepoint, #current_savepoint_name, #exec_rollback_to_savepoint, #release_savepoint

Methods included from QueryCache

#cache, #clear_query_cache, dirties_query_cache, #disable_query_cache!, #enable_query_cache!, included, #query_cache_enabled, #select_all, #uncached

Methods included from DatabaseLimits

#index_name_length, #max_identifier_length, #table_alias_length, #table_name_length

Methods included from Quoting

#cast_bound_value, #lookup_cast_type_from_column, #quote, #quote_column_name, #quote_default_expression, #quote_string, #quote_table_name, #quote_table_name_for_assignment, #quoted_binary, #quoted_date, #quoted_false, #quoted_time, #quoted_true, #sanitize_as_sql_comment, #type_cast, #unquoted_false, #unquoted_true

Methods included from DatabaseStatements

#add_transaction_record, #begin_db_transaction, #begin_deferred_transaction, #begin_isolated_db_transaction, #cacheable_query, #commit_db_transaction, #default_sequence_name, #delete, #empty_insert_statement_value, #exec_delete, #exec_insert, #exec_insert_all, #exec_query, #exec_restart_db_transaction, #exec_rollback_db_transaction, #exec_update, #execute, #explain, #high_precision_current_timestamp, #insert, #insert_fixture, #insert_fixtures_set, #internal_exec_query, #mark_transaction_written_if_write, #query, #query_value, #query_values, #raw_exec_query, #reset_isolation_level, #reset_sequence!, #reset_transaction, #restart_db_transaction, #rollback_db_transaction, #rollback_to_savepoint, #sanitize_limit, #select_all, #select_one, #select_rows, #select_value, #select_values, #to_sql, #transaction, #transaction_isolation_levels, #transaction_open?, #truncate, #truncate_tables, #update, #with_yaml_fallback, #write_query?

Methods included from SchemaStatements

#add_check_constraint, #add_columns, #add_foreign_key, #add_index, #add_index_options, #assume_migrated_upto_version, #build_add_column_definition, #build_change_column_default_definition, #build_create_index_definition, #build_create_join_table_definition, #build_create_table_definition, #bulk_change_table, #change_column_comment, #change_table, #change_table_comment, #check_constraint_exists?, #check_constraint_options, #check_constraints, #column_exists?, #columns, #columns_for_distinct, #create_join_table, #create_schema_dumper, #create_table, #data_source_exists?, #data_sources, #distinct_relation_for_primary_key, #drop_join_table, #drop_table, #dump_schema_information, #foreign_key_column_for, #foreign_key_exists?, #foreign_key_options, #index_algorithm, #index_exists?, #index_name, #index_name_exists?, #indexes, #internal_string_options_for_primary_key, #max_index_name_size, #options_include_default?, #primary_key, #quoted_columns_for_index, #remove_check_constraint, #remove_constraint, #remove_foreign_key, #remove_reference, #remove_timestamps, #rename_index, #schema_creation, #table_alias_for, #table_comment, #table_exists?, #table_options, #tables, #type_to_sql, #update_table_definition, #use_foreign_keys?, #valid_column_definition_options, #valid_primary_key_options, #valid_table_definition_options, #view_exists?, #views

Constructor Details

#initializeSQLite3Adapter

Returns a new instance of SQLite3Adapter.



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 102

def initialize(...)
  super

  @memory_database = false
  case @config[:database].to_s
  when ""
    raise ArgumentError, "No database file specified. Missing argument: database"
  when ":memory:"
    @memory_database = true
  when /\Afile:/
  else
    # Otherwise we have a path relative to Rails.root
    @config[:database] = File.expand_path(@config[:database], Rails.root) if defined?(Rails.root)
    dirname = File.dirname(@config[:database])
    unless File.directory?(dirname)
      begin
        FileUtils.mkdir_p(dirname)
      rescue SystemCallError
        raise ActiveRecord::NoDatabaseError.new(connection_pool: @pool)
      end
    end
  end

  @last_affected_rows = nil
  @previous_read_uncommitted = nil
  @config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)
  @connection_parameters = @config.merge(
    database: @config[:database].to_s,
    results_as_hash: true,
    default_transaction_mode: :immediate,
  )
end

Class Method Details

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



44
45
46
47
48
49
50
51
52
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 44

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

  args << "-#{options[:mode]}" if options[:mode]
  args << "-header" if options[:header]
  args << File.expand_path(config.database, Rails.respond_to?(:root) ? Rails.root : nil)

  find_cmd_and_exec(ActiveRecord.database_cli[:sqlite], *args)
end

.new_client(config) ⇒ Object



34
35
36
37
38
39
40
41
42
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 34

def new_client(config)
  ::SQLite3::Database.new(config[:database].to_s, config)
rescue Errno::ENOENT => error
  if error.message.include?("No such file or directory")
    raise ActiveRecord::NoDatabaseError
  else
    raise
  end
end

Instance Method Details

#add_column(table_name, column_name, type, **options) ⇒ Object

:nodoc:



333
334
335
336
337
338
339
340
341
342
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 333

def add_column(table_name, column_name, type, **options) # :nodoc:
  type = type.to_sym
  if invalid_alter_table_type?(type, options)
    alter_table(table_name) do |definition|
      definition.column(column_name, type, **options)
    end
  else
    super
  end
end

#add_reference(table_name, ref_name, **options) ⇒ Object Also known as: add_belongs_to

:nodoc:



405
406
407
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 405

def add_reference(table_name, ref_name, **options) # :nodoc:
  super(table_name, ref_name, type: :integer, **options)
end

#add_timestamps(table_name, **options) ⇒ Object



392
393
394
395
396
397
398
399
400
401
402
403
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 392

def add_timestamps(table_name, **options)
  options[:null] = false if options[:null].nil?

  if !options.key?(:precision)
    options[:precision] = 6
  end

  alter_table(table_name) do |definition|
    definition.column :created_at, :datetime, **options
    definition.column :updated_at, :datetime, **options
  end
end

#build_insert_sql(insert) ⇒ Object

:nodoc:



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 448

def build_insert_sql(insert) # :nodoc:
  sql = +"INSERT #{insert.into} #{insert.values_list}"

  if insert.skip_duplicates?
    sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
  elsif insert.update_duplicates?
    sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
    if insert.raw_update_sql?
      sql << insert.raw_update_sql
    else
      sql << insert.touch_model_timestamps_unless { |column| "#{column} IS excluded.#{column}" }
      sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
    end
  end

  sql << " RETURNING #{insert.returning}" if insert.returning
  sql
end

#change_column(table_name, column_name, type, **options) ⇒ Object

:nodoc:



380
381
382
383
384
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 380

def change_column(table_name, column_name, type, **options) # :nodoc:
  alter_table(table_name) do |definition|
    definition.change_column(column_name, type, **options)
  end
end

#change_column_default(table_name, column_name, default_or_changes) ⇒ Object

:nodoc:



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

def change_column_default(table_name, column_name, default_or_changes) # :nodoc:
  default = extract_new_default_value(default_or_changes)

  alter_table(table_name) do |definition|
    definition[column_name].default = default
  end
end

#change_column_null(table_name, column_name, null, default = nil) ⇒ Object

:nodoc:



369
370
371
372
373
374
375
376
377
378
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 369

def change_column_null(table_name, column_name, null, default = nil) # :nodoc:
  validate_change_column_null_argument!(null)

  unless null || default.nil?
    internal_exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
  end
  alter_table(table_name) do |definition|
    definition[column_name].null = null
  end
end

#check_all_foreign_keys_valid!Object

:nodoc:



264
265
266
267
268
269
270
271
272
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 264

def check_all_foreign_keys_valid! # :nodoc:
  sql = "PRAGMA foreign_key_check"
  result = execute(sql)

  unless result.blank?
    tables = result.map { |row| row["table"] }
    raise ActiveRecord::StatementInvalid.new("Foreign key violations found: #{tables.join(", ")}", sql: sql, connection_pool: @pool)
  end
end

#check_versionObject

:nodoc:



475
476
477
478
479
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 475

def check_version # :nodoc:
  if database_version < "3.8.0"
    raise "Your version of SQLite (#{database_version}) is too old. Active Record supports SQLite >= 3.8."
  end
end

#connected?Boolean Also known as: active?

Returns:

  • (Boolean)


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

def connected?
  !(@raw_connection.nil? || @raw_connection.closed?)
end

#create_virtual_table(table_name, module_name, values) ⇒ Object

Creates a virtual table

Example:

create_virtual_table :emails, :fts5, ['sender', 'title',' body']


308
309
310
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 308

def create_virtual_table(table_name, module_name, values)
  exec_query "CREATE VIRTUAL TABLE IF NOT EXISTS #{table_name} USING #{module_name} (#{values.join(", ")})"
end

#database_exists?Boolean

Returns:

  • (Boolean)


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

def database_exists?
  @config[:database] == ":memory:" || File.exist?(@config[:database].to_s)
end

#disable_referential_integrityObject

REFERENTIAL INTEGRITY ====================================



250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 250

def disable_referential_integrity # :nodoc:
  old_foreign_keys = query_value("PRAGMA foreign_keys")
  old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys")

  begin
    execute("PRAGMA defer_foreign_keys = ON")
    execute("PRAGMA foreign_keys = OFF")
    yield
  ensure
    execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}")
    execute("PRAGMA foreign_keys = #{old_foreign_keys}")
  end
end

#disconnect!Object

Disconnects from the database if already connected. Otherwise, this method does nothing.



216
217
218
219
220
221
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 216

def disconnect!
  super

  @raw_connection&.close rescue nil
  @raw_connection = nil
end

#drop_virtual_table(table_name, module_name, values, **options) ⇒ Object

Drops a virtual table

Although this command ignores module_name and values, it can be helpful to provide these in a migration’s change method so it can be reverted. In that case, module_name, values and options will be used by #create_virtual_table.



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

def drop_virtual_table(table_name, module_name, values, **options)
  drop_table(table_name)
end

#encodingObject

Returns the current database encoding format as a string, e.g. ‘UTF-8’



232
233
234
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 232

def encoding
  any_raw_connection.encoding.to_s
end

#foreign_keys(table_name) ⇒ Object



412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 412

def foreign_keys(table_name)
  # SQLite returns 1 row for each column of composite foreign keys.
  fk_info = internal_exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
  # Deferred or immediate foreign keys can only be seen in the CREATE TABLE sql
  fk_defs = table_structure_sql(table_name)
              .select do |column_string|
                column_string.start_with?("CONSTRAINT") &&
                column_string.include?("FOREIGN KEY")
              end
              .to_h do |fk_string|
                _, from, table, to = fk_string.match(FK_REGEX).to_a
                _, mode = fk_string.match(DEFERRABLE_REGEX).to_a
                deferred = mode&.downcase&.to_sym || false
                [[table, from, to], deferred]
              end

  grouped_fk = fk_info.group_by { |row| row["id"] }.values.each { |group| group.sort_by! { |row| row["seq"] } }
  grouped_fk.map do |group|
    row = group.first
    options = {
      on_delete: extract_foreign_key_action(row["on_delete"]),
      on_update: extract_foreign_key_action(row["on_update"]),
      deferrable: fk_defs[[row["table"], row["from"], row["to"]]]
    }

    if group.one?
      options[:column] = row["from"]
      options[:primary_key] = row["to"]
    else
      options[:column] = group.map { |row| row["from"] }
      options[:primary_key] = group.map { |row| row["to"] }
    end
    ForeignKeyDefinition.new(table_name, row["table"], options)
  end
end

#get_database_versionObject

:nodoc:



471
472
473
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 471

def get_database_version # :nodoc:
  SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)", "SCHEMA"))
end

#native_database_typesObject

:nodoc:



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

def native_database_types # :nodoc:
  NATIVE_DATABASE_TYPES
end

#primary_keys(table_name) ⇒ Object

SCHEMA STATEMENTS ========================================



276
277
278
279
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 276

def primary_keys(table_name) # :nodoc:
  pks = table_structure(table_name).select { |f| f["pk"] > 0 }
  pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
end

#remove_column(table_name, column_name, type = nil, **options) ⇒ Object

:nodoc:



344
345
346
347
348
349
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 344

def remove_column(table_name, column_name, type = nil, **options) # :nodoc:
  alter_table(table_name) do |definition|
    definition.remove_column column_name
    definition.foreign_keys.delete_if { |fk| fk.column == column_name.to_s }
  end
end

#remove_columns(table_name, *column_names, type: nil, **options) ⇒ Object

:nodoc:



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

def remove_columns(table_name, *column_names, type: nil, **options) # :nodoc:
  alter_table(table_name) do |definition|
    column_names.each do |column_name|
      definition.remove_column column_name
    end
    column_names = column_names.map(&:to_s)
    definition.foreign_keys.delete_if { |fk| column_names.include?(fk.column) }
  end
end

#remove_index(table_name, column_name = nil, **options) ⇒ Object

:nodoc:



281
282
283
284
285
286
287
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 281

def remove_index(table_name, column_name = nil, **options) # :nodoc:
  return if options[:if_exists] && !index_exists?(table_name, column_name, **options)

  index_name = index_name_for_remove(table_name, column_name, options)

  exec_query "DROP INDEX #{quote_column_name(index_name)}"
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



386
387
388
389
390
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 386

def rename_column(table_name, column_name, new_column_name) # :nodoc:
  column = column_for(table_name, column_name)
  alter_table(table_name, rename: { column.name => new_column_name.to_s })
  rename_column_indexes(table_name, column.name, new_column_name)
end

#rename_table(table_name, new_name, **options) ⇒ Object

Renames a table.

Example:

rename_table('octopuses', 'octopi')


325
326
327
328
329
330
331
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 325

def rename_table(table_name, new_name, **options)
  validate_table_length!(new_name) unless options[:_uses_legacy_table_name]
  schema_cache.clear_data_source_cache!(table_name.to_s)
  schema_cache.clear_data_source_cache!(new_name.to_s)
  exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
  rename_table_indexes(table_name, new_name, **options)
end

#requires_reloading?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 159

def requires_reloading?
  true
end

#shared_cache?Boolean

:nodoc:

Returns:

  • (Boolean)


467
468
469
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 467

def shared_cache? # :nodoc:
  @config.fetch(:flags, 0).anybits?(::SQLite3::Constants::Open::SHAREDCACHE)
end

#strict_strings_by_defaultObject

:singleton-method: Configure the SQLite3Adapter to be used in a strict strings mode. This will disable double-quoted string literals, because otherwise typos can silently go unnoticed. For example, it is possible to create an index for a non existing column. If you wish to enable this mode you can add the following line to your application.rb file:

config.active_record.sqlite3_adapter_strict_strings_by_default = true


67
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 67

class_attribute :strict_strings_by_default, default: false

#supports_check_constraints?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 167

def supports_check_constraints?
  true
end

#supports_common_table_expressions?Boolean

Returns:

  • (Boolean)


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

def supports_common_table_expressions?
  database_version >= "3.8.3"
end

#supports_concurrent_connections?Boolean

Returns:

  • (Boolean)


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

def supports_concurrent_connections?
  !@memory_database
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 175

def supports_datetime_with_precision?
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


139
140
141
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 139

def supports_ddl_transactions?
  true
end

#supports_deferrable_constraints?Boolean

Returns:

  • (Boolean)


244
245
246
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 244

def supports_deferrable_constraints?
  true
end

#supports_explain?Boolean

Returns:

  • (Boolean)


236
237
238
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 236

def supports_explain?
  true
end

#supports_expression_index?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 155

def supports_expression_index?
  database_version >= "3.9.0"
end

#supports_foreign_keys?Boolean

Returns:

  • (Boolean)


163
164
165
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 163

def supports_foreign_keys?
  true
end

#supports_index_sort_order?Boolean

Returns:

  • (Boolean)


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

def supports_index_sort_order?
  true
end

#supports_insert_on_conflict?Boolean Also known as: supports_insert_on_duplicate_skip?, supports_insert_on_duplicate_update?, supports_insert_conflict_target?

Returns:

  • (Boolean)


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

def supports_insert_on_conflict?
  database_version >= "3.24.0"
end

#supports_insert_returning?Boolean

Returns:

  • (Boolean)


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

def supports_insert_returning?
  database_version >= "3.35.0"
end

#supports_json?Boolean

Returns:

  • (Boolean)


179
180
181
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 179

def supports_json?
  true
end

#supports_lazy_transactions?Boolean

Returns:

  • (Boolean)


240
241
242
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 240

def supports_lazy_transactions?
  true
end

#supports_partial_index?Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 151

def supports_partial_index?
  true
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 143

def supports_savepoints?
  true
end

#supports_transaction_isolation?Boolean

Returns:

  • (Boolean)


147
148
149
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 147

def supports_transaction_isolation?
  true
end

#supports_views?Boolean

Returns:

  • (Boolean)


171
172
173
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 171

def supports_views?
  true
end

#supports_virtual_columns?Boolean

Returns:

  • (Boolean)


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

def supports_virtual_columns?
  database_version >= "3.31.0"
end

#virtual_tablesObject

Returns a list of defined virtual tables



292
293
294
295
296
297
298
299
300
301
302
# File 'lib/active_record/connection_adapters/sqlite3_adapter.rb', line 292

def virtual_tables
  query = <<~SQL
    SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL %';
  SQL

  exec_query(query, "SCHEMA").cast_values.each_with_object({}) do |row, memo|
    table_name, sql = row[0], row[1]
    _, module_name, arguments = sql.match(VIRTUAL_TABLE_REGEX).to_a
    memo[table_name] = [module_name, arguments]
  end.to_a
end