класс ActiveRecord::ConnectionAdapters::AbstractAdapter
Абстрактный адаптер Active Record
Active Record поддерживает несколько систем баз данных. AbstractAdapter и связанные классы образуют абстракционный слой, что делает это возможным. AbstractAdapter представляет собой соединение с базой данных и предоставляет абстрактный интерфейс для баз данных, специфичной функциональности, такой как установление соединения, экранирование значений, построение правильных SQL фрагментов для :offset и :limit параметров и т.д.
Все конкретные адаптеры баз данных следуют интерфейсу, заданному в этом классе. ActiveRecord::Base.connection возвращает объект AbstractAdapter, который вы можете использовать.
Большинство методов адаптера полезны при миграциях. В частности, методы экземпляров, предоставляемые SchemaStatements, очень полезны.
Константы
- ADAPTER_NAME
- COMMENT_REGEX
- EXTENDED_TYPE_MAPS
- SIMPLE_INT
- TYPE_MAP
Атрибуты
Публичные методы класса
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 382 def self.database_exists?(config) new(config).database_exists? end
Существует ли база данных для этого адаптера?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 124
def self.dbconsole(config, options = {})
raise NotImplementedError
end Открывает сеанс консоли базы данных.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 95
def self.find_cmd_and_exec(commands, *args) # :doc:
commands = Array(commands)
dirs_on_path = ENV["PATH"].to_s.split(File::PATH_SEPARATOR)
unless (ext = RbConfig::CONFIG["EXEEXT"]).empty?
commands = commands.map { |cmd| "#{cmd}#{ext}" }
end
full_path_command = nil
found = commands.detect do |cmd|
dirs_on_path.detect do |path|
full_path_command = File.join(path, cmd)
begin
stat = File.stat(full_path_command)
rescue SystemCallError
else
stat.file? && stat.executable?
end
end
end
if found
exec full_path_command, *args
else
abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
end
end # File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 68
def self.type_cast_config_to_boolean(config)
if config == "false"
false
else
config
end
end # File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 58
def self.type_cast_config_to_integer(config)
if config.is_a?(Integer)
config
elsif SIMPLE_INT.match?(config)
config.to_i
else
config
end
end # File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 76
def self.validate_default_timezone(config)
case config
when nil
when "utc", "local"
config.to_sym
else
raise ArgumentError, "default_timezone must be either 'utc' or 'local'"
end
end Публичные методы экземпляров
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 674 def active? end
Проверяет, активен ли подключение к базе данных. Это включает проверку, действительно ли база данных способна отвечать, то есть, не устарело ли подключение.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 377 def adapter_name self.class::ADAPTER_NAME end
Возвращает удобочитаемое имя адаптера. Используется смешанный регистр — всегда можно использовать строчные буквы, если нужно.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 655 def all_foreign_keys_valid? check_all_foreign_keys_valid! true rescue ActiveRecord::StatementInvalid false end
Переопределить для проверки всех ограничений внешних ключей в базе данных.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 666 def check_all_foreign_keys_valid! end
Переопределить для проверки всех ограничений внешних ключей в базе данных. Адаптер должен вызвать ActiveRecord::StatementInvalid в случае, если ограничения внешних ключей не соблюдены.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 754
def clear_cache!(new_connection: false)
if @statements
@lock.synchronize do
if new_connection
@statements.reset
else
@statements.clear
end
end
end
end Очистить кэширование, которое может использовать адаптер базы данных.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 846 def close pool.checkin self end
Возвращение подключения в пул подключений
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 794 def connect! verify! self end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 222 def connection_retries (@config[:connection_retries] || 1).to_i end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 386 def database_exists? connect! true rescue ActiveRecord::NoDatabaseError false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 234 def default_timezone @default_timezone || ActiveRecord.default_timezone end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 592 def disable_extension(name, **) end
Это должно быть реализовано адаптерами, поддерживающими расширения
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 650 def disable_referential_integrity yield end
Переопределить для отключения целостности ссылок при выполнении &block.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 729 def discard! # This should be overridden by concrete adapters. end
Немедленно забывает, что такое соединение. В отличие от disconnect!, это не будет взаимодействовать с сервером.
После вызова этого метода поведение всех других методов становится неопределенным. Это вызывается внутренне непосредственно перед тем, как разветвленный процесс избавляется от подключения, которое принадлежало его родителю.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 717 def disconnect! clear_cache!(new_connection: true) reset_transaction @raw_connection_dirty = false end
Отключается от базы данных, если уже подключен. В противном случае этот метод ничего не делает.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 596 def enable_extension(name, **) end
Это должно быть реализовано адаптерами, поддерживающими расширения
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 334
def expire
if in_use?
if @owner != ActiveSupport::IsolatedExecutionState.context
raise ActiveRecordError, "Cannot expire connection, " \
"it is owned by a different thread: #{@owner}. " \
"Current thread: #{ActiveSupport::IsolatedExecutionState.context}."
end
@idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@owner = nil
else
raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
end
end Этот метод должен вызываться только при удержании мьютекса пула подключений
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 638 def extensions [] end
Список расширений, который необходимо заполнить адаптерам, поддерживающим их.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 643
def index_algorithms
{}
end Список алгоритмов индексов, который необходимо заполнить адаптерам, поддерживающим их.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 298
def lease
if in_use?
msg = +"Cannot lease connection, "
if @owner == ActiveSupport::IsolatedExecutionState.context
msg << "it is already leased by the current thread."
else
msg << "it is already in use by a different thread: #{@owner}. " \
"Current thread: #{ActiveSupport::IsolatedExecutionState.context}."
end
raise ActiveRecordError, msg
end
@owner = ActiveSupport::IsolatedExecutionState.context
end Этот метод должен вызываться только при удержании мьютекса пула подключений
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 48 def pool=(value) return if value.eql?(@pool) @schema_cache = nil @pool = value @pool.schema_reflection.load!(self) if ActiveRecord.lazily_load_schema_cache end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 426 def prefetch_primary_key?(table_name = nil) false end
Нужно ли выбирать значения первичного ключа из соответствующей последовательности перед оператором вставки? Если true, next_sequence_value вызывается перед каждой вставкой для установки первичного ключа записи.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 265 def prepared_statements? @prepared_statements && !prepared_statements_disabled_cache.include?(object_id) end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 242 def preventing_writes? return true if replica? return false if connection_class.nil? connection_class.current_preventing_writes end
Определяет, предотвращаются ли в данный момент записи.
Возвращает true, если соединение является репликацией, или возвращает значение current_preventing_writes.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 814
def raw_connection
with_raw_connection do |conn|
disable_lazy_transactions!
@raw_connection_dirty = true
conn
end
end Предоставляет доступ к базовому драйверу базы данных для данного адаптера. Например, этот метод возвращает объект Mysql2::Client в случае Mysql2Adapter, и объект PG::Connection в случае PostgreSQLAdapter.
Это полезно, когда вам нужно вызвать собственный метод, такой как методы lo_* PostgreSQL.
Active Record не может отслеживать, если база данных изменяется с помощью этого клиента. В этом случае, как правило, вам нужно будет аннулировать кэш запросов, используя ActiveRecord::Base.clear_query_cache.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 680
def reconnect!(restore_transactions: false)
retries_available = connection_retries
deadline = retry_deadline && Process.clock_gettime(Process::CLOCK_MONOTONIC) + retry_deadline
@lock.synchronize do
reconnect
enable_lazy_transactions!
@raw_connection_dirty = false
@verified = true
reset_transaction(restore: restore_transactions) do
clear_cache!(new_connection: true)
configure_connection
end
rescue => original_exception
translated_exception = translate_exception_class(original_exception, nil, nil)
retry_deadline_exceeded = deadline && deadline < Process.clock_gettime(Process::CLOCK_MONOTONIC)
if !retry_deadline_exceeded && retries_available > 0
retries_available -= 1
if retryable_connection_error?(translated_exception)
backoff(connection_retries - retries_available)
retry
end
end
@verified = false
raise translated_exception
end
end Отключается от базы данных, если она уже подключена, и устанавливает новое соединение с базой данных. Реализаторы должны определить private reconnect вместо этого.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 214 def replica? @config[:replica] || false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 767 def requires_reloading? false end
Возвращает true, если требуется перезагрузка соединения между запросами для режима разработки.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 741 def reset! clear_cache!(new_connection: true) reset_transaction configure_connection end
Сбросить состояние этого соединения, указав DBMS очистить транзакции и другие связанные с соединением состояние на стороне сервера. Обычно операция, зависящая от базы данных.
Если драйвер базы данных или протокол не поддерживает такую функцию, реализаторы могут использовать alias для reconnect!. В противном случае, реализаторы должны вызвать super сразу после сброса соединения (и при этом удерживая @lock).
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 226
def retry_deadline
if @config[:retry_deadline]
@config[:retry_deadline].to_f
else
nil
end
end # File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 319 def role @pool.role end
Роль (например, :writing) для текущего соединения. В приложении без множественных ролей, возвращается :writing.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 410 def savepoint_errors_invalidate_transactions? false end
Воздействуют ли ошибки TransactionRollback на savepoints на родительскую транзакцию?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 329 def schema_cache @schema_cache ||= BoundSchemaReflection.new(@pool.schema_reflection, self) end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 881 def schema_version migration_context.current_version end
Возвращает идентификатор версии схемы, в настоящее время доступной в базе данных. Обычно равно номеру миграции с наибольшим номером, которая была выполнена, или 0, если информация о схеме отсутствует/ база данных пустая.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 325 def shard @pool.shard end
Разделение (например, :default) для текущего соединения. В приложении без разделения возвращается :default.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 419 def supports_advisory_locks? false end
Поддерживает ли этот адаптер консалтинговую блокировку?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 399 def supports_bulk_alter? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 491 def supports_check_constraints? false end
Поддерживает ли этот адаптер создание ограничений check?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 526 def supports_comments? false end
Поддерживает ли этот адаптер комментарии к метаданным об объектах базы данных (таблицы, столбцы, индексы)?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 531 def supports_comments_in_create? false end
Можно ли указывать комментарии для таблиц, столбцов и индексов в операциях CREATE/ALTER TABLE?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 550 def supports_common_table_expressions? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 574 def supports_concurrent_connections? true end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 516 def supports_datetime_with_precision? false end
Поддерживает ли этот адаптер datetime с точностью?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 395 def supports_ddl_transactions? false end
Поддерживает ли этот адаптер откат DDL в транзакциях? То есть, CREATE TABLE или ALTER TABLE будут отменены транзакцией?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 486 def supports_deferrable_constraints? false end
Поддерживает ли этот адаптер создание откладываемых ограничений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 496 def supports_exclusion_constraints? false end
Поддерживает ли этот адаптер создание исключений ограничений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 455 def supports_explain? false end
Поддерживает ли этот адаптер explain?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 450 def supports_expression_index? false end
Поддерживает ли этот адаптер индексы выражений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 465 def supports_extensions? false end
Поддерживает ли этот адаптер расширения базы данных?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 476 def supports_foreign_keys? false end
Поддерживает ли этот адаптер создание ограничений внешнего ключа?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 541 def supports_foreign_tables? false end
Поддерживает ли этот адаптер внешние таблицы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 445 def supports_index_include? false end
Поддерживает ли этот адаптер включение столбцов, не являющихся ключами?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 435 def supports_index_sort_order? false end
Поддерживает ли этот адаптер порядок сортировки индекса?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 471 def supports_indexes_in_create? false end
Поддерживает ли этот адаптер создание индексов в том же операторе, что и создание таблицы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 570 def supports_insert_conflict_target? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 562 def supports_insert_on_duplicate_skip? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 566 def supports_insert_on_duplicate_update? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 558 def supports_insert_returning? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 521 def supports_json? false end
Поддерживает ли этот адаптер тип данных JSON?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 554 def supports_lazy_transactions? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 511 def supports_materialized_views? false end
Поддерживает ли этот адаптер материализованные представления?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 578 def supports_nulls_not_distinct? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 546 def supports_optimizer_hints? false end
Поддерживает ли этот адаптер подсказки оптимизатора?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 440 def supports_partial_index? false end
Поддерживает ли этот адаптер частичные индексы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 430 def supports_partitioned_indexes? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 414 def supports_restart_db_transaction? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 404 def supports_savepoints? false end
Поддерживает ли этот адаптер контрольные точки?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 460 def supports_transaction_isolation? false end
Поддерживает ли этот адаптер установку уровня изоляции для транзакции?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 501 def supports_unique_constraints? false end
Поддерживает ли этот адаптер создание уникальных ограничений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 481 def supports_validate_constraints? false end
Поддерживает ли этот адаптер создание недопустимых ограничений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 506 def supports_views? false end
Поддерживает ли этот адаптер представления?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 536 def supports_virtual_columns? false end
Поддерживает ли этот адаптер виртуальные столбцы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 748 def throw_away! pool.remove self disconnect! end
Удаляет подключение из пула и отключает его.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 368 def unprepared_statement cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements yield ensure cache&.delete(object_id) end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 218 def use_metadata_table? @config.fetch(:use_metadata_table, true) end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 774
def verify!
unless active?
if @unconfigured_connection
@lock.synchronize do
if @unconfigured_connection
@raw_connection = @unconfigured_connection
@unconfigured_connection = nil
configure_connection
@verified = true
return
end
end
end
reconnect!(restore_transactions: true)
end
@verified = true
end Проверяет, активное ли соединение с базой данных (т.е. не устарело). Это делается под капотом путем вызова active?. Если соединение больше не активно, то этот метод переподключится к базе данных.
Приватные методы экземпляров
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 1142
def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block) # :doc:
@instrumenter.instrument(
"sql.active_record",
sql: sql,
name: name,
binds: binds,
type_casted_binds: type_casted_binds,
statement_name: statement_name,
async: async,
connection: self,
&block
)
rescue ActiveRecord::StatementInvalid => ex
raise ex.set_query(sql, binds)
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.