Spec-Zone.ru › Ruby on Rails 4.1

модуль 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) Показать исходный код

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

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

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

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

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

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 267
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 272
def commit_db_transaction()   end
default_sequence_name(table, column) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 278
def default_sequence_name(table, column)
  nil
end
delete(arel, name = nil, binds = []) Показать исходный код

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 93
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
insert_fixture(fixture, table_name) Показать исходный код

Вставляет данный заполнитель в таблицу. Переопределяется в адаптерах, которые требуют чего-то большего, чем простая вставка (например, Oracle).

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 289
def insert_fixture(fixture, table_name)
  columns = schema_cache.columns_hash(table_name)

  key_list   = []
  value_list = fixture.map do |name, value|
    key_list << quote_column_name(name)
    quote(value, columns[name])
  end

  execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
end
limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 305
def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
  "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
end
reset_sequence!(table, column, sequence = nil) Показать исходный код

Устанавливает последовательность в максимальное значение столбца таблицы.

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 283
def reset_sequence!(table, column, sequence = nil)
  # Do nothing by default. Implement for PostgreSQL, Oracle, ...
end
rollback_db_transaction() Показать исходный код

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

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

Очищает заданный параметр LIMIT, чтобы предотвратить SQL-инъекции.

limit может быть чем угодно, что может быть преобразовано в строку через to_s. Он должен выглядеть как целое число, или список целых чисел, разделенных запятыми, или Arel SQL литерал.

Возвращает Integer и Arel::Nodes::SqlLiteral limits как есть. Возвращает очищенный параметр limit, либо как целое число, либо как строку, содержащую список целых чисел, разделенных запятыми.

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 318
def sanitize_limit(limit)
  if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
    limit
  elsif limit.to_s.include?(',')
    Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
  else
    Integer(limit)
  end
end
select_all(arel, name = nil, binds = []) Показать исходный код

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

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

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

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

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

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

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

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

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

select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 42
def select_values(arel, name = nil)
  arel, binds = binds_from_relation arel, []
  select_rows(to_sql(arel, binds), name, binds).map(&:first)
end
supports_statement_cache?() Показать исходный код

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

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

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

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 10
def to_sql(arel, binds = [])
  if arel.respond_to?(:ast)
    binds = binds.dup
    visitor.accept(arel.ast) do
      quote(*binds.shift.reverse)
    end
  else
    arel
  end
end
transaction(options = {}) { || ... } Показать исходный код

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

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

Большинство баз данных не поддерживают истинные вложенные транзакции. На момент написания, единственная база данных, которая поддерживает истинные вложенные транзакции, известна нам, это 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, потому что они затронуты багом, который означает, что уровень изоляции сохраняется вне транзакции.

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 191
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
    within_new_transaction(options) { yield }
  end
rescue ActiveRecord::Rollback
  # rollbacks are silently swallowed
end
transaction_isolation_levels() Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 255
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 226
def transaction_open?
  @transaction.open?
end
update(arel, name = nil, binds = []) Показать исходный код

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

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 100
def update(arel, name = nil, binds = [])
  exec_update(to_sql(arel, binds), name, binds)
end

Защищенные методы экземпляра

binds_from_relation(relation, binds) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 383
def binds_from_relation(relation, binds)
  if relation.is_a?(Relation) && binds.blank?
    relation, binds = relation.arel, relation.bind_values
  end
  [relation, binds]
end
delete_sql(sql, name = nil) Показать исходный код

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

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

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

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 359
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
  execute(sql, name)
  id_value
end
last_inserted_id(result) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 378
def last_inserted_id(result)
  row = result.rows.first
  row && row.first
end
select(sql, name = nil, binds = []) Показать исходный код

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

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 354
def select(sql, name = nil, binds = [])
end
sql_for_insert(sql, pk, id_value, sequence_name, binds) Показать исходный код
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 374
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
  [sql, binds]
end
subquery_for(key, select) Показать исходный код

Возвращает подзапрос для заданного ключа, используя информацию о соединении.

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 347
def subquery_for(key, select)
  subselect = select.clone
  subselect.projections = [key]
  subselect
end
update_sql(sql, name = nil) Показать исходный код

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

# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 365
def update_sql(sql, name = nil)
  execute(sql, name)
end

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

Spec-Zone.ru

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