Skip to content

Commit c95f554

Browse files
erlend-aaslandAlexWaygoodCAM-Gerlachgeryogam
authored
gh-83638: Add sqlite3.Connection.autocommit for PEP 249 compliant behaviour (#93823)
Introduce the autocommit attribute to Connection and the autocommit parameter to connect() for PEP 249-compliant transaction handling. Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: C.A.M. Gerlach <CAM.Gerlach@Gerlach.CAM> Co-authored-by: Géry Ogam <gery.ogam@gmail.com>
1 parent 99972dc commit c95f554

14 files changed

+537
-62
lines changed

Doc/library/sqlite3.rst

+154-17
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,8 @@ Module functions
258258
.. function:: connect(database, timeout=5.0, detect_types=0, \
259259
isolation_level="DEFERRED", check_same_thread=True, \
260260
factory=sqlite3.Connection, cached_statements=128, \
261-
uri=False)
261+
uri=False, \*, \
262+
autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL)
262263

263264
Open a connection to an SQLite database.
264265

@@ -290,11 +291,12 @@ Module functions
290291
By default (``0``), type detection is disabled.
291292

292293
:param isolation_level:
293-
The :attr:`~Connection.isolation_level` of the connection,
294-
controlling whether and how transactions are implicitly opened.
294+
See :attr:`Connection.isolation_level` and
295+
:ref:`sqlite3-transaction-control-isolation-level` for more information.
295296
Can be ``"DEFERRED"`` (default), ``"EXCLUSIVE"`` or ``"IMMEDIATE"``;
296297
or ``None`` to disable opening transactions implicitly.
297-
See :ref:`sqlite3-controlling-transactions` for more.
298+
Has no effect unless :attr:`Connection.autocommit` is set to
299+
:data:`~sqlite3.LEGACY_TRANSACTION_CONTROL` (the default).
298300
:type isolation_level: str | None
299301

300302
:param bool check_same_thread:
@@ -321,6 +323,14 @@ Module functions
321323
The query string allows passing parameters to SQLite,
322324
enabling various :ref:`sqlite3-uri-tricks`.
323325

326+
:param autocommit:
327+
See :attr:`Connection.autocommit` and
328+
:ref:`sqlite3-transaction-control-autocommit` for more information.
329+
*autocommit* currently defaults to
330+
:data:`~sqlite3.LEGACY_TRANSACTION_CONTROL`.
331+
The default will change to ``False`` in a future Python release.
332+
:type autocommit: bool
333+
324334
:rtype: Connection
325335

326336
.. audit-event:: sqlite3.connect database sqlite3.connect
@@ -335,6 +345,9 @@ Module functions
335345
.. versionadded:: 3.10
336346
The ``sqlite3.connect/handle`` auditing event.
337347

348+
.. versionadded:: 3.12
349+
The *autocommit* parameter.
350+
338351
.. function:: complete_statement(statement)
339352

340353
Return ``True`` if the string *statement* appears to contain
@@ -418,6 +431,12 @@ Module functions
418431
Module constants
419432
^^^^^^^^^^^^^^^^
420433

434+
.. data:: LEGACY_TRANSACTION_CONTROL
435+
436+
Set :attr:`~Connection.autocommit` to this constant to select
437+
old style (pre-Python 3.12) transaction control behaviour.
438+
See :ref:`sqlite3-transaction-control-isolation-level` for more information.
439+
421440
.. data:: PARSE_COLNAMES
422441

423442
Pass this flag value to the *detect_types* parameter of
@@ -616,18 +635,27 @@ Connection objects
616635
.. method:: commit()
617636

618637
Commit any pending transaction to the database.
619-
If there is no open transaction, this method is a no-op.
638+
If :attr:`autocommit` is ``True``, or there is no open transaction,
639+
this method does nothing.
640+
If :attr:`!autocommit` is ``False``, a new transaction is implicitly
641+
opened if a pending transaction was committed by this method.
620642

621643
.. method:: rollback()
622644

623645
Roll back to the start of any pending transaction.
624-
If there is no open transaction, this method is a no-op.
646+
If :attr:`autocommit` is ``True``, or there is no open transaction,
647+
this method does nothing.
648+
If :attr:`!autocommit` is ``False``, a new transaction is implicitly
649+
opened if a pending transaction was rolled back by this method.
625650

626651
.. method:: close()
627652

628653
Close the database connection.
629-
Any pending transaction is not committed implicitly;
630-
make sure to :meth:`commit` before closing
654+
If :attr:`autocommit` is ``False``,
655+
any pending transaction is implicitly rolled back.
656+
If :attr:`!autocommit` is ``True`` or :data:`LEGACY_TRANSACTION_CONTROL`,
657+
no implicit transaction control is executed.
658+
Make sure to :meth:`commit` before closing
631659
to avoid losing pending changes.
632660

633661
.. method:: execute(sql, parameters=(), /)
@@ -1224,6 +1252,38 @@ Connection objects
12241252

12251253
.. versionadded:: 3.11
12261254

