From 368525a5a5b43a2955d063c2f81af5d6ed1c2188 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 24 Jul 2014 16:25:34 -0400 Subject: Remove finishing? method from transaction. The finishing variable on the transaction object was a work-around for the savepoint name, so after a rollback/commit the savepoint could be released with the previous name. related: 9296e6939bcc786149a07dac334267c4035b623a 60c88e64e26682a954f7c8cd6669d409ffffcc8b --- .../connection_adapters/abstract/transaction.rb | 33 +++++++--------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index bc4884b538..1721437615 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -78,45 +78,28 @@ module ActiveRecord @parent = parent @records = [] - @finishing = false @joinable = options.fetch(:joinable, true) end - # This state is necessary so that we correctly handle stuff that might - # happen in a commit/rollback. But it's kinda distasteful. Maybe we can - # find a better way to structure it in the future. - def finishing? - @finishing - end def joinable? - @joinable && !finishing? + @joinable end def number - if finishing? - parent.number - else - parent.number + 1 - end + parent.number + 1 end def begin(options = {}) - if finishing? - parent.begin - else - SavepointTransaction.new(connection, self, options) - end + SavepointTransaction.new(connection, self, options) end def rollback - @finishing = true perform_rollback parent end def commit - @finishing = true perform_commit parent end @@ -183,24 +166,28 @@ module ActiveRecord end class SavepointTransaction < OpenTransaction #:nodoc: + attr_reader :savepoint_name + def initialize(connection, parent, options = {}) if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end super - connection.create_savepoint + + @savepoint_name = "active_record_#{number}" + connection.create_savepoint(@savepoint_name) end def perform_rollback - connection.rollback_to_savepoint + connection.rollback_to_savepoint(@savepoint_name) rollback_records end def perform_commit @state.set_state(:committed) @state.parent = parent.state - connection.release_savepoint + connection.release_savepoint(@savepoint_name) end end end -- cgit v1.2.3 From 97bb76dc288d998a684b17a09d79708e2e4b584a Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 24 Jul 2014 13:37:49 -0400 Subject: Transactions refactoring Add a transaction manager per connection, so it can controls the connection responsibilities. Delegate transaction methods to transaction_manager --- .../connection_adapters/abstract/transaction.rb | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 1721437615..7618d6902d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -1,5 +1,63 @@ module ActiveRecord module ConnectionAdapters + class TransactionManager #:nodoc: + def initialize(connection) + @stack = [] + @connection = connection + end + + def begin_transaction(options = {}) + transaction = + if @stack.empty? + RealTransaction.new(@connection, current_transaction, options) + else + SavepointTransaction.new(@connection, current_transaction, options) + end + + @stack.push(transaction) + transaction + end + + def commit_transaction + @stack.pop.commit + end + + def rollback_transaction + @stack.pop.rollback + end + + def within_new_transaction(options = {}) + transaction = begin_transaction options + yield + rescue Exception => error + transaction.rollback if transaction + raise + ensure + begin + transaction.commit unless error + rescue Exception + transaction.rollback + raise + ensure + @stack.pop if transaction + end + end + + def open_transactions + @stack.size + end + + def current_transaction + @stack.last || closed_transaction + end + + private + + def closed_transaction + @closed_transaction ||= ClosedTransaction.new(@connection) + end + end + class Transaction #:nodoc: attr_reader :connection -- cgit v1.2.3 From d37bcc1d5a781687384fbe632a1850ab218ccbfd Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 28 Jul 2014 13:25:19 -0400 Subject: savepoint_name should return nil for non-savepoint transactions Also add test to assets the savepoint name --- .../lib/active_record/connection_adapters/abstract/transaction.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 7618d6902d..54f873a2a2 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -69,6 +69,10 @@ module ActiveRecord def state @state end + + def savepoint_name + nil + end end class TransactionState @@ -233,7 +237,8 @@ module ActiveRecord super - @savepoint_name = "active_record_#{number}" + # Savepoint name only counts the Savepoint transactions, so we need to subtract 1 + @savepoint_name = "active_record_#{number - 1}" connection.create_savepoint(@savepoint_name) end -- cgit v1.2.3 From f5cec76ea8de1b9d076d0b1138ab8c2cabc0390d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 28 Jul 2014 15:04:31 -0300 Subject: Extract the transaction class to a local variable --- .../lib/active_record/connection_adapters/abstract/transaction.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 54f873a2a2..3a266512a9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -7,12 +7,8 @@ module ActiveRecord end def begin_transaction(options = {}) - transaction = - if @stack.empty? - RealTransaction.new(@connection, current_transaction, options) - else - SavepointTransaction.new(@connection, current_transaction, options) - end + transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction + transaction = transaction_class.new(@connection, current_transaction, options) @stack.push(transaction) transaction -- cgit v1.2.3 From dd9829a9ea460ddcfc8d954f2b95161b52fff6e7 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Tue, 29 Jul 2014 10:09:06 -0400 Subject: Remove @state.parent assignment on commit This piece of code was introduced on 67d8bb963d5d51fc644d6b1ca20164efb4cee6d7 , which was calling `committed?` in the `transaction_state` before calling the `committed!` method. However on 7386ffc781fca07a0c656db49fdb54678caef809, the `committed?` check was removed and replaced by a `finalized?`, which only checks if the state is not nil. Thus we can remove that line. --- .../lib/active_record/connection_adapters/abstract/transaction.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 3a266512a9..33cc22425d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -72,7 +72,7 @@ module ActiveRecord end class TransactionState - attr_accessor :parent + attr_reader :parent VALID_STATES = Set.new([:committed, :rolledback, nil]) @@ -245,7 +245,6 @@ module ActiveRecord def perform_commit @state.set_state(:committed) - @state.parent = parent.state connection.release_savepoint(@savepoint_name) end end -- cgit v1.2.3 From 91e4b65093f0c485507dadcb018c1f0d2661ba89 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 28 Jul 2014 14:26:27 -0400 Subject: Remove being/number methods from transaction class --- .../connection_adapters/abstract/transaction.rb | 35 +++++----------------- 1 file changed, 8 insertions(+), 27 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 33cc22425d..1691daf861 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -8,7 +8,7 @@ module ActiveRecord def begin_transaction(options = {}) transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, current_transaction, options) + transaction = transaction_class.new(@connection, current_transaction, "active_record_#{@stack.size}", options) @stack.push(transaction) transaction @@ -102,14 +102,6 @@ module ActiveRecord end class ClosedTransaction < Transaction #:nodoc: - def number - 0 - end - - def begin(options = {}) - RealTransaction.new(connection, self, options) - end - def closed? true end @@ -144,14 +136,6 @@ module ActiveRecord @joinable end - def number - parent.number + 1 - end - - def begin(options = {}) - SavepointTransaction.new(connection, self, options) - end - def rollback perform_rollback parent @@ -202,8 +186,8 @@ module ActiveRecord end class RealTransaction < OpenTransaction #:nodoc: - def initialize(connection, parent, options = {}) - super + def initialize(connection, parent, _, options = {}) + super(connection, parent, options) if options[:isolation] connection.begin_isolated_db_transaction(options[:isolation]) @@ -226,26 +210,23 @@ module ActiveRecord class SavepointTransaction < OpenTransaction #:nodoc: attr_reader :savepoint_name - def initialize(connection, parent, options = {}) + def initialize(connection, parent, savepoint_name, options = {}) if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end - super - - # Savepoint name only counts the Savepoint transactions, so we need to subtract 1 - @savepoint_name = "active_record_#{number - 1}" - connection.create_savepoint(@savepoint_name) + super(connection, parent, options) + connection.create_savepoint(@savepoint_name = savepoint_name) end def perform_rollback - connection.rollback_to_savepoint(@savepoint_name) + connection.rollback_to_savepoint(savepoint_name) rollback_records end def perform_commit @state.set_state(:committed) - connection.release_savepoint(@savepoint_name) + connection.release_savepoint(savepoint_name) end end end -- cgit v1.2.3 From dac9c92e3096ae196d7ea4b58e7141f4a36007ea Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 28 Jul 2014 13:07:47 -0400 Subject: Remove parent on Transaction object --- .../connection_adapters/abstract/transaction.rb | 25 ++++++++-------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 1691daf861..17d57a7519 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -8,7 +8,7 @@ module ActiveRecord def begin_transaction(options = {}) transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, current_transaction, "active_record_#{@stack.size}", options) + transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) @stack.push(transaction) transaction @@ -55,17 +55,13 @@ module ActiveRecord end class Transaction #:nodoc: - attr_reader :connection + attr_reader :connection, :state def initialize(connection) @connection = connection @state = TransactionState.new end - def state - @state - end - def savepoint_name nil end @@ -120,13 +116,12 @@ module ActiveRecord end class OpenTransaction < Transaction #:nodoc: - attr_reader :parent, :records + attr_reader :records attr_writer :joinable - def initialize(connection, parent, options = {}) + def initialize(connection, options = {}) super connection - @parent = parent @records = [] @joinable = options.fetch(:joinable, true) end @@ -138,12 +133,10 @@ module ActiveRecord def rollback perform_rollback - parent end def commit perform_commit - parent end def add_record(record) @@ -158,7 +151,7 @@ module ActiveRecord @state.set_state(:rolledback) records.uniq.each do |record| begin - record.rolledback!(parent.closed?) + record.rolledback!(self.is_a?(RealTransaction)) rescue => e record.logger.error(e) if record.respond_to?(:logger) && record.logger end @@ -186,8 +179,8 @@ module ActiveRecord end class RealTransaction < OpenTransaction #:nodoc: - def initialize(connection, parent, _, options = {}) - super(connection, parent, options) + def initialize(connection, _, options = {}) + super(connection, options) if options[:isolation] connection.begin_isolated_db_transaction(options[:isolation]) @@ -210,12 +203,12 @@ module ActiveRecord class SavepointTransaction < OpenTransaction #:nodoc: attr_reader :savepoint_name - def initialize(connection, parent, savepoint_name, options = {}) + def initialize(connection, savepoint_name, options = {}) if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end - super(connection, parent, options) + super(connection, options) connection.create_savepoint(@savepoint_name = savepoint_name) end -- cgit v1.2.3 From 4140797967a8f50eccaa70614c01531dab6a90f4 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Wed, 30 Jul 2014 14:32:56 -0400 Subject: Make ClosedTransaction a null object --- .../connection_adapters/abstract/transaction.rb | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 17d57a7519..ff7f922d7f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -50,7 +50,7 @@ module ActiveRecord private def closed_transaction - @closed_transaction ||= ClosedTransaction.new(@connection) + @closed_transaction ||= ClosedTransaction.new end end @@ -98,21 +98,12 @@ module ActiveRecord end class ClosedTransaction < Transaction #:nodoc: - def closed? - true - end - - def open? - false - end - - def joinable? - false - end - + def initialize; super(nil); end + def closed?; true; end + def open?; false; end + def joinable?; false; end # This is a noop when there are no open transactions - def add_record(record) - end + def add_record(record); end end class OpenTransaction < Transaction #:nodoc: @@ -126,7 +117,6 @@ module ActiveRecord @joinable = options.fetch(:joinable, true) end - def joinable? @joinable end -- cgit v1.2.3 From 62c75f4eacf6466a3bd1b22f97cda7ab7b597064 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 31 Jul 2014 16:25:51 -0400 Subject: Move TransactionManager to bottom of class --- .../connection_adapters/abstract/transaction.rb | 134 ++++++++++----------- 1 file changed, 67 insertions(+), 67 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index ff7f922d7f..e6a53b2122 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -1,72 +1,5 @@ module ActiveRecord module ConnectionAdapters - class TransactionManager #:nodoc: - def initialize(connection) - @stack = [] - @connection = connection - end - - def begin_transaction(options = {}) - transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) - - @stack.push(transaction) - transaction - end - - def commit_transaction - @stack.pop.commit - end - - def rollback_transaction - @stack.pop.rollback - end - - def within_new_transaction(options = {}) - transaction = begin_transaction options - yield - rescue Exception => error - transaction.rollback if transaction - raise - ensure - begin - transaction.commit unless error - rescue Exception - transaction.rollback - raise - ensure - @stack.pop if transaction - end - end - - def open_transactions - @stack.size - end - - def current_transaction - @stack.last || closed_transaction - end - - private - - def closed_transaction - @closed_transaction ||= ClosedTransaction.new - end - end - - class Transaction #:nodoc: - attr_reader :connection, :state - - def initialize(connection) - @connection = connection - @state = TransactionState.new - end - - def savepoint_name - nil - end - end - class TransactionState attr_reader :parent @@ -97,6 +30,19 @@ module ActiveRecord end end + class Transaction #:nodoc: + attr_reader :connection, :state + + def initialize(connection) + @connection = connection + @state = TransactionState.new + end + + def savepoint_name + nil + end + end + class ClosedTransaction < Transaction #:nodoc: def initialize; super(nil); end def closed?; true; end @@ -212,5 +158,59 @@ module ActiveRecord connection.release_savepoint(savepoint_name) end end + + class TransactionManager #:nodoc: + def initialize(connection) + @stack = [] + @connection = connection + end + + def begin_transaction(options = {}) + transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction + transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) + + @stack.push(transaction) + transaction + end + + def commit_transaction + @stack.pop.commit + end + + def rollback_transaction + @stack.pop.rollback + end + + def within_new_transaction(options = {}) + transaction = begin_transaction options + yield + rescue Exception => error + transaction.rollback if transaction + raise + ensure + begin + transaction.commit unless error + rescue Exception + transaction.rollback + raise + ensure + @stack.pop if transaction + end + end + + def open_transactions + @stack.size + end + + def current_transaction + @stack.last || closed_transaction + end + + private + + def closed_transaction + @closed_transaction ||= ClosedTransaction.new + end + end end end -- cgit v1.2.3 From 057c23715434adcab9b12f987d615979d1f57549 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 31 Jul 2014 16:31:33 -0400 Subject: Replace ClosedTransaction with NullTransaction --- .../active_record/connection_adapters/abstract/transaction.rb | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index e6a53b2122..46aaaae2ec 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -43,8 +43,8 @@ module ActiveRecord end end - class ClosedTransaction < Transaction #:nodoc: - def initialize; super(nil); end + class NullTransaction < Transaction #:nodoc: + def initialize; end def closed?; true; end def open?; false; end def joinable?; false; end @@ -203,14 +203,11 @@ module ActiveRecord end def current_transaction - @stack.last || closed_transaction + @stack.last || NULL_TRANSACTION end private - - def closed_transaction - @closed_transaction ||= ClosedTransaction.new - end + NULL_TRANSACTION = NullTransaction.new end end end -- cgit v1.2.3 From 8298d3adb72eb17186dc0b155afec308071a3900 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Thu, 31 Jul 2014 16:44:55 -0400 Subject: Cleanup Transaction inheritance. Transaction class doesnt need to encapsulate the transaction state using inheritance. This removes all Transaction subclasses, and let the Transaction object controls different actions based on its own state. Basically the only actions would behave differently are `being`,`commit`,`rollback` as they could act in a savepoint or in a real transaction. --- .../connection_adapters/abstract/transaction.rb | 124 +++++++++------------ 1 file changed, 54 insertions(+), 70 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 46aaaae2ec..4a7f2aaca8 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -30,49 +30,24 @@ module ActiveRecord end end - class Transaction #:nodoc: - attr_reader :connection, :state - - def initialize(connection) - @connection = connection - @state = TransactionState.new - end - - def savepoint_name - nil - end - end - - class NullTransaction < Transaction #:nodoc: + class NullTransaction #:nodoc: def initialize; end def closed?; true; end def open?; false; end def joinable?; false; end - # This is a noop when there are no open transactions def add_record(record); end end - class OpenTransaction < Transaction #:nodoc: - attr_reader :records - attr_writer :joinable - - def initialize(connection, options = {}) - super connection - - @records = [] - @joinable = options.fetch(:joinable, true) - end - - def joinable? - @joinable - end + class Transaction #:nodoc: - def rollback - perform_rollback - end + attr_reader :connection, :state, :records, :savepoint_name + attr_writer :joinable - def commit - perform_commit + def initialize(connection, options) + @connection = connection + @state = TransactionState.new + @records = [] + @joinable = options.fetch(:joinable, true) end def add_record(record) @@ -83,19 +58,25 @@ module ActiveRecord end end - def rollback_records + def rollback @state.set_state(:rolledback) + end + + def rollback_records records.uniq.each do |record| begin - record.rolledback!(self.is_a?(RealTransaction)) + record.rolledback! full_rollback? rescue => e record.logger.error(e) if record.respond_to?(:logger) && record.logger end end end - def commit_records + def commit @state.set_state(:committed) + end + + def commit_records records.uniq.each do |record| begin record.committed! @@ -105,57 +86,57 @@ module ActiveRecord end end - def closed? - false - end - - def open? - true - end + def full_rollback?; true; end + def joinable?; @joinable; end + def closed?; false; end + def open?; !closed?; end end - class RealTransaction < OpenTransaction #:nodoc: - def initialize(connection, _, options = {}) - super(connection, options) + class SavepointTransaction < Transaction + def initialize(connection, savepoint_name, options) + super(connection, options) if options[:isolation] - connection.begin_isolated_db_transaction(options[:isolation]) - else - connection.begin_db_transaction + raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end + connection.create_savepoint(@savepoint_name = savepoint_name) end - def perform_rollback - connection.rollback_db_transaction + def rollback + super + connection.rollback_to_savepoint(savepoint_name) rollback_records end - def perform_commit - connection.commit_db_transaction - commit_records + def commit + super + connection.release_savepoint(savepoint_name) end + + def full_rollback?; false; end end - class SavepointTransaction < OpenTransaction #:nodoc: - attr_reader :savepoint_name + class RealTransaction < Transaction - def initialize(connection, savepoint_name, options = {}) + def initialize(connection, options) + super if options[:isolation] - raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" + connection.begin_isolated_db_transaction(options[:isolation]) + else + connection.begin_db_transaction end - - super(connection, options) - connection.create_savepoint(@savepoint_name = savepoint_name) end - def perform_rollback - connection.rollback_to_savepoint(savepoint_name) + def rollback + super + connection.rollback_db_transaction rollback_records end - def perform_commit - @state.set_state(:committed) - connection.release_savepoint(savepoint_name) + def commit + super + connection.commit_db_transaction + commit_records end end @@ -166,9 +147,12 @@ module ActiveRecord end def begin_transaction(options = {}) - transaction_class = @stack.empty? ? RealTransaction : SavepointTransaction - transaction = transaction_class.new(@connection, "active_record_#{@stack.size}", options) - + transaction = + if @stack.empty? + RealTransaction.new(@connection, options) + else + SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options) + end @stack.push(transaction) transaction end -- cgit v1.2.3