On Feb 1, 2011, at 1:20 PM, Andronikos Nedos wrote:

> Hi all,
> 
> This is a slightly complicated problem, which I'm not sure how to tackle.
> 
> I get a 
> """
> StaleDataError: UPDATE statement on table 'D' expected to update 1 row(s); 0 
> were matched.
> """
> in the following setup and action sequence:
> 
> Setup:
> I have defined an association_proxy - named 'tasks' - from class A to class 
> C, via class B, like this
> A -> B -> C
>          |
>          -->D
> 
> There is also a class D that has a 1-1 rel with class B. I have defined a 
> before_delete MapperExtension, as I want to delete D objects only under 
> certain conditions.
> 
> Now, assuming objects a,b,c,d, when I execute  a.tasks = [], the association 
> proxy code nulls B's foreign key that references A, and my "all, 
> delete-orphan" cascade rule is then  
> responsible for actually deleting B objects. Subsequently, the before_delete 
> extension will delete D objects using a 
> connection.execute(Dtable.delete().where(..)) approach. 
> 
> Anyway, at some point  I get the StaleDataError and the cause of the problems 
> seems to be an UPDATE that is executed after a DELETE.
> The last few lines are telling:
> -- 
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: DELETE FROM Dtable WHERE 
> Dtable.id = %s
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: (4L,)
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: DELETE FROM Btable WHERE 
> Btable.uuid = %s
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: 
> ('fe23694052ae469cbff12fa3b557118b',)
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: DELETE FROM syncobjects WHERE 
> syncobjects.uuid = %s
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: 
> ('fe23694052ae469cbff12fa3b557118b',)
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: UPDATE Dtable SET data_id=%s 
> WHERE Dtable.id = %s
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: (None, 4L)
> sqlalchemy.engine.base.Engine.0x...8e8c: INFO: ROLLBACK
> --
> A,B,C all inherit from a SyncObject class.
> 
> The problem appears _most_ of the time, but not _all_ of the time. Statement 
> ordering issue maybe ?
> 
> I'm using SA 0.6.6 with MySQL 5.1.49, though the same problem appears with 
> SQLite.

assuming Dtable.data_id references BTable.

There's a few ways to go about this.  The usual way to alter what gets deleted 
where in a flush is to use SessionExtension.before_flush() to figure out 
whatever needs to happen based on the pending state of things, using 
Session.delete() to mark things as deleted as needed.  That way the flush can 
proceed with all of its assumptions intact.   This is how I would usually do it.

Otherwise if you want deletions of DTable to be embedded in the flush without 
the flush having any awareness of it, you'd have to disable the "set null" 
behavior here, which we provide via the "passive_deletes='all'" option.  If 
you're on 0.6 make sure you use 0.6.6 as it had a regression previous to that.


-- 
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