diff options
Diffstat (limited to 'activerecord/lib')
8 files changed, 35 insertions, 28 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb b/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb index 52a796b926..d6dbef3fc8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb @@ -8,15 +8,15 @@ module ActiveRecord end def create_savepoint(name = current_savepoint_name) - execute("SAVEPOINT #{name}") + execute("SAVEPOINT #{name}", "TRANSACTION") end def exec_rollback_to_savepoint(name = current_savepoint_name) - execute("ROLLBACK TO SAVEPOINT #{name}") + execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION") end def release_savepoint(name = current_savepoint_name) - execute("RELEASE SAVEPOINT #{name}") + execute("RELEASE SAVEPOINT #{name}", "TRANSACTION") end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index c9e84e48cc..7b6321d83b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -98,9 +98,13 @@ module ActiveRecord end def rollback_records - ite = records.uniq + ite = records.uniq(&:object_id) + already_run_callbacks = {} while record = ite.shift - record.rolledback!(force_restore_state: full_rollback?) + trigger_callbacks = record.trigger_transactional_callbacks? + should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks + already_run_callbacks[record] ||= trigger_callbacks + record.rolledback!(force_restore_state: full_rollback?, should_run_callbacks: should_run_callbacks) end ensure ite.each do |i| @@ -113,10 +117,14 @@ module ActiveRecord end def commit_records - ite = records.uniq + ite = records.uniq(&:object_id) + already_run_callbacks = {} while record = ite.shift if @run_commit_callbacks - record.committed! + trigger_callbacks = record.trigger_transactional_callbacks? + should_run_callbacks = !already_run_callbacks[record] && trigger_callbacks + already_run_callbacks[record] ||= trigger_callbacks + record.committed!(should_run_callbacks: should_run_callbacks) else # if not running callbacks, only adds the record to the parent transaction connection.add_transaction_record(record) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 282b2b1838..d239ecff89 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -204,7 +204,7 @@ module ActiveRecord end def begin_db_transaction - execute "BEGIN" + execute("BEGIN", "TRANSACTION") end def begin_isolated_db_transaction(isolation) @@ -213,11 +213,11 @@ module ActiveRecord end def commit_db_transaction #:nodoc: - execute "COMMIT" + execute("COMMIT", "TRANSACTION") end def exec_rollback_db_transaction #:nodoc: - execute "ROLLBACK" + execute("ROLLBACK", "TRANSACTION") end def empty_insert_statement_value(primary_key = nil) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb index d872bd662f..45ec79ca78 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb @@ -145,7 +145,7 @@ module ActiveRecord # Begins a transaction. def begin_db_transaction - execute "BEGIN" + execute("BEGIN", "TRANSACTION") end def begin_isolated_db_transaction(isolation) @@ -155,12 +155,12 @@ module ActiveRecord # Commits a transaction. def commit_db_transaction - execute "COMMIT" + execute("COMMIT", "TRANSACTION") end # Aborts a transaction. def exec_rollback_db_transaction - execute "ROLLBACK" + execute("ROLLBACK", "TRANSACTION") end private diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb index 46ce1a15b5..73b80e8c15 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb @@ -68,15 +68,15 @@ module ActiveRecord alias :exec_update :exec_delete def begin_db_transaction #:nodoc: - log("begin transaction", nil) { @connection.transaction } + log("begin transaction", "TRANSACTION") { @connection.transaction } end def commit_db_transaction #:nodoc: - log("commit transaction", nil) { @connection.commit } + log("commit transaction", "TRANSACTION") { @connection.commit } end def exec_rollback_db_transaction #:nodoc: - log("rollback transaction", nil) { @connection.rollback } + log("rollback transaction", "TRANSACTION") { @connection.rollback } end diff --git a/activerecord/lib/active_record/middleware/database_selector.rb b/activerecord/lib/active_record/middleware/database_selector.rb index b5b5df074c..93a1a39c3e 100644 --- a/activerecord/lib/active_record/middleware/database_selector.rb +++ b/activerecord/lib/active_record/middleware/database_selector.rb @@ -35,10 +35,10 @@ module ActiveRecord # config.active_record.database_resolver = MyResolver # config.active_record.database_resolver_context = MyResolver::MySession class DatabaseSelector - def initialize(app, resolver_klass = Resolver, context_klass = Resolver::Session, options = {}) + def initialize(app, resolver_klass = nil, context_klass = nil, options = {}) @app = app - @resolver_klass = resolver_klass - @context_klass = context_klass + @resolver_klass = resolver_klass || Resolver + @context_klass = context_klass || Resolver::Session @options = options end diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb index b60cc96165..6872b7844e 100644 --- a/activerecord/lib/active_record/touch_later.rb +++ b/activerecord/lib/active_record/touch_later.rb @@ -18,6 +18,7 @@ module ActiveRecord surreptitiously_touch @_defer_touch_attrs add_to_transaction + @_new_record_before_last_commit ||= false # touch the parents as we are not calling the after_save callbacks self.class.reflect_on_all_associations(:belongs_to).each do |r| diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 9e03deede7..148bc0550c 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -333,7 +333,7 @@ module ActiveRecord # Ensure that it is not called if the object was never persisted (failed create), # but call it after the commit of a destroyed object. def committed!(should_run_callbacks: true) #:nodoc: - if should_run_callbacks && trigger_transactional_callbacks? + if should_run_callbacks @_committed_already_called = true _run_commit_without_transaction_enrollment_callbacks _run_commit_callbacks @@ -346,7 +346,7 @@ module ActiveRecord # Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record # state should be rolled back to the beginning or just to the last savepoint. def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc: - if should_run_callbacks && trigger_transactional_callbacks? + if should_run_callbacks _run_rollback_callbacks _run_rollback_without_transaction_enrollment_callbacks end @@ -378,6 +378,11 @@ module ActiveRecord status end + def trigger_transactional_callbacks? # :nodoc: + (@_new_record_before_last_commit || _trigger_update_callback) && persisted? || + _trigger_destroy_callback && destroyed? + end + private attr_reader :_committed_already_called, :_trigger_update_callback, :_trigger_destroy_callback @@ -392,10 +397,7 @@ module ActiveRecord level: 0 } @_start_transaction_state[:level] += 1 - remember_new_record_before_last_commit - end - def remember_new_record_before_last_commit if _committed_already_called @_new_record_before_last_commit = false else @@ -457,10 +459,6 @@ module ActiveRecord self.class.connection.add_transaction_record(self) end - def trigger_transactional_callbacks? - @_new_record_before_last_commit && !new_record? || _trigger_update_callback || _trigger_destroy_callback - end - def has_transactional_callbacks? !_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty? end |