Class: ActiveRecord::ConnectionAdapters::SQLite3Adapter

Inherits:
AbstractAdapter show all
Defined in:
activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb

Overview

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

Options:

  • :database - Path to the database file.

Defined Under Namespace

Classes: BindSubstitution, ExplainPrettyPrinter, StatementPool, Version

Constant Summary

Constants inherited from AbstractAdapter

AbstractAdapter::SIMPLE_INT

Constants included from ActiveSupport::Callbacks

ActiveSupport::Callbacks::CALLBACK_FILTER_TYPES

Instance Attribute Summary

Attributes inherited from AbstractAdapter

#in_use, #last_use, #logger, #pool, #schema_cache, #visitor

Attributes included from QueryCache

#query_cache, #query_cache_enabled

Instance Method Summary collapse

Methods inherited from AbstractAdapter

#case_insensitive_comparison, #case_sensitive_modifier, #close, #current_savepoint_name, #disable_referential_integrity, #expire, #extensions, #index_algorithms, #lease, #open_transactions, #prefetch_primary_key?, #raw_connection, #reconnect!, #reset!, #schema_creation, #substitute_at, #supports_bulk_alter?, #supports_extensions?, #supports_partial_index?, #supports_transaction_isolation?, type_cast_config_to_boolean, type_cast_config_to_integer, #unprepared_statement, #unprepared_visitor, #valid_type?, #verify!

Methods included from ColumnDumper

#column_spec, #migration_keys, #prepare_column_options

Methods included from ActiveSupport::Callbacks

#run_callbacks

Methods included from ActiveSupport::Concern

#append_features, extended, #included

Methods included from QueryCache

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

Methods included from DatabaseLimits

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

Methods included from Quoting

#quote_table_name, #quoted_false, #quoted_true

Methods included from DatabaseStatements

#add_transaction_record, #begin_isolated_db_transaction, #begin_transaction, #case_sensitive_equality_operator, #commit_transaction, #current_transaction, #default_sequence_name, #delete, #empty_insert_statement_value, #exec_insert, #insert, #insert_fixture, #join_to_delete, #join_to_update, #limited_update_conditions, #reset_sequence!, #reset_transaction, #rollback_transaction, #sanitize_limit, #select_all, #select_one, #select_value, #select_values, #to_sql, #transaction, #transaction_isolation_levels, #transaction_open?, #update, #within_new_transaction

Methods included from SchemaStatements

#add_index, #add_reference, #add_timestamps, #assume_migrated_upto_version, #change_table, #column_exists?, #columns_for_distinct, #create_join_table, #create_table, #drop_join_table, #drop_table, #dump_schema_information, #index_exists?, #index_name, #index_name_exists?, #initialize_schema_migrations_table, #remove_columns, #remove_index, #remove_reference, #remove_timestamps, #rename_index, #table_alias_for, #type_to_sql

Constructor Details

#initialize(connection, logger, config) ⇒ SQLite3Adapter

Returns a new instance of SQLite3Adapter


105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 105

def initialize(connection, logger, config)
  super(connection, logger)

  @active     = nil
  @statements = StatementPool.new(@connection,
                                  self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
  @config = config

  if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
    @visitor = Arel::Visitors::SQLite.new self
  else
    @visitor = unprepared_visitor
  end
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)

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

def active?
  @active != false
end

#adapter_nameObject

:nodoc:


120
121
122
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 120

def adapter_name #:nodoc:
  'SQLite'
end

#add_column(table_name, column_name, type, options = {}) ⇒ Object

:nodoc:


449
450
451
452
453
454
455
456
457
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 449

def add_column(table_name, column_name, type, options = {}) #:nodoc:
  if supports_add_column? && valid_alter_table_options( type, options )
    super(table_name, column_name, type, options)
  else
    alter_table(table_name) do |definition|
      definition.column(column_name, type, options)
    end
  end
end

#allowed_index_name_lengthObject

