Module: ArJdbc::SQLite3

Includes:
ActiveRecord::ConnectionAdapters::SQLite3::Quoting, ActiveRecord::ConnectionAdapters::SQLite3::SchemaStatements
Included in:
ActiveRecord::ConnectionAdapters::SQLite3Adapter
Defined in:
lib/arjdbc/sqlite3/adapter.rb

Overview

All the code in this module is a copy of ConnectionAdapters::SQLite3Adapter from active_record 5. The constants at the front of this file are to allow the rest of the file to remain with no modifications from its original source. If you hack on this file try not to modify this module and instead try and put those overrides in SQL3Adapter below. We try and keep a copy of the Rails this adapter supports with the current goal of being able to diff changes easily over time and to also eventually remove this module from ARJDBC altogether.

Defined Under Namespace

Classes: SQLite3Integer

Constant Summary collapse

ConnectionAdapters =

DIFFERENCE: Some common constant names to reduce differences in rest of this module from AR5 version

::ActiveRecord::ConnectionAdapters
IndexDefinition =
::ActiveRecord::ConnectionAdapters::IndexDefinition
Quoting =
::ActiveRecord::ConnectionAdapters::SQLite3::Quoting
RecordNotUnique =
::ActiveRecord::RecordNotUnique
SchemaCreation =
ConnectionAdapters::SQLite3::SchemaCreation
SQLite3Adapter =
ConnectionAdapters::AbstractAdapter
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" },
}

Instance Method Summary collapse

Instance Method Details

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

:nodoc:



222
223
224
225
226
227
228
229
230
# File 'lib/arjdbc/sqlite3/adapter.rb', line 222

def add_column(table_name, column_name, type, options = {}) #:nodoc:
  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:



278
279
280
# File 'lib/arjdbc/sqlite3/adapter.rb', line 278

def add_reference(table_name, ref_name, **options) # :nodoc:
  super(table_name, ref_name, type: :integer, **options)
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



120
121
122
# File 'lib/arjdbc/sqlite3/adapter.rb', line 120

def allowed_index_name_length
  index_name_length - 2
end

#begin_db_transactionObject

DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements def execute(sql, name = nil) #:nodoc:



189
190
191
# File 'lib/arjdbc/sqlite3/adapter.rb', line 189

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

#build_insert_sql(insert) ⇒ Object

:nodoc:



309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/arjdbc/sqlite3/adapter.rb', line 309

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 "
    sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
  end

  sql
end

#build_truncate_statement(table_name) ⇒ Object



326
327
328
# File 'lib/arjdbc/sqlite3/adapter.rb', line 326

def build_truncate_statement(table_name)
  "DELETE FROM #{quote_table_name(table_name)}"
end

#build_truncate_statements(*table_names) ⇒ Object



330
331
332
# File 'lib/arjdbc/sqlite3/adapter.rb', line 330

def build_truncate_statements(*table_names)
  table_names.flatten.map { |table_name| build_truncate_statement table_name }
end

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

:nodoc:



258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/arjdbc/sqlite3/adapter.rb', line 258

def change_column(table_name, column_name, type, options = {}) #:nodoc:
  alter_table(table_name) do |definition|
    definition[column_name].instance_eval do
      self.type    = type
      self.limit   = options[:limit] if options.include?(:limit)
      self.default = options[:default] if options.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)
      self.collation = options[:collation] if options.include?(:collation)
    end
  end
end

#change_column_default(table_name, column_name, default_or_changes) ⇒ Object

:nodoc:



241
242
243
244
245
246
247
# File 'lib/arjdbc/sqlite3/adapter.rb', line 241

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:



249
250
251
252
253
254
255
256
# File 'lib/arjdbc/sqlite3/adapter.rb', line 249

def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
  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

#check_versionObject



339
340
341
342
343
# File 'lib/arjdbc/sqlite3/adapter.rb', line 339

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

#commit_db_transactionObject

:nodoc:



193
194
195
# File 'lib/arjdbc/sqlite3/adapter.rb', line 193

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

#disable_referential_integrityObject

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



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/arjdbc/sqlite3/adapter.rb', line 143

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

#encodingObject

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



129
130
131
# File 'lib/arjdbc/sqlite3/adapter.rb', line 129

def encoding
  @connection.encoding.to_s
end

#exec_rollback_db_transactionObject

:nodoc:



197
198
199
# File 'lib/arjdbc/sqlite3/adapter.rb', line 197

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

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



170
171
172
173
174
# File 'lib/arjdbc/sqlite3/adapter.rb', line 170

def explain(arel, binds = [])
  sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
  # DIFFERENCE: FQN
  ::ActiveRecord::ConnectionAdapters::SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
end

#foreign_keys(table_name) ⇒ Object



283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/arjdbc/sqlite3/adapter.rb', line 283

def foreign_keys(table_name)
  fk_info = exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
  fk_info.map do |row|
    options = {
      column: row["from"],
      primary_key: row["to"],
      on_delete: extract_foreign_key_action(row["on_delete"]),
      on_update: extract_foreign_key_action(row["on_update"])
    }
    # DIFFERENCE: FQN
    ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, row["table"], options)
  end
