]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Implement autocommit isolation level for pysqlite
authorGord Thompson <gord@gordthompson.com>
Sat, 22 Feb 2020 13:44:05 +0000 (06:44 -0700)
committerGord Thompson <gord@gordthompson.com>
Tue, 24 Mar 2020 18:15:02 +0000 (12:15 -0600)
Fixes: #5164
Change-Id: I190b9de552dfed9f2a33babf82e42465ef09c82a

.gitignore
doc/build/changelog/unreleased_13/5164.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/sqlite/base.py
lib/sqlalchemy/dialects/sqlite/pysqlite.py
test/requirements.py

index 48b5ecd4be14b03dd944291b5e451bffd7c63d53..f6b44391d9ed13db5a7c589f72ed7b2f102165c2 100644 (file)
@@ -37,3 +37,4 @@ test/test_schema.db
 /.vscode/
 /.ipynb_checkpoints/
 *.ipynb
+/querytest.db
diff --git a/doc/build/changelog/unreleased_13/5164.rst b/doc/build/changelog/unreleased_13/5164.rst
new file mode 100644 (file)
index 0000000..5883ecb
--- /dev/null
@@ -0,0 +1,5 @@
+.. change::
+    :tags: sqlite, usecase
+    :tickets: 5164
+
+    Implemented AUTOCOMMIT isolation level for SQLite when using pysqlite.
index a63ce0033f1cc1f1564c7a8c8377f12720e861a0..c79357176be8c0a7486b45bc019afe2bca1783b9 100644 (file)
@@ -168,8 +168,8 @@ work when using the pysqlite driver.
 
 .. _sqlite_isolation_level:
 
-Transaction Isolation Level
-----------------------------
+Transaction Isolation Level / Autocommit
+----------------------------------------
 
 SQLite supports "transaction isolation" in a non-standard way, along two
 axes.  One is that of the
@@ -185,6 +185,15 @@ and ``"READ UNCOMMITTED"`` corresponding to a value of 0 and 1, respectively.
 SQLite defaults to ``SERIALIZABLE``, however its behavior is impacted by
 the pysqlite driver's default behavior.
 
+When using the pysqlite driver, the ``"AUTOCOMMIT"`` isolation level is also
+available, which will alter the pysqlite connection using the ``.isolation_level``
+attribute on the DBAPI connection and set it to None for the duration
+of the setting.
+
+.. versionadded:: 1.3.16 added support for SQLite AUTOCOMMIT isolation level
+   when using the pysqlite / sqlite3 SQLite driver.
+
+
 The other axis along which SQLite's transactional locking is impacted is
 via the nature of the ``BEGIN`` statement used.   The three varieties
 are "deferred", "immediate", and "exclusive", as described at
index b8a42a506274c05efdfbe5e609a80e990e28653b..807f9488d1af17dd893dfcc7843c5a60f5826fff 100644 (file)
@@ -324,6 +324,12 @@ ourselves. This is achieved using two event listeners::
         # emit our own BEGIN
         conn.exec_driver_sql("BEGIN")
 
+.. warning:: When using the above recipe, it is advised to not use the
+   :paramref:`.execution_options.isolation_level` setting on
+   :class:`.Connection` and :func:`.create_engine` with the SQLite driver,
+   as this function necessarily will also alter the ".isolation_level" setting.
+
+
 Above, we intercept a new pysqlite connection and disable any transactional
 integration.   Then, at the point at which SQLAlchemy knows that transaction
 scope is to begin, we emit ``"BEGIN"`` ourselves.
@@ -437,6 +443,20 @@ class SQLiteDialect_pysqlite(SQLiteDialect):
     def _get_server_version_info(self, connection):
         return self.dbapi.sqlite_version_info
 
+    def set_isolation_level(self, connection, level):
+        if hasattr(connection, "connection"):
+            dbapi_connection = connection.connection
+        else:
+            dbapi_connection = connection
+
+        if level == "AUTOCOMMIT":
+            dbapi_connection.isolation_level = None
+        else:
+            dbapi_connection.isolation_level = ""
+            return super(SQLiteDialect_pysqlite, self).set_isolation_level(
+                connection, level
+            )
+
     def create_connect_args(self, url):
         if url.username or url.password or url.host or url.port:
             raise exc.ArgumentError(
index e9fb6a305475037a9dc8eb04c6efb6e1316660dc..d9fcd698c3364fd27fbfbb6f4c4f517a2f5e2698 100644 (file)
@@ -381,6 +381,7 @@ class DefaultRequirements(SuiteRequirements):
 
         if against(config, "sqlite"):
             default = "SERIALIZABLE"
+            levels.add("AUTOCOMMIT")
         elif against(config, "postgresql"):
             default = "READ COMMITTED"
             levels.add("AUTOCOMMIT")