[Sqlalchemy-tickets] Issue #3352: nested "begin_nested" blocks don't track owning states (zzzeek/sq
Brought to you by:
zzzeek
|
From: Mike B. <iss...@bi...> - 2015-04-02 15:53:33
|
New issue 3352: nested "begin_nested" blocks don't track owning states https://bitbucket.org/zzzeek/sqlalchemy/issue/3352/nested-begin_nested-blocks-dont-track Mike Bayer: as a result of #2452 in 9cf10db8aa4692dc6, the scope of objects within a begin_nested() is tracked based on dirtyness only. This fails when there was another begin_nested() completing successfully within the block, because dirtyness is reset in that case. Additional bookkeeping will be needed to ensure objects that are dirtied within the nested trans are tracked without being reset by a sub-transaction. ``` #!python from sqlalchemy import Column, Integer from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import Session Base = declarative_base() class Test(Base): __tablename__ = 'test' id = Column(Integer, primary_key=True) value = Column(Integer) engine = create_engine('postgresql://scott:tiger@localhost/test', echo='debug') Base.metadata.drop_all(engine) Base.metadata.create_all(engine) s = Session(engine) t1 = Test(value=1) t2 = Test(value=1) t3 = Test(value=1) s.add_all([t1, t2, t3]) s.commit() try: with s.begin_nested(): t1.value = 2 with s.begin_nested(): t2.value = 2 t3.value = 2 raise ValueError("x") except ValueError: assert (t1.value, t2.value, t3.value) == (1, 1, 1), (t1.value, t2.value, t3.value) else: assert False ``` it seems like the "_dirty" list on transaction is only populated in the subtransaction within the flush, so this never has a chance to propagate outwards on a successful commit. We will need to add something to SessionTransaction.commit() so that the subtransaction has a chance to propagate its dirty list to the parent. may be safe for a 0.9.10 backport. |