Avoid LWTExceptions when updating columns that are part of the condition
This commit is contained in:
@@ -1151,6 +1151,7 @@ class ModelQuerySet(AbstractQuerySet):
|
|||||||
return
|
return
|
||||||
|
|
||||||
nulled_columns = set()
|
nulled_columns = set()
|
||||||
|
updated_columns = set()
|
||||||
us = UpdateStatement(self.column_family_name, where=self._where, ttl=self._ttl,
|
us = UpdateStatement(self.column_family_name, where=self._where, ttl=self._ttl,
|
||||||
timestamp=self._timestamp, conditionals=self._conditional, if_exists=self._if_exists)
|
timestamp=self._timestamp, conditionals=self._conditional, if_exists=self._if_exists)
|
||||||
for name, val in values.items():
|
for name, val in values.items():
|
||||||
@@ -1171,13 +1172,17 @@ class ModelQuerySet(AbstractQuerySet):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
us.add_update(col, val, operation=col_op)
|
us.add_update(col, val, operation=col_op)
|
||||||
|
updated_columns.add(col_name)
|
||||||
|
|
||||||
if us.assignments:
|
if us.assignments:
|
||||||
self._execute(us)
|
self._execute(us)
|
||||||
|
|
||||||
|
null_conditional = [condition for condition in self._conditional
|
||||||
|
if condition.field not in updated_columns]
|
||||||
|
|
||||||
if nulled_columns:
|
if nulled_columns:
|
||||||
ds = DeleteStatement(self.column_family_name, fields=nulled_columns,
|
ds = DeleteStatement(self.column_family_name, fields=nulled_columns,
|
||||||
where=self._where, conditionals=self._conditional, if_exists=self._if_exists)
|
where=self._where, conditionals=null_conditional, if_exists=self._if_exists)
|
||||||
self._execute(ds)
|
self._execute(ds)
|
||||||
|
|
||||||
|
|
||||||
@@ -1262,6 +1267,8 @@ class DMLQuery(object):
|
|||||||
conditionals=self._conditional, if_exists=self._if_exists)
|
conditionals=self._conditional, if_exists=self._if_exists)
|
||||||
for name, col in self.instance._clustering_keys.items():
|
for name, col in self.instance._clustering_keys.items():
|
||||||
null_clustering_key = null_clustering_key and col._val_is_null(getattr(self.instance, name, None))
|
null_clustering_key = null_clustering_key and col._val_is_null(getattr(self.instance, name, None))
|
||||||
|
|
||||||
|
updated_columns = set()
|
||||||
# get defined fields and their column names
|
# get defined fields and their column names
|
||||||
for name, col in self.model._columns.items():
|
for name, col in self.model._columns.items():
|
||||||
# if clustering key is null, don't include non static columns
|
# if clustering key is null, don't include non static columns
|
||||||
@@ -1279,6 +1286,7 @@ class DMLQuery(object):
|
|||||||
|
|
||||||
static_changed_only = static_changed_only and col.static
|
static_changed_only = static_changed_only and col.static
|
||||||
statement.add_update(col, val, previous=val_mgr.previous_value)
|
statement.add_update(col, val, previous=val_mgr.previous_value)
|
||||||
|
updated_columns.add(col.db_field_name)
|
||||||
|
|
||||||
if statement.assignments:
|
if statement.assignments:
|
||||||
for name, col in self.model._primary_keys.items():
|
for name, col in self.model._primary_keys.items():
|
||||||
@@ -1288,6 +1296,10 @@ class DMLQuery(object):
|
|||||||
statement.add_where(col, EqualsOperator(), getattr(self.instance, name))
|
statement.add_where(col, EqualsOperator(), getattr(self.instance, name))
|
||||||
self._execute(statement)
|
self._execute(statement)
|
||||||
|
|
||||||
|
# remove conditions on fields that have been updated
|
||||||
|
self._conditional = [condition for condition in self._conditional
|
||||||
|
if condition.field not in updated_columns]
|
||||||
|
|
||||||
if not null_clustering_key:
|
if not null_clustering_key:
|
||||||
self._delete_null_columns()
|
self._delete_null_columns()
|
||||||
|
|
||||||
|
|||||||
@@ -234,3 +234,18 @@ class TestConditional(BaseCassEngTestCase):
|
|||||||
self.assertIsNotNone(TestConditionalModel.objects(id=t.id).first().text)
|
self.assertIsNotNone(TestConditionalModel.objects(id=t.id).first().text)
|
||||||
TestConditionalModel.objects(id=t.id).iff(count=5).update(text=None)
|
TestConditionalModel.objects(id=t.id).iff(count=5).update(text=None)
|
||||||
self.assertIsNone(TestConditionalModel.objects(id=t.id).first().text)
|
self.assertIsNone(TestConditionalModel.objects(id=t.id).first().text)
|
||||||
|
|
||||||
|
def test_column_delete_after_update(self):
|
||||||
|
# DML path
|
||||||
|
t = TestConditionalModel.create(text='something', count=5)
|
||||||
|
t.iff(count=5).update(text=None, count=6)
|
||||||
|
|
||||||
|
self.assertIsNone(t.text)
|
||||||
|
self.assertEqual(t.count, 6)
|
||||||
|
|
||||||
|
# QuerySet path
|
||||||
|
t = TestConditionalModel.create(text='something', count=5)
|
||||||
|
TestConditionalModel.objects(id=t.id).iff(count=5).update(text=None, count=6)
|
||||||
|
|
||||||
|
self.assertIsNone(TestConditionalModel.objects(id=t.id).first().text)
|
||||||
|
self.assertEqual(TestConditionalModel.objects(id=t.id).first().count, 6)
|
||||||
|
|||||||
Reference in New Issue
Block a user