- A
- B
- C
- D
- E
- H
- I
- N
- R
- S
- T
- U
- W
類別公開方法
new() 連結
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 6 def initialize super reset_transaction end
實體公開方法
add_transaction_record(record, ensure_finalize = true) 連結
用目前的交易註冊一筆紀錄,以便在它完成並回滾後呼叫 after_commit 和 after_rollback 回呼。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 405 def add_transaction_record(record, ensure_finalize = true) current_transaction.add_record(record, ensure_finalize) end
begin_db_transaction() 連結
開始交易(並關閉自動認可)。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 410 def begin_db_transaction() end
begin_isolated_db_transaction(isolation) 連結
開始具有設定的隔離等級的交易。預設會引發錯誤;支援設定隔離等級的適配器應實作這個方法。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 432 def begin_isolated_db_transaction(isolation) raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation" end
commit_db_transaction() 連結
認可交易(並開啟自動認可)。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 446 def commit_db_transaction() end
建立(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil) 連結
預設序列名稱(table, column) 連結
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 468 def default_sequence_name(table, column) nil end
刪除(arel, name = nil, binds = []) 連結
執行刪除陳述,並傳回受影響的列數。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 212 def delete(arel, name = nil, binds = []) sql, binds = to_sql_and_binds(arel, binds) exec_delete(sql, name, binds) end
空白插入陳述值(primary_key = nil) 連結
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 498 def empty_insert_statement_value(primary_key = nil) "DEFAULT VALUES" end
exec_delete(sql, name = nil, binds = []) 連結
在這個連線中執行刪除sql
陳述,並使用binds
作為繫結替換。name
會和執行的sql
陳述一起記錄。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 165 def exec_delete(sql, name = nil, binds = []) affected_rows(internal_execute(sql, name, binds)) end
exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil) 連結
在這個連線中執行插入sql
陳述,並使用binds
作為繫結替換。name
會和執行的sql
陳述一起記錄。有些轉接器支援『returning』關鍵字引數,它可以控制查詢的結果:nil
是預設值且維持預設行為。如果傳遞了欄位名稱的陣列,結果將包含從已插入列傳回的指定欄位值。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 157 def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil) sql, binds = sql_for_insert(sql, pk, binds, returning) internal_exec_query(sql, name, binds) end
exec_query(sql, name = "SQL", binds = [], prepare: false) 連結
在這個連線中執行sql
陳述,並使用binds
作為繫結替換。name
會和執行的sql
陳述一起記錄。
注意:假設查詢有副作用,而且查詢快取會清除。如果查詢是唯讀的,請考慮改用select_all
。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 147 def exec_query(sql, name = "SQL", binds = [], prepare: false) internal_exec_query(sql, name, binds, prepare: prepare) end
exec_update(sql, name = nil, binds = []) 連結
於此連線的脈絡下執行更新 sql
陳述式,使用 binds
作為綁定替代。name
與已執行的 sql
陳述式一起記錄。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 172 def exec_update(sql, name = nil, binds = []) affected_rows(internal_execute(sql, name, binds)) end
execute(sql, name = nil, allow_retry: false) 連結
在此連線的脈絡中執行 SQL 陳述式,並從連線適配器傳回原始結果。
將 allow_retry
設為 true 會使資料庫重新連線並在遇到與連線相關的例外情況時重試執行 SQL 陳述式。這個選項僅應啟用於已知的冪等查詢。
注意:假設查詢有副作用,而且查詢快取會清除。如果查詢是唯讀的,請考慮改用select_all
。
注意:根據您的資料庫連接器,此方法傳回的結果可能會手動記憶體管理。考慮使用 exec_query
封裝器。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 136 def execute(sql, name = nil, allow_retry: false) internal_execute(sql, name, allow_retry: allow_retry) end
high_precision_current_timestamp() 連結
傳回 Arel
SQL 文字,表示 CURRENT_TIMESTAMP,可用於任意精度的日期/時間欄位。
支援精度日期時間的適配器應覆寫此功能,以提供可用的最高精度。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 536 def high_precision_current_timestamp HIGH_PRECISION_CURRENT_TIMESTAMP end
insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil) 連結
執行 INSERT 查詢並傳回新記錄的 ID
id_value
將會傳回,除非這個值為 nil
,對於這種情況資料庫將嘗試計算最後插入的 id 並傳回那個值。
如果下一個 id 已預先計算(例如在 Oracle 中),就應該當做 id_value
傳入。某些適配器支援 'returning` 關鍵字參數,允許定義方法的傳回值:nil
是預設值並維持預設行為。如果傳入一個欄位名稱陣列,就會從方法傳回一個陣列,表示已插入列中指定欄位的數值。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 195 def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil) sql, binds = to_sql_and_binds(arel, binds) value = exec_insert(sql, name, binds, pk, sequence_name, returning: returning) return returning_column_values(value) unless returning.nil? id_value || last_inserted_id(value) end
insert_fixture(fixture, table_name) 連結
將給定的固定資料插入到這個資料表。在需要除了簡單插入之外的事情(例如 Oracle)的適配器中覆寫。大部分的適配器都應該實作 insert_fixtures_set
來利用大量 SQL 插入。我們保留這個方法來為像 SQLite 這些不支援大量插入的資料庫提供後備方案。
來源: 顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 482 def insert_fixture(fixture, table_name) execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert") end
insert_fixtures_set(fixture_set, tables_to_delete = []) 連結
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 486 def insert_fixtures_set(fixture_set, tables_to_delete = []) fixture_inserts = build_fixture_statements(fixture_set) table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" } statements = table_deletes + fixture_inserts transaction(requires_new: true) do disable_referential_integrity do execute_batch(statements, "Fixtures Load") end end end
reset_isolation_level() 連結
隔離的資料庫交易承諾或回滾後,呼叫的掛接點。大多數的介面卡不需要實作任何內容,因為隔離等級基於每筆交易設定。但某些資料庫(例如 SQLite)會針對每個連線層級設定,並在承諾或回滾後需要明確地重設。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 442 def reset_isolation_level end
reset_sequence!(table, column, sequence = nil) 連結
將順序設定為該表格欄位的最大值。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 473 def reset_sequence!(table, column, sequence = nil) # Do nothing by default. Implement for PostgreSQL, Oracle, ... end
restart_db_transaction() 連結
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 458 def restart_db_transaction exec_restart_db_transaction end
rollback_db_transaction() 連結
回滾該交易(並啟動自動提交)。如果交易區塊產生例外或傳回 false,則必須執行此動作。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 450 def rollback_db_transaction exec_rollback_db_transaction rescue ActiveRecord::ConnectionNotEstablished, ActiveRecord::ConnectionFailed # Connection's gone; that counts as a rollback end
rollback_to_savepoint(name = nil) 連結
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 464 def rollback_to_savepoint(name = nil) exec_rollback_to_savepoint(name) end
sanitize_limit(limit) 連結
集中管理給定的 LIMIT 參數,以防止 SQL 注入。
limit
可能任何可透過 to_s 評量為字串的任何內容。它應該看起來像一個整數,或是一個 Arel
SQL 字面值。
傳回 Integer
與 Arel::Nodes::SqlLiteral 的極限不變。
來源:顯示 | 在 GitHub 上
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 508 def sanitize_limit(limit) if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral) limit else Integer(limit) end end
select_all(arel, name = nil, binds = [], preparable: nil, async: false, allow_retry: false) 連結
傳回 ActiveRecord::Result
實例。
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 69 def select_all(arel, name = nil, binds = [], preparable: nil, async: false, allow_retry: false) arel = arel_from_relation(arel) sql, binds, preparable, allow_retry = to_sql_and_binds(arel, binds, preparable, allow_retry) select(sql, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll, allow_retry: allow_retry ) rescue ::RangeError ActiveRecord::Result.empty(async: async) end
select_one(arel, name = nil, binds = [], async: false) 連結
傳回一個紀錄雜湊,包含欄位名稱作為鍵和欄位值作為值。
select_rows(arel, name = nil, binds = [], async: false) 連結
傳回一個陣列,其中包含欄位值。順序與 columns
傳回的順序相同。
select_value(arel, name = nil, binds = [], async: false) 連結
從紀錄傳回單一值
select_values(arel, name = nil, binds = []) 連結
傳回一個陣列,其中包含選取中第一個欄位的數值。
select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
to_sql(arel_or_sql_string, binds = []) 連結
將 arel AST 轉換為 SQL
transaction(requires_new: nil, isolation: nil, &block) 連結
在資料庫交易中執行給定的區塊,並傳回該區塊的結果。
Transaction
回呼
transaction
讓出 ActiveRecord::Transaction
物件,可用於註冊 callback
ActiveRecord::Base.transaction do |transaction|
transaction.before_commit { puts "before commit!" }
transaction.after_commit { puts "after commit!" }
transaction.after_rollback { puts "after rollback!" }
end
巢狀交易支援
transaction
呼叫可以巢狀。預設情況下,這會讓巢狀交易區塊中的所有資料庫陳述都變成長輩交易的一部分。例如,以下是會令人驚訝的行為
ActiveRecord::Base.transaction do
Post.create(title: 'first')
ActiveRecord::Base.transaction do
Post.create(title: 'second')
raise ActiveRecord::Rollback
end
end
這會建立「first」和「second」文章。原因是巢狀區塊中的 ActiveRecord::Rollback
例外沒有發出 ROLLBACK。由於這些例外是在交易區塊中擷取的,因此長輩區塊不會看到它,並且真正的交易會提交。
大多數資料庫不支援真正的巢狀交易。撰寫本文的當時,我們所知的唯一支援真正的巢狀交易的資料庫是 MS-SQL。
若要解決此問題,transaction
會使用儲存點模擬嵌套交易的效果:dev.mysql.com/doc/refman/en/savepoint.html。
如果資料庫交易已開啟,安全地呼叫此方法,亦即在另一個 transaction
區塊內呼叫 transaction
。如果巢狀呼叫,transaction
的表現如下
-
區塊會執行,不做任何事。區塊內的所有資料庫陳述式,實質上都會附加到已開啟的資料庫交易上。
-
不過,如果設定
:requires_new
,區塊會包裝在資料庫儲存點中,作為子交易。
若要取得嵌套交易的 ROLLBACK,你可以傳遞 requires_new: true
,要求一個真正的子交易。如果發生問題,資料庫會備份到子交易的開始,而不會備份母交易。如果我們將其新增到前一個範例中
ActiveRecord::Base.transaction do
Post.create(title: 'first')
ActiveRecord::Base.transaction(requires_new: true) do
Post.create(title: 'second')
raise ActiveRecord::Rollback
end
end
只會建立標題是「first」的貼文。
請參閱 ActiveRecord::Transactions
,以了解更多資訊。
注意事項
MySQL
不支援 DDL 交易。如果你執行 DDL 作業,任何建立的儲存點將自動釋放。例如,如果你建立一個儲存點,然後你執行一個 CREATE TABLE 陳述式,那麼會自動釋放建立的儲存點。
這表示在 MySQL
上,你不應該在 transaction
呼叫中執行 DDL 作業,而且你已經知道可能會建立一個儲存點。否則,transaction
會在嘗試釋放已經自動釋放的儲存點時引發例外狀況
Model.lease_connection.transaction do # BEGIN
Model.lease_connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
Model.lease_connection.create_table(...)
# active_record_1 now automatically released
end # RELEASE SAVEPOINT active_record_1 <--- BOOM! database error!
end
Transaction
隔離
如果你的資料庫支援為交易設定隔離層級,你可以這樣設定
Post.transaction(isolation: :serializable) do
# ...
end
有效的隔離層級如下
-
:read_uncommitted
-
:read_committed
-
:repeatable_read
-
:serializable
你應該查看資料庫文件,以了解這些不同層級的語意
如果發生以下情況,將引發 ActiveRecord::TransactionIsolationError
:
-
配接器不支援設定隔離層級
-
你正在加入一個現有的開啟交易
-
你正在建立一個巢狀(儲存點)交易
mysql2、trilogy 和 postgresql 配接器支援設定交易隔離層級。
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 352 def transaction(requires_new: nil, isolation: nil, joinable: true, &block) if !requires_new && current_transaction.joinable? if isolation raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction" end yield current_transaction.user_transaction else within_new_transaction(isolation: isolation, joinable: joinable, &block) end rescue ActiveRecord::Rollback # rollbacks are silently swallowed end
transaction_isolation_levels() 連結
transaction_open?() 連結
truncate(table_name, name = nil) 連結
執行 truncate 陳述式。
update(arel, name = nil, binds = []) 連結
執行更新陳述並傳回已影響的列數。