[Sqlalchemy-tickets] Issue #4327: Expire on delete (was not expired before) (zzzeek/sqlalchemy)
Brought to you by:
zzzeek
From: Dmytro S. <iss...@bi...> - 2018-08-23 12:15:46
|
New issue 4327: Expire on delete (was not expired before) https://bitbucket.org/zzzeek/sqlalchemy/issues/4327/expire-on-delete-was-not-expired-before Dmytro Starosud: Regression from 1.1.15 to 1.2.11. Maybe related to [this](https://docs.sqlalchemy.org/en/latest/changelog/changelog_12.html#change-21bf00984dcf04fa68883e4588196816). Please consider following code snippet. ``` #!python Base = declarative_base() class Parent(Base): __tablename__ = 'parent' id = Column(Integer, primary_key=True) children = relationship( 'Child', foreign_keys='Child.parent_id', back_populates='parent', cascade='all, delete-orphan') first_child_id = Column(Integer, ForeignKey('child.id')) first_child = relationship('Child', foreign_keys=first_child_id, post_update=True) updated_at = Column(DateTime(), onupdate=func.now()) class Child(Base): __tablename__ = 'child' id = Column(Integer, primary_key=True) parent_id = Column(Integer, ForeignKey(Parent.id), nullable=False) parent = relationship(Parent, foreign_keys=parent_id, back_populates='children') Base.metadata.create_all(session.bind, checkfirst=True) child = Child() parent = Parent(children=[child], first_child=child) session.add(parent) session.flush() parent_id = parent.id session.expunge_all() @event.listens_for(Parent, 'expire') def receive_expire(target, attrs): traceback.print_stack() parent = session.query(Parent).get(parent_id) session.delete(parent) session.flush() print(parent.updated_at) ``` With SQLAlchemy==1.1.15 it outputs `2018-08-23 12:06:19.291603`, nothing more and no failures. With SQLAlchemy==1.2.11 it outputs two stack traces: one from expire event and one when trying access `parent.updated_at`. ``` #!console File "coze.py", line 62, in <module> session.flush() File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/session.py", line 2254, in flush self._flush(objects) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/session.py", line 2344, in _flush flush_context.execute() File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/unitofwork.py", line 391, in execute rec.execute(self) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/unitofwork.py", line 542, in execute persistence.post_update(self.mapper, states, uow, cols) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/persistence.py", line 234, in post_update mapper, table, update) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/persistence.py", line 975, in _emit_post_update_statements c, c.context.compiled_parameters[0]) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/persistence.py", line 1163, in _postfetch_post_update for c in postfetch_cols if c in File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/state.py", line 593, in _expire_attributes self.manager.dispatch.expire(self, attribute_names) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/event/attr.py", line 284, in __call__ fn(*args, **kw) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/events.py", line 202, in wrap return fn(state.obj(), *arg, **kw) File "coze.py", line 57, in receive_expire traceback.print_stack() Traceback (most recent call last): File "coze.py", line 64, in <module> print(parent.updated_at) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py", line 242, in __get__ return self.impl.get(instance_state(instance), dict_) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/attributes.py", line 594, in get value = state._load_expired(state, passive) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/state.py", line 608, in _load_expired self.manager.deferred_scalar_loader(self, toload) File "/usr/local/lib/python3.5/site-packages/sqlalchemy/orm/loading.py", line 881, in load_scalar_attributes raise orm_exc.ObjectDeletedError(state) sqlalchemy.orm.exc.ObjectDeletedError: Instance '<Parent at 0x7fa8177dc160>' has been deleted, or its row is otherwise not present. ``` Please clarify. Does this mean deleted instance cannot be used after flush any more? Thanks a lot in advance. |