On Feb 2, 2013, at 3:34 AM, Christian Theune wrote:

> Hi,
> 
> On Feb 1, 2013, at 5:36 PM, Michael Bayer <mike...@zzzcomputing.com> wrote:
> 
>> OK, had to think a bit for how this should be done.
> 
> Thanks for picking this up, Mike! 
> 
> I looked through your patch and I wondered about a few more conditions: 
> should an object also be expired the moment I mark it for deletion?

Well, the moment you mark for deletion, that wouldn't work at the moment as we 
need the state of collections and references and such in order to perform 
cascades - the expire operation blows all history away right now and it 
essentially means "we no longer can be sure of the state of this object and it 
needs to be refreshed from the DB" - within an ongoing Session transaction this 
is not really the case.  There might be ways to alter the object's state so 
that the ORM has the info it needs but the userland experience of the object 
throws an exception, but this seems like a lot of complexity for not much 
tangible benefit.

There are common scenarios where an object gets marked for deletion but is then 
un-marked, basically when removing it from one collection and then adding it to 
another, when delete-orphan cascade is turned on.   Though this is a bit 
limited - if the flush has occurred then you get an error about the object 
being deleted.  But the pre-flush "deleted" state is currently not necessarily 
permanent.

I know it's not totally seamless, but I've observed the more you try to make it 
"perfect", it becomes a game of diminishing returns where you're adding a lot 
of overhead and creating new problems just to appease certain edge cases that 
actually aren't an issue for the vast majority of users.

Possibly more plausible is to expire it after the flush.   This may or may not 
be a good idea, you can have this effect right now like this:

@event.listens_for(Session, "after_flush")
def del_obj(session, ctx):
    for obj in session.deleted:
        session.expire(obj)

but since the object becomes "detached" after the transaction is over so it 
might be convenient that its former state is still there.


> The actual scenario in my application is a little more complex than what my 
> original snippet has shown: it uses a chain of references (Nodes having NICs 
> having IPAddresses). Deleting a Node already triggers the cascades correctly 
> and the NICs as well as the IPAddresses get marked for deletion and are 
> deleted from the DB.
> 
> Now, when, during a single transaction, I want to delete a Node and then 
> reassign the IPAddress, my application asks the IPAddress whether it has a 
> back reference to a NIC. What happens then depends on application behaviour:
> 
> * the app queries for the Address to be assigned again, gets no result and 
> creates a new object. This works fine.
> * the app still holds a reference (there are scenarios in my application 
> where this makes the code more db agnostic) and uses that object to assign it 
> to a new NIC
> 
> The latter case will currently fail because, although marked for deletion, 
> the objects still have all of their state, including working references.

if IPAddress is expired as it is marked for deletion, then accessing its 
attributes will trigger a flush, delete the row, query for that row, and you'll 
get an ObjectDeleted exception.   How does that help ?

Also, if Node is marked for deletion but hasn't been deleted yet, the NIC and 
IPAddress aren't even marked for deletion at that point - "delete" cascade is 
calculated within the flush, again for the use case that Node was undeleted, or 
similar.

If you want to send along more specifics here that would help, but perhaps 
where your code says delete(Node), you could do some extra work right there to 
perform the detachments/deletions of NIC/IPAddress right there, just a thought. 
  Not sure if that works out.



-- 
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?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to