Skip to content

Commit 9530668

Browse files
committed
add validation of broken transactions
1 parent 0dd2dea commit 9530668

File tree

4 files changed

+33
-4
lines changed

4 files changed

+33
-4
lines changed

django_mongodb_backend/base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ def close_pool(self):
259259
def cursor(self):
260260
return Cursor()
261261

262+
def validate_no_broken_transaction(self):
263+
if self.features.supports_transactions:
264+
super().validate_no_broken_transaction()
265+
262266
def get_database_version(self):
263267
"""Return a tuple of the database's version."""
264268
return tuple(self.connection.server_info()["versionArray"])

django_mongodb_backend/compiler.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ def execute_sql(self, returning_fields=None):
685685
@wrap_database_errors
686686
def insert(self, docs, returning_fields=None):
687687
"""Store a list of documents using field columns as element names."""
688+
self.connection.validate_no_broken_transaction()
688689
inserted_ids = self.collection.insert_many(
689690
docs, session=self.connection.session
690691
).inserted_ids
@@ -770,6 +771,7 @@ def execute_sql(self, result_type):
770771

771772
@wrap_database_errors
772773
def update(self, criteria, pipeline):
774+
self.connection.validate_no_broken_transaction()
773775
return self.collection.update_many(
774776
criteria, pipeline, session=self.connection.session
775777
).matched_count

django_mongodb_backend/features.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
4848
"aggregation.tests.AggregateTestCase.test_order_by_aggregate_transform",
4949
# 'NulledTransform' object has no attribute 'as_mql'.
5050
"lookup.tests.LookupTests.test_exact_none_transform",
51-
# "Save with update_fields did not affect any rows."
52-
"basic.tests.SelectOnSaveTests.test_select_on_save_lying_update",
5351
# BaseExpression.convert_value() crashes with Decimal128.
5452
"aggregation.tests.AggregateTestCase.test_combine_different_types",
5553
"annotations.tests.NonAggregateAnnotationTestCase.test_combined_f_expression_annotation_with_aggregation",
@@ -84,8 +82,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
8482
# Value.as_mql() doesn't call output_field.get_db_prep_save():
8583
# https://github.com/mongodb/django-mongodb-backend/issues/282
8684
"model_fields.test_jsonfield.TestSaveLoad.test_bulk_update_custom_get_prep_value",
87-
# to debug
88-
"transactions.tests.AtomicMiscTests.test_mark_for_rollback_on_error_in_transaction",
8985
}
9086
# $bitAnd, #bitOr, and $bitXor are new in MongoDB 6.3.
9187
_django_test_expected_failures_bitwise = {
@@ -96,11 +92,34 @@ class DatabaseFeatures(BaseDatabaseFeatures):
9692
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_right_null",
9793
"expressions.tests.ExpressionOperatorTests.test_lefthand_transformed_field_bitwise_or",
9894
}
95+
_django_test_expected_failures_no_transactions = {
96+
# "Save with update_fields did not affect any rows." instead of
97+
# "An error occurred in the current transaction. You can't execute
98+
# queries until the end of the 'atomic' block."
99+
"basic.tests.SelectOnSaveTests.test_select_on_save_lying_update",
100+
}
99101
_django_test_expected_failures_transactions = {
100102
# When update_or_create() fails with IntegrityError, the transaction
101103
# is no longer usable.
102104
"get_or_create.tests.UpdateOrCreateTests.test_manual_primary_key_test",
103105
"get_or_create.tests.UpdateOrCreateTestsWithManualPKs.test_create_with_duplicate_primary_key",
106+
# Tests that require savepoints
107+
"admin_views.tests.AdminViewBasicTest.test_disallowed_to_field",
108+
"admin_views.tests.AdminViewPermissionsTest.test_add_view",
109+
"admin_views.tests.AdminViewPermissionsTest.test_change_view",
110+
"admin_views.tests.AdminViewPermissionsTest.test_change_view_save_as_new",
111+
"admin_views.tests.AdminViewPermissionsTest.test_delete_view",
112+
"auth_tests.test_views.ChangelistTests.test_view_user_password_is_readonly",
113+
"fixtures.tests.FixtureLoadingTests.test_loaddata_app_option",
114+
"fixtures.tests.FixtureLoadingTests.test_unmatched_identifier_loading",
115+
"get_or_create.tests.GetOrCreateTests.test_get_or_create_invalid_params",
116+
"get_or_create.tests.UpdateOrCreateTests.test_integrity",
117+
"many_to_many.tests.ManyToManyTests.test_add",
118+
"many_to_one.tests.ManyToOneTests.test_fk_assignment_and_related_object_cache",
119+
"model_fields.test_booleanfield.BooleanFieldTests.test_null_default",
120+
"model_fields.test_floatfield.TestFloatField.test_float_validates_object",
121+
"multiple_database.tests.QueryTestCase.test_generic_key_cross_database_protection",
122+
"multiple_database.tests.QueryTestCase.test_m2m_cross_database_protection",
104123
}
105124

106125
@cached_property
@@ -111,6 +130,8 @@ def django_test_expected_failures(self):
111130
expected_failures.update(self._django_test_expected_failures_bitwise)
112131
if self.supports_transactions:
113132
expected_failures.update(self._django_test_expected_failures_transactions)
133+
else:
134+
expected_failures.update(self._django_test_expected_failures_no_transactions)
114135
return expected_failures
115136

116137
django_test_skips = {

django_mongodb_backend/query.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def __repr__(self):
6161
@wrap_database_errors
6262
def delete(self):
6363
"""Execute a delete query."""
64+
self.compiler.connection.validate_no_broken_transaction()
6465
if self.compiler.subqueries:
6566
raise NotSupportedError("Cannot use QuerySet.delete() when a subquery is required.")
6667
return self.compiler.collection.delete_many(
@@ -73,6 +74,7 @@ def get_cursor(self):
7374
Return a pymongo CommandCursor that can be iterated on to give the
7475
results of the query.
7576
"""
77+
self.compiler.connection.validate_no_broken_transaction()
7678
return self.compiler.collection.aggregate(
7779
self.get_pipeline(), session=self.compiler.connection.session
7880
)

0 commit comments

Comments
 (0)