Returns 62. SQLite supports index names up to 64 characters. The rest is used by rails internally to perform temporary rename operations


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

def allowed_index_name_length
  index_name_length - 2
end

#begin_db_transactionObject

:nodoc:


363
364
365
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 363

def begin_db_transaction #:nodoc:
  log('begin transaction',nil) { @connection.transaction }
end

#change_column(table_name, column_name, type, options = {}) ⇒ Object

:nodoc:


480
481
482
483
484
485
486
487
488
489
490
491
492
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 480

def change_column(table_name, column_name, type, options = {}) #:nodoc:
  alter_table(table_name) do |definition|
    include_default = options_include_default?(options)
    definition[column_name].instance_eval do
      self.type    = type
      self.limit   = options[:limit] if options.include?(:limit)
      self.default = options[:default] if include_default
      self.null    = options[:null] if options.include?(:null)
      self.precision = options[:precision] if options.include?(:precision)
      self.scale   = options[:scale] if options.include?(:scale)
    end
  end
end

#change_column_default(table_name, column_name, default) ⇒ Object

:nodoc:


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

def change_column_default(table_name, column_name, default) #:nodoc:
  alter_table(table_name) do |definition|
    definition[column_name].default = default
  end
end

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


471
472
473
474
475
476
477
478
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 471

def change_column_null(table_name, column_name, null, default = nil)
  unless null || default.nil?
    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

#clear_cache!Object

Clears the prepared statements cache.


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

def clear_cache!
  @statements.clear
end

#columns(table_name) ⇒ Object

Returns an array of SQLite3Column objects for the table specified by table_name.


395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 395

def columns(table_name) #:nodoc:
  table_structure(table_name).map do |field|
    case field["dflt_value"]
    when /^null$/i
      field["dflt_value"] = nil
    when /^'(.*)'$/m
      field["dflt_value"] = $1.gsub("''", "'")
    when /^"(.*)"$/m
      field["dflt_value"] = $1.gsub('""', '"')
    end

    SQLite3Column.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0)
  end
end

#commit_db_transactionObject

:nodoc:


367
368
369
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 367

def commit_db_transaction #:nodoc:
  log('commit transaction',nil) { @connection.commit }
end

#create_savepointObject


351
352
353
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 351

def create_savepoint
  execute("SAVEPOINT #{current_savepoint_name}")
end

#delete_sql(sql, name = nil) ⇒ Object

:nodoc:


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

def delete_sql(sql, name = nil) #:nodoc:
  sql += " WHERE 1=1" unless sql =~ /WHERE/i
  super sql, name
end

#disconnect!Object

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


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

def disconnect!
  super
  @active = false
  @connection.close rescue nil
end

#encodingObject

Returns the current database encoding format as a string, eg: 'UTF-8'


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

def encoding
  @connection.encoding.to_s
end

#exec_delete(sql, name = 'SQL', binds = []) ⇒ Object Also known as: exec_update


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

def exec_delete(sql, name = 'SQL', binds = [])
  exec_query(sql, name, binds)
  @connection.changes
end

#exec_query(sql, name = nil, binds = []) ⇒ Object


291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 291

def exec_query(sql, name = nil, binds = [])
  log(sql, name, binds) do

    # Don't cache statements without bind values
    if binds.empty?
      stmt    = @connection.prepare(sql)
      cols    = stmt.columns
      records = stmt.to_a
      stmt.close
      stmt = records
    else
      cache = @statements[sql] ||= {
        :stmt => @connection.prepare(sql)
      }
      stmt = cache[:stmt]
      cols = cache[:cols] ||= stmt.columns
      stmt.reset!
      stmt.bind_params binds.map { |col, val|
        type_cast(val, col)
      }
    end

    ActiveRecord::Result.new(cols, stmt.to_a)
  end
end

#execute(sql, name = nil) ⇒ Object

:nodoc:


327
328
329
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 327

def execute(sql, name = nil) #:nodoc:
  log(sql, name) { @connection.execute(sql) }
end

