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, StatementPool

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'.freeze
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

#active?Boolean

Returns:

  • (Boolean)


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

def active?
  @active
end

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

deprecate :valid_alter_table_type?



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

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:



315
316
317
# File 'lib/arjdbc/sqlite3/adapter.rb', line 315

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



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

def allowed_index_name_length
  index_name_length - 2
end

#begin_db_transactionObject

:nodoc:



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

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

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

:nodoc:



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

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:



278
279
280
281
282
283
284
# File 'lib/arjdbc/sqlite3/adapter.rb', line 278

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:



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

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

#clear_cache!Object

Clears the prepared statements cache.



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

def clear_cache!
  @statements.clear
end

#commit_db_transactionObject

:nodoc:



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

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

#disable_referential_integrityObject

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



150
151
152
153
154
155
156
157
158
159
# File 'lib/arjdbc/sqlite3/adapter.rb', line 150

def disable_referential_integrity # :nodoc:
  old = query_value("PRAGMA foreign_keys")

  begin
    execute("PRAGMA foreign_keys = OFF")
    yield
  ensure
    execute("PRAGMA foreign_keys = #{old}")
  end
end

#disconnect!Object

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



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

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

#encodingObject

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



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

def encoding
  @connection.encoding.to_s
end

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



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

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

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



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/arjdbc/sqlite3/adapter.rb', line 171

def exec_query(sql, name = nil, binds = [], prepare: false)
  type_casted_binds = type_casted_binds(binds)

  log(sql, name, binds, type_casted_binds) do
    ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
      # Don't cache statements if they are not prepared
      unless prepare
        stmt = @connection.prepare(sql)
        begin
          cols = stmt.columns
          unless without_prepared_statement?(binds)
            stmt.bind_params(type_casted_binds)
          end
          records = stmt.to_a
        ensure
          stmt.close
        end
      else
        cache = @statements[sql] ||= {
            stmt: @connection.prepare(sql)
        }
        stmt = cache[:stmt]
        cols = cache[:cols] ||= stmt.columns
        stmt.reset!
        stmt.bind_params(type_casted_binds)
        records = stmt.to_a
      end

      ActiveRecord::Result.new(cols, records)
    end
  end
end

#exec_rollback_db_transactionObject

:nodoc:



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

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

#execute(sql, name = nil) ⇒ Object

:nodoc:



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

def execute(sql, name = nil) #:nodoc:
  log(sql, name) do
    ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
      @connection.execute(sql)
    end
  end
end

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

-- DATABASE STATEMENTS ====================================== ++



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

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



320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/arjdbc/sqlite3/adapter.rb', line 320

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

#initialize(connection, logger, config) ⇒ Object

DIFFERENCE: we remove connection_options because we are not using it.



66
67
68
69
70
71
72
73
# File 'lib/arjdbc/sqlite3/adapter.rb', line 66

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

  @active     = true
  @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))

  configure_connection
end

#insert_fixtures(rows, table_name) ⇒ Object



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

def insert_fixtures(rows, table_name)
  ActiveSupport::Deprecation.warn(<<-MSG.squish)
      `insert_fixtures` is deprecated and will be removed in the next version of Rails.
      Consider using `insert_fixtures_set` for performance improvement.
  MSG
  insert_fixtures_set(table_name => rows)
end

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



342
343
344
345
346
347
348
349
350
351
352
# File 'lib/arjdbc/sqlite3/adapter.rb', line 342

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



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:



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

def native_database_types #:nodoc:
  NATIVE_DATABASE_TYPES
end

#primary_keys(table_name) ⇒ Object

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



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

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:



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

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, options = {}) ⇒ Object

:nodoc:



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

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:



309
310
311
312
313
# File 'lib/arjdbc/sqlite3/adapter.rb', line 309

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



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

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)


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

def requires_reloading?
  true
end

#supports_datetime_with_precision?Boolean

Returns:

  • (Boolean)


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

def supports_datetime_with_precision?
  true
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


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

def supports_ddl_transactions?
  true
end

#supports_explain?Boolean

Returns:

  • (Boolean)


144
145
146
# File 'lib/arjdbc/sqlite3/adapter.rb', line 144

def supports_explain?
  true
end

#supports_foreign_keys_in_create?Boolean

Returns:

  • (Boolean)


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

def supports_foreign_keys_in_create?
  sqlite_version >= "3.6.19"
end

#supports_index_sort_order?Boolean

Returns:

  • (Boolean)


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

def supports_index_sort_order?
  true
end

#supports_multi_insert?Boolean

Returns:

  • (Boolean)


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

def supports_multi_insert?
  sqlite_version >= "3.7.11"
end

#supports_partial_index?Boolean

Returns:

  • (Boolean)


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

def supports_partial_index?
  sqlite_version >= "3.8.0"
end

#supports_savepoints?Boolean

Returns:

  • (Boolean)


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

def supports_savepoints?
  true
end

#supports_views?Boolean

Returns:

  • (Boolean)


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

def supports_views?
  true
end

#valid_alter_table_type?(type, options = {}) ⇒ Boolean

DIFFERENCE: deprecated causes a JRuby 9.1 bug where "super" calls itself -> do inline

Returns:

  • (Boolean)


256
257
258
259
# File 'lib/arjdbc/sqlite3/adapter.rb', line 256

def valid_alter_table_type?(type, options = {})
  ActiveSupport::Deprecation.deprecation_warning(__method__)
  !invalid_alter_table_type?(type, options)
end