SQLite 3.28: Should Python’s sqlite3 expose a rollback‑allowed flag for DDL?
0 reputation · 30 Sept 2025, 19:50 UTC
0 reputation · 30 Sept 2025, 19:50 UTC
Ensure that schema modifications executed through Python’s sqlite3 module can be safely rolled back, preserving the prior table structure without manual intervention.
SQLite supports transactional DDL in recent releases, but certain ALTER TABLE operations (e.g., dropping a column) are not fully supported, causing OperationalError and making rollback moot. The Python DB‑API does not expose a way to opt out of the module’s default transaction wrapping for DDL statements. Behavior also varies across adapters (psycopg2, MySQLdb) and older SQLite versions (<3.7.9). No documented flag currently exists to disable automatic transaction wrapping, raising questions about future compatibility and developer control.
34775 reputation · 01 Oct 2025, 03:39 UTC
Short answer: No, Python’s sqlite3 module does not need an additional rollback_allowed flag for DDL. The existing isolation_level attribute already gives developers full control over whether DDL statements are wrapped in an implicit transaction.
ALTER TABLE forms (e.g., DROP COLUMN) raise OperationalError and automatically abort the transaction, so a rollback is guaranteed.sqlite3 module wraps every statement in a transaction unless the connection is in autocommit mode (i.e., conn.isolation_level = None). This is the documented way to opt out of the default wrapping.Before executing schema changes you can verify that the underlying SQLite build supports transactional DDL:
import sqlite3
conn = sqlite3.connect(':memory:')
print('SQLite version:', conn.execute('SELECT sqlite_version();').fetchone()[0])
print('Compile options:', conn.execute('PRAGMA compile_options;').fetchall())
Look for the ENABLE_FTS5 and ENABLE_JSON1 options – their presence indicates a modern build that includes transactional DDL support.
conn.execute('BEGIN')
conn.execute('CREATE TABLE t(id INTEGER)')
conn.execute('ROLLBACK')
print('Tables after rollback:', conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall())
The table should not exist after the rollback.
try:
conn.execute('BEGIN')
conn.execute('ALTER TABLE t DROP COLUMN id')
except sqlite3.OperationalError as e:
print('Error:', e)
conn.execute('ROLLBACK')
Even though the operation fails, the transaction is automatically rolled back.
conn.isolation_level = None
conn.execute('CREATE TABLE a(id INTEGER)')
print('Tables after autocommit:', conn.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall())
The table is committed immediately, and there is no surrounding transaction to roll back.
conn.isolation_level = None only when you intentionally want the DDL to commit immediately and are confident the operation is safe.BEGIN … COMMIT block if you want full control and to be able to roll back on error.If you are using a SQLite build older than 3.28 or a third‑party adapter that may behave differently, please let us know the exact SQLite version and adapter name. This will help refine the recommendation for that environment.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.