aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb')
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb103
1 files changed, 66 insertions, 37 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 7c809b088c..163cbb875f 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -33,7 +33,7 @@ module ActiveRecord
ConnectionAdapters::SQLite3Adapter.new(db, logger, nil, config)
rescue Errno::ENOENT => error
if error.message.include?("No such file or directory")
- raise ActiveRecord::NoDatabaseError.new(error.message, error)
+ raise ActiveRecord::NoDatabaseError
else
raise
end
@@ -65,18 +65,6 @@ module ActiveRecord
boolean: { name: "boolean" }
}
- class Version
- include Comparable
-
- def initialize(version_string)
- @version = version_string.split('.').map(&:to_i)
- end
-
- def <=>(version_string)
- @version <=> version_string.split('.').map(&:to_i)
- end
- end
-
class StatementPool < ConnectionAdapters::StatementPool
private
@@ -90,18 +78,17 @@ module ActiveRecord
end
def initialize(connection, logger, connection_options, config)
- super(connection, logger)
+ super(connection, logger, config)
@active = nil
- @statements = StatementPool.new(@connection,
- self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
- @config = config
+ @statements = StatementPool.new(self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
@visitor = Arel::Visitors::SQLite.new self
@quoted_column_names = {}
if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@prepared_statements = true
+ @visitor.extend(DetermineIfPreparableVisitor)
else
@prepared_statements = false
end
@@ -142,6 +129,10 @@ module ActiveRecord
true
end
+ def supports_datetime_with_precision?
+ true
+ end
+
def active?
@active != false
end
@@ -231,7 +222,7 @@ module ActiveRecord
end
class ExplainPrettyPrinter
- # Pretty prints the result of a EXPLAIN QUERY PLAN in a way that resembles
+ # Pretty prints the result of an EXPLAIN QUERY PLAN in a way that resembles
# the output of the SQLite shell:
#
# 0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
@@ -244,15 +235,18 @@ module ActiveRecord
end
end
- def exec_query(sql, name = nil, binds = [])
+ def exec_query(sql, name = nil, binds = [], prepare: false)
type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
log(sql, name, binds) do
# Don't cache statements if they are not prepared
- if without_prepared_statement?(binds)
+ 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
@@ -265,7 +259,7 @@ module ActiveRecord
stmt = cache[:stmt]
cols = cache[:cols] ||= stmt.columns
stmt.reset!
- stmt.bind_params type_casted_binds
+ stmt.bind_params(type_casted_binds)
end
ActiveRecord::Result.new(cols, stmt.to_a)
@@ -320,21 +314,56 @@ module ActiveRecord
# SCHEMA STATEMENTS ========================================
- def tables(name = nil, table_name = nil) #:nodoc:
- sql = <<-SQL
- SELECT name
- FROM sqlite_master
- WHERE (type = 'table' OR type = 'view') 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']
+ def tables(name = nil) # :nodoc:
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ #tables currently returns both tables and views.
+ This behavior is deprecated and will be changed with Rails 5.1 to only return tables.
+ Use #data_sources instead.
+ MSG
+
+ if name
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ Passing arguments to #tables is deprecated without replacement.
+ MSG
end
+
+ data_sources
+ end
+
+ def data_sources
+ select_values("SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'", 'SCHEMA')
end
def table_exists?(table_name)
- table_name && tables(nil, table_name).any?
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
+ #table_exists? currently checks both tables and views.
+ This behavior is deprecated and will be changed with Rails 5.1 to only check tables.
+ Use #data_source_exists? instead.
+ MSG
+
+ data_source_exists?(table_name)
+ end
+
+ def data_source_exists?(table_name)
+ return false unless table_name.present?
+
+ sql = "SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name <> 'sqlite_sequence'"
+ sql << " AND name = #{quote(table_name)}"
+
+ select_values(sql, 'SCHEMA').any?
+ end
+
+ def views # :nodoc:
+ select_values("SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'", 'SCHEMA')
+ end
+
+ def view_exists?(view_name) # :nodoc:
+ return false unless view_name.present?
+
+ sql = "SELECT name FROM sqlite_master WHERE type = 'view' AND name <> 'sqlite_sequence'"
+ sql << " AND name = #{quote(view_name)}"
+
+ select_values(sql, 'SCHEMA').any?
end
# Returns an array of +Column+ objects for the table specified by +table_name+.
@@ -381,13 +410,13 @@ module ActiveRecord
end
end
- def primary_key(table_name) #:nodoc:
+ def primary_keys(table_name) # :nodoc:
pks = table_structure(table_name).select { |f| f['pk'] > 0 }
- return nil unless pks.count == 1
- pks[0]['name']
+ pks.sort_by { |f| f['pk'] }.map { |f| f['name'] }
end
- def remove_index!(table_name, index_name) #:nodoc:
+ 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
@@ -557,7 +586,7 @@ module ActiveRecord
# Older versions of SQLite return:
# column *column_name* is not unique
when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
- RecordNotUnique.new(message, exception)
+ RecordNotUnique.new(message)
else
super
end