#explain(arel, binds = []) ⇒ Object

DATABASE STATEMENTS ======================================


272
273
274
275
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 272

def explain(arel, binds = [])
  sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
  ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', binds))
end

#indexes(table_name, name = nil) ⇒ Object

Returns an array of indexes for the given table.


411
412
413
414
415
416
417
418
419
420
421
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 411

def indexes(table_name, name = nil) #:nodoc:
  exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", 'SCHEMA').map do |row|
    IndexDefinition.new(
      table_name,
      row['name'],
      row['unique'] != 0,
      exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
        col['name']
      })
  end
end

#insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) ⇒ Object Also known as: create

:nodoc:


341
342
343
344
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 341

def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
  super
  id_value || @connection.last_insert_row_id
end

#last_inserted_id(result) ⇒ Object


323
324
325
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 323

def last_inserted_id(result)
  @connection.last_insert_row_id
end

#native_database_typesObject

:nodoc:


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 197

def native_database_types #:nodoc:
  {
    :primary_key => default_primary_key_type,
    :string      => { :name => "varchar", :limit => 255 },
    :text        => { :name => "text" },
    :integer     => { :name => "integer" },
    :float       => { :name => "float" },
    :decimal     => { :name => "decimal" },
    :datetime    => { :name => "datetime" },
    :timestamp   => { :name => "datetime" },
    :time        => { :name => "time" },
    :date        => { :name => "date" },
    :binary      => { :name => "blob" },
    :boolean     => { :name => "boolean" }
  }
end

#primary_key(table_name) ⇒ Object

:nodoc:


423
424
425
426
427
428
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 423

def primary_key(table_name) #:nodoc:
  column = table_structure(table_name).find { |field|
    field['pk'] == 1
  }
  column && column['name']
end

#quote(value, column = nil) ⇒ Object

QUOTING ==================================================


226
227
228
229
230
231
232
233
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 226

def quote(value, column = nil)
  if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary)
    s = column.class.string_to_binary(value).unpack("H*")[0]
    "x'#{s}'"
  else
    super
  end
end

#quote_column_name(name) ⇒ Object

:nodoc:


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

