On Oct 2, 2008, at 10:35 AM, Joril wrote:

>
> Hi everyone!
> I'm sorry, I'm using SQLA 0.5rc1 with autocommit=True, and I'm having
> a problem with rollbacks.. It looks to me that whenever I try to save
> an object that triggers some kind of exception (thus triggering a
> rollback) I lose that object's previous state..

this is expected behavior in 0.5.   If you've rolled the transaction  
back, in theory new state may exist within the database which would  
have to be reloaded in your new transaction, so everything is expired.

There is an option to completely disable 0.5's transaction accounting,  
which is the _enable_tranasction_accounting=False setting.  This  
reenables 0.4's behavior.  However, the Session would then be in an  
undefined state after a rollback() proceeds - in the 0.4 series it was  
often not possible to continue with a Session after a rollback()  
occurs and we generally advised people to issue a clear() and start  
over again.  You might be able to work with this in a narrow range of  
use cases but results aren't guaranteed.

The usual solution here is to construct your application to not depend  
on exception throws as a normal matter of course.  Check for existing  
rows before issuing an INSERT, etc.

The core issue is that SQLA's flush() procedure can't "recontinue"  
after failing, since it does its accounting at the end of the  
transaction complete, so it has to issue a rollback() of some kind so  
that it can start the whole flush again.  Additionally, databases like  
Postgres usually require the rollback() after an IntegrityError is  
raised in any case, so if and when SQLA's flush() gains the ability to  
continue after partial progress, it still wouldn't be a very typical  
usage.

Another strategy which is provided to deal with this is SAVEPOINT  
integration, which works very well in 0.5.  This provides a target  
point for the database and SQLA's flush to be rolled back towards, so  
that an operation can fail, the sub-transaction rolled back, and the  
overall operation proceeds.   You would use Session.begin() to start  
the overall transaction and Session.begin_nested() to start a  
SAVEPOINT transaction.  Any number of begin_nested() calls can be  
issued, and each has its own correspoinding commit() call.  SAVEPOINT  
works on mysql, postgres, and oracle so far.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to