- changed status to resolved
deleted objects aren't fully detached after transaction
Issue #2658
resolved
im editing this description a lot. I think when the flush has proceeded but the transaction is still around, the object needs to remain associated with that Session, since it still is.
this test also illustrates a new "was_deleted" function, since we need to expose state.deleted:
from sqlalchemy import Column, Integer
from sqlalchemy.orm import object_session
from sqlalchemy.orm.util import has_identity, was_deleted
import sqlalchemy
import sqlalchemy.ext.declarative
import sqlalchemy.orm
engine = sqlalchemy.create_engine('sqlite:///:memory:')
session_factory = sqlalchemy.orm.scoped_session(
sqlalchemy.orm.sessionmaker(bind=engine))
Object = sqlalchemy.ext.declarative.declarative_base()
class O(Object):
__tablename__ = 'object'
id = Column(Integer, primary_key=True)
def show_object_state(obj):
if object_session(obj) is not None and was_deleted(obj):
return "deleted in transaction"
if object_session(obj) is None and not has_identity(obj):
return 'transient'
if object_session(obj) is not None and not has_identity(obj):
return 'pending'
if object_session(obj) is None and has_identity(obj):
return 'detached'
if object_session(obj) is not None and has_identity(obj):
return 'persistent'
raise RuntimeError('unknown state')
Object.metadata.create_all(engine)
session = session_factory()
o = O()
o.id = 1
session.add(o)
session.commit()
session.delete(o)
session.flush()
assert object_session(o) is session # because it still could be rolled back
assert show_object_state(o) == 'deleted in transaction'
session.rollback()
assert object_session(o) is session # and its back
assert show_object_state(o) == 'persistent'
session.delete(o)
session.commit()
assert object_session(o) is None
assert show_object_state(o) == 'detached'
patch, also adds util function was_deleted:
diff -r 7790425a993480e81605efc8a07fed13bcdd4841 lib/sqlalchemy/orm/session.py
--- a/lib/sqlalchemy/orm/session.py Mon Jan 28 13:58:01 2013 -0500
+++ b/lib/sqlalchemy/orm/session.py Fri Feb 01 11:28:15 2013 -0500
@@ -255,6 +255,10 @@
if not self.nested and self.session.expire_on_commit:
for s in self.session.identity_map.all_states():
s._expire(s.dict, self.session.identity_map._modified)
+ for s in self._deleted:
+ s.session_id = None
+ self._deleted.clear()
+
def _connection_for_bind(self, bind):
self._assert_is_active()
diff -r 7790425a993480e81605efc8a07fed13bcdd4841 lib/sqlalchemy/orm/util.py
--- a/lib/sqlalchemy/orm/util.py Mon Jan 28 13:58:01 2013 -0500
+++ b/lib/sqlalchemy/orm/util.py Fri Feb 01 11:28:15 2013 -0500
@@ -1213,6 +1213,9 @@
state = attributes.instance_state(object)
return state.has_identity
+def was_deleted(object):
+ state = attributes.instance_state(object)
+ return state.deleted
def instance_str(instance):
"""Return a string describing an instance."""
Comments (2)
-
reporter -
reporter - removed milestone
Removing milestone: 0.8.0final (automated comment)
- Log in to comment
26fb4b81638189547dd24f525ad0d146f2646916