Module: ArJdbc::SQLite3
- Includes:
- ActiveRecord::ConnectionAdapters::SQLite3::ColumnDumper, 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: 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" } }
Instance Method Summary collapse
- #active? ⇒ Boolean
-
#add_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:.
-
#add_reference(table_name, ref_name, **options) ⇒ Object
(also: #add_belongs_to)
:nodoc:.
-
#allowed_index_name_length ⇒ Object
Returns 62.
-
#arel_visitor ⇒ Object
:nodoc:.
-
#begin_db_transaction ⇒ Object
:nodoc:.
-
#change_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:.
-
#change_column_default(table_name, column_name, default_or_changes) ⇒ Object
:nodoc:.
-
#change_column_null(table_name, column_name, null, default = nil) ⇒ Object
:nodoc:.
-
#clear_cache! ⇒ Object
Clears the prepared statements cache.
-
#commit_db_transaction ⇒ Object
:nodoc:.
-
#disable_referential_integrity ⇒ Object
REFERENTIAL INTEGRITY ====================================.
-
#disconnect! ⇒ Object
Disconnects from the database if already connected.
-
#encoding ⇒ Object
Returns the current database encoding format as a string, eg: 'UTF-8'.
- #exec_delete(sql, name = 'SQL', binds = []) ⇒ Object (also: #exec_update)
- #exec_query(sql, name = nil, binds = [], prepare: false) ⇒ Object
-
#exec_rollback_db_transaction ⇒ Object
:nodoc:.
-
#execute(sql, name = nil) ⇒ Object
:nodoc:.
-
#explain(arel, binds = []) ⇒ Object
-- DATABASE STATEMENTS ====================================== ++.
- #foreign_keys(table_name) ⇒ Object
-
#indexes(table_name, name = nil) ⇒ Object
Returns an array of indexes for the given table.
- #initialize(connection, logger, connection_options, config) ⇒ Object
- #last_inserted_id(result) ⇒ Object
-
#native_database_types ⇒ Object
:nodoc:.
-
#new_column_from_field(table_name, field) ⇒ Object
SCHEMA STATEMENTS ========================================.
-
#primary_keys(table_name) ⇒ Object
:nodoc:.
-
#remove_column(table_name, column_name, type = nil, options = {}) ⇒ Object
:nodoc:.
-
#remove_index(table_name, options = {}) ⇒ Object
:nodoc:.
-
#rename_column(table_name, column_name, new_column_name) ⇒ Object
:nodoc:.
-
#rename_table(table_name, new_name) ⇒ Object
Renames a table.
- #requires_reloading? ⇒ Boolean
-
#schema_creation ⇒ Object
:nodoc:.
- #supports_datetime_with_precision? ⇒ Boolean
- #supports_ddl_transactions? ⇒ Boolean
- #supports_explain? ⇒ Boolean
- #supports_foreign_keys_in_create? ⇒ Boolean
- #supports_index_sort_order? ⇒ Boolean
- #supports_multi_insert? ⇒ Boolean
- #supports_partial_index? ⇒ Boolean
- #supports_savepoints? ⇒ Boolean
-
#supports_statement_cache? ⇒ Boolean
Returns true, since this connection adapter supports prepared statement caching.
- #supports_views? ⇒ Boolean
-
#update_table_definition(table_name, base) ⇒ Object
:nodoc:.
-
#valid_alter_table_type?(type) ⇒ Boolean
See: http://www.sqlite.org/lang_altertable.html SQLite has an additional restriction on the ALTER TABLE statement.
Instance Method Details
#active? ⇒ Boolean
122 123 124 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 122 def active? @active != false end |
#add_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:
323 324 325 326 327 328 329 330 331 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 323 def add_column(table_name, column_name, type, = {}) #:nodoc: if valid_alter_table_type?(type) && ![:primary_key] super(table_name, column_name, type, ) else alter_table(table_name) do |definition| definition.column(column_name, type, ) end end end |
#add_reference(table_name, ref_name, **options) ⇒ Object Also known as: add_belongs_to
:nodoc:
376 377 378 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 376 def add_reference(table_name, ref_name, **) # :nodoc: super(table_name, ref_name, type: :integer, **) end |
#allowed_index_name_length ⇒ Object
Returns 62. SQLite supports index names up to 64 characters. The rest is used by Rails internally to perform temporary rename operations
146 147 148 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 146 def allowed_index_name_length index_name_length - 2 end |
#arel_visitor ⇒ Object
:nodoc:
71 72 73 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 71 def arel_visitor # :nodoc: Arel::Visitors::SQLite.new(self) end |
#begin_db_transaction ⇒ Object
:nodoc:
237 238 239 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 237 def begin_db_transaction #:nodoc: log("begin transaction",nil) { @connection.transaction } end |
#change_column(table_name, column_name, type, options = {}) ⇒ Object
:nodoc:
356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 356 def change_column(table_name, column_name, type, = {}) #:nodoc: alter_table(table_name) do |definition| definition[column_name].instance_eval do self.type = type self.limit = [:limit] if .include?(:limit) self.default = [:default] if .include?(:default) self.null = [:null] if .include?(:null) self.precision = [:precision] if .include?(:precision) self.scale = [:scale] if .include?(:scale) self.collation = [:collation] if .include?(:collation) end end end |
#change_column_default(table_name, column_name, default_or_changes) ⇒ Object
:nodoc:
339 340 341 342 343 344 345 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 339 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:
347 348 349 350 351 352 353 354 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 347 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.
135 136 137 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 135 def clear_cache! @statements.clear end |
#commit_db_transaction ⇒ Object
:nodoc:
241 242 243 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 241 def commit_db_transaction #:nodoc: log("commit transaction",nil) { @connection.commit } end |
#disable_referential_integrity ⇒ Object
REFERENTIAL INTEGRITY ====================================
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 165 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.
128 129 130 131 132 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 128 def disconnect! super @active = false @connection.close rescue nil end |
#encoding ⇒ Object
Returns the current database encoding format as a string, eg: 'UTF-8'
155 156 157 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 155 def encoding @connection.encoding.to_s end |
#exec_delete(sql, name = 'SQL', binds = []) ⇒ Object Also known as: exec_update
219 220 221 222 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 219 def exec_delete(sql, name = 'SQL', binds = []) exec_query(sql, name, binds) @connection.changes end |
#exec_query(sql, name = nil, binds = [], prepare: false) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 186 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_transaction ⇒ Object
:nodoc:
245 246 247 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 245 def exec_rollback_db_transaction #:nodoc: log("rollback transaction",nil) { @connection.rollback } end |
#execute(sql, name = nil) ⇒ Object
:nodoc:
229 230 231 232 233 234 235 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 229 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 ====================================== ++
180 181 182 183 184 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 180 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
381 382 383 384 385 386 387 388 389 390 391 392 393 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 381 def foreign_keys(table_name) fk_info = exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA") fk_info.map do |row| = { 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"], ) end end |
#indexes(table_name, name = nil) ⇒ Object
Returns an array of indexes for the given table.
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 268 def indexes(table_name, name = nil) #:nodoc: if name ActiveSupport::Deprecation.warn(<<-MSG.squish) Passing name to #indexes is deprecated without replacement. MSG end exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row| sql = <<-SQL SELECT sql FROM sqlite_master WHERE name=#{quote(row['name'])} AND type='index' UNION ALL SELECT sql FROM sqlite_temp_master WHERE name=#{quote(row['name'])} AND type='index' SQL index_sql = exec_query(sql).first["sql"] match = /\sWHERE\s+(.+)$/i.match(index_sql) where = match[1] if match IndexDefinition.new( table_name, row["name"], row["unique"] != 0, exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col| col["name"] }, nil, nil, where) end end |
#initialize(connection, logger, connection_options, config) ⇒ Object
75 76 77 78 79 80 81 82 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 75 def initialize(connection, logger, , config) super(connection, logger, config) @active = nil @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit])) configure_connection end |
#last_inserted_id(result) ⇒ Object
225 226 227 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 225 def last_inserted_id(result) @connection.last_insert_row_id end |
#native_database_types ⇒ Object
:nodoc:
150 151 152 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 150 def native_database_types #:nodoc: NATIVE_DATABASE_TYPES end |
#new_column_from_field(table_name, field) ⇒ Object
SCHEMA STATEMENTS ========================================
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 251 def new_column_from_field(table_name, field) # :nondoc: 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 collation = field["collation"] sql_type = field["type"] = (sql_type) new_column(field["name"], field["dflt_value"], , field["notnull"].to_i == 0, table_name, nil, collation) end |
#primary_keys(table_name) ⇒ Object
:nodoc:
298 299 300 301 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 298 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:
333 334 335 336 337 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 333 def remove_column(table_name, column_name, type = nil, = {}) #:nodoc: alter_table(table_name) do |definition| definition.remove_column column_name end end |
#remove_index(table_name, options = {}) ⇒ Object
:nodoc:
303 304 305 306 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 303 def remove_index(table_name, = {}) #:nodoc: index_name = index_name_for_remove(table_name, ) exec_query "DROP INDEX #{quote_column_name(index_name)}" end |
#rename_column(table_name, column_name, new_column_name) ⇒ Object
:nodoc:
370 371 372 373 374 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 370 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')
312 313 314 315 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 312 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
102 103 104 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 102 def requires_reloading? true end |
#schema_creation ⇒ Object
:nodoc:
66 67 68 69 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 66 def schema_creation # :nodoc: # DIFFERENCE: FQN ::ActiveRecord::ConnectionAdapters::SQLite3::SchemaCreation.new self end |
#supports_datetime_with_precision? ⇒ Boolean
114 115 116 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 114 def supports_datetime_with_precision? true end |
#supports_ddl_transactions? ⇒ Boolean
84 85 86 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 84 def supports_ddl_transactions? true end |
#supports_explain? ⇒ Boolean
159 160 161 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 159 def supports_explain? true end |
#supports_foreign_keys_in_create? ⇒ Boolean
106 107 108 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 106 def supports_foreign_keys_in_create? sqlite_version >= "3.6.19" end |
#supports_index_sort_order? ⇒ Boolean
139 140 141 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 139 def supports_index_sort_order? true end |
#supports_multi_insert? ⇒ Boolean
118 119 120 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 118 def supports_multi_insert? sqlite_version >= "3.7.11" end |
#supports_partial_index? ⇒ Boolean
92 93 94 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 92 def supports_partial_index? sqlite_version >= "3.8.0" end |
#supports_savepoints? ⇒ Boolean
88 89 90 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 88 def supports_savepoints? true end |
#supports_statement_cache? ⇒ Boolean
Returns true, since this connection adapter supports prepared statement caching.
98 99 100 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 98 def supports_statement_cache? true end |
#supports_views? ⇒ Boolean
110 111 112 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 110 def supports_views? true end |
#update_table_definition(table_name, base) ⇒ Object
:nodoc:
61 62 63 64 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 61 def update_table_definition(table_name, base) # :nodoc: # DIFFERENCE: FQN ::ActiveRecord::ConnectionAdapters::SQLite3::Table.new(table_name, base) end |
#valid_alter_table_type?(type) ⇒ Boolean
See: http://www.sqlite.org/lang_altertable.html SQLite has an additional restriction on the ALTER TABLE statement
319 320 321 |
# File 'lib/arjdbc/sqlite3/adapter.rb', line 319 def valid_alter_table_type?(type) type.to_sym != :primary_key end |