1255+
.. attribute:: autocommit
1256+
1257+
This attribute controls :pep:`249`-compliant transaction behaviour.
1258+
:attr:`!autocommit` has three allowed values:
1259+
1260+
* ``False``: Select :pep:`249`-compliant transaction behaviour,
1261+
implying that :mod:`!sqlite3` ensures a transaction is always open.
1262+
Use :meth:`commit` and :meth:`rollback` to close transactions.
1263+
1264+
This is the recommended value of :attr:`!autocommit`.
1265+
1266+
* ``True``: Use SQLite's `autocommit mode`_.
1267+
:meth:`commit` and :meth:`rollback` have no effect in this mode.
1268+
1269+
* :data:`LEGACY_TRANSACTION_CONTROL`:
1270+
Pre-Python 3.12 (non-:pep:`249`-compliant) transaction control.
1271+
See :attr:`isolation_level` for more details.
1272+
1273+
This is currently the default value of :attr:`!autocommit`.
1274+
1275+
Changing :attr:`!autocommit` to ``False`` will open a new transaction,
1276+
and changing it to ``True`` will commit any pending transaction.
1277+
1278+
See :ref:`sqlite3-transaction-control-autocommit` for more details.
1279+
1280+
.. note::
1281+
1282+
The :attr:`isolation_level` attribute has no effect unless
1283+
:attr:`autocommit` is :data:`LEGACY_TRANSACTION_CONTROL`.
1284+
1285+
.. versionadded:: 3.12
1286+
12271287
.. attribute:: in_transaction
12281288

12291289
This read-only attribute corresponds to the low-level SQLite
@@ -1236,17 +1296,24 @@ Connection objects
12361296

12371297
.. attribute:: isolation_level
12381298

1239-
This attribute controls the :ref:`transaction handling
1240-
<sqlite3-controlling-transactions>` performed by :mod:`!sqlite3`.
1299+
Controls the :ref:`legacy transaction handling mode
1300+
<sqlite3-transaction-control-isolation-level>` of :mod:`!sqlite3`.
12411301
If set to ``None``, transactions are never implicitly opened.
12421302
If set to one of ``"DEFERRED"``, ``"IMMEDIATE"``, or ``"EXCLUSIVE"``,
12431303
corresponding to the underlying `SQLite transaction behaviour`_,
1244-
implicit :ref:`transaction management
1245-
<sqlite3-controlling-transactions>` is performed.
1304+
:ref:`implicit transaction management
1305+
<sqlite3-transaction-control-isolation-level>` is performed.
12461306

12471307
If not overridden by the *isolation_level* parameter of :func:`connect`,
12481308
the default is ``""``, which is an alias for ``"DEFERRED"``.
12491309

1310+
.. note::
1311+
1312+
Using :attr:`autocommit` to control transaction handling is
1313+
recommended over using :attr:`!isolation_level`.
1314+
:attr:`!isolation_level` has no effect unless :attr:`autocommit` is
1315+
set to :data:`LEGACY_TRANSACTION_CONTROL` (the default).
1316+
12501317
.. attribute:: row_factory
12511318

12521319
A callable that accepts two arguments,
@@ -1375,7 +1442,9 @@ Cursor objects
13751442
:meth:`executescript` if you want to execute multiple SQL statements with one
13761443
call.
13771444

1378-
If :attr:`~Connection.isolation_level` is not ``None``,
1445+
If :attr:`~Connection.autocommit` is
1446+
:data:`LEGACY_TRANSACTION_CONTROL`,
1447+
:attr:`~Connection.isolation_level` is not ``None``,
13791448
*sql* is an ``INSERT``, ``UPDATE``, ``DELETE``, or ``REPLACE`` statement,
13801449
and there is no open transaction,
13811450
a transaction is implicitly opened before executing *sql*.
@@ -1403,7 +1472,9 @@ Cursor objects
14031472
.. method:: executescript(sql_script, /)
14041473

14051474
Execute the SQL statements in *sql_script*.
1406-
If there is a pending transaction,
1475+
If the :attr:`~Connection.autocommit` is
1476+
:data:`LEGACY_TRANSACTION_CONTROL`
1477+
and there is a pending transaction,
14071478
an implicit ``COMMIT`` statement is executed first.
14081479
No other implicit transaction control is performed;
14091480
any transaction control must be added to *sql_script*.
@@ -2202,9 +2273,12 @@ the transaction is committed.
22022273
If this commit fails,
22032274
or if the body of the ``with`` statement raises an uncaught exception,
22042275
the transaction is rolled back.
2276+
If :attr:`~Connection.autocommit` is ``False``,
2277+
a new transaction is implicitly opened after committing or rolling back.
22052278

22062279
If there is no open transaction upon leaving the body of the ``with`` statement,
2207-
the context manager is a no-op.
2280+
or if :attr:`~Connection.autocommit` is ``True``,
2281+
the context manager does nothing.
22082282

22092283
.. note::
22102284

@@ -2289,13 +2363,72 @@ can be found in the `SQLite URI documentation`_.
22892363
Explanation
22902364
-----------
22912365

2366+
.. _sqlite3-transaction-control:
22922367
.. _sqlite3-controlling-transactions:
22932368

