класс ActiveRecord::ConnectionAdapters::AbstractAdapter
Абстрактный адаптер Active Record
Active Record поддерживает несколько систем баз данных. AbstractAdapter и связанные классы образуют абстракционную оболочку, которая делает это возможным. AbstractAdapter представляет собой соединение с базой данных и предоставляет абстрактный интерфейс для функций баз данных, таких как установление соединения, экранирование значений, построение правильных фрагментов SQL для :offset и :limit опций и т. д.
Все конкретные адаптеры баз данных следуют интерфейсу, заданному в этом классе. ActiveRecord::Base.lease_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 361 def self.database_exists?(config) new(config).database_exists? end
Существует ли база данных для этого адаптера?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 122
def self.dbconsole(config, options = {})
raise NotImplementedError
end Открывает сеанс консоли базы данных.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 93
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 66
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 56
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 74
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 651 def active? end
Проверяет, активно ли соединение с базой данных. Это включает проверку, может ли база данных фактически отвечать, то есть, не устарело ли соединение.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 356 def adapter_name self.class::ADAPTER_NAME end
Возвращает удобочитаемое имя адаптера. Используйте смешанный регистр — всегда можно использовать строчные буквы, если необходимо.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 636 def check_all_foreign_keys_valid! end
Переопределите, чтобы проверить все ограничения внешних ключей в базе данных. Адаптер должен выбросить ActiveRecord::StatementInvalid, если ограничения внешних ключей не соблюдаются.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 732
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 822 def close pool.checkin self end
Возвратить соединение обратно в пул соединений
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 770 def connect! verify! self end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 644 def connected? !@raw_connection.nil? end
Проверяет, установлено ли соединение с базой данных. Это не включает проверку, может ли база данных фактически отвечать, то есть, не устарело ли соединение.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 217 def connection_retries (@config[:connection_retries] || 1).to_i end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 365 def database_exists? connect! true rescue ActiveRecord::NoDatabaseError false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 229 def default_timezone @default_timezone || ActiveRecord.default_timezone end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 571 def disable_extension(name, **) end
Этот метод должен быть реализован адаптерами, поддерживающими расширения
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 629 def disable_referential_integrity yield end
Переопределите, чтобы отключить целостность ссылок при выполнении &block.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 707 def discard! # This should be overridden by concrete adapters. end
Немедленно забыть, что это соединение когда-либо существовало. В отличие от disconnect!, это не будет взаимодействовать с сервером.
После вызова этого метода поведение всех других методов становится неопределенным. Это вызывается внутри, непосредственно перед тем, как разветвленный процесс избавится от соединения, принадлежавшего его родителю.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 693
def disconnect!
@lock.synchronize do
clear_cache!(new_connection: true)
reset_transaction
@raw_connection_dirty = false
end
end Отсоединяется от базы данных, если соединение уже установлено. В противном случае этот метод ничего не делает.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 575 def enable_extension(name, **) end
Этот метод должен быть реализован адаптерами, поддерживающими расширения
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 313
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 617 def extensions [] end
Список расширений, который должен заполняться адаптерами, поддерживающими расширения.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 622
def index_algorithms
{}
end Список алгоритмов индексирования, который должен заполняться адаптерами, поддерживающими алгоритмы индексирования.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 277
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 end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 405 def prefetch_primary_key?(table_name = nil) false end
Нужно ли выбирать значения первичного ключа из соответствующей последовательности перед операцией вставки? Если true, next_sequence_value вызывается перед каждой вставкой, чтобы установить первичный ключ записи.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 244 def prepared_statements? @prepared_statements && !prepared_statements_disabled_cache.include?(object_id) end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 237 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 790
def raw_connection
with_raw_connection do |conn|
disable_lazy_transactions!
@raw_connection_dirty = true
conn
end
end Предоставляет доступ к основному драйверу базы данных для этого адаптера. Например, этот метод возвращает объект Mysql2::Client в случае Mysql2Adapter и объект PG::Connection в случае PostgreSQLAdapter.
Это полезно, когда вам нужно вызвать собственную функцию, такую как PostgreSQL's lo_* methods.
Active Record не может отслеживать, изменяется ли база данных с использованием этого клиента. В этом случае, как правило, вам нужно будет аннулировать кэш запросов, используя ActiveRecord::Base.clear_query_cache.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 657
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 Отключается от базы данных, если уже подключен, и устанавливает новое соединение с базой данных. Реализаторы должны определить частную переподключение вместо этого.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 213 def replica? @config[:replica] || false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 745 def requires_reloading? false end
Возвращает true, если требуется перезагрузка соединения между запросами для режима разработки.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 719 def reset! clear_cache!(new_connection: true) reset_transaction configure_connection end
Сбросить состояние этого соединения, указав СУБД очистить транзакции и другие состояния соединения на стороне сервера. Обычно это операция, зависящая от базы данных.
Если драйвер базы данных или протокол не поддерживают такую функцию, реализаторы могут использовать псевдоним для reconnect!. В противном случае, реализаторы должны вызвать super сразу после сброса соединения (и пока удерживают @lock).
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 221
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 298 def role @pool.role end
Роль (например, :writing) для текущего соединения. В приложении без многочисленных ролей возвращается :writing.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 389 def savepoint_errors_invalidate_transactions? false end
Ошибки TransactionRollback на уровнях сохранения влияют на родительскую транзакцию?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 308 def schema_cache @pool.schema_cache || (@schema_cache ||= BoundSchemaReflection.for_lone_connection(@pool.schema_reflection, self)) end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 857 def schema_version pool.migration_context.current_version end
Возвращает идентификатор версии схемы, доступной в настоящее время в базе данных. Как правило, это равно номеру самой новой миграции, которая была выполнена, или 0, если информация о схеме отсутствует/ база данных пуста.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 304 def shard @pool.shard end
Разделение (например, :default) для текущего соединения. В приложении без разделения возвращается :default.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 398 def supports_advisory_locks? false end
Поддерживает ли этот адаптер консультационные блокировки, налагаемые приложением?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 378 def supports_bulk_alter? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 470 def supports_check_constraints? false end
Поддерживает ли этот адаптер создание ограничений проверки?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 505 def supports_comments? false end
Поддерживает ли этот адаптер метаданные комментарии к объектам базы данных (таблицы, столбцы, индексы)?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 510 def supports_comments_in_create? false end
Можно ли указывать комментарии к таблицам, столбцам и индексам в операторах создания/изменения таблиц?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 529 def supports_common_table_expressions? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 553 def supports_concurrent_connections? true end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 495 def supports_datetime_with_precision? false end
Поддерживает ли этот адаптер datetime с точностью?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 374 def supports_ddl_transactions? false end
Поддерживает ли этот адаптер откат DDL в транзакциях? То есть, CREATE TABLE или ALTER TABLE будут отменены транзакцией?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 465 def supports_deferrable_constraints? false end
Поддерживает ли этот адаптер создание откладываемых ограничений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 475 def supports_exclusion_constraints? false end
Поддерживает ли этот адаптер создание ограничений исключения?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 434 def supports_explain? false end
Поддерживает ли этот адаптер explain?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 429 def supports_expression_index? false end
Поддерживает ли этот адаптер индексы выражений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 444 def supports_extensions? false end
Поддерживает ли этот адаптер расширения базы данных?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 455 def supports_foreign_keys? false end
Поддерживает ли этот адаптер создание ограничений внешнего ключа?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 520 def supports_foreign_tables? false end
Поддерживает ли этот адаптер внешние таблицы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 424 def supports_index_include? false end
Поддерживает ли этот адаптер включение столбцов, не являющихся ключами?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 414 def supports_index_sort_order? false end
Поддерживает ли этот адаптер порядок сортировки индекса?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 450 def supports_indexes_in_create? false end
Поддерживает ли этот адаптер создание индексов в том же операторе, что и создание таблицы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 549 def supports_insert_conflict_target? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 541 def supports_insert_on_duplicate_skip? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 545 def supports_insert_on_duplicate_update? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 537 def supports_insert_returning? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 500 def supports_json? false end
Поддерживает ли этот адаптер тип данных JSON?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 533 def supports_lazy_transactions? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 490 def supports_materialized_views? false end
Поддерживает ли этот адаптер материализованные представления?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 557 def supports_nulls_not_distinct? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 525 def supports_optimizer_hints? false end
Поддерживает ли этот адаптер подсказки оптимизатора?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 419 def supports_partial_index? false end
Поддерживает ли этот адаптер частичные индексы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 409 def supports_partitioned_indexes? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 393 def supports_restart_db_transaction? false end
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 383 def supports_savepoints? false end
Поддерживает ли этот адаптер точки сохранения?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 439 def supports_transaction_isolation? false end
Поддерживает ли этот адаптер установку уровня изоляции для транзакции?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 480 def supports_unique_constraints? false end
Поддерживает ли этот адаптер создание уникальных ограничений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 460 def supports_validate_constraints? false end
Поддерживает ли этот адаптер создание недопустимых ограничений?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 485 def supports_views? false end
Поддерживает ли этот адаптер представления?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 515 def supports_virtual_columns? false end
Поддерживает ли этот адаптер виртуальные столбцы?
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 726 def throw_away! pool.remove self disconnect! end
Удаляет подключение из пула и отключает его.
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 347 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 752
def verify!
unless active?
@lock.synchronize do
if @unconfigured_connection
@raw_connection = @unconfigured_connection
@unconfigured_connection = nil
configure_connection
@verified = true
return
end
reconnect!(restore_transactions: true)
end
end
@verified = true
end Проверяет, активен ли сейчас подключение к базе данных (т.е. не устарело). Это делается внутри, вызывая active?. Если подключение больше не активно, то этот метод перезапустит подключение к базе данных.
Методы частного экземпляра
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 1118
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,
transaction: current_transaction.user_transaction.presence,
row_count: 0,
&block
)
rescue ActiveRecord::StatementInvalid => ex
raise ex.set_query(sql, binds)
end
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.