end

#get_database_versionObject

:nodoc:



322
323
324
# File 'lib/arjdbc/sqlite3/adapter.rb', line 322

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

#initialize(connection, logger, connection_options, config) ⇒ Object

DIFFERENCE: class_attribute in original adapter is moved down to our section which is a class since we cannot define it here in the module (original source this is a class).



59
60
61
62
# File 'lib/arjdbc/sqlite3/adapter.rb', line 59

def initialize(connection, logger, connection_options, config)
  super(connection, logger, config)
  configure_connection
end

#insert_fixtures_set(fixture_set, tables_to_delete = []) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
# File 'lib/arjdbc/sqlite3/adapter.rb', line 297

def insert_fixtures_set(fixture_set, tables_to_delete = [])
  disable_referential_integrity do
    transaction(requires_new: true) do
      tables_to_delete.each { |table| delete "DELETE FROM #{quote_table_name(table)}", "Fixture Delete" }

      fixture_set.each do |table_name, rows|
        rows.each { |row| insert_fixture(row, table_name) }
      end
    end
  end
end

#last_inserted_id(result) ⇒ Object

DIFFERENCE: implemented in ArJdbc::Abstract::DatabaseStatements def exec_delete(sql, name = "SQL", binds = [])



182
183
184
# File 'lib/arjdbc/sqlite3/adapter.rb', line 182

def last_inserted_id(result)
  @connection.last_insert_row_id
end

#native_database_typesObject

:nodoc:



124
125
126
# File 'lib/arjdbc/sqlite3/adapter.rb', line 124

def native_database_types #:nodoc:
  NATIVE_DATABASE_TYPES
end

#primary_keys(table_name) ⇒ Object

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



203
204
205
206
# File 'lib/arjdbc/sqlite3/adapter.rb', line 203

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:



232
233
234
235
236
237
238
239
# File 'lib/arjdbc/sqlite3/adapter.rb', line 232

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 do |_, fk_options|
      fk_options[:column] == column_name.to_s
    end
  end
end

#remove_index(table_name, options = {}) ⇒ Object

:nodoc:



208
209
210
211
# File 'lib/arjdbc/sqlite3/adapter.rb', line 208

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

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



272
273
274
275
276
# File 'lib/arjdbc/sqlite3/adapter.rb', line 272

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) ⇒ Object

Renames a table.

Example: rename_table('octopuses', 'octopi')



217
218
219
220
# File 'lib/arjdbc/sqlite3/adapter.rb', line 217

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)


80
81
82
# File 'lib/arjdbc/sqlite3/adapter.rb', line 80

def requires_reloading?
  true
end

#supports_common_table_expressions?Boolean

Returns:

  • (Boolean)


100
101
102
# File 'lib/arjdbc/sqlite3/adapter.rb', line 100

def supports_common_table_expressions?
  database_version >= "3.8.3"
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


92
93
94
# File 'lib/arjdbc/sqlite3/adapter.rb', line 92

def supports_datetime_with_precision?
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/arjdbc/sqlite3/adapter.rb', line 64

def supports_ddl_transactions?
  true
end

#supports_explain?Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/arjdbc/sqlite3/adapter.rb', line 133

def supports_explain?
  true
end

#supports_expression_index?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/arjdbc/sqlite3/adapter.rb', line 76

def supports_expression_index?
  database_version >= "3.9.0"
end

#supports_foreign_keys?Boolean

Returns:

  • (Boolean)


84
85
86
# File 'lib/arjdbc/sqlite3/adapter.rb', line 84

def supports_foreign_keys?
  true
end

#supports_index_sort_order?Boolean

DIFFERENCE: active?, reconnect!, disconnect! handles by arjdbc core

Returns:

  • (Boolean)


113
114
115
# File 'lib/arjdbc/sqlite3/adapter.rb', line 113

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)


104
105
106
# File 'lib/arjdbc/sqlite3/adapter.rb', line 104

def supports_insert_on_conflict?
  database_version >= "3.24.0"
end

#supports_json?Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/arjdbc/sqlite3/adapter.rb', line 96

def supports_json?
  true
end

#supports_lazy_transactions?Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/arjdbc/sqlite3/adapter.rb', line 137

def supports_lazy_transactions?
  true
end

#supports_partial_index?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/arjdbc/sqlite3/adapter.rb', line 72

def supports_partial_index?
  database_version >= "3.9.0"
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/arjdbc/sqlite3/adapter.rb', line 68

def supports_savepoints?
  true
end

#supports_views?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/arjdbc/sqlite3/adapter.rb', line 88

def supports_views?
  true
end

#truncate(table_name, name = nil) ⇒ Object



334
335
336
337
# File 'lib/arjdbc/sqlite3/adapter.rb', line 334

def truncate(table_name, name = nil)
  ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
  execute(build_truncate_statement(table_name), name)
end

#write_query?(sql) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


166
167
168
# File 'lib/arjdbc/sqlite3/adapter.rb', line 166

def write_query?(sql) # :nodoc:
  !READ_QUERY.match?(sql)
end