pythonsqliteapsw

"BusyError: cannot rollback savepoint - SQL statements in progress" when using SQLite with APSW


I'm working with an SQLite database using the Python apsw bindings. The code goes like this:

with apsw.Connection(path) as t:
    c = t.cursor()
    c.execute(...)
    ... more code ...
    if c.execute(...).next()[0]:
        raise Exception

I expect the with statement to put a savepoint and the raise statement to rollback to that savepoint (or, if there's nothing to raise, commit the transaction). It commits just fine, but when there's something to raise it refuses to rollback with:

BusyError: BusyError: cannot rollback savepoint - SQL statements in progress

I'm not sure where to look first. As far as I understand the error means there's another connection that blocks the access, but this doesn't look so from the code, and, if this was so, wouldn't it fail on commits as well?

SQLite 3.7.7.1, matching apsw, Python 2.7.


Solution

  • Well, I found it:

    if c.execute(...).next()[0]:
        raise Exception
    

    The problem is that at the moment I get the next row with next(), the underlying cursor stays active, ready to return more rows. It has to be closed explicitly:

    if c.execute(...).next()[0]:
        c.close()
        raise Exception
    

    or implicitly, by reading out all data:

    if list(c.execute(...))[0][0]:
        raise Exception
    

    UPDATE. For convenience I wrote a Python class that wraps apsw.Cursor and provides a context manager, so I can write:

    with Cursor(connection) as c:
        c.execute(...)