@@ -45,6 +45,80 @@ def supports_statement_cache?
4545 true
4646 end
4747
48+ def transaction ( options = { } )
49+ options . assert_valid_keys :requires_new , :joinable
50+
51+ last_transaction_joinable = defined? ( @transaction_joinable ) ? @transaction_joinable : nil
52+ if options . has_key? ( :joinable )
53+ @transaction_joinable = options [ :joinable ]
54+ else
55+ @transaction_joinable = true
56+ end
57+ requires_new = options [ :requires_new ] || !last_transaction_joinable
58+
59+ transaction_open = false
60+ @_current_transaction_records ||= [ ]
61+
62+ begin
63+ if block_given?
64+ if requires_new || open_transactions == 0
65+ if open_transactions == 0
66+ begin_db_transaction
67+ elsif requires_new
68+ create_savepoint
69+ end
70+ increment_open_transactions
71+ transaction_open = true
72+ @_current_transaction_records . push ( [ ] )
73+ end
74+ yield
75+ end
76+ rescue Exception => database_transaction_rollback
77+ if transaction_open && !outside_transaction?
78+ transaction_open = false
79+ decrement_open_transactions
80+ if open_transactions == 0
81+ rollback_db_transaction
82+ rollback_transaction_records ( true )
83+ else
84+ rollback_to_savepoint
85+ rollback_transaction_records ( false )
86+ end
87+ end
88+ raise unless database_transaction_rollback . is_a? ( ActiveRecord ::Rollback )
89+ end
90+ ensure
91+ @transaction_joinable = last_transaction_joinable
92+
93+ if outside_transaction?
94+ @open_transactions = 0
95+ elsif transaction_open
96+ decrement_open_transactions
97+ begin
98+ if open_transactions == 0
99+ commit_db_transaction
100+ commit_transaction_records
101+ else
102+ release_savepoint
103+ save_point_records = @_current_transaction_records . pop
104+ unless save_point_records . blank?
105+ @_current_transaction_records . push ( [ ] ) if @_current_transaction_records . empty?
106+ @_current_transaction_records . last . concat ( save_point_records )
107+ end
108+ end
109+ rescue Exception => database_transaction_rollback
110+ if open_transactions == 0
111+ rollback_db_transaction
112+ rollback_transaction_records ( true )
113+ else
114+ rollback_to_savepoint
115+ rollback_transaction_records ( false )
116+ end
117+ raise
118+ end
119+ end
120+ end
121+
48122 def begin_db_transaction
49123 do_execute "BEGIN TRANSACTION"
50124 end
0 commit comments