def quote_column_name(name) #:nodoc:
  %Q("#{name.to_s.gsub('"', '""')}")
end

#quote_string(s) ⇒ Object

:nodoc:


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

def quote_string(s) #:nodoc:
  @connection.class.quote(s)
end

#quote_table_name_for_assignment(table, attr) ⇒ Object


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

def quote_table_name_for_assignment(table, attr)
  quote_column_name(attr)
end

#quoted_date(value) ⇒ Object

Quote date/time values for use in SQL input. Includes microseconds if the value is a Time responding to usec.


249
250
251
252
253
254
255
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 249

def quoted_date(value) #:nodoc:
  if value.respond_to?(:usec)
    "#{super}.#{sprintf("%06d", value.usec)}"
  else
    super
  end
end

#release_savepointObject


359
360
361
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 359

def release_savepoint
  execute("RELEASE SAVEPOINT #{current_savepoint_name}")
end

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

:nodoc:


459
460
461
462
463
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 459

def remove_column(table_name, column_name, type = nil, options = {}) #:nodoc:
  alter_table(table_name) do |definition|
    definition.remove_column column_name
  end
end

#remove_index!(table_name, index_name) ⇒ Object

:nodoc:


430
431
432
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 430

def remove_index!(table_name, index_name) #:nodoc:
  exec_query "DROP INDEX #{quote_column_name(index_name)}"
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:


494
495
496
497
498
499
500
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 494

def rename_column(table_name, column_name, new_column_name) #:nodoc:
  unless columns(table_name).detect{|c| c.name == column_name.to_s }
    raise ActiveRecord::ActiveRecordError, "Missing column #{table_name}.#{column_name}"
  end
  alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
  rename_column_indexes(table_name, column_name, new_column_name)
end

#rename_table(table_name, new_name) ⇒ Object

Renames a table.

Example:

rename_table('octopuses', 'octopi')

438
439
440
441
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 438

def rename_table(table_name, new_name)
  exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
  rename_table_indexes(table_name, new_name)
end

#requires_reloading?Boolean

Returns:

  • (Boolean)

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

def requires_reloading?
  true
end

#rollback_db_transactionObject

:nodoc:


371
372
373
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 371

def rollback_db_transaction #:nodoc:
  log('rollback transaction',nil) { @connection.rollback }
end

#rollback_to_savepointObject


355
356
357
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 355

def rollback_to_savepoint
  execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
end

#select_rows(sql, name = nil) ⇒ Object


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

def select_rows(sql, name = nil)
  exec_query(sql, name).rows
end

#supports_add_column?Boolean

Returns true

Returns:

  • (Boolean)

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

def supports_add_column?
  true
end

#supports_autoincrement?Boolean

Returns true

Returns:

  • (Boolean)

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

def supports_autoincrement? #:nodoc:
  true
end

#supports_count_distinct?Boolean

Returns true

Returns:

  • (Boolean)

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

def supports_count_distinct? #:nodoc:
  true
end

#supports_ddl_transactions?Boolean

Returns true

Returns:

  • (Boolean)

125
126
127
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 125

def supports_ddl_transactions?
  true
end

#supports_explain?Boolean

Returns true.

Returns:

  • (Boolean)

220
221
222
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 220

def supports_explain?
  true
end

#supports_index_sort_order?Boolean

Returns:

  • (Boolean)

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

def supports_index_sort_order?
  true
end

#supports_migrations?Boolean

Returns true, since this connection adapter supports migrations.

Returns:

  • (Boolean)

141
142
143
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 141

def supports_migrations? #:nodoc:
  true
end

#supports_primary_key?Boolean

Returns true.

Returns:

  • (Boolean)

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

def supports_primary_key? #:nodoc:
  true
end

#supports_savepoints?Boolean

Returns true if SQLite version is '3.6.8' or greater, false otherwise.

Returns:

  • (Boolean)

130
131
132
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 130

def supports_savepoints?
  sqlite_version >= '3.6.8'
end

#supports_statement_cache?Boolean

Returns true, since this connection adapter supports prepared statement caching.

Returns:

  • (Boolean)

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

def supports_statement_cache?
  true
end

#table_exists?(table_name) ⇒ Boolean

Returns:

  • (Boolean)

390
391
392
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 390

def table_exists?(table_name)
  table_name && tables(nil, table_name).any?
end

#tables(name = nil, table_name = nil) ⇒ Object

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


377
378
379
380
381
382
383
384
385
386
387
388
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 377

def tables(name = nil, table_name = nil) #:nodoc:
  sql = <<-SQL
    SELECT name
    FROM sqlite_master
    WHERE type = 'table' AND NOT name = 'sqlite_sequence'
  SQL
  sql << " AND name = #{quote_table_name(table_name)}" if table_name

  exec_query(sql, 'SCHEMA').map do |row|
    row['name']
  end
end

#type_cast(value, column) ⇒ Object

:nodoc:


257
258
259
260
261
262
263
264
265
266
267
268
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 257

def type_cast(value, column) # :nodoc:
  return value.to_f if BigDecimal === value
  return super unless String === value
  return super unless column && value

  value = super
  if column.type == :string && value.encoding == Encoding::ASCII_8BIT
    logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger
    value = value.encode Encoding::UTF_8
  end
  value
end

#update_sql(sql, name = nil) ⇒ Object

:nodoc:


331
332
333
334
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 331

def update_sql(sql, name = nil) #:nodoc:
  super
  @connection.changes
end

#valid_alter_table_options(type, options) ⇒ Object

See: www.sqlite.org/lang_altertable.html SQLite has an additional restriction on the ALTER TABLE statement


445
446
447
# File 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb', line 445

def valid_alter_table_options( type, options)
  type.to_sym != :primary_key
end