[1.6.x] Fixed #22491 -- documented how select_for_update() should be tested.

Thanks Andreas Pelme for the report.

Backport of 668d432d0a from master
This commit is contained in:
Moayad Mardini 2014-07-27 11:12:39 +03:00 committed by Tim Graham
parent a7fe87bd28
commit 6c70b1d7df
2 changed files with 21 additions and 7 deletions

View File

@ -1331,17 +1331,18 @@ backends support ``select_for_update()``. However, MySQL has no support for the
``nowait`` argument. Obviously, users of external third-party backends should
check with their backend's documentation for specifics in those cases.
Passing ``nowait=True`` to ``select_for_update`` using database backends that
Passing ``nowait=True`` to ``select_for_update()`` using database backends that
do not support ``nowait``, such as MySQL, will cause a
:exc:`~django.db.DatabaseError` to be raised. This is in order to prevent code
unexpectedly blocking.
Evaluating a queryset with ``select_for_update`` in autocommit mode is
an error because the rows are then not locked. If allowed, this would
facilitate data corruption, and could easily be caused by calling,
outside of any transaction, code that expects to be run in one.
Evaluating a queryset with ``select_for_update()`` in autocommit mode is
a :exc:`~django.db.transaction.TransactionManagementError` error because the
rows are not locked in that case. If allowed, this would facilitate data
corruption and could easily be caused by calling code that expects to be run in
a transaction outside of one.
Using ``select_for_update`` on backends which do not support
Using ``select_for_update()`` on backends which do not support
``SELECT ... FOR UPDATE`` (such as SQLite) will have no effect.
.. versionchanged:: 1.6.3
@ -1349,6 +1350,16 @@ Using ``select_for_update`` on backends which do not support
It is now an error to execute a query with ``select_for_update()`` in
autocommit mode. With earlier releases in the 1.6 series it was a no-op.
.. warning::
Although ``select_for_update()`` normally fails in autocommit mode, since
:class:`~django.test.TestCase` automatically wraps each test in a
transaction, calling ``select_for_update()`` in a ``TestCase`` even outside
an :func:`~django.db.transaction.atomic()` block will (perhaps unexpectedly)
pass without raising a ``TransactionManagementError``. To properly test
``select_for_update()`` you should use
:class:`~django.test.TransactionTestCase`.
Methods that do not return QuerySets
------------------------------------

View File

@ -623,7 +623,10 @@ to test the effects of commit and rollback:
While ``commit`` and ``rollback`` operations still *appear* to work when
used in ``TestCase``, no actual commit or rollback will be performed by the
database. This can cause your tests to pass or fail unexpectedly. Always
use ``TransactionTestCase`` when testing transactional behavior.
use ``TransactionTestCase`` when testing transactional behavior or any code
that can't normally be excuted in autocommit mode
(:meth:`~django.db.models.query.QuerySet.select_for_update()` is an
example).
.. versionchanged:: 1.5