Added nested transaction support.

Added test cases showing transaction support scenarios.
This commit is contained in:
jvelilla
2014-10-13 18:45:45 -03:00
parent 8d79447cf8
commit 609d71a0e9
2 changed files with 304 additions and 0 deletions

View File

@@ -131,6 +131,142 @@ feature -- Transactions
retry retry
end end
feature --
is_connected_to_storage: BOOLEAN
-- Is connected to the database
do
Result := db_control.is_connected
end
feature -- Transaction Status
in_transaction_session: BOOLEAN
-- Is session started?
transaction_session_depth: INTEGER
-- Depth in the transaction session
feature -- Transaction Operation
begin_transaction2
-- Start session
-- if already started, increase the `transaction_session_depth'
require
in_transaction_session implies transaction_session_depth > 0
not in_transaction_session implies transaction_session_depth = 0
local
l_session_control: like db_control
l_retried: INTEGER
do
if l_retried = 0 then
if not in_transaction_session then
database_error_handler.reset
check transaction_session_depth = 0 end
debug ("database_session")
print ("..Start session%N")
end
connect -- connect the DB
if is_connected_to_storage then
in_transaction_session := True
db_control.begin -- start transaction
else
l_session_control := db_control
if not l_session_control.is_ok then
database_error_handler.add_database_error (l_session_control.error_message_32, l_session_control.error_code)
else
database_error_handler.add_database_error ("Session_not_started_error_message", 0)
end
l_session_control.reset
end
end
transaction_session_depth := transaction_session_depth + 1
else
if l_retried = 1 then
transaction_session_depth := transaction_session_depth + 1
if attached (create {EXCEPTION_MANAGER}).last_exception as e then
if attached {ASSERTION_VIOLATION} e then
--| Ignore for now with MYSQL ...
else
exception_as_error (e)
end
end
in_transaction_session := False
db_control.reset
else
in_transaction_session := False
end
end
ensure
transaction_session_depth = (old transaction_session_depth) + 1
rescue
l_retried := l_retried + 1
retry
end
commit2
-- End session
local
l_retried: BOOLEAN
do
if not l_retried then
transaction_session_depth := transaction_session_depth - 1
if transaction_session_depth = 0 then
debug ("database_session")
print ("..End session%N")
end
if is_connected_to_storage then
if not database_error_handler.has_error then
db_control.commit -- Commit transaction
else
db_control.rollback -- Rollback transaction
end
end
in_transaction_session := False
end
else
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
in_transaction_session := False
transaction_session_depth := transaction_session_depth - 1
db_control.reset
end
rescue
l_retried := True
retry
end
rollback2
-- End session
local
l_retried: BOOLEAN
do
if not l_retried then
transaction_session_depth := transaction_session_depth - 1
if transaction_session_depth = 0 then
debug ("database_session")
print ("..End session%N")
end
if is_connected_to_storage then
db_control.rollback -- Rollback transaction
end
in_transaction_session := False
end
else
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
in_transaction_session := False
transaction_session_depth := transaction_session_depth - 1
db_control.reset
end
rescue
l_retried := True
retry
end
feature -- Change Element feature -- Change Element
not_keep_connection not_keep_connection

View File

@@ -0,0 +1,168 @@
note
description: "[
Eiffel tests that can be executed by testing tool.
]"
author: "EiffelStudio test wizard"
date: "$Date$"
revision: "$Revision$"
testing: "type/manual"
class
TRANSACTION_TEST_SET
inherit
EQA_TEST_SET
redefine
on_prepare,
on_clean
select
default_create
end
ABSTRACT_DB_TEST
rename
default_create as default_db_test
end
feature {NONE} -- Events
on_prepare
-- <Precursor>
do
(create {CLEAN_DB}).clean_db(connection)
end
on_clean
-- <Precursor>
do
end
feature -- Test routines
test_user_rollback
note
testing: "execution/isolated"
do
connection.begin_transaction
user_provider.new_user ("test", "test","test@admin.com")
assert ("Has user:", user_provider.has_user)
connection.rollback
assert ("Not has user:", not user_provider.has_user)
end
test_user_node_rollback
note
testing: "execution/isolated"
do
connection.begin_transaction
user_provider.new_user ("test", "test","test@admin.com")
assert ("Has user:", user_provider.has_user)
node_provider.new_node (default_node)
node_provider.add_author (1, 1)
assert ("Has one node:", node_provider.count = 1)
connection.rollback
assert ("Not has user:", not user_provider.has_user)
assert ("Not has nodes:", node_provider.count = 0)
end
test_user_node_nested_transaction_with_rollback_not_supported
note
testing: "execution/isolated"
do
connection.begin_transaction2
user_provider.new_user ("test", "test","test@admin.com")
assert ("Has user:", user_provider.has_user)
node_provider.new_node (default_node)
assert ("Has one node:", node_provider.count = 1)
connection.begin_transaction2
user_provider.new_user ("test1", "test1","test1@admin.com")
assert ("Has user: test1", attached user_provider.user_by_name ("test1"))
connection.rollback2
connection.commit2
assert ("Has user test:", attached user_provider.user_by_name ("test"))
assert ("Has nodes:", node_provider.count = 1)
assert ("Not has user: test1", user_provider.user_by_name ("test1") = Void)
end
test_user_node_nested_transaction_with_commit
note
testing: "execution/isolated"
do
connection.begin_transaction2
user_provider.new_user ("test", "test","test@admin.com")
assert ("Has user:", user_provider.has_user)
node_provider.new_node (default_node)
assert ("Has one node:", node_provider.count = 1)
connection.begin_transaction2
user_provider.new_user ("test1", "test1","test1@admin.com")
assert ("Has user: test1", attached user_provider.user_by_name ("test1"))
connection.commit2
connection.commit2
assert ("Has user test:", attached user_provider.user_by_name ("test"))
assert ("Has user test1:", attached user_provider.user_by_name ("test1"))
assert ("Has nodes:", node_provider.count = 1)
end
test_user_node_nested_transaction_with_rollback
note
testing: "execution/isolated"
do
connection.begin_transaction2
user_provider.new_user ("test", "test","test@admin.com")
assert ("Has user:", user_provider.has_user)
node_provider.new_node (default_node)
assert ("Has one node:", node_provider.count = 1)
connection.begin_transaction2
user_provider.new_user ("test1", "test1","test1@admin.com")
assert ("Has user: test1", attached user_provider.user_by_name ("test1"))
connection.commit2
connection.rollback2
assert ("Not Has user test:", user_provider.user_by_name ("test") = void)
assert ("Not Has user test1:", user_provider.user_by_name ("test1") = void)
assert ("Has 0 nodes:", node_provider.count = 0)
end
feature {NONE} -- Implementation
node_provider: NODE_DATA_PROVIDER
-- node provider.
once
create Result.make (connection)
end
user_provider: USER_DATA_PROVIDER
-- user provider.
once
create Result.make (connection)
end
feature {NONE} -- Implementation Fixture Factories
default_node: CMS_NODE
do
Result := custom_node ("Default content", "default summary", "Default")
end
custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE
do
create Result.make (a_content, a_summary, a_title)
end
end