Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-94017: Improve clarity of sqlite3 transaction handling docs #94320

Merged
merged 11 commits into from
Jul 6, 2022
99 changes: 60 additions & 39 deletions Doc/library/sqlite3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -406,14 +406,22 @@ Connection Objects

.. attribute:: isolation_level

Get or set the current default isolation level. :const:`None` for autocommit mode or
one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". See section
:ref:`sqlite3-controlling-transactions` for a more detailed explanation.
Get or set the current default isolation level.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
Set to :const:`None` to disable implicit transaction handling,
or one of "", "DEFERRED", "IMMEDIATE" or "EXCLUSIVE".
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
Defaults to the former (`""`), unless overridden at :func:`connect`,
using the *isolation_level* parameter.
"" and "DEFERRED" carry the same meaning;
they both imply deferred isolation level.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
See :ref:`sqlite3-controlling-transactions` for more details.

.. attribute:: in_transaction

This read-only attribute corresponds to the low-level SQLite autocommit
mode.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

:const:`True` if a transaction is active (there are uncommitted changes),
:const:`False` otherwise. Read-only attribute.
:const:`False` otherwise.

.. versionadded:: 3.2

Expand Down Expand Up @@ -868,21 +876,27 @@ Cursor Objects

.. method:: execute(sql[, parameters])

Executes an SQL statement. Values may be bound to the statement using
Execute an SQL statement. Values may be bound to the statement using
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
:ref:`placeholders <sqlite3-placeholders>`.

:meth:`execute` will only execute a single SQL statement. If you try to execute
more than one statement with it, it will raise a :exc:`ProgrammingError`. Use
:meth:`executescript` if you want to execute multiple SQL statements with one
call.

If :attr:`isolation_level` is not :const:`None`,
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
*sql* is an INSERT, UPDATE, DELETE, or REPLACE statement,
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
and there is no open transaction,
a transaction is implicitly opened before executing *sql*.


.. method:: executemany(sql, seq_of_parameters)

Executes a :ref:`parameterized <sqlite3-placeholders>` SQL command
Execute a :ref:`parameterized <sqlite3-placeholders>` SQL command
against all parameter sequences or mappings found in the sequence
*seq_of_parameters*. The :mod:`sqlite3` module also allows using an
*seq_of_parameters*. It is also possible to use an
:term:`iterator` yielding parameters instead of a sequence.
Uses the same implicit transaction handling as :meth:`~Cursor.execute`.

.. literalinclude:: ../includes/sqlite3/executemany_1.py

Expand All @@ -893,12 +907,13 @@ Cursor Objects

.. method:: executescript(sql_script)

This is a nonstandard convenience method for executing multiple SQL statements
at once. It issues a ``COMMIT`` statement first, then executes the SQL script it
gets as a parameter. This method disregards :attr:`isolation_level`; any
transaction control must be added to *sql_script*.
Execute multiple SQL statements at once.
If there is a pending transaciton,
an implicit ``COMMIT`` statement is executed first.
No other implicit transaction control is performed;
any transaction control must be added to *sql_script*.

*sql_script* can be an instance of :class:`str`.
*sql_script* must be a :class:`string <str>`.

Example:

Expand Down Expand Up @@ -1425,33 +1440,39 @@ This section shows recipes for common adapters and converters.
Controlling Transactions
------------------------

The underlying ``sqlite3`` library operates in ``autocommit`` mode by default,
but the Python :mod:`sqlite3` module by default does not.

``autocommit`` mode means that statements that modify the database take effect
immediately. A ``BEGIN`` or ``SAVEPOINT`` statement disables ``autocommit``
mode, and a ``COMMIT``, a ``ROLLBACK``, or a ``RELEASE`` that ends the
outermost transaction, turns ``autocommit`` mode back on.

The Python :mod:`sqlite3` module by default issues a ``BEGIN`` statement
implicitly before a Data Modification Language (DML) statement (i.e.
``INSERT``/``UPDATE``/``DELETE``/``REPLACE``).

You can control which kind of ``BEGIN`` statements :mod:`sqlite3` implicitly
executes via the *isolation_level* parameter to the :func:`connect`
call, or via the :attr:`isolation_level` property of connections.
If you specify no *isolation_level*, a plain ``BEGIN`` is used, which is
equivalent to specifying ``DEFERRED``. Other possible values are ``IMMEDIATE``
and ``EXCLUSIVE``.

You can disable the :mod:`sqlite3` module's implicit transaction management by
setting :attr:`isolation_level` to ``None``. This will leave the underlying
``sqlite3`` library operating in ``autocommit`` mode. You can then completely
control the transaction state by explicitly issuing ``BEGIN``, ``ROLLBACK``,
``SAVEPOINT``, and ``RELEASE`` statements in your code.

Note that :meth:`~Cursor.executescript` disregards
:attr:`isolation_level`; any transaction control must be added explicitly.
The ``sqlite3`` module does not adhere to the transaction handling recommended
by PEP 249.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
Instead of keeping a transaction open and requiring the user to use the
:meth:`~Connection.commit` and :meth:`~Connection.rollback` methods,
``sqlite3`` only implicitly opens new transactions before
:meth:`~Cursor.execute` and :meth:`~Cursor.executemany` executes any of the
following statements:

* INSERT
* UPDATE
* DELETE
* REPLACE
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

In addition, any pending transaction is implicitly committed in
:meth:`~Cursor.executescript`, before execution of the given SQL script.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
No other implicit transaction handling is performed.

You can control which kind of ``BEGIN`` statements ``sqlite3`` implicitly
executes via the :attr:`isolation_level` connection attribute.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

The ``sqlite3`` module lets the user choose bypass its transaction handling, by
setting :attr:`isolation_level` to :const:`None`.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
This leaves the underlying SQLite library in autocommit mode,
but also allows the user to perform any transaction handling using explicit SQL
statements.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
The SQLite library autocommit mode can be queried using the
:attr:`in_transaction` connection attribute.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

.. note::

PEP 249's autocommit concept must not be mistaken for SQLite's autocommit
mode.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved
Though related, they are different concepts with different semantics.
erlend-aasland marked this conversation as resolved.
Show resolved Hide resolved

.. versionchanged:: 3.6
:mod:`sqlite3` used to implicitly commit an open transaction before DDL
Expand Down