From a0bd0063065de054c73d5984d7b4830e29e809e6 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Thu, 14 Apr 2022 07:53:15 +0200 Subject: [PATCH] Made select_for_update() don't raise TransactionManagementError on databases that don't support transactions. --- django/db/models/sql/compiler.py | 7 ++++++- tests/queries/test_explain.py | 16 ++++------------ tests/select_for_update/tests.py | 4 ++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index faa08e376d..1285b647d8 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -653,7 +653,12 @@ class SQLCompiler: params.extend(f_params) if self.query.select_for_update and features.has_select_for_update: - if self.connection.get_autocommit(): + if ( + self.connection.get_autocommit() + # Don't raise an exception when database doesn't + # support transactions, as it's a noop. + and features.supports_transactions + ): raise TransactionManagementError( "select_for_update cannot be used outside of a transaction." ) diff --git a/tests/queries/test_explain.py b/tests/queries/test_explain.py index f61fe01e9d..43ff0bdef3 100644 --- a/tests/queries/test_explain.py +++ b/tests/queries/test_explain.py @@ -32,19 +32,11 @@ class ExplainTests(TestCase): for idx, queryset in enumerate(querysets): for format in all_formats: with self.subTest(format=format, queryset=idx): - with CaptureQueriesContext(connection) as captured_queries: - if queryset.query.select_for_update: - with transaction.atomic(): - result = queryset.explain(format=format) - else: - result = queryset.explain(format=format) - self.assertEqual(len(captured_queries), 1) + with self.assertNumQueries(1) as captured_queries: + result = queryset.explain(format=format) self.assertTrue( - any( - captured_query["sql"].startswith( - connection.ops.explain_prefix - ) - for captured_query in captured_queries + captured_queries[0]["sql"].startswith( + connection.ops.explain_prefix ) ) self.assertIsInstance(result, str) diff --git a/tests/select_for_update/tests.py b/tests/select_for_update/tests.py index 1612a66064..0251014541 100644 --- a/tests/select_for_update/tests.py +++ b/tests/select_for_update/tests.py @@ -491,7 +491,7 @@ class SelectForUpdateTests(TransactionTestCase): str(Person.objects.filter(name="foo").select_for_update().query), ) - @skipUnlessDBFeature("has_select_for_update") + @skipUnlessDBFeature("has_select_for_update", "supports_transactions") def test_for_update_requires_transaction(self): """ A TransactionManagementError is raised @@ -501,7 +501,7 @@ class SelectForUpdateTests(TransactionTestCase): with self.assertRaisesMessage(transaction.TransactionManagementError, msg): list(Person.objects.select_for_update()) - @skipUnlessDBFeature("has_select_for_update") + @skipUnlessDBFeature("has_select_for_update", "supports_transactions") def test_for_update_requires_transaction_only_in_execution(self): """ No TransactionManagementError is raised