fix: disable implicit transactions in sqlite#102
Conversation
- Set isolation_level=None when creating aiosqlite connection - Prevents 'cannot start a transaction within a transaction' error - Allows manual transaction control with BEGIN/COMMIT/ROLLBACK
There was a problem hiding this comment.
Code Review
This pull request updates the SQLite connection creation in src/blacki/storage/sqlite.py to use isolation_level=None. The reviewer points out that this enables autocommit mode, which silently disables connection.commit() and connection.rollback(). This will break transaction handling in other parts of the application, such as src/blacki/workouts/storage.py, which still rely on those methods. The reviewer recommends using explicit SQL statements for committing and rolling back transactions.
| path.parent.mkdir(parents=True, exist_ok=True) | ||
|
|
||
| conn = await aiosqlite.connect(path) | ||
| conn = await aiosqlite.connect(path, isolation_level=None) |
There was a problem hiding this comment.
Setting isolation_level=None puts the connection into autocommit mode and disables Python's automatic transaction management. While this is the correct way to handle manual transactions, it has a critical side effect: calling connection.commit() and connection.rollback() on the connection object becomes a silent no-op in Python's sqlite3 (and thus aiosqlite).
In src/blacki/workouts/storage.py (line 116), create_session starts a manual transaction with BEGIN but attempts to commit/rollback using await self._conn.commit() and await self._conn.rollback(). With isolation_level=None, these calls will do nothing, leaving the transaction open indefinitely and causing subsequent operations to fail with database locks or transaction errors.
To fix this, you must update create_session to use explicit SQL statements for committing and rolling back:
await self._conn.execute("COMMIT")
await self._conn.execute("ROLLBACK")| conn = await aiosqlite.connect(path, isolation_level=None) | |
| # isolation_level=None disables implicit transactions (autocommit mode). | |
| # Note: Use execute("COMMIT") / execute("ROLLBACK") instead of conn.commit() / conn.rollback(). | |
| conn = await aiosqlite.connect(path, isolation_level=None) |
- Replace conn.commit()/rollback() with execute('COMMIT'/'ROLLBACK')
- Required when isolation_level=None (autocommit mode)
- Update all test fixtures to use isolation_level=None
- Update log message to indicate autocommit mode
What
Fix SQLite transaction error by setting isolation_level=None when creating database connections.
Why
The application was experiencing
sqlite3.OperationalError: cannot start a transaction within a transactionerrors when logging workouts. This occurred because:BEGINto start a manual transaction, SQLite rejects it if an implicit transaction is already activeHow
isolation_level=Noneparameter when creating aiosqlite connection insrc/blacki/storage/sqlite.pyBEGIN,COMMIT, andROLLBACKstatements to work correctlyTests
create_sessionmethod in workout storage uses explicit transactions and will now work correctly