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.

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:



255
256
257
258
259
260
261
262
263
# File 'lib/arjdbc/sqlite3/adapter.rb', line 255

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:



306
307
308
# File 'lib/arjdbc/sqlite3/adapter.rb', line 306

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

#begin_db_transactionObject

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



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

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

#build_insert_sql(insert) ⇒ Object

:nodoc:



337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/arjdbc/sqlite3/adapter.rb', line 337

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

  sql
end

#build_truncate_statement(table_name) ⇒ Object



359
360
361
# File 'lib/arjdbc/sqlite3/adapter.rb', line 359

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

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

:nodoc:



291
292
293
294
295
296
297
298
# File 'lib/arjdbc/sqlite3/adapter.rb', line 291

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.options.merge!(options)
    end
  end
end

#change_column_default(table_name, column_name, default_or_changes) ⇒ Object

:nodoc:



274
275
276
277
278
279
280
# File 'lib/arjdbc/sqlite3/adapter.rb', line 274

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:



282
283
284
285
286
287
288
289
# File 'lib/arjdbc/sqlite3/adapter.rb', line 282

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



363
364
365
366
367
# File 'lib/arjdbc/sqlite3/adapter.rb', line 363

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:



221
222
223
# File 'lib/arjdbc/sqlite3/adapter.rb', line 221

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

#disable_referential_integrityObject

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



171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/arjdbc/sqlite3/adapter.rb', line 171

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'



157
158
159
# File 'lib/arjdbc/sqlite3/adapter.rb', line 157

def encoding
  @connection.encoding.to_s
end

#exec_rollback_db_transactionObject

:nodoc:



225
226
227
# File 'lib/arjdbc/sqlite3/adapter.rb', line 225

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

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



198
199
200
201
202
# File 'lib/arjdbc/sqlite3/adapter.rb', line 198

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



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

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:



355
356
357
# File 'lib/arjdbc/sqlite3/adapter.rb', line 355

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).



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

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

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



325
326
327
328
329
330
331
332
333
334
335
# File 'lib/arjdbc/sqlite3/adapter.rb', line 325

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 = [])



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

def last_inserted_id(result)
  @connection.last_insert_row_id
end

#native_database_typesObject

:nodoc:



152
153
154
# File 'lib/arjdbc/sqlite3/adapter.rb', line 152

def native_database_types #:nodoc:
  NATIVE_DATABASE_TYPES
end

#primary_keys(table_name) ⇒ Object

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



231
232
233
234
# File 'lib/arjdbc/sqlite3/adapter.rb', line 231

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:



265
266
267
268
269
270
271
272
# File 'lib/arjdbc/sqlite3/adapter.rb', line 265

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, column_name = nil, **options) ⇒ Object

:nodoc:



236
237
238
239
240
241
242
# File 'lib/arjdbc/sqlite3/adapter.rb', line 236

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:



300
301
302
303
304
# File 'lib/arjdbc/sqlite3/adapter.rb', line 300

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')



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

def rename_table(table_name, new_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)
end

#requires_reloading?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/arjdbc/sqlite3/adapter.rb', line 111

def requires_reloading?
  true
end

#shared_cache?Boolean

Returns:

  • (Boolean)


351
352
353
# File 'lib/arjdbc/sqlite3/adapter.rb', line 351

def shared_cache?
  config[:properties] && config[:properties][:shared_cache] == true
end

#supports_check_constraints?Boolean

Returns:

  • (Boolean)


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

def supports_check_constraints?
  true
end

#supports_common_table_expressions?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'lib/arjdbc/sqlite3/adapter.rb', line 135

def supports_common_table_expressions?
  database_version >= "3.8.3"
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/arjdbc/sqlite3/adapter.rb', line 127

def supports_datetime_with_precision?
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


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

def supports_ddl_transactions?
  true
end

#supports_explain?Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/arjdbc/sqlite3/adapter.rb', line 161

def supports_explain?
  true
end

#supports_expression_index?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/arjdbc/sqlite3/adapter.rb', line 107

def supports_expression_index?
  database_version >= "3.9.0"
end

#supports_foreign_keys?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/arjdbc/sqlite3/adapter.rb', line 115

def supports_foreign_keys?
  true
end

#supports_index_sort_order?Boolean

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

Returns:

  • (Boolean)


148
149
150
# File 'lib/arjdbc/sqlite3/adapter.rb', line 148

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)


139
140
141
# File 'lib/arjdbc/sqlite3/adapter.rb', line 139

def supports_insert_on_conflict?
  database_version >= "3.24.0"
end

#supports_json?Boolean

Returns:

  • (Boolean)


131
132
133
# File 'lib/arjdbc/sqlite3/adapter.rb', line 131

def supports_json?
  true
end

#supports_lazy_transactions?Boolean

Returns:

  • (Boolean)


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

def supports_lazy_transactions?
  true
end

#supports_partial_index?Boolean

Returns:

  • (Boolean)


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

def supports_partial_index?
  database_version >= "3.9.0"
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


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

def supports_savepoints?
  true
end

#supports_transaction_isolation?Boolean

Returns:

  • (Boolean)


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

def supports_transaction_isolation?
  true
end

#supports_views?Boolean

Returns:

  • (Boolean)


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

def supports_views?
  true
end

#write_query?(sql) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


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

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