22942369
Transaction control
22952370
^^^^^^^^^^^^^^^^^^^
22962371

2297-
The :mod:`!sqlite3` module does not adhere to the transaction handling recommended
2298-
by :pep:`249`.
2372+
:mod:`!sqlite3` offers multiple methods of controlling whether,
2373+
when and how database transactions are opened and closed.
2374+
:ref:`sqlite3-transaction-control-autocommit` is recommended,
2375+
while :ref:`sqlite3-transaction-control-isolation-level`
2376+
retains the pre-Python 3.12 behaviour.
2377+
2378+
.. _sqlite3-transaction-control-autocommit:
2379+
2380+
Transaction control via the ``autocommit`` attribute
2381+
""""""""""""""""""""""""""""""""""""""""""""""""""""
2382+
2383+
The recommended way of controlling transaction behaviour is through
2384+
the :attr:`Connection.autocommit` attribute,
2385+
which should preferrably be set using the *autocommit* parameter
2386+
of :func:`connect`.
2387+
2388+
It is suggested to set *autocommit* to ``False``,
2389+
which implies :pep:`249`-compliant transaction control.
2390+
This means:
2391+
2392+
* :mod:`!sqlite3` ensures that a transaction is always open,
2393+
so :meth:`Connection.commit` and :meth:`Connection.rollback`
2394+
will implicitly open a new transaction immediately after closing
2395+
the pending one.
2396+
:mod:`!sqlite3` uses ``BEGIN DEFERRED`` statements when opening transactions.
2397+
* Transactions should be committed explicitly using :meth:`!commit`.
2398+
* Transactions should be rolled back explicitly using :meth:`!rollback`.
2399+
* An implicit rollback is performed if the database is
2400+
:meth:`~Connection.close`-ed with pending changes.
2401+
2402+
Set *autocommit* to ``True`` to enable SQLite's `autocommit mode`_.
2403+
In this mode, :meth:`Connection.commit` and :meth:`Connection.rollback`
2404+
have no effect.
2405+
Note that SQLite's autocommit mode is distinct from
2406+
the :pep:`249`-compliant :attr:`Connection.autocommit` attribute;
2407+
use :attr:`Connection.in_transaction` to query
2408+
the low-level SQLite autocommit mode.
2409+
2410+
Set *autocommit* to :data:`LEGACY_TRANSACTION_CONTROL`
2411+
to leave transaction control behaviour to the
2412+
:attr:`Connection.isolation_level` attribute.
2413+
See :ref:`sqlite3-transaction-control-isolation-level` for more information.
2414+
2415+
2416+
.. _sqlite3-transaction-control-isolation-level:
2417+
2418+
Transaction control via the ``isolation_level`` attribute
2419+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
2420+
2421+
.. note::
2422+
2423+
The recommended way of controlling transactions is via the
2424+
:attr:`~Connection.autocommit` attribute.
2425+
See :ref:`sqlite3-transaction-control-autocommit`.
2426+
2427+
If :attr:`Connection.autocommit` is set to
2428+
:data:`LEGACY_TRANSACTION_CONTROL` (the default),
2429+
transaction behaviour is controlled using
2430+
the :attr:`Connection.isolation_level` attribute.
2431+
Otherwise, :attr:`!isolation_level` has no effect.
22992432

23002433
If the connection attribute :attr:`~Connection.isolation_level`
23012434
is not ``None``,
@@ -2326,6 +2459,10 @@ regardless of the value of :attr:`~Connection.isolation_level`.
23262459
:mod:`!sqlite3` used to implicitly commit an open transaction before DDL
23272460
statements. This is no longer the case.
23282461

2462+
.. versionchanged:: 3.12
2463+
The recommended way of controlling transactions is now via the
2464+
:attr:`~Connection.autocommit` attribute.
2465+
23292466
.. _autocommit mode:
23302467
https://www.sqlite.org/lang_transaction.html#implicit_versus_explicit_transactions
23312468

Doc/whatsnew/3.12.rst

+7
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ sqlite3
263263
* Add a :ref:`command-line interface <sqlite3-cli>`.
264264
(Contributed by Erlend E. Aasland in :gh:`77617`.)
265265

266+
* Add the :attr:`~sqlite3.Connection.autocommit` attribute
267+
to :class:`~sqlite3.Connection`
268+
and the *autocommit* parameter to :func:`~sqlite3.connect`
269+
to control :pep:`249`-compliant
270+
:ref:`transaction handling <sqlite3-transaction-control-autocommit>`.
271+
(Contributed by Erlend E. Aasland in :gh:`83638`.)
272+
266273
threading
267274
---------
268275

Include/internal/pycore_global_objects_fini_generated.h

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

+1
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ struct _Py_global_strings {
269269
STRUCT_FOR_ID(as_integer_ratio)
270270
STRUCT_FOR_ID(attribute)
271271
STRUCT_FOR_ID(authorizer_callback)
272+
STRUCT_FOR_ID(autocommit)
272273
STRUCT_FOR_ID(b)
273274
STRUCT_FOR_ID(backtick)
274275
STRUCT_FOR_ID(base)

Include/internal/pycore_runtime_init_generated.h

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)