On Oct 2, 2012, at 3:49 PM, Mark Friedenbach wrote:

> Well it's hard to boil it down to a specific test case, as it affects the 
> underlying assumptions that went into the design of ORM-tree. Here's an 
> explanation of what I'm doing, and perhaps you can tell me if I'm (ab)using 
> the API correctly:
> 
> The meat of the code is a mapper extension whose insert, update, and delete 
> hooks execute SQL expressions directly to update the nested-interval tree 
> parameters. For efficiency I use the SQL expression layer and then manually 
> update the working set of ORM objects to reflect the new state.
> 
> In essence:
> 
>     connection.execute(...update in sql expression language...)
>     for obj in session.identity_map:
>         ...same update, as python...
> 
> (The session.identity_map is accessible to the mapper extension because it 
> was tucked away as a hidden attribute in the object in a session extension 
> before_flush handler.)
> 
> As far as I can tell, the update to the session objects is now triggering a 
> 2nd flush, even though the purpose of the update was to refresh the objects 
> with their current database values. On the 2nd flush the SQL expression 
> updates get executed again, resulting in a corrupt database.
> 
> Any red flags in what I'm doing?

Basically, when the flush is finished, session.dirty, session.new and 
session.deleted should be empty.  If you add a quick after_flush_postexec() 
event, and inside the event assert that these are all empty, then you shouldn't 
get any subsequent flush.

If session.dirty is acquiring state due to attribute set events, as I see a lot 
of setattr() going on, you can set attributes without establishing history 
using set_committed_value(): 
http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#sqlalchemy.orm.attributes.set_committed_value
 .  However, if that's in fact what's happening, I might need to look into that 
because the "dirty" state of attributes should be unconditionally reset before 
the flush completes.  I just did a test to confirm that, so I'd be curious to 
see a test (unless I can come up with one here) that illustrates plain 
setattr() of a column-based attribute causing a second flush.   In theory it 
would be only .new and .dirty that might have state after the flush completes.


-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
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