[sqlalchemy] Re: Never-saved orphans are an error?

2007-02-12 Thread SteveTether



On Feb 10, 11:48 am, Michael Bayer [EMAIL PROTECTED] wrote:
  del p.children[3]

 basically cascade has nothing to say about this operation when applied to
 transient instances.  the history tracking will not see the item as ever
 being part of the children collection since you added it then removed it
 without flushing.

Cascade *does* have something to say about it because the instance was
not transient. Like a dummy I used the all cascade option on the
relation, which caused the child to get attached to the session, i.e.,
go from transient to pending, as soon as it was added to the the
parent's list of children. The full error message, which I should have
included, was:

sqlalchemy.exceptions.FlushError: instance Child('Cheshire') is an
unsaved, pending instance and is an orphan (is not attached to any
parent 'Parent' instance via that classes' 'children' attribute)

I checked sess.new after the del and there it was, without my having
called sess.save() on it. In my application I was after fully explicit
control of sess.save() operations, applying them only to members of
the data structure and only (or course) if they were not already
attached to the session. I'm afraid my over-simplified example didn't
make my motives clear, sorry.

 also, the delete cascade operation does not remove the item from the
 session, it only marks the item to be deleted from the DB, which after a
 flush results in the item being removed from the session.  but this item
 cant be deleted since it was never persisted.  SA basically knows nothing
 about the instance's relationships to anything else and would rather not
 guess what you'd like to do with it.

The delete cascade does not apply since I never called
sess.delete(). It's delete-orphan that applies here and I can avoid
the problem with it by removing all from the cascade options. I'm
structuring my application so that the high-level logic layer does not
know how persistence is implemented, so most of the cascade options
should not be in effect. Everything that should be saved is part of a
graph having a well-defined traversal which the persistence layer can
use to make sure that all the nodes get saved.

By the way, the orphan objects that prompted the FlushError in my
application weren't even known to the high-level layer; they were
association objects created because I was managing a many-to-many
relation with AssociationProxy. The _AssociationList used with it
doesn't implement __delitem__ or slicing. It was only when I added
those for the sake of transparency that I ran into the flush error. I
want the high-level layer to be able to use the full set of list
operations even on lists managed by SA.


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



[sqlalchemy] Never-saved orphans are an error?

2007-02-09 Thread SteveTether

The following code raises a FlushError because the child object named
Cheshire is an orphan and the delete-orphan cascade rule is in effect.
It seems to me that an orphan which has no database identity should be
detached from its session, just as it was attached when appended to a
parent's list of children. Why does SA raise an exception instead?


from sqlalchemy import *

import sys

meta = BoundMetaData(sys.argv[1])

parentTable = Table(tether_parents,
  meta,
  Column(id, Integer,
Sequence(seq_tether_parents), primary_key = True),
  Column(name, String(10), nullable = False))


childTable = Table(tether_children,
   meta,
   Column(id, Integer,
Sequence(seq_tether_children), primary_key = True),
   Column(parent_id, Integer,
ForeignKey(tether_parents.id), nullable = False),
   Column(name, String(10), nullable = False))

class Child(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return Child(%s) % repr(self.name)

class Parent(object):
def __init__(self, name):
self.name = name
children = []
def __repr__(self):
return Parent(%s) % repr(self.name)

mapper(Child, childTable)

mapper(Parent, parentTable, properties = dict(children =
relation(Child,cascade=all,delete-orphan)))

meta.drop_all()
meta.create_all()

meta.engine.echo = False

sess = create_session()

p = Parent(Carroll)
p.children = [Child(Alice), Child(Dee), Child(Dum)]
sess.save(p)
sess.flush()
sess.close()

sess = create_session(echo_uow = True)
p = sess.query(Parent).get_by_name(Carroll)
# New child.
p.children.append(Child(Cheshire))
# Oops, changed my mind.
del p.children[3]
sess.flush()
sess.close()


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



[sqlalchemy] Re: Never-saved orphans are an error?

2007-02-09 Thread SteveTether

Forgot to say I'm using SA 0.3.4.

On Feb 9, 5:05 pm, SteveTether [EMAIL PROTECTED] wrote:
 The following code raises a FlushError because the child object named
 Cheshire is an orphan and the delete-orphan cascade rule is in effect.
 It seems to me that an orphan which has no database identity should be
 detached from its session, just as it was attached when appended to a
 parent's list of children. Why does SA raise an exception instead?


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