You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classTestModel(Model):
""" A model for testing """classMeta:
region='us-east-1'table_name='pynamodb-ci'host=ddb_urlforum=UnicodeAttribute(hash_key=True)
score=NumberAttribute()
version=VersionAttribute()
a simple update on the model without getting it first resets it's version to 1:
obj=TestModel('1')
obj.save()
assertTestModel.get('1').version==1obj.score=1obj.save()
assertTestModel.get('1').version==2obj_by_key=TestModel('1') # try to update item without getting it firstobj_by_key.update(
actions=[
TestModel.score.set(2), # no version increment
],
add_version_condition=False
)
updated_obj=TestModel.get('1')
assertupdated_obj.score==2assertupdated_obj.version==2# AssertionError: assert 1 == 2
manual version update also fails with "Two document paths overlap with each other" error as the update method automatically adds a SET operation for the version and they conflict:
obj_2=TestModel('2')
obj_2.save()
assertTestModel.get('2').version==1obj_2.score=1obj_2.save()
assertTestModel.get('2').version==2obj_2_by_key=TestModel('2') # try to update item without getting it firstobj_2_by_key.update(
actions=[
TestModel.score.set(2),
TestModel.version.set(TestModel.version+1) # increment version manually
],
add_version_condition=False
) # pynamodb.exceptions.UpdateError: Failed to update item: An error occurred (ValidationException) on request (c46f93e9-5ffd-4c08-8b3a-59926cd2d8a8) on table (pynamodb-ci) when calling the UpdateItem operation: Invalid UpdateExpression: Two document paths overlap with each other; must remove or rewrite one of these paths; path one: [version], path two: [version]updated_obj_2=TestModel.get('2')
assertupdated_obj_2.score==2assertupdated_obj_2.version==3
The same issues apply to updates in transactions.
See the integration tests in the linked pull request for runnable versions of these examples.
Root cause
The root cause seems to be in Model._handle_version_attribute, which automatically tries to increment the models version and sets it to 1 if getattr(self, self._version_attribute_name) returns None.
Solution proposal
I propose to add an increment_version flag to the relevant Model methods, similar to add_version_condition.
For example:
You shouldn't need to run a GetItem operation before running an UpdateItem.
If the existing version of record is say 6, we shouldn't write the update operation as SET version = 7 but rather SET version = version + 1 That way the increment operation doesn't need to know the previous value. This would also work for the case where there is no version attribute set yet.
bpsoos
changed the title
updating an item without getting it first resets it's version to 1
bug: updating an item without getting it first resets it's version to 1
Aug 23, 2024
The Issue
Given a model with a version attribute:
a simple update on the model without getting it first resets it's version to 1:
manual version update also fails with "Two document paths overlap with each other" error as the
update
method automatically adds aSET
operation for the version and they conflict:The same issues apply to updates in transactions.
See the integration tests in the linked pull request for runnable versions of these examples.
Root cause
The root cause seems to be in Model._handle_version_attribute, which automatically tries to increment the models version and sets it to 1 if
getattr(self, self._version_attribute_name)
returnsNone
.Solution proposal
I propose to add an
increment_version
flag to the relevant Model methods, similar toadd_version_condition
.For example:
The text was updated successfully, but these errors were encountered: