The attached script fails with "sqlalchemy.exc.InvalidRequestError:
Instance '<Bug at 0x1e6f3d10>' has been deleted. Use the make_transient()
function to send this object back to the transient state."
While this example is somewhat convoluted, I have a few questions about
sqlalchemy behavior here:
1) At the session.flush(), even though the Rock and the bugs relationship
have been expunged, the pending delete still is issued to the database.
Would you expect/intend sqlalchemy to delete even after the expunge()?
2) After the flush(), shouldn't the history of the 'bugs' relationship have
been updated to reflect the statement issued to the database? (See print
statement)
3) The InvalidRequestError is only raised if the 'bugs' relationship has a
backref, otherwise it isn't raised. Any idea why?
4) Don't hate me for asking: is there a work around? I'm trying to
understand this scenario since in a rare case, it presents.
Thanks very much!
Kent
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/sqlalchemy/-/6oYSFMbpnEsJ.
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.
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.orm import attributes
engine = create_engine('sqlite:///', echo=True)
metadata = MetaData(engine)
Session = sessionmaker(bind=engine)
rocks_table = Table("rocks", metadata,
Column("id", Integer, primary_key=True),
)
bugs_table = Table("bugs", metadata,
Column("id", Integer, primary_key=True),
Column("rockid", Integer, ForeignKey('rocks.id')),
)
class Object(object):
def __init__(self, **attrs):
self.__dict__.update(attrs)
class Rock(Object):
def __repr__(self):
return '<Rock: id=[%s]>' % self.__dict__.get('id')
class Bug(Object):
def __repr__(self):
return '<Bug: id=[%s]>' % self.__dict__.get('id')
mapper(Rock, rocks_table,
properties={'bugs': relationship(Bug,
cascade='all,delete-orphan',
backref=backref('rock',cascade='refresh-expire,expunge'))
})
mapper(Bug, bugs_table)
metadata.create_all()
try:
session = Session()
r = Rock(id=1)
r.bugs=[Bug(id=1)]
session.add(r)
session.commit()
session = Session()
r = Rock(id=1)
r.bugs=[]
merged = session.merge(r)
session.expunge(merged)
# if merged is now detached, should flush() still delete Bug?
session.flush()
# should history still have deleted Bug?
print "\n############\nadd: %r\nunchanged: %r\ndelete: %r\n" % attributes.get_history(merged, 'bugs')
# this only fails if the backref 'rock' is present in relationship
session.add(merged)
finally:
metadata.drop_all()