aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/transaction.rb124
1 files changed, 124 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
new file mode 100644
index 0000000000..0a4649ffa7
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
@@ -0,0 +1,124 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Transaction # :nodoc:
+ class State
+ attr_reader :connection
+
+ def initialize(connection)
+ @connection = connection
+ end
+ end
+
+ class Closed < State
+ def begin
+ Open.new(connection, self)
+ end
+
+ def closed?
+ true
+ end
+
+ def open?
+ false
+ end
+
+ # This is a noop when there are no open transactions
+ def add_record(record)
+ end
+ end
+
+ class Open < State
+ attr_reader :parent, :records
+
+ def initialize(connection, parent)
+ super connection
+
+ @parent = parent
+ @records = []
+
+ if parent.open?
+ connection.create_savepoint
+ else
+ connection.begin_db_transaction
+ end
+
+ connection.increment_open_transactions
+ end
+
+ def begin
+ Open.new(connection, self)
+ end
+
+ def rollback
+ connection.decrement_open_transactions
+
+ if parent.open?
+ connection.rollback_to_savepoint
+ else
+ connection.rollback_db_transaction
+ end
+
+ rollback_records
+ parent
+ end
+
+ def commit
+ connection.decrement_open_transactions
+
+ begin
+ if parent.open?
+ connection.release_savepoint
+ records.each { |r| parent.add_record(r) }
+ else
+ connection.commit_db_transaction
+ commit_records
+ end
+ rescue Exception
+ if parent.open?
+ connection.rollback_to_savepoint
+ else
+ connection.rollback_db_transaction
+ end
+
+ rollback_records
+ raise
+ end
+
+ parent
+ end
+
+ def add_record(record)
+ records << record
+ end
+
+ def rollback_records
+ records.uniq.each do |record|
+ begin
+ record.rolledback!(parent.closed?)
+ rescue => e
+ record.logger.error(e) if record.respond_to?(:logger) && record.logger
+ end
+ end
+ end
+
+ def commit_records
+ records.uniq.each do |record|
+ begin
+ record.committed!
+ rescue => e
+ record.logger.error(e) if record.respond_to?(:logger) && record.logger
+ end
+ end
+ end
+
+ def closed?
+ false
+ end
+
+ def open?
+ true
+ end
+ end
+ end
+ end
+end