[sqlalchemy] 0.9.7: Intermittently find a dead weakref to a listens_for function while checking _stored_in_collection of a registry
Hi folks, While running my test suite, I hit an issue with the following stack trace: ERROR at setup of test_track_before_delete request = SubRequest 'database_session' for Function 'test_track_before_delete', engine = Engine(sqlite:///test.db) @pytest.fixture def database_session(request, engine): connection = engine.connect() trans = connection.begin() meta.Session = scoped_session(sessionmaker(autocommit=False, autoflush=True, bind=connection)) register_session_listeners(meta.Session) meta.Session.begin_nested() @event.listens_for(meta.Session, after_transaction_end) def restart_savepoint(session, transaction): if transaction.nested and not transaction._parent.nested: automated_tests/conftest.py:52: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/api. py:94: in decorate listen(target, identifier, fn, *args, **kw) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/api. py:63: in listen _event_key(target, identifier, fn).listen(*args, **kw) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/ registry.py:187: in listen self.dispatch_target.dispatch._listen(self, *args, **kw) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/base. py:184: in _listen event_key.base_listen(propagate=propagate, insert=insert, named=named) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/ registry.py:226: in base_listen for_modify(target.dispatch).append(self, propagate) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/attr. py:118: in append registry._stored_in_collection(event_key, self) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ event_key = sqlalchemy.event.registry._EventKey object at 0x111c6b3d0, owner = sqlalchemy.event.attr._DispatchDescriptor object at 0x10eac8590 def _stored_in_collection(event_key, owner): key = event_key._key dispatch_reg = _key_to_collection[key] owner_ref = owner.ref listen_ref = weakref.ref(event_key._listen_fn) if owner_ref in dispatch_reg: assert dispatch_reg[owner_ref] == listen_ref E assert weakref at 0x111cc25d0; dead == weakref at 0x111cc2af8 ; to 'function' at 0x111c7f668 (restart_savepoint) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/ registry.py:74: AssertionError While running the @event.listens_for decorator in the setup of a test fixture, SQLAlchemy throws an assertion because the ref it has in the dispatch registry isn't identical to the ref to the listener function. We're on SQLAlchemy 0.9.7, pytest 2.6.4. Note that the test suite is setting up nested transactions on SQLite; we are using the recommended workaround from SQLAlchemy documentation to take control of transactional integration from pysqlite. Since there's an assertion in the code in _stored_in_collection(), I assume that there's some expectation that the refs might not match; am I doing something wrong in my setup which this assertion is meant to catch? I've only seen this error once (while tracking down a different nondeterministic error in my own app's code), so I can't provide much more information than this, but the portion of test fixture code seen above in the stack trace is basically the entire reproduction case. This fixture runs before every test in my suite, but I've only seen an error once across a large number of runs, so the error is *very* intermittent. Because of that, I'm not worried too much about the error itself, but I thought I should post it here in case it's a symptom of something I should be worrying about. Thanks, Evan James -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] 0.9.7: Intermittently find a dead weakref to a listens_for function while checking _stored_in_collection of a registry
On 4/2/15 4:28 PM, Evan James wrote: Hi folks, While running my test suite, I hit an issue with the following stack trace: | ERROR at setup of test_track_before_delete request =SubRequest'database_session'forFunction'test_track_before_delete',engine =Engine(sqlite:///test.db) @pytest.fixture defdatabase_session(request,engine): connection =engine.connect() trans =connection.begin() meta.Session=scoped_session(sessionmaker(autocommit=False,autoflush=True,bind=connection)) register_session_listeners(meta.Session) meta.Session.begin_nested() @event.listens_for(meta.Session,after_transaction_end) defrestart_savepoint(session,transaction): iftransaction.nested andnottransaction._parent.nested: automated_tests/conftest.py:52: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/api.py:94:indecorate listen(target,identifier,fn,*args,**kw) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/api.py:63:inlisten _event_key(target,identifier,fn).listen(*args,**kw) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/registry.py:187:inlisten self.dispatch_target.dispatch._listen(self,*args,**kw) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/base.py:184:in_listen event_key.base_listen(propagate=propagate,insert=insert,named=named) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/registry.py:226:inbase_listen for_modify(target.dispatch).append(self,propagate) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/attr.py:118:inappend registry._stored_in_collection(event_key,self) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ event_key =sqlalchemy.event.registry._EventKey objectat 0x111c6b3d0,owner =sqlalchemy.event.attr._DispatchDescriptor objectat 0x10eac8590 def_stored_in_collection(event_key,owner): key =event_key._key dispatch_reg =_key_to_collection[key] owner_ref =owner.ref listen_ref =weakref.ref(event_key._listen_fn) ifowner_ref indispatch_reg: assertdispatch_reg[owner_ref]==listen_ref E assertweakref at 0x111cc25d0;dead==weakref at 0x111cc2af8;to 'function'at 0x111c7f668(restart_savepoint) ../../../.virtualenvs/ERP/lib/python2.7/site-packages/sqlalchemy/event/registry.py:74:AssertionError | While running the @event.listens_for decorator in the setup of a test fixture, SQLAlchemy throws an assertion because the ref it has in the dispatch registry isn't identical to the ref to the listener function. We're on SQLAlchemy 0.9.7, pytest 2.6.4. Note that the test suite is setting up nested transactions on SQLite; we are using the recommended workaround from SQLAlchemy documentation to take control of transactional integration from pysqlite. Since there's an assertion in the code in _stored_in_collection(), I assume that there's some expectation that the refs might not match; am I doing something wrong in my setup which this assertion is meant to catch? I've only seen this error once (while tracking down a different nondeterministic error in my own app's code), so I can't provide much more information than this, but the portion of test fixture code seen above in the stack trace is basically the entire reproduction case. This fixture runs before every test in my suite, but I've only seen an error once across a large number of runs, so the error is *very* intermittent. Because of that, I'm not worried too much about the error itself, but I thought I should post it here in case it's a symptom of something I should be worrying about. this was issue https://bitbucket.org/zzzeek/sqlalchemy/issue/3199 and has been fixed as of 0.9.8. Thanks, Evan James -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at
Re: [sqlalchemy] Inherited class column override
Seems like exactly what I need! Many thanks for all your help, I will try that out right away :) On Wednesday, April 1, 2015 at 7:04:51 PM UTC+2, Michael Bayer wrote: On 4/1/15 10:28 AM, Pierre B wrote: Here's a simple visual of the schema OK, so that's called a polymorphic foreign key. SQLAlchemy doesn't have first class support for this concept because it's relationally incorrect, but there is an example at http://docs.sqlalchemy.org/en/rel_0_9/_modules/examples/generic_associations/generic_fk.html which shows one way to produce this effect.The key aspects to this in reference to your model attempts are that there are no ForeignKey objects; objects like Column and ForeignKey are schema-level objects, and if you construct one, that implies it exists in the schema. That's why you can't make two Column objects with the same name pointing to the same table, and this is what I'm referring to when I say that the schema has to be considered when building out these declarations. The techniques to make the relationship here involve using the primaryjoin argument to establish how the tables join directly, as well as the foreign() annotation and/or foreign_keys argument which you can see used in the example; that is, how the tables join is constructed using all ORM constructs and not schema-level constructs. https://i.imgur.com/TaC2V6b.png There are no foreign key constraints in the database schema, id1 and id2 are just stored there, a type column is used to retrieve records e.g type equals B for an association between RightB and ReftB and equals A between RightA and LeftA. That is why I'm trying to set a default value for the type column so I don't have to deal with that junction table when inserting records. On Wednesday, April 1, 2015 at 4:11:03 PM UTC+2, Michael Bayer wrote: On 4/1/15 4:55 AM, Pierre B wrote: Unfortunately I'm inheriting the relational model from an old application. I have dozens of tables using a single junction table for associations. I can not completely redesign my relational model because it needs to be compatible with the old application. I was asking no such thing. I only ask that you consider the relational model when building *new* elements of the application. If these models are in fact mapping to an existing schema, I find it surprising that your existing database schema includes *two* foreign key constraints present on each of people4l2.id1 and people4l2.id2, constraining each column to both left1.id/left2.id and right1.id/right2.id. At this point, I think my best option is setting up table inheritance at the database level (database is Postgresql) and migrating records into children tables. Minimal code refactoring would be involved in the old application and it would be possible to use the association object pattern. On Tuesday, March 31, 2015 at 8:05:19 PM UTC+2, Michael Bayer wrote: Pierre B rocambol...@gmail.com wrote: I tried using the association object pattern before but can't get it to work because I use the same id1 and id2 columns for all foreign keys and I'm not able to override them in the sub-classes (conflicts with existing column error). class MyClass(HasSomeAttribute, db.Model): __tablename__ = 'people4l2' id = db.Column(db.Integer, primary_key=True) class MySubClass1(MyClass): right1_id = db.Column('id2', db.Integer, ForeignKey('right1.id')) left1_id = db.Column('id1', db.Integer, ForeignKey('left1.id')) class MySubClass2(MyClass): right2_id = db.Column('id2', db.Integer, ForeignKey('right2.id')) left2_id = db.Column('id1', db.Integer, ForeignKey('left2.id’)) That’s because you do not have a __tablename__ for these subclasses, so when you put a column on the subclass, that is physically a column on the ‘people4l2’ table; the names cannot be conflicting. Also, it is not possible to have a column named “people4l2.id2” which is in some cases a foreign key to “right1.id” and in other cases to “right2.id”. This probably all seems very complicated if you only think of it in terms of a Python object model. That’s why it is essential that you design your database schema in terms of database tables, and how those tables will work within a purely relational model, without Python being involved, first. For simple cases, the design of the relational model and the object model are so similar that this explicit step isn’t necessary, but once the goals become a little bit divergent between relational and object model, that’s when the relational model has to be developed separately, up front. This is the essence of how SQLAlchemy works, which becomes apparent the moment you get into models like these which are typically impossible on most other ORMs, since most ORMs do not consider design of the relational model as separate from the
Re: [sqlalchemy] PostgreSQL UNION with ORDER or LIMIT parenthesis patch
haha it's not resolved :) UNIONs are really tough, as are SQLite's choice of quirks in this area. On 4/1/15 11:27 PM, Charles Leifer wrote: Funnily enough I ran into this particular question regarding Peewee ORM and, googling Postgresql UNION parentheses, I found this post. I ran into the same thing where PG likes the parentheses, but SQLite doesn't. I know this is a very old post, but out of curiosity, how did you end up resolving this? On Thursday, July 5, 2012 at 4:35:51 PM UTC-5, Michael Bayer wrote: On Jul 5, 2012, at 4:57 PM, Sergey Shepelev wrote: Problem: sa.union_all(*qs).order_by('y') will generate invalid SQL like this: SELECT ... ORDER BY x LIMIT 10 UNION ALL SELECT ... ORDER BY x LIMIT 10 ORDER BY y Order in inner queries could be required for LIMIT or DISTINCT ON (field). Solution: sqlalchemy should put all inner queries that contain ORDER BY or LIMIT clauses into parenthesis, like this: SELECT ... UNION ALL (SELECT ... ORDER BY x LIMIT 10) ORDER BY y Test: def test_with_order(self): q = sa.select([2]).order_by('1') union = sa.union(q, q).limit(3) db.postgresql.execute(union) self.assertEqual(str(union), (SELECT 2 ORDER BY 1) UNION (SELECT 2 ORDER BY 1) LIMIT 3) Monkey patch at https://gist.github.com/3056292 https://gist.github.com/3056292 This is tricky because the SQL expression language doesn't like to make guesses like that, that is, decides about the structure of the query based on things inside of select() constructs. The ORM does that kind of thing more acceptably, but it isn't covering this case either at the moment. The above SQL is not accepted on some backends - that is, it fails on SQLite at least. Odd structures like that tend to not work on several of the more quirky backends, common culprits are Oracle, Firebird, SQL Server, older MySQL versions. So to make this magic here is to make the select() construct behave differently on the PG backend, or maybe just not on the SQLite backend, but this is tricky to decide without knowing the true compatibility here and what's going to break for whom if we make a change like that - the SQL expression language tends to want you to manually apply structural conventions right now (such as, if you say select().select(), there's no alias generated automatically, things like that). I would have expected alias() to work here, but it doesn't. so it's on deck to work on why that is at some point. The point is right now you can force the parens using self_group(), and I'd be more comfortable if you stuck with that for this particular case right now, though I may change my mind about handling this case in the future: q = select([2]).limit(5).order_by('1').self_group() union = union(q, q).limit(3) print union i put up http://www.sqlalchemy.org/trac/ticket/2528 http://www.sqlalchemy.org/trac/ticket/2528, where the goal is to test the compatibility of this kind of query across the most common backends and see what the best approach might be. I'd probably go as far as alias() rending parenthesis, though (that is, self_group() will likely remain exactly what you want here). -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] PostgreSQL UNION with ORDER or LIMIT parenthesis patch
I wish I saw this earlier. This thread basically describes a situation I've had, and explains a few of the weird hacks I've had to use. If you need a workaround, I've been getting around this by using a union on 2 subqueries, querying the union columns, and using plaintext sql to order (the sql ordering works in = 0.9.9 and = 1.0.0b4) q_a = s.query(Foo).subquery(name='select_a') q_b = s.query(Foo).subquery(name='select_b') q_union = sqlalchemy.union(q_a.select(), q_b.select()).alias('select_ab') q = s.query(q_union.c.field).order_by( sqlalchemy.desc('plaintext')) -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] Nested transaction rollback does not undo changes to instances
On 4/2/15 10:01 AM, Chris Wilson wrote: Dear SQLAlchemy developers, I think I've found a problem with SQLAlchemy not rolling back changes to instances that are committed in an inner nested transaction, when the outer nested transaction rolls back. The manual says: When begin_nested() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.begin_nested is called, a flush() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.flush is unconditionally issued (regardless of the autoflush setting). This is so that when a rollback() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.rollback occurs, the full state of the session is expired, thus causing all subsequent attribute/instance access to reference the full state of the Session http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session right before begin_nested() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.begin_nestedwas called. So I think that if we make a change to an instance, inside a transaction, and then rollback, we should see the old values in any instances, as if the transaction never happened. And indeed this appears to work for simple cases: from sqlalchemy import Column, Integer, Boolean from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker Base = declarative_base() class Test(Base): __tablename__ = 'test' id = Column(Integer, primary_key=True) value = Column(Boolean) engine = create_engine('sqlite:///sqlalchemy_example.db') Base.metadata.create_all(engine) DBSession = sessionmaker(bind=engine) session = DBSession(autocommit=True) session.begin() test_data = Test(value=False) session.add(test_data) session.commit() print test_data.value, in the beginning try: with session.begin(): # with session.begin_nested(): test_data.value = True print test_data.value, before rollback raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after rollback Which, as expected, resets value from True to False during rollback(): False in the beginning True before rollback ValueError caught: force a rollback False after rollback Note: this example doesn't work with my SQLite install because it doesn't seem to support savepoints properly, even though it's documented to do so. I used postgresql to actually run these tests, and created the table as follows: CREATE TABLE test (id SERIAL NOT NULL PRIMARY KEY, value BOOLEAN); GRANT ALL ON TABLE test TO standard; GRANT ALL ON TABLE test_id_seq TO standard; It even works if you rollback a nested transaction: try: with session.begin(): try: with session.begin_nested(): test_data.value = True print test_data.value, after nested commit, before nested rollback raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after nested rollback assert not test_data.value, should have been rolled back assert session.transaction is not None raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after outer rollback However, it does NOT work if you roll back a nested transaction that has a committed nested transaction inside it (differences highlighted): try: with session.begin(): try: with session.begin_nested(): with session.begin_nested(): test_data.value = True print test_data.value, after nested commit, before nested rollback raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after nested rollback # assert not test_data.value, should have been rolled back; this assertion fails if enabled assert session.transaction is not None raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after outer rollback assert session.transaction is None Which outputs: False in the beginning
[sqlalchemy] Nested transaction rollback does not undo changes to instances
Dear SQLAlchemy developers, I think I've found a problem with SQLAlchemy not rolling back changes to instances that are committed in an inner nested transaction, when the outer nested transaction rolls back. The manual says: When begin_nested() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.begin_nested is called, a flush() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.flush is unconditionally issued (regardless of the autoflush setting). This is so that when a rollback() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.rollback occurs, the full state of the session is expired, thus causing all subsequent attribute/instance access to reference the full state of the Session http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session right before begin_nested() http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.begin_nestedwas called. So I think that if we make a change to an instance, inside a transaction, and then rollback, we should see the old values in any instances, as if the transaction never happened. And indeed this appears to work for simple cases: from sqlalchemy import Column, Integer, Boolean from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker Base = declarative_base() class Test(Base): __tablename__ = 'test' id = Column(Integer, primary_key=True) value = Column(Boolean) engine = create_engine('sqlite:///sqlalchemy_example.db') Base.metadata.create_all(engine) DBSession = sessionmaker(bind=engine) session = DBSession(autocommit=True) session.begin() test_data = Test(value=False) session.add(test_data) session.commit() print test_data.value, in the beginning try: with session.begin(): # with session.begin_nested(): test_data.value = True print test_data.value, before rollback raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after rollback Which, as expected, resets value from True to False during rollback(): False in the beginning True before rollback ValueError caught: force a rollback False after rollback Note: this example doesn't work with my SQLite install because it doesn't seem to support savepoints properly, even though it's documented to do so. I used postgresql to actually run these tests, and created the table as follows: CREATE TABLE test (id SERIAL NOT NULL PRIMARY KEY, value BOOLEAN); GRANT ALL ON TABLE test TO standard; GRANT ALL ON TABLE test_id_seq TO standard; It even works if you rollback a nested transaction: try: with session.begin(): try: with session.begin_nested(): test_data.value = True print test_data.value, after nested commit, before nested rollback raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after nested rollback assert not test_data.value, should have been rolled back assert session.transaction is not None raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after outer rollback However, it does NOT work if you roll back a nested transaction that has a committed nested transaction inside it (differences highlighted): try: with session.begin(): try: with session.begin_nested(): with session.begin_nested(): test_data.value = True print test_data.value, after nested commit, before nested rollback raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after nested rollback # assert not test_data.value, should have been rolled back; this assertion fails if enabled assert session.transaction is not None raise ValueError(force a rollback) except ValueError as e: print ValueError caught: {}.format(e) print test_data.value, after outer rollback assert session.transaction is None Which outputs: False in the beginning True after nested commit, before nested rollback ValueError caught: force a rollback True after nested rollback ValueError caught: force a rollback False after outer rollback You can see that after the nested transaction rollback, the value on the instance has not been reset to False, but the outer (final) rollback successfully resets it. We spotted this because we run tests in transactions (currently nested transactions, although now I have to change it to work around this issue),
Re: [sqlalchemy] Nested transaction rollback does not undo changes to instances
On 4/2/15 11:54 AM, Mike Bayer wrote: it's a bug, and I've captured the origin, diagnosis and probable solution here: https://bitbucket.org/zzzeek/sqlalchemy/issue/3352/nested-begin_nested-blocks-dont-track this issue is fixed for 0.9.10 and 1.0.0b5, you can test now using either latest master or the rel_0_9 branch. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.