Spec-Zone.ru › Ruby on Rails 4.2

модуль ActiveRecord::ConnectionAdapters::DatabaseStatements

Публичные методы класса

new() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 4
def initialize
  super
  reset_transaction
end
Вызывает метод родительского класса

Публичные методы экземпляра

add_transaction_record(record) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 233
def add_transaction_record(record)
  current_transaction.add_record(record)
end

Регистрирует запись в текущей транзакции, чтобы можно было вызвать её обратные вызовы after_commit и after_rollback.

begin_db_transaction() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 242
def begin_db_transaction()    end

Начинает транзакцию (и отключает автоматическое подтверждение).

begin_isolated_db_transaction(isolation) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 256
def begin_isolated_db_transaction(isolation)
  raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation"
end

Начинает транзакцию с заданным уровнем изоляции. По умолчанию вызывает ошибку; адаптеры, поддерживающие настройку уровня изоляции, должны реализовывать этот метод.

commit_db_transaction() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 261
def commit_db_transaction()   end

Подтверждает транзакцию (и включает автоматическое подтверждение).

delete(arel, name = nil, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 118
def delete(arel, name = nil, binds = [])
  exec_delete(to_sql(arel, binds), name, binds)
end

Выполняет оператор DELETE и возвращает количество изменённых строк.

exec_delete(sql, name, binds) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 82
def exec_delete(sql, name, binds)
  exec_query(sql, name, binds)
end

Выполняет оператор DELETE sql в контексте этого подключения, используя binds в качестве подстановок связывания. name регистрируется вместе с выполненным оператором sql.

exec_insert(sql, name, binds, pk = nil, sequence_name = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 75
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
  exec_query(sql, name, binds)
end

Выполняет оператор INSERT sql в контексте этого подключения, используя binds в качестве подстановок связывания. name регистрируется вместе с выполненным оператором sql.

exec_query(sql, name = 'SQL', binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 69
def exec_query(sql, name = 'SQL', binds = [])
end

Выполняет оператор sql в контексте этого подключения, используя binds в качестве подстановок связывания. name регистрируется вместе с выполненным оператором sql.

exec_update(sql, name, binds) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 94
def exec_update(sql, name, binds)
  exec_query(sql, name, binds)
end

Выполняет оператор UPDATE sql в контексте этого подключения, используя binds в качестве подстановок связывания. name регистрируется вместе с выполненным оператором sql.

execute(sql, name = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 62
def execute(sql, name = nil)
end

Выполняет SQL-оператор в контексте этого подключения.

insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 106
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
  sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
  value      = exec_insert(sql, name, binds, pk, sequence_name)
  id_value || last_inserted_id(value)
end

Возвращает последний сгенерированный идентификатор из затронутой таблицы.

id_value будет возвращён, если значение не равно null, в противном случае база данных попытается вычислить последний вставленный идентификатор и вернуть это значение.

Если следующий идентификатор был вычислен заранее (как в Oracle), он должен быть передан как id_value.

rollback_db_transaction() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 265
def rollback_db_transaction
  exec_rollback_db_transaction
end

Откатывает транзакцию (и включает автоматическое подтверждение). Это необходимо сделать, если блок транзакции вызывает исключение или возвращает false.

select_all(arel, name = nil, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 30
def select_all(arel, name = nil, binds = [])
  arel, binds = binds_from_relation arel, binds
  select(to_sql(arel, binds), name, binds)
end

Возвращает экземпляр ActiveRecord::Result.

select_one(arel, name = nil, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 37
def select_one(arel, name = nil, binds = [])
  select_all(arel, name, binds).first
end

Возвращает хэш записи, где имена столбцов являются ключами, а значения столбцов — значениями.

select_rows(sql, name = nil, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 57
def select_rows(sql, name = nil, binds = [])
end

Возвращает массив массивов, содержащих значения полей. Порядок соответствует порядку, возвращаемому columns.

select_value(arel, name = nil, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 42
def select_value(arel, name = nil, binds = [])
  if result = select_one(arel, name, binds)
    result.values.first
  end
end

Возвращает единственное значение из записи

select_values(arel, name = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 50
def select_values(arel, name = nil)
  arel, binds = binds_from_relation arel, []
  select_rows(to_sql(arel, binds), name, binds).map(&:first)
end

Возвращает массив значений первого столбца в запросе:

select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
supports_statement_cache?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 124
def supports_statement_cache?
  false
end

Возвращает true если адаптер подключения поддерживает кеширование подготовленных запросов, иначе возвращает false.

to_sql(arel, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 10
def to_sql(arel, binds = [])
  if arel.respond_to?(:ast)
    collected = visitor.accept(arel.ast, collector)
    collected.compile(binds.dup, self)
  else
    arel
  end
end

Преобразует AST arel в SQL

END_OF_DOCUMENT_MARKER
transaction(options = {}) { || ... } Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 204
def transaction(options = {})
  options.assert_valid_keys :requires_new, :joinable, :isolation

  if !options[:requires_new] && current_transaction.joinable?
    if options[:isolation]
      raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
    end
    yield
  else
    transaction_manager.within_new_transaction(options) { yield }
  end
rescue ActiveRecord::Rollback
  # rollbacks are silently swallowed
end

Выполняет заданный блок в транзакции базы данных и возвращает результат блока.

Поддержка вложенных транзакций

Большинство баз данных не поддерживают истинные вложенные транзакции. На момент написания, единственная база данных, о которой нам известно, поддерживающая истинные вложенные транзакции, это MS-SQL.

Для решения этой проблемы, transaction эмулирует эффект вложенных транзакций, используя контрольные точки: dev.mysql.com/doc/refman/5.0/en/savepoint.html Контрольные точки поддерживаются MySQL и PostgreSQL. SQLite3 версии >= '3.6.8' поддерживает контрольные точки.

Этот метод безопасно вызывать, если транзакция базы данных уже открыта, т.е. если transaction вызывается внутри другого блока transaction. В случае вложенного вызова, transaction будет вести себя следующим образом:

  • Блок будет выполнен без каких-либо действий. Все операторы базы данных, которые происходят внутри блока, фактически добавляются к уже открытой транзакции базы данных.

  • Однако, если :requires_new установлено, блок будет обернут в контрольную точку базы данных, действующую как подтранзакция.

Ограничения

MySQL не поддерживает транзакции DDL. Если вы выполните операцию DDL, все созданные контрольные точки будут автоматически освобождены. Например, если вы создали контрольную точку, затем выполнили оператор CREATE TABLE, тогда созданная контрольная точка будет автоматически освобождена.

Это означает, что в MySQL не следует выполнять операции DDL внутри вызова transaction, который, как вы знаете, может создать контрольную точку. В противном случае, transaction будет генерировать исключения при попытке освободить уже автоматически освобождённые контрольные точки:

Model.connection.transaction do  # BEGIN
  Model.connection.transaction(requires_new: true) do  # CREATE SAVEPOINT active_record_1
    Model.connection.create_table(...)
    # active_record_1 now automatically released
  end  # RELEASE SAVEPOINT active_record_1  <--- BOOM! database error!
end

Изоляция транзакции

Если ваша база данных поддерживает установку уровня изоляции для транзакции, вы можете установить его так:

Post.transaction(isolation: :serializable) do
  # ...
end

Допустимые уровни изоляции:

  • :read_uncommitted

  • :read_committed

  • :repeatable_read

  • :serializable

Вы должны обратиться к документации вашей базы данных для понимания семантики этих различных уровней:

  • www.postgresql.org/docs/9.1/static/transaction-iso.html

  • dev.mysql.com/doc/refman/5.0/en/set-transaction.html

Исключение ActiveRecord::TransactionIsolationError будет сгенерировано, если:

  • Адаптер не поддерживает установку уровня изоляции

  • Вы присоединяетесь к уже открытой транзакции

  • Вы создаёте вложенную (контрольную точку) транзакцию

Адаптеры mysql, mysql2 и postgresql поддерживают установку уровня изоляции транзакций. Однако поддержка отключена для версий MySQL ниже 5, поскольку они затронуты ошибкой ошибкой, которая означает, что уровень изоляции сохраняется за пределами транзакции.

transaction_isolation_levels() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 244
def transaction_isolation_levels
  {
    read_uncommitted: "READ UNCOMMITTED",
    read_committed:   "READ COMMITTED",
    repeatable_read:  "REPEATABLE READ",
    serializable:     "SERIALIZABLE"
  }
end
transaction_open?() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 223
def transaction_open?
  current_transaction.open?
end
transaction_state() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 237
def transaction_state
  current_transaction.state
end
truncate(table_name, name = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 87
def truncate(table_name, name = nil)
  raise NotImplementedError
end

Выполняет оператор truncate.

update(arel, name = nil, binds = []) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 113
def update(arel, name = nil, binds = [])
  exec_update(to_sql(arel, binds), name, binds)
end

Выполняет оператор update и возвращает количество изменённых строк.

© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API