add nested transaction with savepoints

This commit is contained in:
Brian J. Cardiff 2016-12-13 16:15:25 -03:00
parent 9bde76865e
commit c491bd8962
4 changed files with 243 additions and 3 deletions

View file

@ -68,6 +68,29 @@ class DummyDriver < DB::Driver
super
@rolledback = true
end
protected def create_save_point_transaction(parent, savepoint_name : String)
DummySavePointTransaction.new(parent, savepoint_name)
end
end
class DummySavePointTransaction < DB::SavePointTransaction
getter committed = false
getter rolledback = false
def initialize(parent, savepoint_name)
super(parent, savepoint_name)
end
def commit
super
@committed = true
end
def rollback
super
@rolledback = true
end
end
class DummyStatement < DB::Statement

View file

@ -0,0 +1,127 @@
require "./spec_helper"
private class FooException < Exception
end
private def with_dummy_top_transaction
with_dummy_connection do |cnn|
cnn.transaction do |tx|
yield tx.as(DummyDriver::DummyTransaction), cnn
end
end
end
private def with_dummy_nested_transaction
with_dummy_connection do |cnn|
cnn.transaction do |tx|
tx.transaction do |nested|
yield nested.as(DummyDriver::DummySavePointTransaction), cnn
end
end
end
end
describe DB::SavePointTransaction do
{% for context in [:with_dummy_top_transaction, :with_dummy_nested_transaction] %}
describe "{{context.id}}" do
it "begin/commit transaction from parent transaction" do
{{context.id}} do |parent_tx|
tx = parent_tx.begin_transaction
tx.commit
end
end
it "begin/rollback transaction from parent transaction" do
{{context.id}} do |parent_tx|
tx = parent_tx.begin_transaction
tx.rollback
end
end
it "raise if begin over existing transaction" do
{{context.id}} do |parent_tx|
parent_tx.begin_transaction
expect_raises(DB::Error, "There is an existing nested transaction in this transaction") do
parent_tx.begin_transaction
end
end
end
it "allow sequential transactions" do
{{context.id}} do |parent_tx|
tx = parent_tx.begin_transaction
tx.rollback
tx = parent_tx.begin_transaction
tx.commit
end
end
it "transaction with block from parent transaction should be committed" do
t = uninitialized DummyDriver::DummySavePointTransaction
with_witness do |w|
{{context.id}} do |parent_tx|
parent_tx.transaction do |tx|
if tx.is_a?(DummyDriver::DummySavePointTransaction)
t = tx
w.check
end
end
end
end
t.committed.should be_true
t.rolledback.should be_false
end
end
{% end %}
it "only nested transaction with block from parent transaction should be rolledback if raise DB::Rollback" do
top = uninitialized DummyDriver::DummyTransaction
t = uninitialized DummyDriver::DummySavePointTransaction
with_witness do |w|
with_dummy_top_transaction do |parent_tx|
top = parent_tx
parent_tx.transaction do |tx|
if tx.is_a?(DummyDriver::DummySavePointTransaction)
t = tx
w.check
end
raise DB::Rollback.new
end
end
end
t.rolledback.should be_true
t.committed.should be_false
top.rolledback.should be_false
top.committed.should be_true
end
it "only nested transaction with block from parent nested transaction should be rolledback if raise DB::Rollback" do
top = uninitialized DummyDriver::DummySavePointTransaction
t = uninitialized DummyDriver::DummySavePointTransaction
with_witness do |w|
with_dummy_nested_transaction do |parent_tx|
top = parent_tx
parent_tx.transaction do |tx|
if tx.is_a?(DummyDriver::DummySavePointTransaction)
t = tx
w.check
end
raise DB::Rollback.new
end
end
end
t.rolledback.should be_true
t.committed.should be_false
top.rolledback.should be_false
top.committed.should be_true
end
end