### Description
Update docs with workaround for SAVEPOINT in aiosqlite, based on https://github.com/sqlalchemy/sqlalchemy/discussions/10463
### Checklist
This pull request is:
- [x] A documentation / typographical / small typing error fix
- Good to go, no issue or tests are needed
Closes: #10491
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/10491
Pull-request-sha:
0516c205d2c4c046d449b5684c13a06f813dabe1
Change-Id: I6bb92f18c99f2a53f5488a2d5812781cb2a003b7
aiosqlite extends pysqlite to support async, so we can create our own user-defined functions (UDFs)
in Python and use them directly in SQLite queries as described here: :ref:`pysqlite_udfs`.
+.. _aiosqlite_serializable:
+
+Serializable isolation / Savepoints / Transactional DDL (asyncio version)
+-------------------------------------------------------------------------
+
+Similarly to pysqlite, aiosqlite does not support SAVEPOINT feature.
+
+The solution is similar to :ref:`pysqlite_serializable`. This is achieved by the event listeners in async::
+
+ from sqlalchemy import create_engine, event
+ from sqlalchemy.ext.asyncio import create_async_engine
+
+ engine = create_async_engine("sqlite+aiosqlite:///myfile.db")
+
+ @event.listens_for(engine.sync_engine, "connect")
+ def do_connect(dbapi_connection, connection_record):
+ # disable aiosqlite's emitting of the BEGIN statement entirely.
+ # also stops it from emitting COMMIT before any DDL.
+ dbapi_connection.isolation_level = None
+
+ @event.listens_for(engine.sync_engine, "begin")
+ def do_begin(conn):
+ # emit our own BEGIN
+ conn.exec_driver_sql("BEGIN")
+
+.. warning:: When using the above recipe, it is advised to not use the
+ :paramref:`.Connection.execution_options.isolation_level` setting on
+ :class:`_engine.Connection` and :func:`_sa.create_engine`
+ with the SQLite driver,
+ as this function necessarily will also alter the ".isolation_level" setting.
""" # noqa
SQLite's transactional scope is impacted by unresolved
issues in the pysqlite driver, which defers BEGIN statements to a greater
degree than is often feasible. See the section :ref:`pysqlite_serializable`
- for techniques to work around this behavior.
+ or :ref:`aiosqlite_serializable` for techniques to work around this behavior.
.. seealso::
.. warning::
SQLite's SAVEPOINT feature is impacted by unresolved
- issues in the pysqlite driver, which defers BEGIN statements to a greater
- degree than is often feasible. See the section :ref:`pysqlite_serializable`
+ issues in the pysqlite and aiosqlite drivers, which defer BEGIN statements
+ to a greater degree than is often feasible. See the sections
+ :ref:`pysqlite_serializable` and :ref:`aiosqlite_serializable`
for techniques to work around this behavior.
Transactional DDL
For a general description of ORM begin nested, see
:meth:`_orm.Session.begin_nested`.
+ .. seealso::
+
+ :ref:`aiosqlite_serializable` - special workarounds required
+ with the SQLite asyncio driver in order for SAVEPOINT to work
+ correctly.
+
""" # noqa: E501
For a general description of ORM begin nested, see
:meth:`_orm.Session.begin_nested`.
+ .. seealso::
+
+ :ref:`aiosqlite_serializable` - special workarounds required
+ with the SQLite asyncio driver in order for SAVEPOINT to work
+ correctly.
+
"""
return AsyncSessionTransaction(self, nested=True)
:ref:`pysqlite_serializable` - special workarounds required
with the SQLite driver in order for SAVEPOINT to work
- correctly.
+ correctly. For asyncio use cases, see the section
+ :ref:`aiosqlite_serializable`.
""" # noqa: E501
.. tip:: When using SQLite, the SQLite driver included through
Python 3.11 does not handle SAVEPOINTs correctly in all cases
- without workarounds. See the section
- :ref:`pysqlite_serializable` for details on current workarounds.
+ without workarounds. See the sections
+ :ref:`pysqlite_serializable` and :ref:`aiosqlite_serializable`
+ for details on current workarounds.
* ``"control_fully"`` - the :class:`_orm.Session` will take
control of the given transaction as its own;
:ref:`pysqlite_serializable` - special workarounds required
with the SQLite driver in order for SAVEPOINT to work
- correctly.
+ correctly. For asyncio use cases, see the section
+ :ref:`aiosqlite_serializable`.
"""
return self.begin(nested=True)