nested "begin_nested" blocks don't track owning states
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.
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.
Comments (4)
-
reporter -
reporter - changed milestone to 0.9.10
-
reporter - changed status to resolved
- Fixed bug where the state tracking within multiple, nested
:meth:
.Session.begin_nested
operations would fail to propagate the "dirty" flag for an object that had been updated within the inner savepoint, such that if the enclosing savepoint were rolled back, the object would not be part of the state that was expired and therefore reverted to its database state. fixes#3352
→ <<cset 359f471a1203>>
-
reporter - Fixed bug where the state tracking within multiple, nested
:meth:
.Session.begin_nested
operations would fail to propagate the "dirty" flag for an object that had been updated within the inner savepoint, such that if the enclosing savepoint were rolled back, the object would not be part of the state that was expired and therefore reverted to its database state. fixes#3352
(cherry picked from commit 359f471a1203cafd5dc99b5b078ba7d788b67cec)
→ <<cset 7c32b4c2a61e>>
- Fixed bug where the state tracking within multiple, nested
:meth:
- Log in to comment
OK, this is all it needs: