Spec-Zone.ru › Ruby on Rails 5.0

модуль 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) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 252
def add_transaction_record(record)
  current_transaction.add_record(record)
end

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

begin_db_transaction() Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 261
def begin_db_transaction()    end

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

begin_isolated_db_transaction(isolation) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 275
def begin_isolated_db_transaction(isolation)
  raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation"
end

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

commit_db_transaction() Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 280
def commit_db_transaction()   end

Фиксирует транзакцию (и включает автоматическую фиксацию).

create(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
Псевдоним для: insert
delete(arel, name = nil, binds = []) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 139
def delete(arel, name = nil, binds = [])
  exec_delete(to_sql(arel, binds), name, binds)
end

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

Также является псевдонимом для: delete_sql
delete_sql(arel, name = nil, binds = [])
Псевдоним для: delete
exec_delete(sql, name, binds) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 98
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) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 91
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 = [], prepare: false) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 84
def exec_query(sql, name = 'SQL', binds = [], prepare: false)
  raise NotImplementedError
end

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

exec_update(sql, name, binds) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 110
def exec_update(sql, name, binds)
  exec_query(sql, name, binds)
end

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

execute(sql, name = nil) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 77
def execute(sql, name = nil)
  raise NotImplementedError
end

Выполняет SQL-запрос в контексте этого соединения и возвращает необработанный результат от адаптера соединения. Примечание: в зависимости от вашего коннектора к базе данных, результат, возвращаемый этим методом, может управляться вручную в памяти. Рассмотрите возможность использования обертки #exec_query вместо этого.

insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 122
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
  sql, binds, pk, sequence_name = 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

Выполняет запрос INSERT и возвращает ID новой записи

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

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

Также является псевдонимом для: create, insert_sql
insert_sql(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
Псевдоним для: insert
rollback_db_transaction() Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 284
def rollback_db_transaction
  exec_rollback_db_transaction
end

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

select_all(arel, name = nil, binds = [], preparable: nil) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 30
def select_all(arel, name = nil, binds = [], preparable: nil)
  arel, binds = binds_from_relation arel, binds
  sql = to_sql(arel, binds)
  if !prepared_statements || (arel.is_a?(String) && preparable.nil?)
    preparable = false
  else
    preparable = visitor.preparable
  end
  if prepared_statements && preparable
    select_prepared(sql, name, binds)
  else
    select(sql, name, binds)
  end
end

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

select_one(arel, name = nil, binds = []) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 47
def select_one(arel, name = nil, binds = [])
  select_all(arel, name, binds).first
end

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

select_rows(sql, name = nil, binds = []) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 68
def select_rows(sql, name = nil, binds = [])
  exec_query(sql, name, binds).rows
end

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

select_value(arel, name = nil, binds = []) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 52
def select_value(arel, name = nil, binds = [])
  arel, binds = binds_from_relation arel, binds
  if result = select_rows(to_sql(arel, binds), name, binds).first
    result.first
  end
end

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

select_values(arel, name = nil, binds = []) Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 61
def select_values(arel, name = nil, binds = [])
  arel, binds = binds_from_relation arel, binds
  select_rows(to_sql(arel, binds), name, binds).map(&:first)
end

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

select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
supports_statement_cache?() Show source
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 147
def supports_statement_cache?
  false
end

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

to_sql(arel, binds = []) Show source
# 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

transaction(requires_new: nil, isolation: nil, joinable: true) { || ... } Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 225
def transaction(requires_new: nil, isolation: nil, joinable: true)
  if !requires_new && current_transaction.joinable?
    if isolation
      raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
    end
    yield
  else
    transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) { yield }
  end
rescue ActiveRecord::Rollback
  # rollbacks are silently swallowed
end

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

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

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

Для решения этой проблемы, метод transaction эмулирует эффект вложенных транзакций, используя сохраняемые точки: dev.mysql.com/doc/refman/5.7/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/current/static/transaction-iso.html

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

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

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

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

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

Адаптеры mysql2 и postgresql поддерживают настройку уровня изоляции транзакций.

transaction_isolation_levels() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 263
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 242
def transaction_open?
  current_transaction.open?
end
transaction_state() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 256
def transaction_state
  current_transaction.state
end
truncate(table_name, name = nil) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 103
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 132
def update(arel, name = nil, binds = [])
  exec_update(to_sql(arel, binds), name, binds)
end

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

Также алиас: update_sql
update_sql(arel, name = nil, binds = [])
Псевдоним для: update

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

Spec-Zone.ru

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