is_active remains True after a database exception is thrown

Issue #4218 closed
Christophe Biocca
created an issue

is_active should be False when a session is in a "partial rollback" state. The test case attached demonstrates that after catching an exception (one that should put the database in a "partial rollback" state AFAICT), session.is_active is still True.

The kind of db exception doesn't seem to make a difference (IntegrityError was the original case I ran into).

Postgres 10.3 Psycopg2 2.7.4 SQLAlchemy 1.2.5

Comments (4)

  1. Michael Bayer repo owner

    hi there!

    From http://docs.sqlalchemy.org/en/latest/orm/session_api.html?highlight=is_active#sqlalchemy.orm.session.Session.is_active:

    The “partial rollback” state refers to when an “inner” transaction, typically used during a flush, encounters an error and emits a rollback of the DBAPI connection. At this point, the Session is in “partial rollback” and awaits for the user to call Session.rollback(), in order to close out the transaction stack.

    your test does not illustrate an "inner" transaction, which is actually a "subtransaction", being invoked here or being rolled back. is_active has nothing to do with exceptions, only when a "subtransaction" used by flush() (or if you were to use session.begin(subtransactions=True)) has been rolled back.

    In fact in this test your session is still entirely active, still holding onto an active connection, and usable:

    import sqlalchemy
    import sqlalchemy.orm
    
    engine = sqlalchemy.create_engine("sqlite://")
    
    Session = sqlalchemy.orm.sessionmaker(bind=engine)
    
    session = Session()
    
    try:
        # This next statement causes a DB error.
        # Any statement that causes a DB error seems to work as well (failing a null/fk constraint, for example).
        session.execute("HELLO!")
    except Exception as e:
        print(e)
    
    print(session.scalar("select 'IM AWAKE'"))
    
    $ python test.py 
    (sqlite3.OperationalError) near "HELLO": syntax error [SQL: 'HELLO!'] (Background on this error at: http://sqlalche.me/e/e3q8)
    IM AWAKE
    
  2. Christophe Biocca reporter

    Ok, I see the distinction.

    However your example still does not work with postgresql/psycopg2:

    sqlalchemy.exc.InternalError: (psycopg2.InternalError) current transaction is aborted, commands ignored until end of transaction block

    Seems like any failed statement will make psycopg2 stop further statements from being executed until a proper ROLLBACK is issued.

    I guess this is postgres or psycopg2 specific, and thus out of scope here?

  3. Log in to comment