Discussion:
[Wt-interest] Question about Wt::Dbo example code -- Transaction destructor and rollback
K. Frank
2015-08-03 18:56:46 UTC
Permalink
Hello List!

I am looking at the Wt::Dbo tutorial:

http://www.webtoolkit.eu/wt/doc/tutorial/dbo.html

and, specifically, the example code:

...
/*
* A unit of work happens always within a transaction.
*/
dbo::Transaction transaction(session);

User *user = new User();
user->name = "Joe";
user->password = "Secret";
user->role = User::Visitor;
user->karma = 13;

dbo::ptr<User> userPtr = session.add(user);
}

I would like to clarify a few points:

First, as I understand it, the constructor of Wt::Dbo::Transaction
(called when the local variable "transaction" is declared) causes
the "begin transaction" SQL statement to be called. Is this correct?

Then, when the destructor is called (when "transaction" goes out
of scope at the closing brace in the example), the transaction is
committed, i.e., the "commit transaction" SQL statement is called.
Is this also correct?

I'm a little confused about what happens if an exception is thrown.
Presumably an SQL "rollback transaction" will be executed. But
how? Destructors will be called for local variable within the try block.
So, tweaking the example code a little:

try {
dbo::Transaction transaction(session);

User *user = new User();
user->name = "Joe";
user->password = "Secret";
user->role = User::Visitor;
user->karma = 13;

dbo::ptr<User> userPtr = session.add(user);
}
catch (...) {
// ...
}

If an exception is thrown in the try block, the destructor for "transaction"
will be called. How will this destructor know to call "rollback transaction",
rather than "commit transaction"? One possibility is that if the call to
"session.add" fails and throws an exception, it could first set some
"dirty transaction" flag that gets inspection by Wt::Dbo::Transaction's
destructor. But what if it's not a Wt::Dbo exception? Suppose I add
the line "if (42) throw 17;" to the try block. How would the destructor
then know to roll back the SQL transaction?

(Or is this some kind of c++ thing where the destructor "knows" that
it's being called in an exception-triggered stack unwind?)


Thanks for any clarification.


K. Frank

------------------------------------------------------------------------------
Aaron Laws
2015-08-03 20:22:38 UTC
Permalink
Post by K. Frank
Hello List!
http://www.webtoolkit.eu/wt/doc/tutorial/dbo.html
...
/*
* A unit of work happens always within a transaction.
*/
dbo::Transaction transaction(session);
User *user = new User();
user->name = "Joe";
user->password = "Secret";
user->role = User::Visitor;
user->karma = 13;
dbo::ptr<User> userPtr = session.add(user);
}
First, as I understand it, the constructor of Wt::Dbo::Transaction
(called when the local variable "transaction" is declared) causes
the "begin transaction" SQL statement to be called. Is this correct?
yup. To see evidence of this (and much more), use
Wt::Dbo::backend::Sqlite3::setProperty("show-queries", "true");
Post by K. Frank
Then, when the destructor is called (when "transaction" goes out
of scope at the closing brace in the example), the transaction is
committed, i.e., the "commit transaction" SQL statement is called.
Is this also correct?
As long as no exception is being thrown, yes.
Post by K. Frank
I'm a little confused about what happens if an exception is thrown.
Presumably an SQL "rollback transaction" will be executed. But
how? Destructors will be called for local variable within the try block.
try {
dbo::Transaction transaction(session);
User *user = new User();
user->name = "Joe";
user->password = "Secret";
user->role = User::Visitor;
user->karma = 13;
dbo::ptr<User> userPtr = session.add(user);
}
catch (...) {
// ...
}
If an exception is thrown in the try block, the destructor for
"transaction"
will be called. How will this destructor know to call "rollback transaction",
rather than "commit transaction"? One possibility is that if the call to
"session.add" fails and throws an exception, it could first set some
"dirty transaction" flag that gets inspection by Wt::Dbo::Transaction's
destructor. But what if it's not a Wt::Dbo exception? Suppose I add
the line "if (42) throw 17;" to the try block. How would the destructor
then know to roll back the SQL transaction?
(Or is this some kind of c++ thing where the destructor "knows" that
it's being called in an exception-triggered stack unwind?)
It's some kind of C++ thing:
http://en.cppreference.com/w/cpp/error/uncaught_exception

Happy coding!

In Christ,
Aaron Laws
K. Frank
2015-08-04 01:23:27 UTC
Permalink
Aaron -

Thanks for your answers.
Post by Aaron Laws
Post by K. Frank
Hello List!
http://www.webtoolkit.eu/wt/doc/tutorial/dbo.html
...
I'm a little confused about what happens if an exception is thrown.
Presumably an SQL "rollback transaction" will be executed. But
how? Destructors will be called for local variable within the try block.
try {
dbo::Transaction transaction(session);
User *user = new User();
user->name = "Joe";
user->password = "Secret";
user->role = User::Visitor;
user->karma = 13;
dbo::ptr<User> userPtr = session.add(user);
}
catch (...) {
// ...
}
If an exception is thrown in the try block, the destructor for "transaction"
will be called. How will this destructor know to call "rollback transaction",
rather than "commit transaction"? One possibility is that if the call to
"session.add" fails and throws an exception, it could first set some
"dirty transaction" flag that gets inspection by Wt::Dbo::Transaction's
destructor. But what if it's not a Wt::Dbo exception? Suppose I add
the line "if (42) throw 17;" to the try block. How would the destructor
then know to roll back the SQL transaction?
(Or is this some kind of c++ thing where the destructor "knows" that
it's being called in an exception-triggered stack unwind?)
http://en.cppreference.com/w/cpp/error/uncaught_exception
Very good. That clears up my question. (I wasn't aware of
std::uncaught_exception().)

(I deduce from your comment that the destructor for transaction
calls std::uncaught_exception(), and if the stack IS being unwound,
it rolls back the transaction, while if the stack is NOT being unwound,
it commits the transaction. All good.)
Post by Aaron Laws
Happy coding!
In Christ,
Aaron Laws
Thanks again.


K. Frank

------------------------------------------------------------------------------
Loading...