session transaction is not deactivated when rollback fails

Issue #4050 resolved
Mike Bayer repo owner created an issue

due to #3934, affects downstream oslo.db test_cause_for_failed_flush_plus_no_savepoint

        users, User = self.tables.users, self.classes.User

        mapper(User, users)
        session = Session(bind=testing.db)

        rollback_error = testing.db.dialect.dbapi.InterfaceError(
            "Can't roll back to savepoint")

        def prevent_savepoint_rollback(
                cursor, statement, parameters, context=None):
            if "rollback to savepoint" in statement.lower():
                raise rollback_error

        self.event_listen(
            testing.db.dialect,
            "do_execute", prevent_savepoint_rollback)

        with session.transaction:
            session.add(User(id=1, name='x'))

        session.begin_nested()
        # raises IntegrityError on flush
        session.add(User(id=1, name='x'))
        assert_raises_message(
            sa_exc.InterfaceError,
            "Can't roll back to savepoint",
            session.commit,
        )

        # rollback succeeds, because the Session is deactivated
        eq_(session.transaction._state, _session.DEACTIVE)
        session.rollback()

        # back to normal
        eq_(session.transaction._state, _session.ACTIVE)

        trans = session.transaction

        # leave the outermost trans
        session.rollback()

        # trans is now closed
        eq_(trans._state, _session.CLOSED)

        # outermost transction is new
        is_not_(session.transaction, trans)

        # outermost is active
        eq_(session.transaction._state, _session.ACTIVE)

Comments (2)

  1. Mike Bayer reporter

    Deactivate transaction if rollback fails

    Fixed regression introduced in 1.2.0b1 due to 🎫3934 where the :class:.Session would fail to "deactivate" the transaction, if a rollback failed (the target issue is when MySQL loses track of a SAVEPOINT). This would cause a subsequent call to :meth:.Session.rollback to raise an error a second time, rather than completing and bringing the :class:.Session back to ACTIVE.

    Fixes: #4050 Change-Id: Id245e8dd3487cb006b2d6631c8bd513b5ce81abe

    → <<cset 8b53548b9e97>>

  2. Log in to comment