Re: [sqlalchemy] Why ORM objects in a session expire immediately after a failure in flush?

2014-01-10 Thread Claudio Freire
On Thu, Jan 9, 2014 at 9:59 PM, Michael Bayer mike...@zzzcomputing.com wrote:
 I do notice that you’re catching an IntegrityError.The typical pattern
 when writing code that wants to catch these and then continue is to run the
 individual set of questionable operations within a SAVEPOINT, that is a
 begin_nested()/commit() block.  Recent versions of SQLAlchemy have the
 behavior such that when a flush() exception rolls back the SAVEPOINT,
 objects that were not modified within the SAVEPOINT are not expired; only
 those objects that changed within the save point’s scope do.

How recent does recent mean there? (just curious)

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] Why ORM objects in a session expire immediately after a failure in flush?

2014-01-10 Thread Michael Bayer
changelog in 0.8.0b1:

http://docs.sqlalchemy.org/en/rel_0_9/changelog/changelog_08.html#change-1df6e3552ee895cd48952f95c0f0730a

ticket:

http://www.sqlalchemy.org/trac/ticket/2452

I wonder if offering that the automatic rollback() on flush() might be 
optionally disabled (which means, a corrupted flush is in danger of being 
committed if the user is not careful) would be a compromise for this behavior 
in the bigger sense.




On Jan 10, 2014, at 8:41 AM, Claudio Freire klaussfre...@gmail.com wrote:

 On Thu, Jan 9, 2014 at 9:59 PM, Michael Bayer mike...@zzzcomputing.com 
 wrote:
 I do notice that you’re catching an IntegrityError.The typical pattern
 when writing code that wants to catch these and then continue is to run the
 individual set of questionable operations within a SAVEPOINT, that is a
 begin_nested()/commit() block.  Recent versions of SQLAlchemy have the
 behavior such that when a flush() exception rolls back the SAVEPOINT,
 objects that were not modified within the SAVEPOINT are not expired; only
 those objects that changed within the save point’s scope do.
 
 How recent does recent mean there? (just curious)
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+unsubscr...@googlegroups.com.
 To post to this group, send email to sqlalchemy@googlegroups.com.
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/groups/opt_out.



signature.asc
Description: Message signed with OpenPGP using GPGMail


[sqlalchemy] Why ORM objects in a session expire immediately after a failure in flush?

2014-01-09 Thread Weikai Xie
Hi, folks,

I observed that it seems all ORM objects  in a session will expire 
immediately if there is a failure in session.flush(). I was wondering 
what's the rationale behind this behavior.

Following is an artificial web application code to illustrate the idea:

def PUT():
   
  # session and engine are all created with default parameter

user = session.query(UserProfile).first()
   
# deliberately tries to insert a Login record which has the same 
primary key as an existing one such that the later session.flush() will fail
try:
   duplicated_login_record = Login(id=0, username=username:weikai)
   session.add(duplicated_login_record)
   session.flush()   
except IntegrityError:
session.rollback() 

print user.id   
...

By turning on logging, I noticed the print user.id line always result in 
a new SELECT being issued to database, which is an indicator that somehow 
user object got expired after the failure in session.flush().

For some other good reason which I don't want to elaborate here, we really 
don't want to have an extra SELECT going to DB in the processing of one 
HTTP request. Therefore, I was just wondering why is this behavior and 
whether it can be turned off. 

 


 

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Re: [sqlalchemy] Why ORM objects in a session expire immediately after a failure in flush?

2014-01-09 Thread Michael Bayer

On Jan 9, 2014, at 7:17 PM, Weikai Xie xiewei...@gmail.com wrote:

 Hi, folks,
 
 I observed that it seems all ORM objects  in a session will expire 
 immediately if there is a failure in session.flush(). I was wondering what's 
 the rationale behind this behavior.
 
 Following is an artificial web application code to illustrate the idea:
 
 def PUT():

   # session and engine are all created with default parameter
 
 user = session.query(UserProfile).first()

 # deliberately tries to insert a Login record which has the same 
 primary key as an existing one such that the later session.flush() will fail
 try:
duplicated_login_record = Login(id=0, username=username:weikai)
session.add(duplicated_login_record)
session.flush()   
 except IntegrityError:
 session.rollback() 
 
 print user.id   
 ...
 
 By turning on logging, I noticed the print user.id line always result in a 
 new SELECT being issued to database, which is an indicator that somehow user 
 object got expired after the failure in session.flush().
 
 For some other good reason which I don't want to elaborate here, we really 
 don't want to have an extra SELECT going to DB in the processing of one HTTP 
 request. Therefore, I was just wondering why is this behavior and whether it 
 can be turned off. 

The short answer is that this behavior can’t be disabled across the board, 
unless you are using SAVEPOINTs, which you probably should here.  The flush() 
process does a rollback() immediately on the inner transaction when an 
exception occurs, and once the transaction is rolled back all data is expired; 
as the objects are proxies for the state of the database, and the transaction 
has been rolled back, the state of the objects is invalid.

I do notice that you’re catching an IntegrityError.The typical pattern when 
writing code that wants to catch these and then continue is to run the 
individual set of questionable operations within a SAVEPOINT, that is a 
begin_nested()/commit() block.  Recent versions of SQLAlchemy have the behavior 
such that when a flush() exception rolls back the SAVEPOINT, objects that were 
not modified within the SAVEPOINT are not expired; only those objects that 
changed within the save point’s scope do.

There’s also an option called _enable_transaction_accounting which if set to 
False will disable *all* rollback/commit accounting, basically reverts to 
pre-0.5 behavior.  Using this flag, you’re giving up a lot of the Session’s 
functionality and as this mode is not really supported I’m not sure what other 
useful features you might be giving up.



 
  
 
 
  
 
 
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to sqlalchemy+unsubscr...@googlegroups.com.
 To post to this group, send email to sqlalchemy@googlegroups.com.
 Visit this group at http://groups.google.com/group/sqlalchemy.
 For more options, visit https://groups.google.com/groups/opt_out.



signature.asc
Description: Message signed with OpenPGP using GPGMail