我正在使用Python apsw
绑定使用SQLite数据库。代码如下:
with apsw.Connection(path) as t:
c = t.cursor()
c.execute(...)
... more code ...
if c.execute(...).next()[0]:
raise Exception
我希望with
语句将一个保存点和raise
语句回滚到该保存点(或者,如果没有任何东西可以提交,则提交事务)。它提交得很好,但是当有raise
的东西时,它拒绝回滚:
BusyError: BusyError: cannot rollback savepoint - SQL statements in progress
我不确定先看哪里。据我所知,错误意味着还有另一个阻止访问的连接,但是从代码看起来并不是这样,如果是这样的话,它也不会在提交时失败吗?
SQLite 3.7.7.1,匹配apsw
,Python 2.7。
答案 0 :(得分:3)
好吧,我找到了它:
if c.execute(...).next()[0]:
raise Exception
问题是,当我得到next()
的下一行时,底层游标保持活动状态,准备返回更多行。它必须明确关闭:
if c.execute(...).next()[0]:
c.close()
raise Exception
或隐含地,通过读出所有数据:
if list(c.execute(...))[0][0]:
raise Exception
更新。为方便起见,我写了一个包装apsw.Cursor
并提供a context manager的Python类,所以我可以写:
with Cursor(connection) as c:
c.execute(...)
答案 1 :(得分:3)
这是SQLite本身的一个问题。它在2012年3月修订,版本为3.7.11。来自changelog:
待处理语句不再阻止ROLLBACK。相反,挂起语句将在ROLLBACK之后的下一次访问时返回SQLITE_ABORT。