Hey Koen,
2012/1/4 Koen Deforche <k...@emweb.be>
> Hey Dmitriy,
>
> 2012/1/4 Dmitriy Igrishin <dmit...@gmail.com>:
> >>> I think that more correct way to detecting that is to use
> >>> transaction status, returned by the backend. In case of
> >>> Postgres (libpq) its a function PQtransactionStatus().
>
> True, that is one source for an exception. But there could also be
> other exceptions (not database-specific) which prevent the transaction
> from completing.
>
Ah, right, than the "auto-rollback" would be indeed suitable :-)
>
> > Although, there is one serious drawback with
> > the idea of "auto-commit" transactions -- the
> > "COMMIT" SQL command performed during the
> > deletion of the Transaction object (from
> > the destructor) may fails by some reasons. But the
> > user may wants to know these reasons and the
> > user usually wants to be sure that the transaction
> > *really* committed by the backend. So, the only
> > way to inform the user about an error is to throw
> > an exception from the descructor which seems to
> > me as a very bad design approach, since as all we
> > know, exceptions should not leave destructors.
>
> Actually, the fact that exceptions should not be thrown from a
> destructor is just a guideline that should almost always be followed.
> The guideline is motivated by the fact that only a single uncaught
> exception may be active at a time, and destructors are automatically
> called during stack unwinding.
>
Of course, and the std::uncaught_exception() tries to help
the programmer to detect the "exception in progress" case.
But this function is really useless.
But in this case, it is actually warranted:
> - if the destructor is called during stack unwinding (because of
> another exception), the transaction will rollback and not throw an
> exception.
Well, suppose that the Transaction::~Transaction() looks like:
Transaction::~Transaction()
{
if (std::uncaught_exception()) {
// tries to rollback
} else {
// tries to commit
}
}
And suppose My_class::~My_class() looks like:
My_class::~My_class()
{
try {
Transaction t(........);
// some actions ...
} catch (...) {
// some actions ...
}
}
Then,
void f(......)
{
My_class obj(.....);
throw 1;
}
Opps and ugh, because the transaction in the
My_class::~My_class() will be rolled back because
of stack unwinding instead of commit!
- if the destructor is called simply because we reach the end of a
> scope, we try to commit the transaction, and if this fails, we
> rollback and throw the exception from the destructor. But this cannot
> lead to problems since we know for certain that no other exception is
> currently being thrown.
>
> > I propose the "auto-rollback" on descruction instead
> > of "auto-commit" which seems to me more safe.
>
> That was actually the previous behavior. But having to put t.commit()
> in all return paths from a function can be annoying, especially since
> I believe that it is the default intent of a transaction (rollback is
> the exception).
>
It is maybe annoying, but it seems to me more reliable :-)
>
> Regards,
> koen
>
--
// Dmitriy.
------------------------------------------------------------------------------
Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex
infrastructure or vast IT resources to deliver seamless, secure access to
virtual desktops. With this all-in-one solution, easily deploy virtual
desktops for less than the cost of PCs and save 60% on VDI infrastructure
costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest