From 417bd1afa2d61b5c65e9213e7b017d41f78fca86 Mon Sep 17 00:00:00 2001 From: Andrew Ekstedt Date: Fri, 30 Mar 2018 15:02:23 -0700 Subject: [PATCH] fix pypy build PyPy (>= 3.6) was consistently erroring out during `pokedex load`, with the error OperationalError: (_sqlite3.OperationalError) cannot commit transaction - SQL statements in progress (Background on this error at: http://sqlalche.me/e/e3q8) It turns out PyPy was not garbage collecting something, causing a database cursor to be left open. See the giant comment block for details. --- pokedex/db/load.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pokedex/db/load.py b/pokedex/db/load.py index 2ecc109..5b04fcd 100644 --- a/pokedex/db/load.py +++ b/pokedex/db/load.py @@ -156,8 +156,21 @@ def load(session, tables=[], directory=None, drop_tables=False, verbose=False, s # SQLite speed tweaks if not safe and engine.dialect.name == 'sqlite': - session.execute("PRAGMA synchronous=OFF") - session.execute("PRAGMA journal_mode=OFF") + # We have to explicity call close here because session.execute + # returns a ResultProxy object that hangs onto the database cursor + # in case you wanted to see the results of your statement, and + # these PRAGMA commands helpfully return the string 'OFF'. + # + # This would not normally be a problem, except that when + # journal_mode=OFF, SQLite sometimes doesn't like it when you + # have multiple database cursors open. + # + # This would still not normally be a problem because CPython + # will free the ResultProxy immediately because it isn't referenced, + # closing the database cursor, but this isn't true in PyPy, + # which doesn't use reference counting. + session.execute("PRAGMA synchronous=OFF").close() + session.execute("PRAGMA journal_mode=OFF").close() # Drop all tables if requested if drop_tables: